128 lines
4.8 KiB
JavaScript
128 lines
4.8 KiB
JavaScript
|
// Copyright 2015 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.
|
||
|
|
||
|
var target = {};
|
||
|
var configurable_desc = {
|
||
|
value: 123,
|
||
|
configurable: true,
|
||
|
writable: true,
|
||
|
enumerable: false,
|
||
|
};
|
||
|
Object.defineProperty(target, "configurable", configurable_desc);
|
||
|
var nonconfigurable_desc = {
|
||
|
value: 234,
|
||
|
configurable: false,
|
||
|
writable: false,
|
||
|
enumerable: true
|
||
|
}
|
||
|
Object.defineProperty(target, "nonconfigurable", nonconfigurable_desc);
|
||
|
|
||
|
var proxied_desc = {
|
||
|
value: 345,
|
||
|
configurable: true
|
||
|
};
|
||
|
|
||
|
var handler = {
|
||
|
"getOwnPropertyDescriptor": function(target, name) {
|
||
|
if (name === "proxied") {
|
||
|
return proxied_desc;
|
||
|
}
|
||
|
if (name === "return_null") {
|
||
|
return null;
|
||
|
}
|
||
|
return Object.getOwnPropertyDescriptor(target, name);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var proxy = new Proxy(target, handler);
|
||
|
var proxy_without_handler = new Proxy(target, {});
|
||
|
|
||
|
// Checking basic functionality:
|
||
|
|
||
|
assertEquals(configurable_desc,
|
||
|
Object.getOwnPropertyDescriptor(proxy, "configurable"));
|
||
|
assertEquals(nonconfigurable_desc,
|
||
|
Object.getOwnPropertyDescriptor(proxy, "nonconfigurable"));
|
||
|
assertEquals({ value: proxied_desc.value,
|
||
|
configurable: proxied_desc.configurable,
|
||
|
enumerable: false,
|
||
|
writable: false },
|
||
|
Object.getOwnPropertyDescriptor(proxy, "proxied"));
|
||
|
assertEquals(configurable_desc,
|
||
|
Object.getOwnPropertyDescriptor(proxy_without_handler,
|
||
|
"configurable"));
|
||
|
assertEquals(nonconfigurable_desc,
|
||
|
Object.getOwnPropertyDescriptor(proxy_without_handler,
|
||
|
"nonconfigurable"));
|
||
|
|
||
|
assertThrows('Object.getOwnPropertyDescriptor(proxy, "return_null")');
|
||
|
|
||
|
handler.getOwnPropertyDescriptor = undefined;
|
||
|
assertEquals(configurable_desc,
|
||
|
Object.getOwnPropertyDescriptor(proxy, "configurable"));
|
||
|
|
||
|
// Checking invariants mentioned explicitly by the ES spec:
|
||
|
|
||
|
// (Inv-1) "A property cannot be reported as non-existent, if it exists as a
|
||
|
// non-configurable own property of the target object."
|
||
|
handler.getOwnPropertyDescriptor = function(target, name) { return undefined; };
|
||
|
assertThrows('Object.getOwnPropertyDescriptor(proxy, "nonconfigurable")');
|
||
|
assertEquals(undefined, Object.getOwnPropertyDescriptor(proxy, "configurable"));
|
||
|
|
||
|
// (Inv-2) "A property cannot be reported as non-configurable, if it does not
|
||
|
// exist as an own property of the target object or if it exists as a
|
||
|
// configurable own property of the target object."
|
||
|
handler.getOwnPropertyDescriptor = function(target, name) {
|
||
|
return {value: 234, configurable: false, enumerable: true};
|
||
|
};
|
||
|
assertThrows('Object.getOwnPropertyDescriptor(proxy, "nonexistent")');
|
||
|
assertThrows('Object.getOwnPropertyDescriptor(proxy, "configurable")');
|
||
|
assertEquals(
|
||
|
false,
|
||
|
Object.getOwnPropertyDescriptor(proxy, "nonconfigurable").configurable);
|
||
|
|
||
|
// (Inv-3) "A property cannot be reported as non-existent, if it exists as an
|
||
|
// own property of the target object and the target object is not extensible."
|
||
|
Object.seal(target);
|
||
|
handler.getOwnPropertyDescriptor = function(target, name) { return undefined; };
|
||
|
assertThrows('Object.getOwnPropertyDescriptor(proxy, "configurable")');
|
||
|
assertThrows('Object.getOwnPropertyDescriptor(proxy, "nonconfigurable")');
|
||
|
assertEquals(undefined, Object.getOwnPropertyDescriptor(proxy, "nonexistent"));
|
||
|
|
||
|
// (Inv-4) "A property cannot be reported as existent, if it does not exist as
|
||
|
// an own property of the target object and the target object is not
|
||
|
// extensible."
|
||
|
var existent_desc = {value: "yes"};
|
||
|
handler.getOwnPropertyDescriptor = function() { return existent_desc; };
|
||
|
assertThrows('Object.getOwnPropertyDescriptor(proxy, "nonexistent")');
|
||
|
assertEquals(
|
||
|
{value: "yes", writable: false, enumerable: false, configurable: false},
|
||
|
Object.getOwnPropertyDescriptor(proxy, "configurable"));
|
||
|
|
||
|
// Checking individual bailout points in the implementation:
|
||
|
|
||
|
// Step 6: Trap is not callable.
|
||
|
handler.getOwnPropertyDescriptor = {};
|
||
|
assertThrows('Object.getOwnPropertyDescriptor(proxy, "configurable")');
|
||
|
|
||
|
// Step 8: Trap throws.
|
||
|
handler.getOwnPropertyDescriptor = function() { throw "ball"; };
|
||
|
assertThrows('Object.getOwnPropertyDescriptor(proxy, "configurable")');
|
||
|
|
||
|
// Step 9: Trap result is neither undefined nor an object.
|
||
|
handler.getOwnPropertyDescriptor = function() { return 1; }
|
||
|
assertThrows('Object.getOwnPropertyDescriptor(proxy, "configurable")');
|
||
|
|
||
|
// Step 11b: See (Inv-1) above.
|
||
|
// Step 11e: See (Inv-3) above.
|
||
|
|
||
|
// Step 16: Incompatible PropertyDescriptor; a non-configurable property
|
||
|
// cannot be reported as configurable. (Inv-4) above checks more cases.
|
||
|
handler.getOwnPropertyDescriptor = function(target, name) {
|
||
|
return {value: 456, configurable: true, writable: true}
|
||
|
};
|
||
|
assertThrows('Object.getOwnPropertyDescriptor(proxy, "nonconfigurable")');
|
||
|
|
||
|
// Step 17: See (Inv-2) above.
|