A study about the stability of Array.prototype.sort method on React Native

Kai Xie
4 min readAug 26, 2022

--

The sort() method sorts the elements of an array in place and returns the reference to the same array, now sorted. And we can also specify a compare function, with that the sorting method is applied. — https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

But is the sorting function stable on React Native? Let’s test it.

We say the sorting is stable if it keeps the order of the elements that has same values to compare. Like we apply the sorting function with index as the sorting key with ascending to an array like

const list = [
{
name: 'name-1',
index: 2,
},
{
name: 'name-2',
index: 0,
},
{
name: 'name-3',
index: 1,
},
{
name: 'name-4',
index: 0,
},
{
name: 'name-5',
index: 0,
},
{
name: 'name-6',
index: 0,
},
{
name: 'name-7',
index: 0,
},
];

and get the output like

const list = [
{
name: 'name-2',
index: 0,
},
{
name: 'name-4',
index: 0,
},
{
name: 'name-5',
index: 0,
},
{
name: 'name-6',
index: 0,
},
{
name: 'name-7',
index: 0,
},
{
name: 'name-3',
index: 1,
},
{
name: 'name-1',
index: 2,
},
];

then we say this sorting method is stable because it keeps the order of the element name-2, name-4, name-5, name-6, name-7, that have same sorting key, as they are

On the contrary, the sorting is unstable if it might break the order of elements with same sorting key. It is not saying it would break the order to all possible input, but if there is at least one input that breaks the order, it is unstable.

And then let’s test whether it is stable on React Native?

We can create an example project according to the instruction (https://reactnative.dev/) or follow the tutorial (https://kxie0124.medium.com/implementing-a-sticky-banner-with-animations-in-react-native-df5f619a6bb8).

And add following code in the App.tsx, just above the return statement

const list = [
{
name: 'name-1',
index: 2,
},
{
name: 'name-2',
index: 0,
},
{
name: 'name-3',
index: 1,
},
{
name: 'name-4',
index: 0,
},
{
name: 'name-5',
index: 0,
},
{
name: 'name-6',
index: 0,
},
{
name: 'name-7',
index: 0,
},
];

console.log(list.map(item => item.name));
const sortedList = list.sort((a, b) => a.index - b.index)
console.log(sortedList.map(item => item.name));

And then we can run the app with command line

yarn run android

or

yarn run ios

on two platforms.

And we should see the log of input array and sorted array in the terminal that running the metro server like

LOG  ["name-1", "name-2", "name-3", "name-4", "name-5", "name-6", "name-7"]LOG  ["name-2", "name-4", "name-5", "name-6", "name-7", "name-3", "name-1"]

So it is obvious stable because the order of name-2, name-4, name-5, name-6, name-7 retains.

But it also said

Since version 10 (or EcmaScript 2019), the specification dictates that Array.prototype.sort is stable. Before version 10 (or EcmaScript 2019), sort stability was not guaranteed — https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

But is it stable on older React Native versions? Let’s test it.

Firstly we can check the React Native version from the package.json, then we can find the react native version of this project is 0.69.4, latest version so far.

Let’s create another project with older React Native version, like 0.64. We can run following command to create project with specific React Native version

npx react-native init sorting --template react-native-template-typescript@6.6

We can find the table at https://www.npmjs.com/package/react-native-template-typescript

And then we build the app with same modification and run it, we would find the sorting function is also stable.

So we can make a simple conclusion that the sorting function is stable with default JS engine because we all know the JS code is running on JS engine on React Native.

But how about other JS engine, like Hermes. We all know the Hermes engine has better performance, but with some cost.

Ok. Let enable Hermes engine as https://reactnative.dev/docs/hermes

And rebuild and run the app again, we would find the it printed

LOG  ["name-1", "name-2", "name-3", "name-4", "name-5", "name-6", "name-7"]LOG  ["name-4", "name-5", "name-6", "name-7", "name-2", "name-3", "name-1"]

The order of elements with same sorting key changes. It is not a stable sorting.

So it is obvious an issue of Hermes engine.

How about other version of Hermes engine. But unfortunately, the Hermes engine version is bundled with React Native version as https://github.com/facebook/hermes/releases

So we need to upgrade React Native first with command

npx react-native upgrade x.xx.x

We can find React Native release versions at https://github.com/facebook/react-native/releases

After testing several versions, we would find the Hermes 0.11 on React Native 0.69.4 fixed this unstable sorting issue.

Actually, this issue is also addressed at https://github.com/facebook/hermes/issues/212.

So case closed.

--

--