зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1567174 - Move expression evaluation to a proper Redux action. r=jdescottes.
The goal is to not directly use the panel.hud.ui.proxy reference directly from the JsTerm, so we're in better shape when Fission comes. It's also a nice refactor to make the JSTerm component more React-like. As a nice benefit, we can handle telemetry and history persistence from their middleware. As the `requestEvaluation` method is removed from the JSTerm, some callsites needed to be updated to still work. Differential Revision: https://phabricator.services.mozilla.com/D39022 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
65526f541b
Коммит
734f57b508
|
@ -359,26 +359,27 @@ class MarkupContextMenu {
|
|||
* temp variable on the content window. Also opens the split console and
|
||||
* autofills it with the temp variable.
|
||||
*/
|
||||
_useInConsole() {
|
||||
this.toolbox.openSplitConsole().then(() => {
|
||||
const { hud } = this.toolbox.getPanel("webconsole");
|
||||
async _useInConsole() {
|
||||
await this.toolbox.openSplitConsole();
|
||||
const { hud } = this.toolbox.getPanel("webconsole");
|
||||
|
||||
const evalString = `{ let i = 0;
|
||||
while (window.hasOwnProperty("temp" + i) && i < 1000) {
|
||||
i++;
|
||||
}
|
||||
window["temp" + i] = $0;
|
||||
"temp" + i;
|
||||
}`;
|
||||
const evalString = `{ let i = 0;
|
||||
while (window.hasOwnProperty("temp" + i) && i < 1000) {
|
||||
i++;
|
||||
}
|
||||
window["temp" + i] = $0;
|
||||
"temp" + i;
|
||||
}`;
|
||||
|
||||
const options = {
|
||||
selectedNodeActor: this.selection.nodeFront.actorID,
|
||||
};
|
||||
hud.jsterm.requestEvaluation(evalString, options).then(res => {
|
||||
hud.setInputValue(res.result);
|
||||
this.inspector.emit("console-var-ready");
|
||||
});
|
||||
});
|
||||
const options = {
|
||||
selectedNodeActor: this.selection.nodeFront.actorID,
|
||||
};
|
||||
const res = await hud.ui.webConsoleClient.evaluateJSAsync(
|
||||
evalString,
|
||||
options
|
||||
);
|
||||
hud.setInputValue(res.result);
|
||||
this.inspector.emit("console-var-ready");
|
||||
}
|
||||
|
||||
_buildA11YMenuItem(menu) {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
const actionModules = [
|
||||
require("./autocomplete"),
|
||||
require("./filters"),
|
||||
require("./input"),
|
||||
require("./messages"),
|
||||
require("./ui"),
|
||||
require("./notifications"),
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { Utils: WebConsoleUtils } = require("devtools/client/webconsole/utils");
|
||||
const { EVALUATE_EXPRESSION } = require("devtools/client/webconsole/constants");
|
||||
|
||||
loader.lazyServiceGetter(
|
||||
this,
|
||||
"clipboardHelper",
|
||||
"@mozilla.org/widget/clipboardhelper;1",
|
||||
"nsIClipboardHelper"
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"saveScreenshot",
|
||||
"devtools/shared/screenshot/save"
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"messagesActions",
|
||||
"devtools/client/webconsole/actions/messages"
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"historyActions",
|
||||
"devtools/client/webconsole/actions/history"
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"ConsoleCommand",
|
||||
"devtools/client/webconsole/types",
|
||||
true
|
||||
);
|
||||
const HELP_URL = "https://developer.mozilla.org/docs/Tools/Web_Console/Helpers";
|
||||
|
||||
function evaluateExpression(expression) {
|
||||
return async ({ dispatch, services }) => {
|
||||
if (!expression) {
|
||||
expression = services.getInputValue();
|
||||
}
|
||||
if (!expression) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// We use the messages action as it's doing additional transformation on the message.
|
||||
dispatch(
|
||||
messagesActions.messagesAdd([
|
||||
new ConsoleCommand({
|
||||
messageText: expression,
|
||||
timeStamp: Date.now(),
|
||||
}),
|
||||
])
|
||||
);
|
||||
dispatch({
|
||||
type: EVALUATE_EXPRESSION,
|
||||
expression,
|
||||
});
|
||||
|
||||
WebConsoleUtils.usageCount++;
|
||||
|
||||
let mappedExpressionRes;
|
||||
try {
|
||||
mappedExpressionRes = await services.getMappedExpression(expression);
|
||||
} catch (e) {
|
||||
console.warn("Error when calling getMappedExpression", e);
|
||||
}
|
||||
|
||||
expression = mappedExpressionRes
|
||||
? mappedExpressionRes.expression
|
||||
: expression;
|
||||
|
||||
const { frameActor, client } = services.getFrameActor();
|
||||
|
||||
// Even if requestEvaluation rejects (because of webConsoleClient.evaluateJSAsync),
|
||||
// we still need to pass the error response to onExpressionEvaluated.
|
||||
const onSettled = res => res;
|
||||
|
||||
const response = await client
|
||||
.evaluateJSAsync(expression, {
|
||||
frameActor,
|
||||
selectedNodeActor: services.getSelectedNodeActor(),
|
||||
mapped: mappedExpressionRes ? mappedExpressionRes.mapped : null,
|
||||
})
|
||||
.then(onSettled, onSettled);
|
||||
|
||||
return onExpressionEvaluated(response, {
|
||||
dispatch,
|
||||
services,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The JavaScript evaluation response handler.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} response
|
||||
* The message received from the server.
|
||||
*/
|
||||
async function onExpressionEvaluated(response, { dispatch, services } = {}) {
|
||||
if (response.error) {
|
||||
console.error(`Evaluation error`, response.error, ": ", response.message);
|
||||
return;
|
||||
}
|
||||
|
||||
// If the evaluation was a top-level await expression that was rejected, there will
|
||||
// be an uncaught exception reported, so we don't need to do anything.
|
||||
if (response.topLevelAwaitRejected === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!response.helperResult) {
|
||||
dispatch(messagesActions.messagesAdd([response]));
|
||||
return;
|
||||
}
|
||||
|
||||
await handleHelperResult(response, { dispatch, services });
|
||||
}
|
||||
|
||||
async function handleHelperResult(response, { dispatch, services }) {
|
||||
const result = response.result;
|
||||
const helperResult = response.helperResult;
|
||||
const helperHasRawOutput = !!(helperResult || {}).rawOutput;
|
||||
|
||||
if (helperResult && helperResult.type) {
|
||||
switch (helperResult.type) {
|
||||
case "clearOutput":
|
||||
dispatch(messagesActions.messagesClear());
|
||||
break;
|
||||
case "clearHistory":
|
||||
dispatch(historyActions.clearHistory());
|
||||
break;
|
||||
case "inspectObject":
|
||||
services.inspectObjectActor(helperResult.object);
|
||||
break;
|
||||
case "help":
|
||||
services.openLink(HELP_URL);
|
||||
break;
|
||||
case "copyValueToClipboard":
|
||||
clipboardHelper.copyString(helperResult.value);
|
||||
break;
|
||||
case "screenshotOutput":
|
||||
const { args, value } = helperResult;
|
||||
const screenshotMessages = await saveScreenshot(
|
||||
services.getPanelWindow(),
|
||||
args,
|
||||
value
|
||||
);
|
||||
dispatch(
|
||||
messagesActions.messagesAdd(
|
||||
screenshotMessages.map(message => ({
|
||||
message,
|
||||
type: "logMessage",
|
||||
}))
|
||||
)
|
||||
);
|
||||
// early return as we already dispatched necessary messages.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const hasErrorMessage =
|
||||
response.exceptionMessage ||
|
||||
(helperResult && helperResult.type === "error");
|
||||
|
||||
// Hide undefined results coming from helper functions.
|
||||
const hasUndefinedResult =
|
||||
result && typeof result == "object" && result.type == "undefined";
|
||||
|
||||
if (hasErrorMessage || helperHasRawOutput || !hasUndefinedResult) {
|
||||
dispatch(messagesActions.messagesAdd([response]));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
evaluateExpression,
|
||||
};
|
|
@ -8,6 +8,7 @@ DevToolsModules(
|
|||
'filters.js',
|
||||
'history.js',
|
||||
'index.js',
|
||||
'input.js',
|
||||
'messages.js',
|
||||
'notifications.js',
|
||||
'ui.js',
|
||||
|
|
|
@ -300,7 +300,6 @@ class App extends Component {
|
|||
key: "reverse-search-input",
|
||||
setInputValue: serviceContainer.setInputValue,
|
||||
focusInput: serviceContainer.focusInput,
|
||||
evaluateInput: serviceContainer.evaluateInput,
|
||||
initialValue: reverseSearchInitialValue,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -23,14 +23,14 @@ const {
|
|||
class EditorToolbar extends Component {
|
||||
static get propTypes() {
|
||||
return {
|
||||
webConsoleUI: PropTypes.object.isRequired,
|
||||
editorMode: PropTypes.bool,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
webConsoleUI: PropTypes.object.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const { editorMode, webConsoleUI, dispatch } = this.props;
|
||||
const { editorMode, dispatch, webConsoleUI } = this.props;
|
||||
|
||||
if (!editorMode) {
|
||||
return null;
|
||||
|
@ -48,7 +48,7 @@ class EditorToolbar extends Component {
|
|||
"webconsole.editor.toolbar.executeButton.tooltip",
|
||||
[isMacOS ? "Cmd + Enter" : "Ctrl + Enter"]
|
||||
),
|
||||
onClick: () => webConsoleUI.jsterm.execute(),
|
||||
onClick: () => dispatch(actions.evaluateExpression()),
|
||||
},
|
||||
l10n.getStr("webconsole.editor.toolbar.executeButton.label")
|
||||
),
|
||||
|
|
|
@ -8,12 +8,6 @@ const { Utils: WebConsoleUtils } = require("devtools/client/webconsole/utils");
|
|||
const Services = require("Services");
|
||||
const { debounce } = require("devtools/shared/debounce");
|
||||
|
||||
loader.lazyServiceGetter(
|
||||
this,
|
||||
"clipboardHelper",
|
||||
"@mozilla.org/widget/clipboardhelper;1",
|
||||
"nsIClipboardHelper"
|
||||
);
|
||||
loader.lazyRequireGetter(this, "Debugger", "Debugger");
|
||||
loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
|
||||
loader.lazyRequireGetter(
|
||||
|
@ -37,12 +31,6 @@ loader.lazyRequireGetter(
|
|||
"Editor",
|
||||
"devtools/client/shared/sourceeditor/editor"
|
||||
);
|
||||
loader.lazyRequireGetter(this, "Telemetry", "devtools/client/shared/telemetry");
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"saveScreenshot",
|
||||
"devtools/shared/screenshot/save"
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"focusableSelector",
|
||||
|
@ -50,10 +38,6 @@ loader.lazyRequireGetter(
|
|||
true
|
||||
);
|
||||
|
||||
const l10n = require("devtools/client/webconsole/utils/l10n");
|
||||
|
||||
const HELP_URL = "https://developer.mozilla.org/docs/Tools/Web_Console/Helpers";
|
||||
|
||||
// React & Redux
|
||||
const { Component } = require("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
|
@ -67,8 +51,7 @@ const {
|
|||
const {
|
||||
getAutocompleteState,
|
||||
} = require("devtools/client/webconsole/selectors/autocomplete");
|
||||
const historyActions = require("devtools/client/webconsole/actions/history");
|
||||
const autocompleteActions = require("devtools/client/webconsole/actions/autocomplete");
|
||||
const actions = require("devtools/client/webconsole/actions/index");
|
||||
|
||||
// Constants used for defining the direction of JSTerm input history navigation.
|
||||
const {
|
||||
|
@ -100,6 +83,8 @@ class JSTerm extends Component {
|
|||
// Handler for clipboard 'paste' event (also used for 'drop' event, callback).
|
||||
onPaste: PropTypes.func,
|
||||
codeMirrorEnabled: PropTypes.bool,
|
||||
// Evaluate provided expression.
|
||||
evaluateExpression: PropTypes.func.isRequired,
|
||||
// Update position in the history after executing an expression (action).
|
||||
updateHistoryPosition: PropTypes.func.isRequired,
|
||||
// Update autocomplete popup state.
|
||||
|
@ -142,8 +127,6 @@ class JSTerm extends Component {
|
|||
this.inputNode = null;
|
||||
this.completeNode = null;
|
||||
|
||||
this._telemetry = new Telemetry();
|
||||
|
||||
EventEmitter.decorate(this);
|
||||
webConsoleUI.jsterm = this;
|
||||
}
|
||||
|
@ -596,204 +579,26 @@ class JSTerm extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The JavaScript evaluation response handler.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} response
|
||||
* The message received from the server.
|
||||
*/
|
||||
/* eslint-disable complexity */
|
||||
async _executeResultCallback(response) {
|
||||
if (!this.webConsoleUI) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (response.error) {
|
||||
console.error(
|
||||
"Evaluation error " + response.error + ": " + response.message
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
// If the evaluation was a top-level await expression that was rejected, there will
|
||||
// be an uncaught exception reported, so we don't want need to print anything here.
|
||||
if (response.topLevelAwaitRejected === true) {
|
||||
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;
|
||||
const helperResult = response.helperResult;
|
||||
const helperHasRawOutput = !!(helperResult || {}).rawOutput;
|
||||
|
||||
if (helperResult && helperResult.type) {
|
||||
switch (helperResult.type) {
|
||||
case "clearOutput":
|
||||
this.webConsoleUI.clearOutput();
|
||||
break;
|
||||
case "clearHistory":
|
||||
this.props.clearHistory();
|
||||
break;
|
||||
case "inspectObject":
|
||||
this.webConsoleUI.inspectObjectActor(helperResult.object);
|
||||
break;
|
||||
case "error":
|
||||
try {
|
||||
errorMessage = l10n.getStr(helperResult.message);
|
||||
} catch (ex) {
|
||||
errorMessage = helperResult.message;
|
||||
}
|
||||
break;
|
||||
case "help":
|
||||
this.webConsoleUI.hud.openLink(HELP_URL);
|
||||
break;
|
||||
case "copyValueToClipboard":
|
||||
clipboardHelper.copyString(helperResult.value);
|
||||
break;
|
||||
case "screenshotOutput":
|
||||
const { args, value } = helperResult;
|
||||
const results = await saveScreenshot(
|
||||
this.webConsoleUI.window,
|
||||
args,
|
||||
value
|
||||
);
|
||||
this.screenshotNotify(results);
|
||||
// early return as screenshot notify has dispatched all necessary messages
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide undefined results coming from JSTerm helper functions.
|
||||
if (
|
||||
!errorMessage &&
|
||||
result &&
|
||||
typeof result == "object" &&
|
||||
result.type == "undefined" &&
|
||||
helperResult &&
|
||||
!helperHasRawOutput
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this.webConsoleUI.wrapper) {
|
||||
return this.webConsoleUI.wrapper.dispatchMessageAdd(response, true);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
/* eslint-enable complexity */
|
||||
|
||||
screenshotNotify(results) {
|
||||
const wrappedResults = results.map(message => ({
|
||||
message,
|
||||
type: "logMessage",
|
||||
}));
|
||||
this.webConsoleUI.wrapper.dispatchMessagesAdd(wrappedResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a string. Execution happens asynchronously in the content process.
|
||||
*
|
||||
* @param {String} executeString
|
||||
* The string you want to execute. If this is not provided, the current
|
||||
* user input is used - taken from |this._getValue()|.
|
||||
* @returns {Promise}
|
||||
* Resolves with the message once the result is displayed.
|
||||
*/
|
||||
async execute(executeString) {
|
||||
execute(executeString) {
|
||||
// attempt to execute the content of the inputNode
|
||||
executeString = executeString || this._getValue();
|
||||
if (!executeString) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Append executed expression into the history list.
|
||||
this.props.appendToHistory(executeString);
|
||||
|
||||
WebConsoleUtils.usageCount++;
|
||||
|
||||
if (!this.props.editorMode) {
|
||||
this._setValue("");
|
||||
}
|
||||
|
||||
this.clearCompletion();
|
||||
|
||||
let selectedNodeActor = null;
|
||||
const inspectorSelection = this.webConsoleUI.hud.getInspectorSelection();
|
||||
if (inspectorSelection && inspectorSelection.nodeFront) {
|
||||
selectedNodeActor = inspectorSelection.nodeFront.actorID;
|
||||
}
|
||||
|
||||
const { ConsoleCommand } = require("devtools/client/webconsole/types");
|
||||
const cmdMessage = new ConsoleCommand({
|
||||
messageText: executeString,
|
||||
timeStamp: Date.now(),
|
||||
});
|
||||
this.webConsoleUI.proxy.dispatchMessageAdd(cmdMessage);
|
||||
|
||||
let mappedExpressionRes = null;
|
||||
try {
|
||||
mappedExpressionRes = await this.webConsoleUI.hud.getMappedExpression(
|
||||
executeString
|
||||
);
|
||||
} catch (e) {
|
||||
console.warn("Error when calling getMappedExpression", e);
|
||||
}
|
||||
|
||||
executeString = mappedExpressionRes
|
||||
? mappedExpressionRes.expression
|
||||
: executeString;
|
||||
|
||||
const options = {
|
||||
selectedNodeActor,
|
||||
mapped: mappedExpressionRes ? mappedExpressionRes.mapped : null,
|
||||
};
|
||||
|
||||
// Even if requestEvaluation rejects (because of webConsoleClient.evaluateJSAsync),
|
||||
// we still need to pass the error response to executeResultCallback.
|
||||
const onEvaluated = this.requestEvaluation(executeString, 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]
|
||||
* Options for evaluation:
|
||||
* - 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.
|
||||
* - mapped: basically getMappedExpression().mapped. An object that indicates
|
||||
* which modifications were done to the input entered by the user.
|
||||
* @return object
|
||||
* A promise object that is resolved when the server response is
|
||||
* received.
|
||||
*/
|
||||
requestEvaluation(str, options = {}) {
|
||||
// Send telemetry event. If we are in the browser toolbox we send -1 as the
|
||||
// toolbox session id.
|
||||
this.props.serviceContainer.recordTelemetryEvent("execute_js", {
|
||||
lines: str.split(/\n/).length,
|
||||
});
|
||||
|
||||
const { frameActor, client } = this.props.serviceContainer.getFrameActor();
|
||||
|
||||
return client.evaluateJSAsync(str, {
|
||||
frameActor,
|
||||
...options,
|
||||
});
|
||||
this.props.evaluateExpression(executeString);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1800,13 +1605,15 @@ function mapStateToProps(state) {
|
|||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
appendToHistory: expr => dispatch(historyActions.appendToHistory(expr)),
|
||||
clearHistory: () => dispatch(historyActions.clearHistory()),
|
||||
appendToHistory: expr => dispatch(actions.appendToHistory(expr)),
|
||||
clearHistory: () => dispatch(actions.clearHistory()),
|
||||
updateHistoryPosition: (direction, expression) =>
|
||||
dispatch(historyActions.updateHistoryPosition(direction, expression)),
|
||||
dispatch(actions.updateHistoryPosition(direction, expression)),
|
||||
autocompleteUpdate: (force, getterPath) =>
|
||||
dispatch(autocompleteActions.autocompleteUpdate(force, getterPath)),
|
||||
autocompleteClear: () => dispatch(autocompleteActions.autocompleteClear()),
|
||||
dispatch(actions.autocompleteUpdate(force, getterPath)),
|
||||
autocompleteClear: () => dispatch(actions.autocompleteClear()),
|
||||
evaluateExpression: expression =>
|
||||
dispatch(actions.evaluateExpression(expression)),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,6 @@ class ReverseSearchInput extends Component {
|
|||
dispatch: PropTypes.func.isRequired,
|
||||
setInputValue: PropTypes.func.isRequired,
|
||||
focusInput: PropTypes.func.isRequired,
|
||||
evaluateInput: PropTypes.func.isRequired,
|
||||
reverseSearchResult: PropTypes.string,
|
||||
reverseSearchTotalResults: PropTypes.number,
|
||||
reverseSearchResultPosition: PropTypes.number,
|
||||
|
@ -92,10 +91,10 @@ class ReverseSearchInput extends Component {
|
|||
}
|
||||
|
||||
onEnterKeyboardShortcut(event) {
|
||||
const { dispatch, evaluateInput } = this.props;
|
||||
const { dispatch } = this.props;
|
||||
event.stopPropagation();
|
||||
dispatch(actions.reverseSearchInputToggle());
|
||||
evaluateInput();
|
||||
dispatch(actions.evaluateExpression());
|
||||
}
|
||||
|
||||
onEscapeKeyboardShortcut(event) {
|
||||
|
|
|
@ -15,6 +15,7 @@ const actionTypes = {
|
|||
BATCH_ACTIONS: "BATCH_ACTIONS",
|
||||
CLEAR_HISTORY: "CLEAR_HISTORY",
|
||||
EDITOR_TOGGLE: "EDITOR_TOGGLE",
|
||||
EVALUATE_EXPRESSION: "EVALUATE_EXPRESSION",
|
||||
FILTER_TEXT_SET: "FILTER_TEXT_SET",
|
||||
FILTER_TOGGLE: "FILTER_TOGGLE",
|
||||
FILTERS_CLEAR: "FILTERS_CLEAR",
|
||||
|
|
|
@ -8,6 +8,7 @@ const {
|
|||
FILTER_TEXT_SET,
|
||||
FILTER_TOGGLE,
|
||||
DEFAULT_FILTERS_RESET,
|
||||
EVALUATE_EXPRESSION,
|
||||
MESSAGES_ADD,
|
||||
PERSIST_TOGGLE,
|
||||
} = require("devtools/client/webconsole/constants");
|
||||
|
@ -50,6 +51,13 @@ function eventTelemetryMiddleware(telemetry, sessionId, store) {
|
|||
session_id: sessionId,
|
||||
}
|
||||
);
|
||||
} else if (action.type === EVALUATE_EXPRESSION) {
|
||||
// Send telemetry event. If we are in the browser toolbox we send -1 as the
|
||||
// toolbox session id.
|
||||
telemetry.recordEvent("execute_js", "webconsole", null, {
|
||||
lines: action.expression.split(/\n/).length,
|
||||
session_id: sessionId,
|
||||
});
|
||||
}
|
||||
|
||||
return res;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
const {
|
||||
APPEND_TO_HISTORY,
|
||||
CLEAR_HISTORY,
|
||||
EVALUATE_EXPRESSION,
|
||||
} = require("devtools/client/webconsole/constants");
|
||||
|
||||
const historyActions = require("devtools/client/webconsole/actions/history");
|
||||
|
@ -35,7 +36,11 @@ function historyPersistenceMiddleware(store) {
|
|||
return next => action => {
|
||||
const res = next(action);
|
||||
|
||||
const triggerStoreActions = [APPEND_TO_HISTORY, CLEAR_HISTORY];
|
||||
const triggerStoreActions = [
|
||||
APPEND_TO_HISTORY,
|
||||
CLEAR_HISTORY,
|
||||
EVALUATE_EXPRESSION,
|
||||
];
|
||||
|
||||
// Save the current history entries when modified, but wait till
|
||||
// entries from the previous session are loaded.
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
const {
|
||||
APPEND_TO_HISTORY,
|
||||
CLEAR_HISTORY,
|
||||
EVALUATE_EXPRESSION,
|
||||
HISTORY_LOADED,
|
||||
UPDATE_HISTORY_POSITION,
|
||||
HISTORY_BACK,
|
||||
|
@ -46,6 +47,7 @@ function getInitialState() {
|
|||
function history(state = getInitialState(), action, prefsState) {
|
||||
switch (action.type) {
|
||||
case APPEND_TO_HISTORY:
|
||||
case EVALUATE_EXPRESSION:
|
||||
return appendToHistory(state, prefsState, action.expression);
|
||||
case CLEAR_HISTORY:
|
||||
return clearHistory(state);
|
||||
|
|
|
@ -20,7 +20,7 @@ const WebConsoleWrapper = require("devtools/client/webconsole/webconsole-wrapper
|
|||
const { messagesAdd } = require("devtools/client/webconsole/actions/messages");
|
||||
|
||||
async function getWebConsoleWrapper() {
|
||||
const hud = { target: { client: {} } };
|
||||
const hud = { target: { client: {} }, getMappedExpression: () => {} };
|
||||
const webConsoleUi = {
|
||||
emit: () => {},
|
||||
hud,
|
||||
|
@ -30,6 +30,7 @@ async function getWebConsoleWrapper() {
|
|||
ensureCSSErrorReportingEnabled: () => {},
|
||||
},
|
||||
},
|
||||
inspectObjectActor: () => {},
|
||||
};
|
||||
|
||||
const wcow = new WebConsoleWrapper(null, webConsoleUi, null, null);
|
||||
|
|
|
@ -109,8 +109,11 @@ async function storeAsVariable(hud, msg, type, varIdx, equalTo) {
|
|||
|
||||
is(getInputValue(hud), "temp" + varIdx, "Input was set");
|
||||
|
||||
const equal = await hud.jsterm.requestEvaluation(
|
||||
"temp" + varIdx + " === " + equalTo
|
||||
await executeAndWaitForMessage(
|
||||
hud,
|
||||
`temp${varIdx} === ${equalTo}`,
|
||||
true,
|
||||
".result"
|
||||
);
|
||||
is(equal.result, true, "Correct variable assigned into console.");
|
||||
ok(true, "Correct variable assigned into console.");
|
||||
}
|
||||
|
|
|
@ -164,10 +164,12 @@ function createContextMenu(
|
|||
selectedObjectActor: actor,
|
||||
};
|
||||
|
||||
webConsoleUI.jsterm.requestEvaluation(evalString, options).then(res => {
|
||||
webConsoleUI.jsterm.focus();
|
||||
webConsoleUI.hud.setInputValue(res.result);
|
||||
});
|
||||
webConsoleUI.webConsoleClient
|
||||
.evaluateJSAsync(evalString, options)
|
||||
.then(res => {
|
||||
webConsoleUI.jsterm.focus();
|
||||
webConsoleUI.hud.setInputValue(res.result);
|
||||
});
|
||||
},
|
||||
})
|
||||
);
|
||||
|
|
|
@ -204,10 +204,6 @@ class WebConsoleWrapper {
|
|||
return webConsoleUI.jsterm && webConsoleUI.jsterm.focus();
|
||||
},
|
||||
|
||||
evaluateInput: expression => {
|
||||
return webConsoleUI.jsterm && webConsoleUI.jsterm.execute(expression);
|
||||
},
|
||||
|
||||
requestEvaluation: (string, options) => {
|
||||
return webConsoleUI.webConsoleClient.evaluateJSAsync(string, options);
|
||||
},
|
||||
|
@ -230,6 +226,9 @@ class WebConsoleWrapper {
|
|||
}
|
||||
return webConsoleUI.jsterm.completeNode;
|
||||
},
|
||||
getMappedExpression: this.hud.getMappedExpression.bind(this.hud),
|
||||
getPanelWindow: () => webConsoleUI.window,
|
||||
inspectObjectActor: webConsoleUI.inspectObjectActor.bind(webConsoleUI),
|
||||
};
|
||||
|
||||
// Set `openContextMenu` this way so, `serviceContainer` variable
|
||||
|
|
Загрузка…
Ссылка в новой задаче