New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Different String.startsWith behaviour on Android vs iOS #11370

Closed
jdmunro opened this Issue Dec 8, 2016 · 30 comments

Comments

Projects
None yet
@jdmunro
Copy link

jdmunro commented Dec 8, 2016

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
@MatthewAwesome

This comment has been minimized.

Copy link

MatthewAwesome commented 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

This comment has been minimized.

Copy link
Contributor

blaues0cke commented 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 JSON response. And it only appears when no debugger is attached.

rn-fail

@zhuyifan2013

This comment has been minimized.

Copy link

zhuyifan2013 commented Jun 5, 2017

Still exists in RN 44

@ide

This comment has been minimized.

Copy link
Collaborator

ide commented 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

This comment has been minimized.

Copy link
Contributor

levsero commented Aug 3, 2017

@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

@artdent

This comment has been minimized.

Copy link

artdent commented 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

This comment has been minimized.

Copy link

jlangr commented 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

This comment has been minimized.

Copy link
Collaborator

ide commented 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

This comment has been minimized.

Copy link

jlangr commented 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

This comment has been minimized.

Copy link
Collaborator

ide commented Aug 25, 2017

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

@jlangr

This comment has been minimized.

Copy link

jlangr commented 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

This comment has been minimized.

Copy link
Collaborator

ide commented Aug 25, 2017

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

@stale

This comment has been minimized.

Copy link

stale bot commented 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.

@stale stale bot added the Stale label Oct 24, 2017

@artdent

This comment has been minimized.

Copy link

artdent commented Oct 24, 2017

This issue has not been fixed. In this case, two months of inactivity just means that there's nothing more to describe about the bug. Please keep it open.

@stale stale bot removed the Stale label Oct 24, 2017

@jdmunro

This comment has been minimized.

Copy link
Author

jdmunro commented Oct 25, 2017

I'd forgotten all about this issue but it actually still impacts my app. Can add a temporary work around to my code, but it looks like there are 2 longer term solutions for RN:

  1. Update to more modern version of JSC as @ide mentioned
  2. Always polyfill startsWith

Is there any reason not to do 2. as this seems to be a legitimate bug potentially affecting any app that uses startsWith on Android?

As another temporary workaround it might be worth trying this newer version of JSC for Android: https://github.com/SoftwareMansion/jsc-android-buildscripts#how-to-use-it-with-my-react-native-app

@stale

This comment has been minimized.

Copy link

stale bot commented Dec 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.

@stale stale bot added the Stale label Dec 24, 2017

@artdent

This comment has been minimized.

Copy link

artdent commented Dec 24, 2017

Please keep it open.

This issue has not been fixed. In this case, two months of inactivity just means that there's nothing more to describe about the bug.

@stale stale bot removed the Stale label Dec 24, 2017

@stale

This comment has been minimized.

Copy link

stale bot commented Feb 22, 2018

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.

@stale stale bot added the Stale label Feb 22, 2018

@jdmunro

This comment has been minimized.

Copy link
Author

jdmunro commented Feb 23, 2018

Please keep this open 馃憤
There's nothing else to describe about the bug at this stage.

@stale stale bot removed the Stale label Feb 23, 2018

@react-native-bot

This comment has been minimized.

Copy link
Collaborator

react-native-bot commented Feb 24, 2018

Thanks for posting this! It looks like you may not be using the latest version of React Native, v0.53.0, released on January 2018. Can you make sure this issue can still be reproduced in the latest version?

I am going to close this, but please feel free to open a new issue if you are able to confirm that this is still a problem in v0.53.0 or newer.

How to ContributeWhat to Expect from Maintainers

@stale stale bot removed the Stale label Feb 24, 2018

@blaues0cke

This comment has been minimized.

Copy link
Contributor

blaues0cke commented Feb 27, 2018

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
@ziyafenn

This comment has been minimized.

Copy link

ziyafenn commented Jul 15, 2018

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

@patrickkempff

This comment has been minimized.

Copy link
Collaborator

patrickkempff commented 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

This comment has been minimized.

Copy link

hey99xx commented 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

This comment has been minimized.

Copy link

ziyafenn commented Dec 1, 2018

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

@ahmetabdi

This comment has been minimized.

Copy link

ahmetabdi commented Dec 6, 2018

Same issue with latest RN

corporateanon pushed a commit to jskalama/kalama that referenced this issue Jan 7, 2019

@yernandus

This comment has been minimized.

Copy link

yernandus commented Jan 21, 2019

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

@ahmetabdi

This comment has been minimized.

Copy link

ahmetabdi commented Jan 22, 2019

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

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

@yernandus

This comment has been minimized.

Copy link

yernandus commented Jan 22, 2019

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

@hey99xx

This comment has been minimized.

Copy link

hey99xx commented 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment