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
|
// Test that SavedFrame.prototype.parent gives the next older frame whose
// principals are subsumed by the caller's principals.
// Given a string of letters |expected|, say "abc", assert that the stack
// contains calls to a series of functions named by the next letter from
// the string, say a, b, and then c. Younger frames appear earlier in
// |expected| than older frames.
function check(expected, stack) {
print("check(" + uneval(expected) + ") against:\n" + stack);
count++;
while (stack.length && expected.length) {
assertEq(stack.shift(), expected[0]);
expected = expected.slice(1);
}
if (expected.length > 0) {
throw new Error("Missing frames for: " + expected);
}
if (stack.length > 0 && !stack.every(s => s === null)) {
throw new Error("Unexpected extra frame(s):\n" + stack);
}
}
// Go from a SavedFrame linked list to an array of function display names.
function extract(stack) {
const results = [];
while (stack) {
results.push(stack.functionDisplayName);
stack = stack.parent;
}
return results;
}
const low = newGlobal({ principal: 0 });
const mid = newGlobal({ principal: 0xffff });
const high = newGlobal({ principal: 0xfffff });
var count = 0;
eval('function a() { check("a", extract(saveStack())); b(); }');
low .eval('function b() { check("b", extract(saveStack())); c(); }');
mid .eval('function c() { check("cba", extract(saveStack())); d(); }');
high.eval('function d() { check("dcba", extract(saveStack())); e(); }');
eval('function e() { check("ecba", extract(saveStack())); f(); }');
low .eval('function f() { check("fb", extract(saveStack())); g(); }');
mid .eval('function g() { check("gfecba", extract(saveStack())); h(); }');
high.eval('function h() { check("hgfedcba", extract(saveStack())); }');
// Make everyone's functions visible to each other, as needed.
b = low .b;
low .c = mid .c;
mid .d = high.d;
high.e = e;
f = low .f;
low .g = mid .g;
mid .h = high.h;
low.check = mid.check = high.check = check;
// They each must have their own extract so that CCWs don't mess up the
// principals when we ask for the parent property.
low. eval("" + extract);
mid. eval("" + extract);
high.eval("" + extract);
// Kick the whole process off.
a();
assertEq(count, 8);
|