diff options
Diffstat (limited to 'js/ductwork/debugger/jsdebugger.jsm')
-rw-r--r-- | js/ductwork/debugger/jsdebugger.jsm | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/js/ductwork/debugger/jsdebugger.jsm b/js/ductwork/debugger/jsdebugger.jsm new file mode 100644 index 0000000000..4189594179 --- /dev/null +++ b/js/ductwork/debugger/jsdebugger.jsm @@ -0,0 +1,93 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var EXPORTED_SYMBOLS = [ "addDebuggerToGlobal", "addSandboxedDebuggerToGlobal" ]; + +/* + * This is the js module for Debugger. Import it like so: + * Components.utils.import("resource://gre/modules/jsdebugger.jsm"); + * addDebuggerToGlobal(this); + * + * This will create a 'Debugger' object, which provides an interface to debug + * JavaScript code running in other compartments in the same process, on the + * same thread. + * + * For documentation on the API, see: + * https://developer.mozilla.org/en-US/docs/Tools/Debugger-API + */ + +const init = Cc["@mozilla.org/jsdebugger;1"].createInstance(Ci.IJSDebugger); +function addDebuggerToGlobal(global) { + init.addClass(global); + initPromiseDebugging(global); +} + +// Defines the Debugger in a sandbox global in a separate compartment. This +// ensures the debugger and debuggee are in different compartments. +function addSandboxedDebuggerToGlobal(global) { + var sb = Cu.Sandbox(global, {freshCompartment: true}); + addDebuggerToGlobal(sb); + global.Debugger = sb.Debugger; +} + +function initPromiseDebugging(global) { + if (global.Debugger.Object.prototype.PromiseDebugging) { + return; + } + + // If the PromiseDebugging object doesn't have all legacy functions, we're + // using the new accessors on Debugger.Object already. + if (!PromiseDebugging.getDependentPromises) { + return; + } + + // Otherwise, polyfill them using PromiseDebugging. + global.Debugger.Object.prototype.PromiseDebugging = PromiseDebugging; + global.eval(polyfillSource); +} + +let polyfillSource = ` + Object.defineProperty(Debugger.Object.prototype, "promiseState", { + get() { + const state = this.PromiseDebugging.getState(this.unsafeDereference()); + return { + state: state.state, + value: this.makeDebuggeeValue(state.value), + reason: this.makeDebuggeeValue(state.reason) + }; + } + }); + Object.defineProperty(Debugger.Object.prototype, "promiseLifetime", { + get() { + return this.PromiseDebugging.getPromiseLifetime(this.unsafeDereference()); + } + }); + Object.defineProperty(Debugger.Object.prototype, "promiseTimeToResolution", { + get() { + return this.PromiseDebugging.getTimeToSettle(this.unsafeDereference()); + } + }); + Object.defineProperty(Debugger.Object.prototype, "promiseDependentPromises", { + get() { + let promises = this.PromiseDebugging.getDependentPromises(this.unsafeDereference()); + return promises.map(p => this.makeDebuggeeValue(p)); + } + }); + Object.defineProperty(Debugger.Object.prototype, "promiseAllocationSite", { + get() { + return this.PromiseDebugging.getAllocationStack(this.unsafeDereference()); + } + }); + Object.defineProperty(Debugger.Object.prototype, "promiseResolutionSite", { + get() { + let state = this.promiseState.state; + if (state === "fulfilled") { + return this.PromiseDebugging.getFullfillmentStack(this.unsafeDereference()); + } else { + return this.PromiseDebugging.getRejectionStack(this.unsafeDereference()); + } + } + }); +`; |