From 9cb28b9a7eb9ae06a595dbe6819c0f768c28e543 Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Thu, 23 Jun 2016 19:09:00 -0700 Subject: [PATCH] RN: Avoid Infinite Loop w/ Polyfills Reviewed By: voideanvalue Differential Revision: D3472319 fbshipit-source-id: 87c8bd6719eb1771ec16c7e363cec9ee247d87fe --- .../InitializeJavaScriptAppEngine.js | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js b/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js index 0883d949896179..ba5fa68fc9bdf4 100644 --- a/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js +++ b/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js @@ -77,7 +77,6 @@ function defineProperty(object: Object, name: string, newValue: mixed): void { value: object[name], }); } - const {enumerable, writable} = descriptor || {}; Object.defineProperty(object, name, { configurable: true, @@ -87,32 +86,42 @@ function defineProperty(object: Object, name: string, newValue: mixed): void { }); } -function defineLazyProperty( +function defineLazyProperty( object: Object, name: string, - getValue: () => mixed + getNewValue: () => T ): void { const descriptor = getPropertyDescriptor(object, name); if (descriptor) { const backupName = `original${name[0].toUpperCase()}${name.substr(1)}`; Object.defineProperty(object, backupName, descriptor); } - - const {enumerable, writable} = descriptor || {}; - Object.defineProperty(object, name, { + const config = { configurable: true, - enumerable: enumerable !== false, - get() { - return (object[name] = getValue()); - }, - set(value) { - Object.defineProperty(object, name, { - configurable: true, - enumerable: enumerable !== false, - writable: writable !== false, - value, - }); + enumerable: descriptor ? descriptor.enumerable !== false : true, + writable: descriptor ? descriptor.writable !== false : true, + }; + let value; + let valueSet = false; + function getValue(): T { + // WORKAROUND: A weird infinite loop occurs where calling `getValue` calls + // `setValue` which calls `Object.defineProperty` which somehow triggers + // `getValue` again. Adding `valueSet` breaks this loop. + if (!valueSet) { + setValue(getNewValue()); } + return value; + } + function setValue(newValue: T): void { + value = newValue; + valueSet = true; + Object.defineProperty(object, name, {...config, value: newValue}); + } + Object.defineProperty(object, name, { + configurable: config.configurable, + enumerable: config.enumerable, + get: getValue, + set: setValue, }); }