blob: 204e1341ceca86d08defda9fd83cb351610c3504 [file] [log] [blame]
//@ defaultNoNoLLIntRun if $architecture == "arm64" or $architecture == "arm"
function assert(b) {
if (!b)
throw new Error("bad assertion");
}
{
assert(Proxy.revocable.length === 2);
assert(Proxy.revocable.name === "revocable");
{
let threw = false;
try {
new Proxy.revocable;
} catch(e) {
threw = true;
assert(e.toString() === "TypeError: Proxy.revocable cannot be constructed. It can only be called");
}
assert(threw);
}
{
let threw = false;
try {
Proxy.revocable();
} catch(e) {
threw = true;
assert(e.toString() === "TypeError: Proxy.revocable needs to be called with two arguments: the target and the handler");
}
assert(threw);
}
{
let threw = false;
try {
Proxy.revocable({});
} catch(e) {
threw = true;
assert(e.toString() === "TypeError: Proxy.revocable needs to be called with two arguments: the target and the handler");
}
assert(threw);
}
{
let threw = false;
try {
Proxy.revocable({}, null);
} catch(e) {
threw = true;
assert(e.toString() === "TypeError: A Proxy's 'handler' should be an Object");
}
assert(threw);
}
{
let threw = false;
try {
Proxy.revocable(null, {});
} catch(e) {
threw = true;
assert(e.toString() === "TypeError: A Proxy's 'target' should be an Object");
}
assert(threw);
}
{
let threw = false;
try {
Proxy.revocable({}, {}, {}); // It's okay to call with > 2 arguments.
} catch(e) {
threw = true;
}
assert(!threw);
}
for (let i = 0; i < 500; i++) {
let threw = false;
try {
let {revoke} = Proxy.revocable({}, {}); // It's okay to call with > 2 arguments.
new revoke;
} catch(e) {
threw = true;
assert(e.toString() === "TypeError: function is not a constructor (evaluating 'new revoke')");
}
assert(threw);
}
for (let i = 0; i < 500; i++) {
function foo() {
let threw = false;
let {proxy, revoke} = Proxy.revocable({}, {});
revoke();
try {
new Proxy(proxy, {});
} catch(e) {
threw = true;
assert(e.toString() === "TypeError: A Proxy's 'target' shouldn't be a revoked Proxy");
}
assert(threw);
}
foo();
}
}
function callAllHandlers(proxy) {
Reflect.getPrototypeOf(proxy);
Reflect.setPrototypeOf(proxy, null);
Reflect.isExtensible(proxy);
Reflect.preventExtensions(proxy);
Reflect.getOwnPropertyDescriptor(proxy, "x")
Reflect.has(proxy, "x")
Reflect.get(proxy, "x")
proxy["x"] = 20; // Reflect.set
Reflect.deleteProperty(proxy, "x");
Reflect.defineProperty(proxy, "x", {value: 40, enumerable: true, configurable: true});
Reflect.ownKeys(proxy);
Reflect.apply(proxy, this, []);
Reflect.construct(proxy, []);
}
function shouldThrowNullHandler(f) {
let threw = false;
try {
f();
} catch(e) {
threw = true;
assert(e.toString() === "TypeError: Proxy has already been revoked. No more operations are allowed to be performed on it");
}
assert(threw);
}
function allHandlersShouldThrow(proxy) {
shouldThrowNullHandler(() => Reflect.getPrototypeOf(proxy));
shouldThrowNullHandler(() => Reflect.setPrototypeOf(proxy, null));
shouldThrowNullHandler(() => Reflect.isExtensible(proxy));
shouldThrowNullHandler(() => Reflect.preventExtensions(proxy));
shouldThrowNullHandler(() => Reflect.getOwnPropertyDescriptor(proxy, "x"));
shouldThrowNullHandler(() => Reflect.has(proxy, "x"));
shouldThrowNullHandler(() => Reflect.get(proxy, "x"));
shouldThrowNullHandler(() => proxy["x"] = 20); // Reflect.set
shouldThrowNullHandler(() => Reflect.deleteProperty(proxy, "x"));
shouldThrowNullHandler(() => Reflect.defineProperty(proxy, "x", {value: 40, enumerable: true, configurable: true}));
shouldThrowNullHandler(() => Reflect.ownKeys(proxy));
shouldThrowNullHandler(() => Reflect.apply(proxy, this, []));
shouldThrowNullHandler(() => Reflect.construct(proxy, []));
}
const traps = [
"getPrototypeOf",
"setPrototypeOf",
"isExtensible",
"preventExtensions",
"getOwnPropertyDescriptor",
"has",
"get",
"set",
"deleteProperty",
"defineProperty",
"ownKeys",
"apply",
"construct"
];
for (let i = 0; i < 500; i++) {
let handler = {};
let count = 0;
let trapsCalled = new Set;
for (let trap of traps) {
let func;
if (trap !== "set") {
func = `(function ${trap}(...args) { count++; trapsCalled.add(${"'" + trap + "'"}); return Reflect.${trap}(...args); })`;
} else {
func = `(function ${trap}(proxy, prop, v) { trapsCalled.add(${"'" + trap + "'"}); count++; proxy[prop] = v; })`;
}
handler[trap] = eval(func);
}
let {proxy, revoke} = Proxy.revocable(function(){}, handler); // To make callable and constructible true.
callAllHandlers(proxy);
assert(count >= traps.length);
for (let trap of traps) {
let result = trapsCalled.has(trap);
assert(result);
}
revoke();
allHandlersShouldThrow(proxy);
for (let i = 0; i < 50; i++)
revoke(); // Repeatedly calling revoke is OK.
}