Source code

Revision control

Copy as Markdown

Other Tools

// Copyright (C) 2017 Caitlin Potter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-object.keys
description: >
Object.keys() observably performs [[GetOwnProperty]]
info: |
19.1.2.16 Object.keys ( O )
1. Let obj be ? ToObject(O).
2. Let nameList be ? EnumerableOwnProperties(obj, "key").
...
7.3.21 EnumerableOwnProperties ( O, kind )
1. Assert: Type(O) is Object.
2. Let ownKeys be ? O.[[OwnPropertyKeys]]().
3. Let properties be a new empty List.
4. For each element key of ownKeys in List order, do
a. If Type(key) is String, then
i. Let desc be ? O.[[GetOwnProperty]](key).
...
features: [Symbol]
---*/
let log = [];
let s = Symbol("test");
let target = {
x: true
};
let ownKeys = {
get length() {
log.push({
name: "get ownKeys['length']",
receiver: this
});
return 3;
},
get 0() {
log.push({
name: "get ownKeys[0]",
receiver: this
});
return "a";
},
get 1() {
log.push({
name: "get ownKeys[1]",
receiver: this
});
return s;
},
get 2() {
log.push({
name: "get ownKeys[2]",
receiver: this
});
return "b";
}
};
let ownKeysDescriptors = {
"a": {
enumerable: true,
configurable: true,
value: 1
},
"b": {
enumerable: false,
configurable: true,
value: 2
},
[s]: {
enumerable: true,
configurable: true,
value: 3
}
};
let handler = {
get ownKeys() {
log.push({
name: "get handler.ownKeys",
receiver: this
});
return (...args) => {
log.push({
name: "call handler.ownKeys",
receiver: this,
args
});
return ownKeys;
};
},
get getOwnPropertyDescriptor() {
log.push({
name: "get handler.getOwnPropertyDescriptor",
receiver: this
});
return (...args) => {
log.push({
name: "call handler.getOwnPropertyDescriptor",
receiver: this,
args
});
const name = args[1];
return ownKeysDescriptors[name];
};
}
};
let proxy = new Proxy(target, handler);
let keys = Object.keys(proxy);
assert.sameValue(log.length, 10);
assert.sameValue(log[0].name, "get handler.ownKeys");
assert.sameValue(log[0].receiver, handler);
assert.sameValue(log[1].name, "call handler.ownKeys");
assert.sameValue(log[1].receiver, handler);
assert.sameValue(log[1].args.length, 1);
assert.sameValue(log[1].args[0], target);
// CreateListFromArrayLike(trapResultArray, « String, Symbol »).
assert.sameValue(log[2].name, "get ownKeys['length']");
assert.sameValue(log[2].receiver, ownKeys);
assert.sameValue(log[3].name, "get ownKeys[0]");
assert.sameValue(log[3].receiver, ownKeys);
assert.sameValue(log[4].name, "get ownKeys[1]");
assert.sameValue(log[4].receiver, ownKeys);
assert.sameValue(log[5].name, "get ownKeys[2]");
assert.sameValue(log[5].receiver, ownKeys);
// Let desc be ? O.[[GetOwnProperty]]("a").
assert.sameValue(log[6].name, "get handler.getOwnPropertyDescriptor");
assert.sameValue(log[6].receiver, handler);
assert.sameValue(log[7].name, "call handler.getOwnPropertyDescriptor");
assert.sameValue(log[7].receiver, handler);
assert.sameValue(log[7].args.length, 2);
assert.sameValue(log[7].args[0], target);
assert.sameValue(log[7].args[1], "a");
// Let desc be ? O.[[GetOwnProperty]]("b").
assert.sameValue(log[8].name, "get handler.getOwnPropertyDescriptor");
assert.sameValue(log[8].receiver, handler);
assert.sameValue(log[9].name, "call handler.getOwnPropertyDescriptor");
assert.sameValue(log[9].receiver, handler);
assert.sameValue(log[9].args.length, 2);
assert.sameValue(log[9].args[0], target);
assert.sameValue(log[9].args[1], "b");
// "a" is the only enumerable String-keyed property.
assert.sameValue(keys.length, 1);
assert.sameValue(keys[0], "a");
reportCompare(0, 0);