Source code

Revision control

Copy as Markdown

Other Tools

/*
* Any copyright is dedicated to the Public Domain.
*/
var gTestfile = "getPrototypeOf.js";
var BUGNUMBER = 888969;
var summary = "Scripted proxies' [[GetPrototypeOf]] behavior";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
const log = [];
function observe(obj)
{
var observingHandler = new Proxy({}, {
get(target, p, receiver) {
log.push(p);
return Reflect.get(target, p, receiver);
}
});
return new Proxy(obj, observingHandler);
}
function nop() {}
var p, h;
// 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
// 2. If handler is null, throw a TypeError exception.
// 3. Assert: Type(handler) is Object.
var rev = Proxy.revocable({}, {});
p = rev.proxy;
assertEq(Object.getPrototypeOf(p), Object.prototype);
rev.revoke();
assertThrowsInstanceOf(() => Object.getPrototypeOf(p), TypeError);
// 4. Let target be the value of the [[ProxyTarget]] internal slot of O.
// 5. Let trap be ? GetMethod(handler, "getPrototypeOf").
// Getting handler.getPrototypeOf might throw.
assertThrowsValue(() => Object.getPrototypeOf(new Proxy({},
{ get getPrototypeOf() {
throw 17;
} })),
17);
// The handler's getPrototypeOf, once gotten, might throw.
p = new Proxy({}, { getPrototypeOf() { throw 42; } });
assertThrowsValue(() => Object.getPrototypeOf(p), 42);
// The trap might not be callable.
p = new Proxy({}, { getPrototypeOf: 17 });
assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
TypeError);
// 6. If trap is undefined, then
// a. Return ? target.[[GetPrototypeOf]]().
var x, tp;
tp =
new Proxy(new Number(8675309), // behavior overridden by getPrototypeOf
{ getPrototypeOf() { x = "getPrototypeOf trap"; return null; } });
// The target's [[GetPrototypeOf]] should be invoked if the handler's
// .getPrototypeOf is undefined.
p = new Proxy(tp, { getPrototypeOf: undefined });
x = "unset";
assertEq(Object.getPrototypeOf(p), null);
assertEq(x, "getPrototypeOf trap");
// Likewise if the handler's .getPrototypeOf is null.
p = new Proxy(tp, { getPrototypeOf: null });
x = "unset";
assertEq(Object.getPrototypeOf(p), null);
assertEq(x, "getPrototypeOf trap");
// Now the target is an empty object with a Number object as its [[Prototype]].
var customProto = new Number(8675309);
tp =
new Proxy({},
{ getPrototypeOf() {
x = "getPrototypeOf trap";
return customProto;
} });
// The target's [[GetPrototypeOf]] should be invoked if the handler's
// .getPrototypeOf is undefined.
p = new Proxy(tp, { getPrototypeOf: undefined });
x = "unset";
assertEq(Object.getPrototypeOf(p), customProto);
assertEq(x, "getPrototypeOf trap");
// Likewise if the handler's .getPrototypeOf is null.
p = new Proxy(tp, { getPrototypeOf: null });
x = "unset";
assertEq(Object.getPrototypeOf(p), customProto);
assertEq(x, "getPrototypeOf trap");
// 7. Let handlerProto be ? Call(trap, handler, « target »).
// The trap callable might throw.
p = new Proxy({}, { getPrototypeOf() { throw "ohai"; } });
assertThrowsValue(() => Object.getPrototypeOf(p),
"ohai");
var throwingTrap =
new Proxy(function() { throw "not called"; },
{ apply() { throw 37; } });
p = new Proxy({}, { getPrototypeOf: throwingTrap });
assertThrowsValue(() => Object.getPrototypeOf(p),
37);
// The trap callable must *only* be called.
p = new Proxy({},
{
getPrototypeOf: observe(function() { throw "boo-urns"; })
});
log.length = 0;
assertThrowsValue(() => Object.getPrototypeOf(p),
"boo-urns");
assertEq(log.length, 1);
assertEq(log[0], "apply");
// 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError exception.
var rval;
var typeTestingTarget = {};
p = new Proxy(typeTestingTarget, { getPrototypeOf() { return rval; } });
function returnsPrimitives()
{
rval = undefined;
assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
TypeError);
rval = true;
assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
TypeError);
rval = false;
assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
TypeError);
rval = 0.0;
assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
TypeError);
rval = -0.0;
assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
TypeError);
rval = 3.141592654;
assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
TypeError);
rval = NaN;
assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
TypeError);
rval = -Infinity;
assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
TypeError);
rval = "[[Prototype]] FOR REALZ";
assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
TypeError);
rval = Symbol("[[Prototype]] FOR REALZ");
assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
TypeError);
}
returnsPrimitives();
Object.preventExtensions(typeTestingTarget);
returnsPrimitives();
// 9. Let extensibleTarget be ? IsExtensible(target).
var act, extens;
var typeTestingProxyTarget =
new Proxy({}, { isExtensible() {
seen = act();
return extens;
} });
p = new Proxy(typeTestingProxyTarget, { getPrototypeOf() { return rval; } });
rval = null;
act = () => { throw "fnord" };
assertThrowsValue(() => Object.getPrototypeOf(p),
"fnord");
rval = /abc/;
act = () => { throw "fnord again" };
assertThrowsValue(() => Object.getPrototypeOf(p),
"fnord again");
rval = Object.prototype;
act = () => { throw "fnord" };
assertThrowsValue(() => Object.getPrototypeOf(p),
"fnord");
// 10. If extensibleTarget is true, return handlerProto.
p = new Proxy({}, { getPrototypeOf() { return rval; } });
rval = Number.prototype;
assertEq(Object.getPrototypeOf(p), Number.prototype);
// 11. Let targetProto be ? target.[[GetPrototypeOf]]().
var targetProto;
var targetWithProto =
new Proxy(Object.preventExtensions(Object.create(null)),
{ getPrototypeOf() { act2(); return targetProto; } });
p = new Proxy(targetWithProto,
{ getPrototypeOf() { act1(); return rval; } });
rval = null;
targetProto = null;
var regex = /targetProto/;
act1 = () => log.push("act1");
act2 = () => log.push("act2");
log.length = 0;
assertEq(Object.getPrototypeOf(p), null);
assertEq(log.length, 2);
assertEq(log[0], "act1");
assertEq(log[1], "act2");
act1 = () => log.push("act1 again");
act2 = () => { throw "target throw"; };
log.length = 0;
assertThrowsValue(() => Object.getPrototypeOf(p),
"target throw");
assertEq(log.length, 1);
assertEq(log[0], "act1 again");
// 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError exception.
act1 = act2 = nop;
rval = /a/;
assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
TypeError);
// 13. Return handlerProto.
rval = null;
targetProto = null;
assertEq(Object.getPrototypeOf(p), null);
p = new Proxy(Object.preventExtensions(new Number(55)),
{ getPrototypeOf() { return Number.prototype; } });
assertEq(Object.getPrototypeOf(p), Number.prototype);
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("Tests complete");