diff options
Diffstat (limited to 'js/ductwork')
-rw-r--r-- | js/ductwork/debugger/IJSDebugger.idl | 20 | ||||
-rw-r--r-- | js/ductwork/debugger/JSDebugger.cpp | 86 | ||||
-rw-r--r-- | js/ductwork/debugger/JSDebugger.h | 30 | ||||
-rw-r--r-- | js/ductwork/debugger/jsdebugger.jsm | 85 | ||||
-rw-r--r-- | js/ductwork/debugger/moz.build | 23 | ||||
-rw-r--r-- | js/ductwork/debugger/tests/head_dbg.js | 17 | ||||
-rw-r--r-- | js/ductwork/debugger/tests/test_nativewrappers.js | 30 | ||||
-rw-r--r-- | js/ductwork/debugger/tests/xpcshell.ini | 8 |
8 files changed, 299 insertions, 0 deletions
diff --git a/js/ductwork/debugger/IJSDebugger.idl b/js/ductwork/debugger/IJSDebugger.idl new file mode 100644 index 0000000000..dc3cd0423a --- /dev/null +++ b/js/ductwork/debugger/IJSDebugger.idl @@ -0,0 +1,20 @@ +/* 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/. */ + +#include "nsISupports.idl" + +/** + * Do not use this interface. Instead, write: + * Components.utils.import("resource://gre/modules/jsdebugger.jsm"); + * addDebuggerToGlobal(global); + */ +[scriptable, uuid(a36fa816-31da-4b23-bc97-6412771f0867)] +interface IJSDebugger : nsISupports +{ + /** + * Define the global Debugger constructor on a given global. + */ + [implicit_jscontext] + void addClass(in jsval global); +}; diff --git a/js/ductwork/debugger/JSDebugger.cpp b/js/ductwork/debugger/JSDebugger.cpp new file mode 100644 index 0000000000..074008cdcd --- /dev/null +++ b/js/ductwork/debugger/JSDebugger.cpp @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */ + +#include "JSDebugger.h" +#include "nsIXPConnect.h" +#include "nsThreadUtils.h" +#include "jsapi.h" +#include "jsfriendapi.h" +#include "jswrapper.h" +#include "mozilla/ModuleUtils.h" +#include "nsServiceManagerUtils.h" +#include "nsMemory.h" + +#define JSDEBUGGER_CONTRACTID \ + "@mozilla.org/jsdebugger;1" + +#define JSDEBUGGER_CID \ +{ 0x0365cbd5, 0xd46e, 0x4e94, { 0xa3, 0x9f, 0x83, 0xb6, 0x3c, 0xd1, 0xa9, 0x63 } } + +namespace mozilla { +namespace jsdebugger { + +NS_GENERIC_FACTORY_CONSTRUCTOR(JSDebugger) + +NS_IMPL_ISUPPORTS(JSDebugger, IJSDebugger) + +JSDebugger::JSDebugger() +{ +} + +JSDebugger::~JSDebugger() +{ +} + +NS_IMETHODIMP +JSDebugger::AddClass(JS::Handle<JS::Value> global, JSContext* cx) +{ + nsresult rv; + nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID(), &rv); + + if (!global.isObject()) { + return NS_ERROR_INVALID_ARG; + } + + JS::RootedObject obj(cx, &global.toObject()); + obj = js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false); + if (!obj) { + return NS_ERROR_FAILURE; + } + + JSAutoCompartment ac(cx, obj); + if (JS_GetGlobalForObject(cx, obj) != obj) { + return NS_ERROR_INVALID_ARG; + } + + if (!JS_DefineDebuggerObject(cx, obj)) { + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + +} // namespace jsdebugger +} // namespace mozilla + +NS_DEFINE_NAMED_CID(JSDEBUGGER_CID); + +static const mozilla::Module::CIDEntry kJSDebuggerCIDs[] = { + { &kJSDEBUGGER_CID, false, nullptr, mozilla::jsdebugger::JSDebuggerConstructor }, + { nullptr } +}; + +static const mozilla::Module::ContractIDEntry kJSDebuggerContracts[] = { + { JSDEBUGGER_CONTRACTID, &kJSDEBUGGER_CID }, + { nullptr } +}; + +static const mozilla::Module kJSDebuggerModule = { + mozilla::Module::kVersion, + kJSDebuggerCIDs, + kJSDebuggerContracts +}; + +NSMODULE_DEFN(jsdebugger) = &kJSDebuggerModule; diff --git a/js/ductwork/debugger/JSDebugger.h b/js/ductwork/debugger/JSDebugger.h new file mode 100644 index 0000000000..ce5ab81ad8 --- /dev/null +++ b/js/ductwork/debugger/JSDebugger.h @@ -0,0 +1,30 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */ + +#ifndef JSDebugger_h +#define JSDebugger_h + +#include "IJSDebugger.h" +#include "mozilla/Attributes.h" + +namespace mozilla { +namespace jsdebugger { + +class JSDebugger final : public IJSDebugger +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_IJSDEBUGGER + + JSDebugger(); + +private: + ~JSDebugger(); +}; + +} // namespace jsdebugger +} // namespace mozilla + +#endif /* JSDebugger_h */ diff --git a/js/ductwork/debugger/jsdebugger.jsm b/js/ductwork/debugger/jsdebugger.jsm new file mode 100644 index 0000000000..8b87c0a059 --- /dev/null +++ b/js/ductwork/debugger/jsdebugger.jsm @@ -0,0 +1,85 @@ +/* -*- 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/. */ + +this.EXPORTED_SYMBOLS = [ "addDebuggerToGlobal" ]; + +/* + * 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 = Components.classes["@mozilla.org/jsdebugger;1"].createInstance(Components.interfaces.IJSDebugger); +this.addDebuggerToGlobal = function addDebuggerToGlobal(global) { + init.addClass(global); + initPromiseDebugging(global); +}; + +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()); + } + } + }); +`; diff --git a/js/ductwork/debugger/moz.build b/js/ductwork/debugger/moz.build new file mode 100644 index 0000000000..c1140db356 --- /dev/null +++ b/js/ductwork/debugger/moz.build @@ -0,0 +1,23 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +XPIDL_SOURCES += [ + 'IJSDebugger.idl', +] + +XPIDL_MODULE = 'jsdebugger' + +XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell.ini'] + +SOURCES += [ + 'JSDebugger.cpp', +] + +EXTRA_JS_MODULES += [ + 'jsdebugger.jsm', +] + +FINAL_LIBRARY = 'xul' diff --git a/js/ductwork/debugger/tests/head_dbg.js b/js/ductwork/debugger/tests/head_dbg.js new file mode 100644 index 0000000000..0ffeed26bd --- /dev/null +++ b/js/ductwork/debugger/tests/head_dbg.js @@ -0,0 +1,17 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; +const Cr = Components.results; + +function testGlobal(aName) { + let systemPrincipal = Cc["@mozilla.org/systemprincipal;1"] + .createInstance(Ci.nsIPrincipal); + + let sandbox = Cu.Sandbox(systemPrincipal); + Cu.evalInSandbox("this.__name = '" + aName + "'", sandbox); + return sandbox; +} diff --git a/js/ductwork/debugger/tests/test_nativewrappers.js b/js/ductwork/debugger/tests/test_nativewrappers.js new file mode 100644 index 0000000000..9ee96701e2 --- /dev/null +++ b/js/ductwork/debugger/tests/test_nativewrappers.js @@ -0,0 +1,30 @@ +function run_test() +{ + Components.utils.import("resource://gre/modules/jsdebugger.jsm"); + addDebuggerToGlobal(this); + var g = testGlobal("test1"); + + var dbg = new Debugger(); + dbg.addDebuggee(g); + dbg.onDebuggerStatement = function(aFrame) { + let args = aFrame["arguments"]; + try { + args[0]; + do_check_true(true); + } catch(ex) { + do_check_true(false); + } + }; + + g.eval("function stopMe(arg) {debugger;}"); + + g2 = testGlobal("test2"); + g2.g = g; + g2.eval("(" + function createBadEvent() { + let parser = Components.classes["@mozilla.org/xmlextras/domparser;1"].createInstance(Components.interfaces.nsIDOMParser); + let doc = parser.parseFromString("<foo></foo>", "text/xml"); + g.stopMe(doc.createEvent("MouseEvent")); + } + ")()"); + + dbg.enabled = false; +} diff --git a/js/ductwork/debugger/tests/xpcshell.ini b/js/ductwork/debugger/tests/xpcshell.ini new file mode 100644 index 0000000000..cc60c2e4df --- /dev/null +++ b/js/ductwork/debugger/tests/xpcshell.ini @@ -0,0 +1,8 @@ +[DEFAULT] +head = head_dbg.js +tail = +skip-if = toolkit == 'android' + +[test_nativewrappers.js] +# Bug 685068 +fail-if = os == "android" |