1 // Test calling SavedFrame getters across wrappers from privileged and
2 // un-privileged globals.
4 const {addDebuggerToGlobal} = ChromeUtils.importESModule("resource://gre/modules/jsdebugger.sys.mjs");
5 addDebuggerToGlobal(globalThis);
7 const lowP = Services.scriptSecurityManager.createNullPrincipal({});
8 const highP = Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal);
10 const low = new Cu.Sandbox(lowP);
11 const high = new Cu.Sandbox(highP);
14 // Privileged compartment accessing unprivileged stack.
15 high.stack = getSavedFrameInstanceFromSandbox(low);
16 Cu.evalInSandbox("this.parent = stack.parent", high);
17 Cu.evalInSandbox("this.asyncParent = stack.asyncParent", high);
18 Cu.evalInSandbox("this.source = stack.source", high);
19 Cu.evalInSandbox("this.functionDisplayName = stack.functionDisplayName", high);
21 // Un-privileged compartment accessing privileged stack.
22 low.stack = getSavedFrameInstanceFromSandbox(high);
24 Cu.evalInSandbox("this.parent = stack.parent", low);
27 Cu.evalInSandbox("this.asyncParent = stack.asyncParent", low);
30 Cu.evalInSandbox("this.source = stack.source", low);
33 Cu.evalInSandbox("this.functionDisplayName = stack.functionDisplayName", low);
36 // Privileged compartment accessing privileged stack.
37 let stack = getSavedFrameInstanceFromSandbox(high);
38 let parent = stack.parent;
39 let asyncParent = stack.asyncParent;
40 let source = stack.source;
41 let functionDisplayName = stack.functionDisplayName;
43 ok(true, "Didn't crash");
46 // Get a SavedFrame instance from inside the given sandbox.
48 // We can't use Cu.getJSTestingFunctions().saveStack() because Cu isn't
49 // available to sandboxes that don't have the system principal. The easiest way
50 // to get the SavedFrame is to use the Debugger API to track allocation sites
51 // and then do an allocation.
52 function getSavedFrameInstanceFromSandbox(sandbox) {
53 const dbg = new Debugger(sandbox);
55 dbg.memory.trackingAllocationSites = true;
56 Cu.evalInSandbox("(function iife() { return new RegExp }())", sandbox);
57 const allocs = dbg.memory.drainAllocationsLog().filter(e => e.class === "RegExp");
58 dbg.memory.trackingAllocationSites = false;
60 ok(allocs[0], "We should observe the allocation");
61 const { frame } = allocs[0];
63 if (sandbox !== high) {
64 ok(Cu.isXrayWrapper(frame), "`frame` should be an xray...");
65 equal(Object.prototype.toString.call(Cu.waiveXrays(frame)),
66 "[object SavedFrame]",
67 "...and that xray should wrap a SavedFrame");