Skip to content

Commit 0aa83b4

Browse files
javachefacebook-github-bot
authored andcommitted
Polyfill Array copying methods
Summary: Install guarded `Array.prototype.toSorted` and `Array.prototype.toReversed` polyfills during core environment setup. Both methods return shallow copies and preserve native implementations when the runtime already provides them. Changelog: [General][Added] - Polyfill `Array.prototype.toSorted` and `Array.prototype.toReversed` when the JavaScript runtime does not provide them Differential Revision: D125283374
1 parent ababa4d commit 0aa83b4

3 files changed

Lines changed: 145 additions & 0 deletions

File tree

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow strict
8+
* @format
9+
*/
10+
11+
'use strict';
12+
13+
const arrayPrototype = Array.prototype;
14+
const toSortedProperty: string = 'toSorted';
15+
const toReversedProperty: string = 'toReversed';
16+
const originalToSorted = Object.getOwnPropertyDescriptor(
17+
arrayPrototype,
18+
toSortedProperty,
19+
);
20+
const originalToReversed = Object.getOwnPropertyDescriptor(
21+
arrayPrototype,
22+
toReversedProperty,
23+
);
24+
25+
function removeCopyingMethods(): void {
26+
Object.defineProperty(arrayPrototype, toSortedProperty, {
27+
configurable: true,
28+
value: undefined,
29+
writable: true,
30+
});
31+
Object.defineProperty(arrayPrototype, toReversedProperty, {
32+
configurable: true,
33+
value: undefined,
34+
writable: true,
35+
});
36+
}
37+
38+
function restoreCopyingMethods(): void {
39+
if (originalToSorted == null) {
40+
Reflect.deleteProperty(arrayPrototype, toSortedProperty);
41+
} else {
42+
Object.defineProperty(arrayPrototype, toSortedProperty, originalToSorted);
43+
}
44+
if (originalToReversed == null) {
45+
Reflect.deleteProperty(arrayPrototype, toReversedProperty);
46+
} else {
47+
Object.defineProperty(
48+
arrayPrototype,
49+
toReversedProperty,
50+
originalToReversed,
51+
);
52+
}
53+
}
54+
55+
describe('setUpArrayES2023Methods', () => {
56+
beforeEach(() => {
57+
jest.resetModules();
58+
removeCopyingMethods();
59+
});
60+
61+
afterEach(() => {
62+
restoreCopyingMethods();
63+
});
64+
65+
test('installs non-mutating copying methods', () => {
66+
require('../setUpArrayES2023Methods');
67+
68+
const input = [3, 1, 2];
69+
expect(input.toSorted((a, b) => a - b)).toEqual([1, 2, 3]);
70+
expect(input.toReversed()).toEqual([2, 1, 3]);
71+
expect(input).toEqual([3, 1, 2]);
72+
expect(
73+
Object.getOwnPropertyDescriptor(arrayPrototype, toSortedProperty)
74+
?.enumerable,
75+
).toBe(false);
76+
expect(
77+
Object.getOwnPropertyDescriptor(arrayPrototype, toReversedProperty)
78+
?.enumerable,
79+
).toBe(false);
80+
});
81+
82+
test('preserves native implementations', () => {
83+
const nativeToSorted = jest.fn(() => ['sorted']);
84+
const nativeToReversed = jest.fn(() => ['reversed']);
85+
Object.defineProperty(arrayPrototype, toSortedProperty, {
86+
configurable: true,
87+
value: nativeToSorted,
88+
writable: true,
89+
});
90+
Object.defineProperty(arrayPrototype, toReversedProperty, {
91+
configurable: true,
92+
value: nativeToReversed,
93+
writable: true,
94+
});
95+
96+
require('../setUpArrayES2023Methods');
97+
98+
expect(arrayPrototype.toSorted).toBe(nativeToSorted);
99+
expect(arrayPrototype.toReversed).toBe(nativeToReversed);
100+
});
101+
});
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow strict
8+
* @format
9+
*/
10+
11+
'use strict';
12+
13+
const arrayPrototype = Array.prototype;
14+
15+
if (arrayPrototype.toSorted == null) {
16+
const toSortedProperty: string = 'toSorted';
17+
Object.defineProperty(arrayPrototype, toSortedProperty, {
18+
configurable: true,
19+
value: function <T>(
20+
this: Array<T>,
21+
compareFn?: (a: T, b: T) => number,
22+
): Array<T> {
23+
const copy = Array.from(this);
24+
copy.sort(compareFn);
25+
return copy;
26+
},
27+
writable: true,
28+
});
29+
}
30+
31+
if (arrayPrototype.toReversed == null) {
32+
const toReversedProperty: string = 'toReversed';
33+
Object.defineProperty(arrayPrototype, toReversedProperty, {
34+
configurable: true,
35+
value: function <T>(this: Array<T>): Array<T> {
36+
const copy = Array.from(this);
37+
copy.reverse();
38+
return copy;
39+
},
40+
writable: true,
41+
});
42+
}

‎packages/react-native/Libraries/Core/setUpGlobals.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
'use client';
1212
'use strict';
1313

14+
import './setUpArrayES2023Methods';
15+
1416
/**
1517
* Sets up global variables for React Native.
1618
* You can use this module directly, or just require InitializeCore.

0 commit comments

Comments
 (0)