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
|
// Create two different globals whose compartments have two different
// principals. Test getting the first frame on the stack with some given
// principals in various configurations of JS stack and of wanting self-hosted
// frames or not.
const g1 = newGlobal({
principal: 0xffff
});
const g2 = newGlobal({
principal: 0xff
});
// Introduce everyone to themselves and each other.
g1.g2 = g2.g2 = g2;
g1.g1 = g2.g1 = g1;
g1.g2obj = g2.eval("new Object");
g1.evaluate(`
const global = this;
// Capture the stack back to the first frame in the g2 global.
function capture(shouldIgnoreSelfHosted = true) {
return captureFirstSubsumedFrame(global.g2obj, shouldIgnoreSelfHosted);
}
`, {
fileName: "script1.js"
});
g2.evaluate(`
const capture = g1.capture;
// Use our Function.prototype.bind, not capture.bind (which is ===
// g1.Function.prototype.bind) so that the generated bound function is in our
// compartment and has our principals.
const boundTrue = Function.prototype.bind.call(capture, null, true);
const boundFalse = Function.prototype.bind.call(capture, null, false);
function getOldestFrame(stack) {
while (stack.parent) {
stack = stack.parent;
}
return stack;
}
function dumpStack(name, stack) {
print("Stack " + name + " =");
while (stack) {
print(" " + stack.functionDisplayName + " @ " + stack.source);
stack = stack.parent;
}
print();
}
// When the youngest frame is not self-hosted, it doesn't matter whether or not
// we specify that we should ignore self hosted frames when capturing the first
// frame with the given principals.
//
// Stack: iife1 (g2) <- capture (g1)
(function iife1() {
const captureTrueStack = capture(true);
dumpStack("captureTrueStack", captureTrueStack);
assertEq(getOldestFrame(captureTrueStack).functionDisplayName, "iife1");
assertEq(getOldestFrame(captureTrueStack).source, "script2.js");
const captureFalseStack = capture(false);
dumpStack("captureFalseStack", captureFalseStack);
assertEq(getOldestFrame(captureFalseStack).functionDisplayName, "iife1");
assertEq(getOldestFrame(captureFalseStack).source, "script2.js");
}());
// When the youngest frame is a self hosted frame, we get two different
// captured stacks depending on whether or not we ignore self-hosted frames.
//
// Stack: iife2 (g2) <- bound function (g2) <- capture (g1)
(function iife2() {
const boundTrueStack = boundTrue();
dumpStack("boundTrueStack", boundTrueStack);
assertEq(getOldestFrame(boundTrueStack).functionDisplayName, "iife2");
assertEq(getOldestFrame(boundTrueStack).source, "script2.js");
const boundFalseStack = boundFalse();
dumpStack("boundFalseStack", boundFalseStack);
assertEq(getOldestFrame(boundFalseStack).functionDisplayName !== "iife2", true);
assertEq(getOldestFrame(boundFalseStack).source, "self-hosted");
}());
`, {
fileName: "script2.js"
});
|