Motivation
Surfaced during the #69 Object folder rollout (commit 9d16edc). When Object.create's second argument (the property-descriptors map) is a built-in object like Math, Error.prototype, or a function instance, our impl fails to iterate its own enumerable properties.
Per ECMA-262 §20.1.2.2.1 (ObjectDefineProperties):
- Let keys be ? props.[OwnPropertyKeys].
- For each element nextKey of keys, do
a. Let propDesc be ? props.[GetOwnProperty].
b. If propDesc is not undefined and propDesc.[[Enumerable]] is true, then
i. Let descObj be ? Get(props, nextKey).
ii. Let desc be ? ToPropertyDescriptor(descObj).
The [[OwnPropertyKeys]] invocation must work uniformly on any object — including built-in singletons.
Sample failing test
test/built-ins/Object/create/15.2.3.5-4-10.js:
Object.defineProperty(Math, "prop", {
get: function() {
result = (this === Math);
return {};
},
enumerable: true,
configurable: true
});
var newObj = Object.create({}, Math);
assert(result, 'result !== true');
assert(newObj.hasOwnProperty("prop"));
The test attaches an enumerable accessor prop to Math, then passes Math as the property-descriptor map. ECMA says iterate Math's own enumerable property keys (just "prop" here, since the standard Math.PI etc. are non-enumerable), invoke the getter, treat the returned object as a descriptor, and define newObj.prop.
Impact
| API |
Bucket |
Count |
Object.create |
RuntimeError |
128 |
Most are variants of the above pattern: Object.create({}, X) where X is one of Math, Error("msg"), function(){}, String(...), Number(...), Boolean(...), etc.
Suggested approach
- Audit
Object.create (and the shared ObjectDefineProperties shim that backs it) — the iteration step must call [[OwnPropertyKeys]] on the properties argument regardless of its concrete .NET type.
- Verify each built-in singleton type (
SharpTSMath, SharpTSError, SharpTSNumber, SharpTSBoolean, etc.) implements OwnPropertyKeys() returning the correct enumerable keys (including any properties dynamically attached via defineProperty).
- Cross-check:
for...in over Math after defineProperty(Math, "prop", {enumerable: true, ...}) should yield "prop". If that's broken, this fix is upstream of Object.create and lands a multiplier benefit.
Acceptance
- The 128
Object.create RuntimeError tests flip out of RuntimeError.
Object.keys(Math) after a defineProperty with enumerable: true returns the new key.
- No regressions in
Object/keys, Object/getOwnPropertyNames, for-in baselines.
Related
Part of #69. Likely shares root cause with parts of #103 (PropertyKey handling).
Motivation
Surfaced during the #69 Object folder rollout (commit 9d16edc). When
Object.create's second argument (the property-descriptors map) is a built-in object likeMath,Error.prototype, or a function instance, our impl fails to iterate its own enumerable properties.Per ECMA-262 §20.1.2.2.1 (
ObjectDefineProperties):The
[[OwnPropertyKeys]]invocation must work uniformly on any object — including built-in singletons.Sample failing test
test/built-ins/Object/create/15.2.3.5-4-10.js:The test attaches an enumerable accessor
proptoMath, then passesMathas the property-descriptor map. ECMA says iterateMath's own enumerable property keys (just"prop"here, since the standardMath.PIetc. are non-enumerable), invoke the getter, treat the returned object as a descriptor, and definenewObj.prop.Impact
Object.createMost are variants of the above pattern:
Object.create({}, X)whereXis one ofMath,Error("msg"),function(){},String(...),Number(...),Boolean(...), etc.Suggested approach
Object.create(and the sharedObjectDefinePropertiesshim that backs it) — the iteration step must call[[OwnPropertyKeys]]on thepropertiesargument regardless of its concrete .NET type.SharpTSMath,SharpTSError,SharpTSNumber,SharpTSBoolean, etc.) implementsOwnPropertyKeys()returning the correct enumerable keys (including any properties dynamically attached viadefineProperty).for...inoverMathafterdefineProperty(Math, "prop", {enumerable: true, ...})should yield"prop". If that's broken, this fix is upstream ofObject.createand lands a multiplier benefit.Acceptance
Object.createRuntimeError tests flip out ofRuntimeError.Object.keys(Math)after adefinePropertywithenumerable: truereturns the new key.Object/keys,Object/getOwnPropertyNames,for-inbaselines.Related
Part of #69. Likely shares root cause with parts of #103 (PropertyKey handling).