Skip to content

Different String.startsWith behaviour on Android vs iOS #11370

Closed

Description

@jdmunro

Description

I'm using the startsWith method on JavaScript strings to compare some values. Specifically the string contains emoji characters, but not at the beginning of the string.

On iOS:

'Fish and Chips 🐟🍟'.startsWith('F') // true

The exact same code on Android:

'Fish and Chips 🐟🍟'.startsWith('F') // false

This may not be an issue of React Native but the underlying JS implementation - just a guess.

Reproduction

Here's a reproduction of the issue: https://rnplay.org/apps/yKn2qA

If you delete the emoji characters from the string the bug goes away.

Additional Information

  • React Native version: v0.33 to v0.39
  • Platform: Android

Activity

  1. MatthewAwesome commented on Apr 8, 2017

    @MatthewAwesome

    Issue persists in RN version 42, and I get it even with usual characters :( More of annoyance than anything, as String.indexOf('subString') == 0 as suffices as a workaround.

  2. blaues0cke commented on May 31, 2017

    @blaues0cke
    Contributor

    Can confirm that this issue exists in RN 42, too. Also have no emojis (but the text is encoded to support emojis). In my case this occurs in a regular JSON response. And it only appears when no debugger is attached.

    rn-fail

  3. zhuyifan2013 commented on Jun 5, 2017

    @zhuyifan2013

    Still exists in RN 44

  4. ide commented on Jun 5, 2017

    @ide
    Contributor

    This issue exists because iOS uses many different versions of JavaScriptCore (a different version of iOS 8, 9, 10, 11) and RN Android uses its own JSC version. So there will always be some differences between different platforms until JSC completely stabilizes (maybe never, since JS changes each year).

    To work around this you could write a polyfill or your own startsWith function instead.

  5. levsero commented on Aug 3, 2017

    @levsero
    Contributor

    @ide String.startsWith is already polyfilled in rn so I believe it should work regardless of the platform - https://github.com/facebook/react-native/blob/master/Libraries/polyfills/String.prototype.es6.js#L20

  6. artdent commented on Aug 3, 2017

    @artdent
    Contributor

    As you can see, the polyfill is only installed if the native version does not exist.

    In this case, either the JSC implementation on Android should be fixed or the polyfill should be uninstalled unconditionally. It's disconcerting to encounter bugs in the JS standard library.

  7. jlangr commented on Aug 25, 2017

    @jlangr

    In my case, the following expression returns false:
    if (url.toLowerCase().startsWith('this://'))
    ... when no debugger is attached, and when url (loaded from a GET request) has the value 'this://44'. The byte codes of all the chars match, too.
    When a debugger is attached, the expression returns true.

    If I explicitly set String.prototype.startsWith to the version defined in the polyfill source-- https://github.com/facebook/react-native/blob/master/Libraries/polyfills/String.prototype.es6.js#L20 -- the expression returns true when expected. (The polyfill also matches the source I can view from my browser when attached to the debugger.)

    (I'd like to see the source used for startsWith when not attached to a debugger, but calling toString() against the function just tells me that it's picking up native code--same result as when the debugger is attached. Is there another technique?)

    Thanks MatthewAwesome for the (successful) workaround tip.

  8. ide commented on Aug 25, 2017

    @ide
    Contributor

    The debugger has different behavior because it runs on a different computer and on a different VM. Currently I really recommend that you use it only to debug specific issues rather than the way you develop.

    This startsWith issue may get fixed in a few months if we are able to upgrade JSC. There is no real ETA though and if this issue is pressing for you I recommend you use your own String polyfill.

  9. jlangr commented on Aug 25, 2017

    @jlangr

    Thanks for the quick response ide!

    I get the bit about the debugger, thanks. The curiosity I have: (When I was not attached to the debugger,) I substituted the RN source as above (supposedly the polyfill used) and things worked just fine. So without this substitution, when startsWith does not behave correctly, some other source must be getting used--is there an easy way to know where that's coming from?

  10. ide commented on Aug 25, 2017

    @ide
    Contributor

    You could print ''.startsWith.toString() to see its source and then grep for that in node_modules.

  11. jlangr commented on Aug 25, 2017

    @jlangr

    Unfortunately it just tells me it's [native code]. In node_modules it looks like there are at least a few definitions of String.prototype.startsWith.

  12. ide commented on Aug 25, 2017

    @ide
    Contributor

    That means it's using the native startsWith implementation then.

  13. stale commented on Oct 24, 2017

    @stale

    This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Maybe the issue has been fixed in a recent release, or perhaps it is not affecting a lot of people. If you think this issue should definitely remain open, please let us know why. Thank you for your contributions.

  14. added
    StaleThere has been a lack of activity on this issue and it may be closed soon.
    on Oct 24, 2017
  15. 15 remaining items

  16. removed
    StaleThere has been a lack of activity on this issue and it may be closed soon.
    on Feb 24, 2018
  17. blaues0cke commented on Feb 27, 2018

    @blaues0cke
    Contributor

    Cannot reproduce this in v0.53.0 using the Android simulator, tested on:

    • Nexus_6P_API_23(AVD) - 6.0
    • Nexus_4_API_22(AVD) - 5.1.1
  18. ziyafenn commented on Jul 15, 2018

    @ziyafenn

    Using v0.55.4 and problem still exist in Android version.

  19. patrickkempff commented on Jul 15, 2018

    @patrickkempff
    Contributor

    Thank you @ziyafenn. Can you verify if the issue also exists if you use the JavaScriptCode from https://github.com/react-community/jsc-android-buildscripts?

  20. hey99xx commented on Oct 3, 2018

    @hey99xx

    I tried "this://44" thing mentioned above but couldn't get incorrect results with that. I could only see incorrect values when emojis are included. Also String.prototype.endsWith() seems broken symmetrically.

    Rather than checking jsc-android-buildscripts that is not production-ready yet, I'd be more curious to know if this issue happens on iOS 8/9 devices or not, but I don't have any devices to test. If it does not happen this bug might also mean FB's android-jsc is truly incompatible with standard iOS JSC runtimes.

  21. ziyafenn commented on Dec 1, 2018

    @ziyafenn

    Hi @patrickkempff. Sorry for a VERY late answer. I checked it with jsc-android and there was no issue with it.

  22. ahmetabdi commented on Dec 6, 2018

    @ahmetabdi

    Same issue with latest RN

  23. yernandus commented on Jan 21, 2019

    @yernandus

    Still facing this problem. url.startsWith('http') returns true on IOS and false on Android

  24. ahmetabdi commented on Jan 22, 2019

    @ahmetabdi

    @yernandus An alternative (till they fix the issue) that works on both is:

    url.indexOf('http') === 0

  25. yernandus commented on Jan 22, 2019

    @yernandus

    @ahmetabdi, thank you. I used lodash startsWith, since lodash was used for other things already.

  26. hey99xx commented on Jan 23, 2019

    @hey99xx

    RN made the JSC upgrade in master branch, expected release is 0.59 #19737 (comment) This should likely be fixed with that.

  27. locked as resolved and limited conversation to collaborators on Dec 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Ran CommandsOne of our bots successfully processed a command.Resolution: LockedThis issue was locked by the bot.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions