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