React Native and the Array.reverse bug

Christian Brevik

The news that broke a couple of days ago about the Array.reverse-bug that occurs in the newly released iOS 12 was a bit scary. I first learnt about it from this Stack Overflow-post by way of Hacker News.

Developers have experienced a JavaScript-bug in Safari iOS 12, where an Array.reverse will cache the Array value state, which will still remain reversed even if you reload the page. I think most developers will understand why that is a problem. And apparently the same error exists on macOS as well, not just iOS.

After researching it a bit more, I found that it's a bit misleading to call it a "Safari bug" though, because the WebKit bug report suggests that it actually exists in the JavaScriptCore-framework. Having contributed a bit to the React Native (RN) framework, I quickly noticed that this might be trouble. Because the RN JavaScript-bundle actually runs inside the JavaScriptCore-framework on iOS!

I am currently working at Ice (the Norwegian mobile operator) on their app, which is made with RN, and knew I had to look into this right away.

What I found is that everyone who upgrades to iOS 12 on their device, will experience this bug with React Native-apps they have installed.

So RN-developers should start getting a little worried.

Demonstrating the bug

I have made an example app to demonstrate that this bug will occur in RN-apps as well:

The Array.reverse bug inside a React Native-app

It is important to note here that if you have the RN remote debugger attached, this bug will not occur. This is because the remote debugger runs the JS-bundle inside of the Chrome-debugger.

Now your gut reaction may be to run to your codebases and search for "Array.reverse", and manually fix it in all those locations. But remember that any dependencies you use will also experience the same bug. This might lead to some really subtle bugs that will be difficult to debug.

Fixing the bug

Of course, this being the JavaScript-community, someone has already released a polyfill for this bug. You can install this package with:

yarn add array-reverse-polyfill

And then include it up top in your root index.js file:

import "array-reverse-polyfill";
import { AppRegistry } from "react-native";
import App from "./App";
import { name as appName } from "./app.json";

AppRegistry.registerComponent(appName, () => App);

This will override the Array.prototype.reverse with a fixed version, if the original version is found to be buggy:

fixed

If you only want to apply this fix for devices running iOS 12, you could do something like this instead:

import { Platform } from "react-native";
if (Platform.Version === "12.0") {
  require("array-reverse-polyfill");
}

It's important to say that I have not published any apps with this fix to the AppStore, and you should carefully test your apps if you want to apply this fix.

Outro

On a personal note, I think "just" applying fixes like this is going down the wrong road. If we have to manually polyfill for every little bug, then we're reverting back to practices which were not productive to begin with. I believe it is a good idea to encourage people to upgrade to a version of iOS that fixes the problem, since it is a global bug which can affect many other apps.

But of course, if this bug causes major problems in your app, a quick fix is better than nothing.

It is important to note that this will also occur in other frameworks or apps using JavaScriptCore, which includes Chrome on iOS, and WebViews which native apps are displaying, etc.

Check out the example code here if you want to test for yourself.