--- a/devtools/client/webconsole/components/JSTerm.js
+++ b/devtools/client/webconsole/components/JSTerm.js
@@ -5,17 +5,16 @@
"use strict";
const {Utils: WebConsoleUtils} = require("devtools/client/webconsole/utils");
const Services = require("Services");
loader.lazyServiceGetter(this, "clipboardHelper",
"@mozilla.org/widget/clipboardhelper;1",
"nsIClipboardHelper");
-loader.lazyRequireGetter(this, "defer", "devtools/shared/defer");
loader.lazyRequireGetter(this, "Debugger", "Debugger");
loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
loader.lazyRequireGetter(this, "AutocompletePopup", "devtools/client/shared/autocomplete-popup");
loader.lazyRequireGetter(this, "PropTypes", "devtools/client/shared/vendor/react-prop-types");
loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
loader.lazyRequireGetter(this, "KeyCodes", "devtools/client/shared/keycodes", true);
loader.lazyRequireGetter(this, "Editor", "devtools/client/sourceeditor/editor");
loader.lazyRequireGetter(this, "Telemetry", "devtools/client/shared/telemetry");
@@ -315,29 +314,26 @@ class JSTerm extends Component {
this.inputNode.focus();
}
}
/**
* The JavaScript evaluation response handler.
*
* @private
- * @param function [callback]
- * Optional function to invoke when the evaluation result is added to
- * the output.
* @param object response
* The message received from the server.
*/
- async _executeResultCallback(callback, response) {
+ async _executeResultCallback(response) {
if (!this.hud) {
- return;
+ return null;
}
if (response.error) {
console.error("Evaluation error " + response.error + ": " + response.message);
- return;
+ return null;
}
let errorMessage = response.exceptionMessage;
// Wrap thrown strings in Error objects, so `throw "foo"` outputs "Error: foo"
if (typeof response.exception === "string") {
errorMessage = new Error(errorMessage).toString();
}
const result = response.result;
@@ -368,31 +364,32 @@ class JSTerm extends Component {
case "copyValueToClipboard":
clipboardHelper.copyString(helperResult.value);
break;
case "screenshotOutput":
const { args, value } = helperResult;
const results = await processScreenshot(this.hud.window, args, value);
this.screenshotNotify(results);
// early return as screenshot notify has dispatched all necessary messages
- return;
+ return null;
}
}
// Hide undefined results coming from JSTerm helper functions.
if (!errorMessage && result && typeof result == "object" &&
result.type == "undefined" &&
helperResult && !helperHasRawOutput) {
- callback && callback();
- return;
+ return null;
}
if (this.hud.consoleOutput) {
- this.hud.consoleOutput.dispatchMessageAdd(response, true).then(callback);
+ return this.hud.consoleOutput.dispatchMessageAdd(response, true);
}
+
+ return null;
}
inspectObjectActor(objectActor) {
this.hud.consoleOutput.dispatchMessageAdd({
helperResult: {
type: "inspectObject",
object: objectActor
}
@@ -403,29 +400,23 @@ class JSTerm extends Component {
screenshotNotify(results) {
const wrappedResults = results.map(result => ({ result }));
this.hud.consoleOutput.dispatchMessagesAdd(wrappedResults);
}
/**
* Execute a string. Execution happens asynchronously in the content process.
*
- * @param string [executeString]
+ * @param {String} executeString
* The string you want to execute. If this is not provided, the current
* user input is used - taken from |this.getInputValue()|.
- * @param function [callback]
- * Optional function to invoke when the result is displayed.
- * This is deprecated - please use the promise return value instead.
- * @returns Promise
+ * @returns {Promise}
* Resolves with the message once the result is displayed.
*/
- async execute(executeString, callback) {
- const deferred = defer();
- const resultCallback = msg => deferred.resolve(msg);
-
+ async execute(executeString) {
// attempt to execute the content of the inputNode
executeString = executeString || this.getInputValue();
if (!executeString) {
return null;
}
// Append executed expression into the history list.
this.props.appendToHistory(executeString);
@@ -436,32 +427,33 @@ class JSTerm extends Component {
let selectedNodeActor = null;
const inspectorSelection = this.hud.owner.getInspectorSelection();
if (inspectorSelection && inspectorSelection.nodeFront) {
selectedNodeActor = inspectorSelection.nodeFront.actorID;
}
const { ConsoleCommand } = require("devtools/client/webconsole/types");
- const message = new ConsoleCommand({
+ const cmdMessage = new ConsoleCommand({
messageText: executeString,
});
- this.hud.proxy.dispatchMessageAdd(message);
-
- const onResult = this._executeResultCallback.bind(this, resultCallback);
+ this.hud.proxy.dispatchMessageAdd(cmdMessage);
const options = {
frame: this.SELECTED_FRAME,
- selectedNodeActor: selectedNodeActor,
+ selectedNodeActor,
};
const mappedString = await this.hud.owner.getMappedExpression(executeString);
- this.requestEvaluation(mappedString, options).then(onResult, onResult);
-
- return deferred.promise;
+ // Even if requestEvaluation rejects (because of webConsoleClient.evaluateJSAsync),
+ // we still need to pass the error response to executeResultCallback.
+ const onEvaluated = this.requestEvaluation(mappedString, options)
+ .then(res => res, res => res);
+ const response = await onEvaluated;
+ return this._executeResultCallback(response);
}
/**
* Request a JavaScript string evaluation from the server.
*
* @param string str
* String to execute.
* @param object [options]
@@ -480,48 +472,37 @@ class JSTerm extends Component {
* 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.
*/
requestEvaluation(str, options = {}) {
const toolbox = gDevTools.getToolbox(this.hud.owner.target);
- const deferred = defer();
- function onResult(response) {
- if (!response.error) {
- deferred.resolve(response);
- } else {
- deferred.reject(response);
- }
- }
+ // Send telemetry event. If we are in the browser toolbox we send -1 as the
+ // toolbox session id.
+ this._telemetry.recordEvent("devtools.main", "execute_js", "webconsole", null, {
+ "lines": str.split(/\n/).length,
+ "session_id": toolbox ? toolbox.sessionId : -1
+ });
let frameActor = null;
if ("frame" in options) {
frameActor = this.getFrameActor(options.frame);
}
const evalOptions = {
bindObjectActor: options.bindObjectActor,
- frameActor: frameActor,
+ frameActor,
selectedNodeActor: options.selectedNodeActor,
selectedObjectActor: options.selectedObjectActor,
};
- this.webConsoleClient.evaluateJSAsync(str, onResult, evalOptions);
-
- // Send telemetry event. If we are in the browser toolbox we send -1 as the
- // toolbox session id.
- this._telemetry.recordEvent("devtools.main", "execute_js", "webconsole", null, {
- "lines": str.split(/\n/).length,
- "session_id": toolbox ? toolbox.sessionId : -1
- });
-
- return deferred.promise;
+ return this.webConsoleClient.evaluateJSAsync(str, null, evalOptions);
}
/**
* Copy the object/variable by invoking the server
* which invokes the `copy(variable)` command and makes it
* available in the clipboard
* @param evalString - string which has the evaluation string to be copied
* @param options - object - Options for evaluation