From bdf5adc40b21b5850c72a131fdfad1ce85f19e89 Mon Sep 17 00:00:00 2001 From: Cameron Hunter Date: Fri, 5 Aug 2016 21:44:32 -0700 Subject: [PATCH] Ensure that existing properties are configurable before redefining Summary: `Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js` attempts to setup global variables typical in most JavaScript environments. It finds the previous property value using `Object.getOwnPropertyDescriptor` and preserves it as `original[PropertyName]` (if it existed), it then redefines the property using `Object.defineProperty`. Properties may only be redefined if the property descriptor specifies that it is configurable ([MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor)). Attempting to redefine an non-configurable property will result in an error: `TypeError: Cannot redefine property: [PropertyName]`. Not all properties being setup in `InitializeJavaScriptAppEngine.js` are necessarily configurable in the target environment. Closes https://github.com/facebook/react-native/pull/9244 Differential Revision: D3679683 fbshipit-source-id: cd3398ef2cdf38e58c58862e64b159951c2b22c2 --- .../InitializeJavaScriptAppEngine.js | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js b/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js index 60b574709..bec2ddfbf 100644 --- a/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js +++ b/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js @@ -77,13 +77,16 @@ function defineProperty(object: Object, name: string, newValue: mixed): void { value: object[name], }); } - const {enumerable, writable} = descriptor || {}; - Object.defineProperty(object, name, { - configurable: true, - enumerable: enumerable !== false, - writable: writable !== false, - value: newValue, - }); + + const {enumerable, writable, configurable} = descriptor || {}; + if (!descriptor || configurable) { + Object.defineProperty(object, name, { + configurable: true, + enumerable: enumerable !== false, + writable: writable !== false, + value: newValue, + }); + } } function defineLazyProperty( @@ -98,11 +101,15 @@ function defineLazyProperty( const backupName = `original${name[0].toUpperCase()}${name.substr(1)}`; Object.defineProperty(object, backupName, descriptor); } - defineLazyObjectProperty(object, name, { - get: getNewValue, - enumerable: descriptor ? descriptor.enumerable !== false : true, - writable: descriptor ? descriptor.writable !== false : true, - }); + + const {configurable} = descriptor || {}; + if (!descriptor || configurable) { + defineLazyObjectProperty(object, name, { + get: getNewValue, + enumerable: descriptor ? descriptor.enumerable !== false : true, + writable: descriptor ? descriptor.writable !== false : true, + }); + } } function setUpErrorHandler(): void {