You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Different String.startsWith behaviour on Android vs iOS #11370
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.
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
Reacted by Sibelius Seraphini, Jacob Lee, Thiago Lewin, bootstraponline, Jonas Bengtsson, Temitope, Matt Kennedy, Michael Bilenko, tonychan818, 337240552 and 2 more
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.
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.
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.
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.
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.
(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.
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.
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?
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.
Reacted by Jacob Lee, James Munro, 337240552, hey99xx, wkmcyz and yernar
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.
Activity
MatthewAwesome commentedon Apr 8, 2017
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.
blaues0cke commentedon May 31, 2017
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
JSONresponse. And it only appears when no debugger is attached.zhuyifan2013 commentedon Jun 5, 2017
Still exists in RN 44
ide commentedon Jun 5, 2017
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.
levsero commentedon Aug 3, 2017
@ide
String.startsWithis 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#L20artdent commentedon Aug 3, 2017
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.
jlangr commentedon Aug 25, 2017
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.
ide commentedon Aug 25, 2017
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.
jlangr commentedon Aug 25, 2017
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?
ide commentedon Aug 25, 2017
You could print
''.startsWith.toString()to see its source and then grep for that in node_modules.jlangr commentedon Aug 25, 2017
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.
ide commentedon Aug 25, 2017
That means it's using the native startsWith implementation then.
stale commentedon Oct 24, 2017
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.
15 remaining items
blaues0cke commentedon Feb 27, 2018
Cannot reproduce this in v0.53.0 using the Android simulator, tested on:
ziyafenn commentedon Jul 15, 2018
Using v0.55.4 and problem still exist in Android version.
patrickkempff commentedon Jul 15, 2018
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?
hey99xx commentedon Oct 3, 2018
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.
ziyafenn commentedon Dec 1, 2018
Hi @patrickkempff. Sorry for a VERY late answer. I checked it with
jsc-androidand there was no issue with it.ahmetabdi commentedon Dec 6, 2018
Same issue with latest RN
startsWith is fucked up in RN react/react-native#11370
yernandus commentedon Jan 21, 2019
Still facing this problem.
url.startsWith('http')returns true on IOS and false on Androidahmetabdi commentedon Jan 22, 2019
@yernandus An alternative (till they fix the issue) that works on both is:
url.indexOf('http') === 0yernandus commentedon Jan 22, 2019
@ahmetabdi, thank you. I used lodash startsWith, since lodash was used for other things already.
hey99xx commentedon Jan 23, 2019
RN made the JSC upgrade in master branch, expected release is 0.59 #19737 (comment) This should likely be fixed with that.