v8/test/mjsunit/harmony/object-get-own-property-descriptors.js
caitpotter88 8134986917 [builtins] don't create keys for undefined property descriptors in O.gOPDs
Implements the change proposed at https://github.com/tc39/ecma262/pull/593.

In summary, Object.getOwnPropertyDescriptors can produce results which cause
Object.defineProperties() to throw, by inserting a property with an undefined
descriptor into the result object. This change to the algorithm requires that
the descriptor only be added to the result object if it is not undefined.

BUG=v8:4725
R=littledan@chromium.org, adamk@chromium.org, jwolfe@igalia.com

Review-Url: https://codereview.chromium.org/2118613003
Cr-Commit-Position: refs/heads/master@{#37504}
2016-07-04 18:04:05 +00:00

236 lines
5.3 KiB
JavaScript

// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-object-own-property-descriptors
// Flags: --allow-natives-syntax
function DataDescriptor(value) {
return { "enumerable": true, "configurable": true, "writable": true, value };
}
function TestMeta() {
assertEquals(1, Object.getOwnPropertyDescriptors.length);
assertEquals(Function.prototype,
Object.getPrototypeOf(Object.getOwnPropertyDescriptors));
assertEquals(
'getOwnPropertyDescriptors', Object.getOwnPropertyDescriptors.name);
var desc = Reflect.getOwnPropertyDescriptor(
Object, 'getOwnPropertyDescriptors');
assertFalse(desc.enumerable);
assertTrue(desc.writable);
assertTrue(desc.configurable);
}
TestMeta();
function TestToObject() {
assertThrows(function() {
Object.getOwnPropertyDescriptors(null);
}, TypeError);
assertThrows(function() {
Object.getOwnPropertyDescriptors(undefined);
}, TypeError);
assertThrows(function() {
Object.getOwnPropertyDescriptors();
}, TypeError);
}
TestToObject();
function TestPrototypeProperties() {
function F() {};
F.prototype.a = "A";
F.prototype.b = "B";
var F2 = new F();
Object.defineProperties(F2, {
"b": {
enumerable: false,
configurable: true,
writable: false,
value: "Shadowed 'B'"
},
"c": {
enumerable: false,
configurable: true,
writable: false,
value: "C"
}
});
assertEquals({
"b": {
enumerable: false,
configurable: true,
writable: false,
value: "Shadowed 'B'"
},
"c": {
enumerable: false,
configurable: true,
writable: false,
value: "C"
}
}, Object.getOwnPropertyDescriptors(F2));
}
TestPrototypeProperties();
function TestPrototypeProperties() {
function F() {};
F.prototype.a = "A";
F.prototype.b = "B";
var F2 = new F();
Object.defineProperties(F2, {
"b": {
enumerable: false,
configurable: true,
writable: false,
value: "Shadowed 'B'"
},
"c": {
enumerable: false,
configurable: true,
writable: false,
value: "C"
}
});
assertEquals({
"b": {
enumerable: false,
configurable: true,
writable: false,
value: "Shadowed 'B'"
},
"c": {
enumerable: false,
configurable: true,
writable: false,
value: "C"
}
}, Object.getOwnPropertyDescriptors(F2));
}
TestPrototypeProperties();
function TestTypeFilteringAndOrder() {
var log = [];
var sym = Symbol("foo");
var psym = %CreatePrivateSymbol("private");
var O = {
0: 0,
[sym]: 3,
"a": 2,
[psym]: 4,
1: 1,
};
var P = new Proxy(O, {
ownKeys(target) {
log.push("ownKeys()");
return Reflect.ownKeys(target);
},
getOwnPropertyDescriptor(target, name) {
log.push(`getOwnPropertyDescriptor(${String(name)})`);
return Reflect.getOwnPropertyDescriptor(target, name);
},
get(target, name) { assertUnreachable(); },
set(target, name, value) { assertUnreachable(); },
deleteProperty(target, name) { assertUnreachable(); },
defineProperty(target, name, desc) { assertUnreachable(); }
});
var result1 = Object.getOwnPropertyDescriptors(O);
assertEquals({
0: DataDescriptor(0),
1: DataDescriptor(1),
"a": DataDescriptor(2),
[sym]: DataDescriptor(3)
}, result1);
var result2 = Object.getOwnPropertyDescriptors(P);
assertEquals([
"ownKeys()",
"getOwnPropertyDescriptor(0)",
"getOwnPropertyDescriptor(1)",
"getOwnPropertyDescriptor(a)",
"getOwnPropertyDescriptor(Symbol(foo))"
], log);
assertEquals({
0: DataDescriptor(0),
1: DataDescriptor(1),
"a": DataDescriptor(2),
[sym]: DataDescriptor(3)
}, result2);
}
TestTypeFilteringAndOrder();
function TestDuplicateKeys() {
var i = 0;
var log = [];
var P = new Proxy({}, {
ownKeys() {
log.push(`ownKeys()`);
return ["A", "A"];
},
getOwnPropertyDescriptor(t, name) {
log.push(`getOwnPropertyDescriptor(${name})`);
if (i++) return;
return {
configurable: true,
writable: false,
value: "VALUE"
};
},
get(target, name) { assertUnreachable(); },
set(target, name, value) { assertUnreachable(); },
deleteProperty(target, name) { assertUnreachable(); },
defineProperty(target, name, desc) { assertUnreachable(); }
});
var result = Object.getOwnPropertyDescriptors(P);
assertEquals({
"A": {
"value": "VALUE",
"writable": false,
"enumerable": false,
"configurable": true
}
}, result);
assertTrue(result.hasOwnProperty("A"));
assertEquals([
"ownKeys()",
"getOwnPropertyDescriptor(A)",
"getOwnPropertyDescriptor(A)"
], log);
}
TestDuplicateKeys();
function TestFakeProperty() {
var log = [];
var P = new Proxy({}, {
ownKeys() {
log.push(`ownKeys()`);
return ["fakeProperty"];
},
getOwnPropertyDescriptor(target, name) {
log.push(`getOwnPropertyDescriptor(${name})`);
return;
}
});
var result = Object.getOwnPropertyDescriptors(P);
assertEquals({}, result);
assertFalse(result.hasOwnProperty("fakeProperty"));
assertEquals([
"ownKeys()",
"getOwnPropertyDescriptor(fakeProperty)"
], log);
}
TestFakeProperty();