Skip to content

Commit 17026c3

Browse files
davidaurelioMartin Konicek
authored andcommitted
Respect original enumerability/writability when polyfilling globals
Summary: Reuses the original property descriptor when overwriting / polyfilling globals to ensure enumerability and writability are the same Closes #7704 Differential Revision: D3338119 Pulled By: davidaurelio fbshipit-source-id: ab456324a3346cd3ec8b2c3e3a2378408c92087c
1 parent af819a8 commit 17026c3

1 file changed

Lines changed: 34 additions & 17 deletions

File tree

Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -54,40 +54,47 @@ function setUpConsole() {
5454
* https://github.com/facebook/react-native/issues/934
5555
*/
5656
function polyfillGlobal(name, newValue, scope = global) {
57-
var descriptor = Object.getOwnPropertyDescriptor(scope, name) || {
58-
// jest for some bad reasons runs the polyfill code multiple times. In jest
59-
// environment, XmlHttpRequest doesn't exist so getOwnPropertyDescriptor
60-
// returns undefined and defineProperty default for writable is false.
61-
// Therefore, the second time it runs, defineProperty will fatal :(
62-
writable: true,
63-
};
64-
65-
if (scope[name] !== undefined) {
66-
var backupName = `original${name[0].toUpperCase()}${name.substr(1)}`;
57+
const descriptor = Object.getOwnPropertyDescriptor(scope, name);
58+
if (descriptor) {
59+
const backupName = `original${name[0].toUpperCase()}${name.substr(1)}`;
6760
Object.defineProperty(scope, backupName, {...descriptor, value: scope[name]});
6861
}
6962

70-
Object.defineProperty(scope, name, {...descriptor, value: newValue});
63+
const {enumerable, writable} = descriptor || {};
64+
65+
// jest for some bad reasons runs the polyfill code multiple times. In jest
66+
// environment, XmlHttpRequest doesn't exist so getOwnPropertyDescriptor
67+
// returns undefined and defineProperty default for writable is false.
68+
// Therefore, the second time it runs, defineProperty will fatal :(
69+
70+
Object.defineProperty(scope, name, {
71+
configurable: true,
72+
enumerable: enumerable !== false,
73+
writable: writable !== false,
74+
value: newValue,
75+
});
7176
}
7277

7378
function polyfillLazyGlobal(name, valueFn, scope = global) {
74-
if (scope[name] !== undefined) {
75-
const descriptor = Object.getOwnPropertyDescriptor(scope, name);
79+
const descriptor = getPropertyDescriptor(scope, name);
80+
if (descriptor) {
7681
const backupName = `original${name[0].toUpperCase()}${name.substr(1)}`;
77-
Object.defineProperty(scope, backupName, {...descriptor, value: scope[name]});
82+
Object.defineProperty(scope, backupName, descriptor);
7883
}
7984

85+
const {enumerable, writable} = descriptor || {};
8086
Object.defineProperty(scope, name, {
8187
configurable: true,
82-
enumerable: true,
88+
enumerable: enumerable !== false,
8389
get() {
8490
return (this[name] = valueFn());
8591
},
8692
set(value) {
8793
Object.defineProperty(this, name, {
8894
configurable: true,
89-
enumerable: true,
90-
value
95+
enumerable: enumerable !== false,
96+
writable: writable !== false,
97+
value,
9198
});
9299
}
93100
});
@@ -217,6 +224,16 @@ function setUpDevTools() {
217224
}
218225
}
219226

227+
function getPropertyDescriptor(object, name) {
228+
while (object) {
229+
const descriptor = Object.getOwnPropertyDescriptor(object, name);
230+
if (descriptor) {
231+
return descriptor;
232+
}
233+
object = Object.getPrototypeOf(object);
234+
}
235+
}
236+
220237
setUpProcess();
221238
setUpConsole();
222239
setUpTimers();

0 commit comments

Comments
 (0)