| function assert(b) { |
| if (!b) |
| throw new Error; |
| } |
| |
| function test1(f) { |
| f.__proto__ = {}; |
| Object.defineProperty(f, "caller", {value:42}); |
| assert(f.caller === 42); |
| Object.defineProperty(f, "arguments", {value:32}); |
| assert(f.arguments === 32); |
| } |
| for (let i = 0; i < 1000; ++i) { |
| test1(function () { "use strict"; }); |
| test1(class C { }); |
| test1(() => undefined); |
| test1(async function foo(){}); |
| test1(function* foo() { }); |
| } |
| |
| function test2(f, p = {}) { |
| f.__proto__ = p; |
| f.caller = 42; |
| assert(f.caller === 42); |
| f.arguments = 44; |
| assert(f.arguments === 44); |
| } |
| |
| { |
| let proxy = new Proxy({}, { |
| has(...args) { |
| throw new Error("Should not be called!"); |
| } |
| }); |
| for (let i = 0; i < 1000; ++i) { |
| test2(function () { "use strict"; }, proxy); |
| test2(class C { }, proxy); |
| test2(() => undefined, proxy); |
| test2(async function foo(){}, proxy); |
| test2(function* foo() { }, proxy); |
| } |
| } |
| |
| for (let i = 0; i < 1000; ++i) { |
| test2(function () { "use strict"; }); |
| test2(class C { }); |
| test2(() => undefined); |
| test2(async function foo(){}); |
| test2(function* foo() { }); |
| } |
| |
| function test3(f) { |
| f.__proto__ = {}; |
| f.caller = 42; |
| assert(f.caller === 42); |
| assert(f.hasOwnProperty("caller")); |
| assert(delete f.caller === true); |
| assert(f.caller === undefined); |
| assert(!f.hasOwnProperty("caller")); |
| |
| f.arguments = 44; |
| assert(f.arguments === 44); |
| assert(f.hasOwnProperty("arguments")); |
| assert(delete f.arguments === true); |
| assert(f.arguments === undefined); |
| assert(!f.hasOwnProperty("arguments")); |
| } |
| for (let i = 0; i < 1000; ++i) { |
| test3(function () { "use strict"; }); |
| test3(class C { }); |
| test3(() => undefined); |
| test3(async function foo(){}); |
| test3(function* foo() { }); |
| } |