diff --git a/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js b/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js index ba5fa68fc..ea0d4f4ea 100644 --- a/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js +++ b/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js @@ -91,37 +91,17 @@ function defineLazyProperty( name: string, getNewValue: () => T ): void { + const defineLazyObjectProperty = require('defineLazyObjectProperty'); + const descriptor = getPropertyDescriptor(object, name); if (descriptor) { const backupName = `original${name[0].toUpperCase()}${name.substr(1)}`; Object.defineProperty(object, backupName, descriptor); } - const config = { - configurable: true, + defineLazyObjectProperty(object, name, { + get: getNewValue, 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, }); } diff --git a/Libraries/Utilities/defineLazyObjectProperty.js b/Libraries/Utilities/defineLazyObjectProperty.js new file mode 100644 index 000000000..7013ab6cb --- /dev/null +++ b/Libraries/Utilities/defineLazyObjectProperty.js @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule defineLazyObjectProperty + * @flow + */ + +'use strict'; + +/** + * Defines a lazily evaluated property on the supplied `object`. + */ +function defineLazyObjectProperty( + object: Object, + name: string, + descriptor: { + get: () => T, + enumerable?: boolean, + writable?: boolean, + }, +): void { + const {get} = descriptor; + const enumerable = descriptor.enumerable !== false; + const writable = descriptor.writable !== false; + + 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(get()); + } + return value; + } + function setValue(newValue: T): void { + value = newValue; + valueSet = true; + Object.defineProperty(object, name, { + value: newValue, + configurable: true, + enumerable, + writable, + }); + } + + Object.defineProperty(object, name, { + get: getValue, + set: setValue, + configurable: true, + enumerable, + }); +} + +module.exports = defineLazyObjectProperty;