From e2ad979a384600215ae9c5661ad6c07ff95ad815 Mon Sep 17 00:00:00 2001 From: Mike Conley Date: Thu, 31 Jul 2014 13:07:27 -0400 Subject: [PATCH] Bug 787975 - Make JSTerm $0 helper work across content processes. r=msucan. --HG-- extra : rebase_source : b7a3a698effb0b223160fabae5b6f9b0fe820888 --- browser/devtools/webconsole/hudservice.js | 24 ++++++++++++++ browser/devtools/webconsole/webconsole.js | 16 ++++++++- toolkit/devtools/server/actors/webconsole.js | 14 ++++++++ toolkit/devtools/webconsole/client.js | 6 ++++ toolkit/devtools/webconsole/utils.js | 34 +++----------------- 5 files changed, 63 insertions(+), 31 deletions(-) diff --git a/browser/devtools/webconsole/hudservice.js b/browser/devtools/webconsole/hudservice.js index 58620f2ccd88..ed9682e1c1b1 100644 --- a/browser/devtools/webconsole/hudservice.js +++ b/browser/devtools/webconsole/hudservice.js @@ -580,6 +580,30 @@ WebConsole.prototype = { return null; }, + /** + * Retrieves the current selection from the Inspector, if such a selection + * exists. This is used to pass the ID of the selected actor to the Web + * Console server for the $0 helper. + * + * @return object|null + * A Selection referring to the currently selected node in the + * Inspector. + * If the inspector was never opened, or no node was ever selected, + * then |null| is returned. + */ + getInspectorSelection: function WC_getInspectorSelection() + { + let toolbox = gDevTools.getToolbox(this.target); + if (!toolbox) { + return null; + } + let panel = toolbox.getPanel("inspector"); + if (!panel || !panel.selection) { + return null; + } + return panel.selection; + }, + /** * Destroy the object. Call this method to avoid memory leaks when the Web * Console is closed. diff --git a/browser/devtools/webconsole/webconsole.js b/browser/devtools/webconsole/webconsole.js index ee40d8400681..89107707e077 100644 --- a/browser/devtools/webconsole/webconsole.js +++ b/browser/devtools/webconsole/webconsole.js @@ -3264,6 +3264,12 @@ JSTerm.prototype = { return; } + let selectedNodeActor = null; + let inspectorSelection = this.hud.owner.getInspectorSelection(); + if (inspectorSelection) { + selectedNodeActor = inspectorSelection.nodeFront.actorID; + } + let message = new Messages.Simple(aExecuteString, { category: "input", severity: "log", @@ -3271,7 +3277,11 @@ JSTerm.prototype = { this.hud.output.addMessage(message); let onResult = this._executeResultCallback.bind(this, message, aCallback); - let options = { frame: this.SELECTED_FRAME }; + let options = { + frame: this.SELECTED_FRAME, + selectedNodeActor: selectedNodeActor, + }; + this.requestEvaluation(aExecuteString, options).then(onResult, onResult); // Append a new value in the history of executed code, or overwrite the most @@ -3301,6 +3311,9 @@ JSTerm.prototype = { * user-selected stackframe. * If you do not provide a |frame| the string will be evaluated in the * global content window. + * - selectedNodeActor: tells the NodeActor ID of the current selection in + * the Inspector, if such a selection exists. This is used by helper + * functions that can evaluate on the current selection. * @return object * A promise object that is resolved when the server response is * received. @@ -3326,6 +3339,7 @@ JSTerm.prototype = { let evalOptions = { bindObjectActor: aOptions.bindObjectActor, frameActor: frameActor, + selectedNodeActor: aOptions.selectedNodeActor, }; this.webConsoleClient.evaluateJS(aString, onResult, evalOptions); diff --git a/toolkit/devtools/server/actors/webconsole.js b/toolkit/devtools/server/actors/webconsole.js index 3abb70e7aa94..caab05324cd0 100644 --- a/toolkit/devtools/server/actors/webconsole.js +++ b/toolkit/devtools/server/actors/webconsole.js @@ -725,7 +725,9 @@ WebConsoleActor.prototype = bindObjectActor: aRequest.bindObjectActor, frameActor: aRequest.frameActor, url: aRequest.url, + selectedNodeActor: aRequest.selectedNodeActor, }; + let evalInfo = this.evalWithDebugger(input, evalOptions); let evalResult = evalInfo.result; let helperResult = evalInfo.helperResult; @@ -967,6 +969,10 @@ WebConsoleActor.prototype = * ObjectActor. * - frameActor: the FrameActor ID to use for evaluation. The given * debugger frame is used for evaluation, instead of the global window. + * - selectedNodeActor: the NodeActor ID of the currently selected node + * in the Inspector (or null, if there is no selection). This is used + * for helper functions that make reference to the currently selected + * node, like $0. * @return object * An object that holds the following properties: * - dbg: the debugger where the string was evaluated. @@ -1031,6 +1037,13 @@ WebConsoleActor.prototype = bindings._self = bindSelf; } + if (aOptions.selectedNodeActor) { + let actor = this.conn.getActor(aOptions.selectedNodeActor); + if (actor) { + helpers.selectedNode = actor.rawNode; + } + } + // Check if the Debugger.Frame or Debugger.Object for the global include // $ or $$. We will not overwrite these functions with the jsterm helpers. let found$ = false, found$$ = false; @@ -1075,6 +1088,7 @@ WebConsoleActor.prototype = let helperResult = helpers.helperResult; delete helpers.evalInput; delete helpers.helperResult; + delete helpers.selectedNode; if ($) { bindings.$ = $; diff --git a/toolkit/devtools/webconsole/client.js b/toolkit/devtools/webconsole/client.js index 983bcb70278f..f1eb08980adf 100644 --- a/toolkit/devtools/webconsole/client.js +++ b/toolkit/devtools/webconsole/client.js @@ -104,6 +104,11 @@ WebConsoleClient.prototype = { * * - url: the url to evaluate the script as. Defaults to * "debugger eval code". + * + * - selectedNodeActor: the NodeActor ID of the current selection in the + * Inspector, if such a selection exists. This is used by helper functions + * that can reference the currently selected node in the Inspector, like + * $0. */ evaluateJS: function WCC_evaluateJS(aString, aOnResponse, aOptions = {}) { @@ -114,6 +119,7 @@ WebConsoleClient.prototype = { bindObjectActor: aOptions.bindObjectActor, frameActor: aOptions.frameActor, url: aOptions.url, + selectedNodeActor: aOptions.selectedNodeActor, }; this._client.request(packet, aOnResponse); }, diff --git a/toolkit/devtools/webconsole/utils.js b/toolkit/devtools/webconsole/utils.js index 9b94c3b95b2e..d32848f486ae 100644 --- a/toolkit/devtools/webconsole/utils.js +++ b/toolkit/devtools/webconsole/utils.js @@ -1563,38 +1563,12 @@ function JSTermHelpers(aOwner) /** * Returns the currently selected object in the highlighter. * - * TODO: this implementation crosses the client/server boundaries! This is not - * usable within a remote browser. To implement this feature correctly we need - * support for remote inspection capabilities within the Inspector as well. - * See bug 787975. - * - * @return nsIDOMElement|null - * The DOM element currently selected in the highlighter. + * @return Object representing the current selection in the + * Inspector, or null if no selection exists. */ - Object.defineProperty(aOwner.sandbox, "$0", { + Object.defineProperty(aOwner.sandbox, "$0", { get: function() { - let window = aOwner.chromeWindow(); - if (!window) { - return null; - } - - let target = null; - try { - target = devtools.TargetFactory.forTab(window.gBrowser.selectedTab); - } - catch (ex) { - // If we report this exception the user will get it in the Browser - // Console every time when she evaluates any string. - } - - if (!target) { - return null; - } - - let toolbox = gDevTools.getToolbox(target); - let node = toolbox && toolbox.selection ? toolbox.selection.node : null; - - return node ? aOwner.makeDebuggeeValue(node) : null; + return aOwner.makeDebuggeeValue(aOwner.selectedNode) }, enumerable: true, configurable: false