michael@0: // Any copyright is dedicated to the Public Domain. michael@0: // http://creativecommons.org/publicdomain/zero/1.0/ michael@0: michael@0: // Test Debugger.Object.prototype.unsafeDereference in the presence of michael@0: // interesting cross-compartment wrappers. michael@0: // michael@0: // This is not really a debugger server test; it's more of a Debugger test. michael@0: // But we need xpcshell and Components.utils.Sandbox to get michael@0: // cross-compartment wrappers with interesting properties, and this is the michael@0: // xpcshell test directory most closely related to the JS Debugger API. michael@0: michael@0: Components.utils.import("resource://gre/modules/jsdebugger.jsm"); michael@0: addDebuggerToGlobal(this); michael@0: michael@0: // Add a method to Debugger.Object for fetching value properties michael@0: // conveniently. michael@0: Debugger.Object.prototype.getProperty = function (aName) { michael@0: let desc = this.getOwnPropertyDescriptor(aName); michael@0: if (!desc) michael@0: return undefined; michael@0: if (!desc.value) { michael@0: throw Error("Debugger.Object.prototype.getProperty: " + michael@0: "not a value property: " + aName); michael@0: } michael@0: return desc.value; michael@0: }; michael@0: michael@0: function run_test() { michael@0: // Create a low-privilege sandbox, and a chrome-privilege sandbox. michael@0: let contentBox = Components.utils.Sandbox('http://www.example.com'); michael@0: let chromeBox = Components.utils.Sandbox(this); michael@0: michael@0: // Create an objects in this compartment, and one in each sandbox. We'll michael@0: // refer to the objects as "mainObj", "contentObj", and "chromeObj", in michael@0: // variable and property names. michael@0: var mainObj = { name: "mainObj" }; michael@0: Components.utils.evalInSandbox('var contentObj = { name: "contentObj" };', michael@0: contentBox); michael@0: Components.utils.evalInSandbox('var chromeObj = { name: "chromeObj" };', michael@0: chromeBox); michael@0: michael@0: // Give each global a pointer to all the other globals' objects. michael@0: contentBox.mainObj = chromeBox.mainObj = mainObj; michael@0: var contentObj = chromeBox.contentObj = contentBox.contentObj; michael@0: var chromeObj = contentBox.chromeObj = chromeBox.chromeObj; michael@0: michael@0: // First, a whole bunch of basic sanity checks, to ensure that JavaScript michael@0: // evaluated in various scopes really does see the world the way this michael@0: // test expects it to. michael@0: michael@0: // The objects appear as global variables in the sandbox, and as michael@0: // the sandbox object's properties in chrome. michael@0: do_check_true(Components.utils.evalInSandbox('mainObj', contentBox) michael@0: === contentBox.mainObj); michael@0: do_check_true(Components.utils.evalInSandbox('contentObj', contentBox) michael@0: === contentBox.contentObj); michael@0: do_check_true(Components.utils.evalInSandbox('chromeObj', contentBox) michael@0: === contentBox.chromeObj); michael@0: do_check_true(Components.utils.evalInSandbox('mainObj', chromeBox) michael@0: === chromeBox.mainObj); michael@0: do_check_true(Components.utils.evalInSandbox('contentObj', chromeBox) michael@0: === chromeBox.contentObj); michael@0: do_check_true(Components.utils.evalInSandbox('chromeObj', chromeBox) michael@0: === chromeBox.chromeObj); michael@0: michael@0: // We (the main global) can see properties of all objects in all globals. michael@0: do_check_true(contentBox.mainObj.name === "mainObj"); michael@0: do_check_true(contentBox.contentObj.name === "contentObj"); michael@0: do_check_true(contentBox.chromeObj.name === "chromeObj"); michael@0: michael@0: // chromeBox can see properties of all objects in all globals. michael@0: do_check_eq(Components.utils.evalInSandbox('mainObj.name', chromeBox), michael@0: 'mainObj'); michael@0: do_check_eq(Components.utils.evalInSandbox('contentObj.name', chromeBox), michael@0: 'contentObj'); michael@0: do_check_eq(Components.utils.evalInSandbox('chromeObj.name', chromeBox), michael@0: 'chromeObj'); michael@0: michael@0: // contentBox can see properties of the content object, but not of either michael@0: // chrome object, because by default, content -> chrome wrappers hide all michael@0: // object properties. michael@0: do_check_eq(Components.utils.evalInSandbox('mainObj.name', contentBox), michael@0: undefined); michael@0: do_check_eq(Components.utils.evalInSandbox('contentObj.name', contentBox), michael@0: 'contentObj'); michael@0: do_check_eq(Components.utils.evalInSandbox('chromeObj.name', contentBox), michael@0: undefined); michael@0: michael@0: // When viewing an object in compartment A from the vantage point of michael@0: // compartment B, Debugger should give the same results as debuggee code michael@0: // would. michael@0: michael@0: // Create a debugger, debugging our two sandboxes. michael@0: let dbg = new Debugger; michael@0: michael@0: // Create Debugger.Object instances referring to the two sandboxes, as michael@0: // seen from their own compartments. michael@0: let contentBoxDO = dbg.addDebuggee(contentBox); michael@0: let chromeBoxDO = dbg.addDebuggee(chromeBox); michael@0: michael@0: // Use Debugger to view the objects from contentBox. We should get the michael@0: // same D.O instance from both getProperty and makeDebuggeeValue, and the michael@0: // same property visibility we checked for above. michael@0: let mainFromContentDO = contentBoxDO.getProperty('mainObj'); michael@0: do_check_eq(mainFromContentDO, contentBoxDO.makeDebuggeeValue(mainObj)); michael@0: do_check_eq(mainFromContentDO.getProperty('name'), undefined); michael@0: do_check_eq(mainFromContentDO.unsafeDereference(), mainObj); michael@0: michael@0: let contentFromContentDO = contentBoxDO.getProperty('contentObj'); michael@0: do_check_eq(contentFromContentDO, contentBoxDO.makeDebuggeeValue(contentObj)); michael@0: do_check_eq(contentFromContentDO.getProperty('name'), 'contentObj'); michael@0: do_check_eq(contentFromContentDO.unsafeDereference(), contentObj); michael@0: michael@0: let chromeFromContentDO = contentBoxDO.getProperty('chromeObj'); michael@0: do_check_eq(chromeFromContentDO, contentBoxDO.makeDebuggeeValue(chromeObj)); michael@0: do_check_eq(chromeFromContentDO.getProperty('name'), undefined); michael@0: do_check_eq(chromeFromContentDO.unsafeDereference(), chromeObj); michael@0: michael@0: // Similarly, viewing from chromeBox. michael@0: let mainFromChromeDO = chromeBoxDO.getProperty('mainObj'); michael@0: do_check_eq(mainFromChromeDO, chromeBoxDO.makeDebuggeeValue(mainObj)); michael@0: do_check_eq(mainFromChromeDO.getProperty('name'), 'mainObj'); michael@0: do_check_eq(mainFromChromeDO.unsafeDereference(), mainObj); michael@0: michael@0: let contentFromChromeDO = chromeBoxDO.getProperty('contentObj'); michael@0: do_check_eq(contentFromChromeDO, chromeBoxDO.makeDebuggeeValue(contentObj)); michael@0: do_check_eq(contentFromChromeDO.getProperty('name'), 'contentObj'); michael@0: do_check_eq(contentFromChromeDO.unsafeDereference(), contentObj); michael@0: michael@0: let chromeFromChromeDO = chromeBoxDO.getProperty('chromeObj'); michael@0: do_check_eq(chromeFromChromeDO, chromeBoxDO.makeDebuggeeValue(chromeObj)); michael@0: do_check_eq(chromeFromChromeDO.getProperty('name'), 'chromeObj'); michael@0: do_check_eq(chromeFromChromeDO.unsafeDereference(), chromeObj); michael@0: }