|
1 // Test that SavedFrame.prototype.parent gives the next older frame whose |
|
2 // principals are subsumed by the caller's principals. |
|
3 |
|
4 // Given a string of letters |expected|, say "abc", assert that the stack |
|
5 // contains calls to a series of functions named by the next letter from |
|
6 // the string, say a, b, and then c. Younger frames appear earlier in |
|
7 // |expected| than older frames. |
|
8 function check(expected, stack) { |
|
9 print("check(" + uneval(expected) + ") against:\n" + stack); |
|
10 count++; |
|
11 |
|
12 while (stack.length && expected.length) { |
|
13 assertEq(stack.shift(), expected[0]); |
|
14 expected = expected.slice(1); |
|
15 } |
|
16 |
|
17 if (expected.length > 0) { |
|
18 throw new Error("Missing frames for: " + expected); |
|
19 } |
|
20 if (stack.length > 0 && !stack.every(s => s === null)) { |
|
21 throw new Error("Unexpected extra frame(s):\n" + stack); |
|
22 } |
|
23 } |
|
24 |
|
25 // Go from a SavedFrame linked list to an array of function display names. |
|
26 function extract(stack) { |
|
27 const results = []; |
|
28 while (stack) { |
|
29 results.push(stack.functionDisplayName); |
|
30 stack = stack.parent; |
|
31 } |
|
32 return results; |
|
33 } |
|
34 |
|
35 const low = newGlobal({ principal: 0 }); |
|
36 const mid = newGlobal({ principal: 0xffff }); |
|
37 const high = newGlobal({ principal: 0xfffff }); |
|
38 |
|
39 var count = 0; |
|
40 |
|
41 eval('function a() { check("a", extract(saveStack())); b(); }'); |
|
42 low .eval('function b() { check("b", extract(saveStack())); c(); }'); |
|
43 mid .eval('function c() { check("cba", extract(saveStack())); d(); }'); |
|
44 high.eval('function d() { check("dcba", extract(saveStack())); e(); }'); |
|
45 eval('function e() { check("edcba", extract(saveStack())); f(); }'); // no principal, so checks skipped |
|
46 low .eval('function f() { check("fb", extract(saveStack())); g(); }'); |
|
47 mid .eval('function g() { check("gfecba", extract(saveStack())); h(); }'); |
|
48 high.eval('function h() { check("hgfedcba", extract(saveStack())); }'); |
|
49 |
|
50 // Make everyone's functions visible to each other, as needed. |
|
51 b = low .b; |
|
52 low .c = mid .c; |
|
53 mid .d = high.d; |
|
54 high.e = e; |
|
55 f = low .f; |
|
56 low .g = mid .g; |
|
57 mid .h = high.h; |
|
58 |
|
59 low.check = mid.check = high.check = check; |
|
60 |
|
61 // They each must have their own extract so that CCWs don't mess up the |
|
62 // principals when we ask for the parent property. |
|
63 low. eval("" + extract); |
|
64 mid. eval("" + extract); |
|
65 high.eval("" + extract); |
|
66 |
|
67 // Kick the whole process off. |
|
68 a(); |
|
69 |
|
70 assertEq(count, 8); |