From ed784d68999f0a24e84fd48778e23e25f1c95ca4 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 28 Sep 2018 15:52:11 -0700 Subject: [PATCH] Add abstract support to Object.getOwnPropertySymbols (#2575) Summary: Release notes: none Fixes https://github.com/facebook/prepack/issues/2574. This PR adds abstract value support to `Object.getOwnPropertySymbols` like we have done other internal methods (like `Object.keys` and `Array.from`) where we know the internal method creates an array with unknown numeric properties. Pull Request resolved: https://github.com/facebook/prepack/pull/2575 Differential Revision: D10114237 Pulled By: trueadm fbshipit-source-id: 07301147e2dff1ab370243a8dc9648745bbbbb96 --- src/intrinsics/ecma262/Object.js | 22 +++++++++- src/realm.js | 4 +- src/serializer/functions.js | 2 +- .../optimizations/getOwnPropertySymbols.js | 40 +++++++++++++++++++ 4 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 test/serializer/optimizations/getOwnPropertySymbols.js diff --git a/src/intrinsics/ecma262/Object.js b/src/intrinsics/ecma262/Object.js index 233a3d3c5..dc91d392b 100644 --- a/src/intrinsics/ecma262/Object.js +++ b/src/intrinsics/ecma262/Object.js @@ -495,11 +495,29 @@ export default function(realm: Realm): NativeFunctionValue { }); // ECMA262 19.1.2.9 - if (!realm.isCompatibleWith(realm.MOBILE_JSC_VERSION) && !realm.isCompatibleWith("mobile")) - func.defineNativeMethod("getOwnPropertySymbols", 1, (context, [O]) => { + if (!realm.isCompatibleWith(realm.MOBILE_JSC_VERSION) && !realm.isCompatibleWith("mobile")) { + let getOwnPropertySymbols = func.defineNativeMethod("getOwnPropertySymbols", 1, (context, [O]) => { + if (O instanceof AbstractValue && realm.isInPureScope()) { + let obj = O instanceof AbstractObjectValue ? O : To.ToObject(realm, O); + + realm.callReportObjectGetOwnProperties(obj); + return ArrayValue.createTemporalWithWidenedNumericProperty( + realm, + [getOwnPropertySymbols, obj], + createOperationDescriptor("UNKNOWN_ARRAY_METHOD_CALL") + ); + } else if (ArrayValue.isIntrinsicAndHasWidenedNumericProperty(O)) { + realm.callReportObjectGetOwnProperties(O); + return ArrayValue.createTemporalWithWidenedNumericProperty( + realm, + [getOwnPropertySymbols, O], + createOperationDescriptor("UNKNOWN_ARRAY_METHOD_CALL") + ); + } // Return ? GetOwnPropertyKeys(O, Symbol). return GetOwnPropertyKeys(realm, O, SymbolValue); }); + } // ECMA262 19.1.2.10 func.defineNativeMethod("getPrototypeOf", 1, (context, [O]) => { diff --git a/src/realm.js b/src/realm.js index f9938595d..ff70103c7 100644 --- a/src/realm.js +++ b/src/realm.js @@ -365,7 +365,7 @@ export class Realm { modifiedProperties: void | PropertyBindings; createdObjects: void | CreatedObjects; createdObjectsTrackedForLeaks: void | CreatedObjects; - reportObjectGetOwnProperties: void | (ObjectValue => void); + reportObjectGetOwnProperties: void | ((ObjectValue | AbstractObjectValue) => void); reportSideEffectCallbacks: Set< (sideEffectType: SideEffectType, binding: void | Binding | PropertyBinding, expressionLocation: any) => void >; @@ -1491,7 +1491,7 @@ export class Realm { return binding; } - callReportObjectGetOwnProperties(ob: ObjectValue): void { + callReportObjectGetOwnProperties(ob: ObjectValue | AbstractObjectValue): void { if (this.reportObjectGetOwnProperties !== undefined) { this.reportObjectGetOwnProperties(ob); } diff --git a/src/serializer/functions.js b/src/serializer/functions.js index 84cab06ff..6ad8e069c 100644 --- a/src/serializer/functions.js +++ b/src/serializer/functions.js @@ -390,7 +390,7 @@ export class Functions { writtenObjects.add(key.object); }); let oldReportObjectGetOwnProperties = this.realm.reportObjectGetOwnProperties; - this.realm.reportObjectGetOwnProperties = (ob: ObjectValue) => { + this.realm.reportObjectGetOwnProperties = (ob: ObjectValue | AbstractObjectValue) => { let location = this.realm.currentLocation; invariant(location); if (writtenObjects.has(ob) && !conflicts.has(location)) diff --git a/test/serializer/optimizations/getOwnPropertySymbols.js b/test/serializer/optimizations/getOwnPropertySymbols.js new file mode 100644 index 000000000..32fbff41d --- /dev/null +++ b/test/serializer/optimizations/getOwnPropertySymbols.js @@ -0,0 +1,40 @@ +function objectSpread(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? arguments[i] : {}; + var ownKeys = Object.keys(source); + + if (typeof Object.getOwnPropertySymbols === "function") { + ownKeys = ownKeys.concat( + Object.getOwnPropertySymbols(source).filter(function(sym) { + return Object.getOwnPropertyDescriptor(source, sym).enumerable; + }) + ); + } + + ownKeys.forEach(function(key) { + babelHelpers.defineProperty(target, key, source[key]); + }); + } + + return target; +} + +function fn(baseHeaders, contentEncoding, userAgent) { + var headers = objectSpread({}, baseHeaders); + + if (contentEncoding) { + headers["Content-Encoding"] = contentEncoding; + } + + if (userAgent) { + headers["User-Agent"] = userAgent; + } + + return headers; +} + +global.__optimize && __optimize(fn); + +inspect = function() { + return JSON.stringify(fn({ a: 1, b: 2 }, "123", "456")); +};