summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/basic/call-construct-hook.js
blob: ed6cb23e0108dd350485e49a6e3a5bb12ac3c16e (plain)
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();