call-construct-hook.js (3281B)
1 // Tests for invoking JSClass call/construct hooks. 2 3 function testBasic() { 4 let obj = {fun: newObjectWithCallHook()}; 5 for (var i = 0; i < 1000; i++) { 6 let res = obj.fun(1, 2, 3); 7 assertEq(res.this, obj); 8 assertEq(res.callee, obj.fun); 9 assertEq(JSON.stringify(res.arguments), "[1,2,3]"); 10 assertEq(res.newTarget, undefined); 11 12 res = new obj.fun(1, 2, 3); 13 assertEq(res.this, "<is_constructing>"); 14 assertEq(res.callee, obj.fun); 15 assertEq(JSON.stringify(res.arguments), "[1,2,3]"); 16 assertEq(res.newTarget, obj.fun); 17 } 18 } 19 testBasic(); 20 21 function testSpread() { 22 let obj = {fun: newObjectWithCallHook()}; 23 for (var i = 0; i < 1000; i++) { 24 let res = obj.fun(...[1, 2, 3]); 25 assertEq(res.this, obj); 26 assertEq(res.callee, obj.fun); 27 assertEq(JSON.stringify(res.arguments), "[1,2,3]"); 28 assertEq(res.newTarget, undefined); 29 30 res = new obj.fun(...[1, 2, 3]); 31 assertEq(res.this, "<is_constructing>"); 32 assertEq(res.callee, obj.fun); 33 assertEq(JSON.stringify(res.arguments), "[1,2,3]"); 34 assertEq(res.newTarget, obj.fun); 35 } 36 } 37 testSpread(); 38 39 function testNewTarget() { 40 let obj = newObjectWithCallHook(); 41 let newTargetVal = function() {}; 42 for (var i = 0; i < 1000; i++) { 43 let res = Reflect.construct(obj, [], newTargetVal); 44 assertEq(res.this, "<is_constructing>"); 45 assertEq(res.callee, obj); 46 assertEq(res.arguments.length, 0); 47 assertEq(res.newTarget, newTargetVal); 48 } 49 } 50 testNewTarget(); 51 52 function testRealmSwitch() { 53 // We currently switch to the callable's realm for class hook calls (similar to 54 // JS function calls). This might change at some point, but for now assert the 55 // returned object's realm matches that of the callee. 56 57 let g = newGlobal({sameCompartmentAs: this}); 58 let obj = g.newObjectWithCallHook(); 59 assertEq(objectGlobal(obj), g); 60 61 for (var i = 0; i < 1000; i++) { 62 let res = obj(1, 2); 63 assertEq(objectGlobal(res), g); 64 assertEq(res.this, undefined); 65 assertEq(res.callee, obj); 66 assertEq(JSON.stringify(res.arguments), "[1,2]"); 67 68 res = new obj(1, 2); 69 assertEq(objectGlobal(res), g); 70 assertEq(res.this, "<is_constructing>"); 71 assertEq(res.callee, obj); 72 assertEq(JSON.stringify(res.arguments), "[1,2]"); 73 assertEq(res.newTarget, obj); 74 } 75 } 76 testRealmSwitch(); 77 78 function testCrossCompartmentWrapper() { 79 // Call/construct hooks can be called through cross-compartment wrappers. 80 81 let g = newGlobal({newCompartment: true}); 82 let obj = g.newObjectWithCallHook(); 83 assertEq(isProxy(obj), true); // It's a CCW. 84 85 for (var i = 0; i < 1000; i++) { 86 let res = obj(1, 2); 87 assertEq(isProxy(res), true); 88 assertEq(res.this, undefined); 89 assertEq(res.callee, obj); 90 assertEq(JSON.stringify(res.arguments), "[1,2]"); 91 92 res = new obj(1, 2); 93 assertEq(isProxy(res), true); 94 assertEq(res.this, "<is_constructing>"); 95 assertEq(res.callee, obj); 96 assertEq(JSON.stringify(res.arguments), "[1,2]"); 97 assertEq(res.newTarget, obj); 98 } 99 } 100 testCrossCompartmentWrapper();