// 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" });