Bug 1568143 - Don't use JsTerm reference to evaluate code. r=jdescottes.

JSTerm `execute` function is renamed to `_execute` to emphasize
that it's a private function.
A `dispatchEvaluateExpression` is added to the WebConsoleWrapper
so other panels can use that if they need to.
A test helper is added to be able to evaluate without grabbing
the jsterm reference, and tests are modified to use the new
helper, or the existing `executeAndWaitForMessage`.

Differential Revision: https://phabricator.services.mozilla.com/D39024

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Nicolas Chevobbe 2019-08-02 11:50:28 +00:00
parent 734f57b508
commit 9eb7ab91ab
88 changed files with 740 additions and 561 deletions

View File

@ -30,9 +30,7 @@ async function setupToolboxTest(extensionId) {
}
}
const console = await toolbox.selectTool("webconsole");
const { hud } = console;
const { jsterm } = hud;
const consoleFront = await toolbox.target.getFront("console");
const netmonitor = await toolbox.selectTool("netmonitor");
@ -40,7 +38,7 @@ async function setupToolboxTest(extensionId) {
// Call a function defined in the target extension to make it
// fetch from an expected http url.
await jsterm.execute(`doFetchHTTPRequest("${expectedURL}");`);
await consoleFront.evaluateJSAsync(`doFetchHTTPRequest("${expectedURL}");`);
await waitFor(() => {
return !netmonitor.panelWin.document.querySelector(
@ -70,7 +68,7 @@ async function setupToolboxTest(extensionId) {
// Call a function defined in the target extension to make assertions
// on the network requests collected by the netmonitor panel.
await jsterm.execute(
await consoleFront.evaluateJSAsync(
`testNetworkRequestReceived(${JSON.stringify(requests)});`
);

View File

@ -87,11 +87,12 @@ function toolboxTestScript(toolbox, devtoolsTab) {
.selectTool("webconsole")
.then(async console => {
const { hud } = console;
const { jsterm } = hud;
const onMessage = waitFor(() => {
return findMessages(hud, "Background page function called").length > 0;
});
await jsterm.execute("myWebExtensionAddonFunction()");
hud.ui.wrapper.dispatchEvaluateExpression(
"myWebExtensionAddonFunction()"
);
await onMessage;
await removeTab(devtoolsTab);
})

View File

@ -186,7 +186,6 @@ add_task(async function testWebExtensionsToolboxWebConsole() {
});
async function toolboxTestScript(toolbox, devtoolsTab) {
let jsterm;
const popupFramePromise = new Promise(resolve => {
const listener = data => {
if (data.frames.some(({ url }) => url && url.endsWith("popup.html"))) {
@ -223,8 +222,8 @@ async function toolboxTestScript(toolbox, devtoolsTab) {
await clickNoAutoHideMenu();
dump(`Clicked the menu button\n`);
jsterm = console.hud.jsterm;
jsterm.execute("myWebExtensionShowPopup()");
const consoleWrapper = console.hud.ui.wrapper;
consoleWrapper.dispatchEvaluateExpression("myWebExtensionShowPopup()");
await Promise.all([
// Wait the initial frame update (which list the background page).
@ -265,7 +264,9 @@ async function toolboxTestScript(toolbox, devtoolsTab) {
wait(1000),
]);
await waitForNavigated;
await jsterm.execute("myWebExtensionPopupAddonFunction()");
consoleWrapper.dispatchEvaluateExpression(
"myWebExtensionPopupAddonFunction()"
);
info("Wait for all pending requests to settle on the DebuggerClient");
await toolbox.target.client.waitForRequestsToSettle();

View File

@ -80,9 +80,8 @@ DebuggerPanel.prototype = {
},
openConsoleAndEvaluate: async function(input) {
const webconsolePanel = await this.toolbox.selectTool("webconsole");
const jsterm = webconsolePanel.hud.jsterm;
jsterm.execute(input);
const { hud } = await this.toolbox.selectTool("webconsole");
hud.ui.wrapper.dispatchEvaluateExpression(input);
},
openElementInInspector: async function(grip) {

View File

@ -14,8 +14,8 @@ add_task(async function() {
const toolbox = await openNewTabAndToolbox(url, "webconsole");
// Type "debugger" into console
let jsterm = toolbox.getPanel("webconsole").hud.jsterm;
jsterm.execute("debugger");
let wrapper = toolbox.getPanel("webconsole").hud.ui.wrapper;
wrapper.dispatchEvaluateExpression("debugger");
// Wait for the debugger to be selected and make sure it's paused
await waitOnToolbox(toolbox, "jsdebugger-selected");
@ -23,10 +23,6 @@ add_task(async function() {
// Create a dbg context
const dbg = createDebuggerContext(toolbox);
const {
selectors: { getSelectedSource },
getState
} = dbg;
// Make sure the thread is paused in the right source and location
await waitForPaused(dbg);

View File

@ -25,20 +25,22 @@ function findMessages(win, query) {
return Array.prototype.filter.call(
win.document.querySelectorAll(".message"),
e => e.innerText.includes(query)
)
);
}
async function hasMessage(dbg, msg) {
const webConsole = await dbg.toolbox.getPanel("webconsole")
return waitFor(async () => findMessages(
webConsole._frameWindow,
msg
).length > 0)
const webConsole = await dbg.toolbox.getPanel("webconsole");
return waitFor(
async () => findMessages(webConsole._frameWindow, msg).length > 0
);
}
add_task(async function() {
Services.prefs.setBoolPref("devtools.toolbox.splitconsoleEnabled", true);
Services.prefs.setBoolPref("devtools.debugger.features.map-await-expression", true);
Services.prefs.setBoolPref(
"devtools.debugger.features.map-await-expression",
true
);
const dbg = await initDebugger("doc-script-switching.html", "switching-01");
@ -48,10 +50,10 @@ add_task(async function() {
await getSplitConsole(dbg);
ok(dbg.toolbox.splitConsole, "Split console is shown.");
const webConsole = await dbg.toolbox.getPanel("webconsole")
const jsterm = webConsole.hud.jsterm;
const webConsole = await dbg.toolbox.getPanel("webconsole");
const wrapper = webConsole.hud.ui.wrapper;
await jsterm.execute(`
wrapper.dispatchEvaluateExpression(`
let sleep = async (time, v) => new Promise(
res => setTimeout(() => res(v+'!!!'), time)
)
@ -59,6 +61,6 @@ add_task(async function() {
await hasMessage(dbg, "sleep");
await jsterm.execute(`await sleep(200, "DONE")`);
wrapper.dispatchEvaluateExpression(`await sleep(200, "DONE")`);
await hasMessage(dbg, "DONE!!!");
});

View File

@ -23,8 +23,8 @@ function getSplitConsole(dbg) {
async function evaluate(dbg, expression) {
const { toolbox } = dbg;
let jsterm = toolbox.getPanel("webconsole").hud.jsterm;
const msg = await jsterm.execute(expression);
const { hud } = toolbox.getPanel("webconsole");
const msg = await evaluateExpressionInConsole(hud, expression);
return msg.innerText;
}

View File

@ -30,15 +30,11 @@ async function evalInConsoleAtPoint(
}
async function assertConsoleEval(dbg, statements) {
const jsterm = (await dbg.toolbox.selectTool("webconsole")).hud.jsterm;
const { hud } = await dbg.toolbox.selectTool("webconsole");
for (const [index, statement] of statements.entries()) {
await dbg.client.evaluate(`
window.TEST_RESULT = false;
`);
await jsterm.execute(`
TEST_RESULT = ${statement};
`);
await dbg.client.evaluate(`window.TEST_RESULT = false;`);
await evaluateExpressionInConsole(hud, `TEST_RESULT = ${statement};`);
const result = await dbg.client.evaluate(`window.TEST_RESULT`);
is(result.result, true, `'${statement}' evaluates to true`);
@ -71,7 +67,7 @@ add_task(async function() {
`aNamed2 === "a-named2"`,
`aDefault3 === "a-default3"`,
`anAliased3 === "an-original3"`,
`aNamed3 === "a-named3"`
`aNamed3 === "a-named3"`,
]
);

View File

@ -19,11 +19,11 @@ var { Task } = require("devtools/shared/task");
var asyncStorage = require("devtools/shared/async-storage");
const {
getSelectedLocation
getSelectedLocation,
} = require("devtools/client/debugger/src/utils/selected-location");
const {
resetSchemaVersion
resetSchemaVersion,
} = require("devtools/client/debugger/src/utils/prefs");
function log(msg, data) {
@ -57,7 +57,7 @@ function waitForNextDispatch(store, actionType) {
predicate: action => action.type === actionType,
run: (dispatch, getState, action) => {
resolve(action);
}
},
});
});
}
@ -93,7 +93,7 @@ function waitForDispatch(dbg, actionType, eventRepeat = 1) {
},
run: (dispatch, getState, action) => {
resolve(action);
}
},
});
});
}
@ -211,7 +211,7 @@ function waitForSelectedSource(dbg, url) {
const {
getSelectedSourceWithContent,
hasSymbols,
getBreakableLines
getBreakableLines,
} = dbg.selectors;
return waitForState(
@ -266,7 +266,7 @@ function assertEmptyLines(dbg, lines) {
function getVisibleSelectedFrameLine(dbg) {
const {
selectors: { getVisibleSelectedFrame }
selectors: { getVisibleSelectedFrame },
} = dbg;
const frame = getVisibleSelectedFrame();
return frame && frame.location.line;
@ -782,7 +782,7 @@ function getFirstBreakpointColumn(dbg, { line, sourceId }) {
const source = getSource(sourceId);
const position = getFirstBreakpointPosition({
line,
sourceId
sourceId,
});
return getSelectedLocation(position, source).column;
@ -843,7 +843,7 @@ function findBreakpoint(dbg, url, line) {
async function loadAndAddBreakpoint(dbg, filename, line, column) {
const {
selectors: { getBreakpoint, getBreakpointCount, getBreakpointsMap }
selectors: { getBreakpoint, getBreakpointCount, getBreakpointsMap },
} = dbg;
await waitForSources(dbg, filename);
@ -885,7 +885,7 @@ async function invokeWithBreakpoint(
const invokeFailed = await Promise.race([
waitForPaused(dbg),
invokeResult.then(() => new Promise(() => {}), () => true)
invokeResult.then(() => new Promise(() => {}), () => true),
]);
if (invokeFailed) {
@ -987,7 +987,7 @@ async function togglePauseOnExceptions(
function waitForActive(dbg) {
const {
selectors: { getIsPaused, getCurrentThread }
selectors: { getIsPaused, getCurrentThread },
} = dbg;
return waitForState(dbg, state => !getIsPaused(getCurrentThread()), "active");
}
@ -1009,7 +1009,7 @@ function invokeInTab(fnc, ...args) {
info(`Invoking in tab: ${fnc}(${args.map(uneval).join(",")})`);
return ContentTask.spawn(gBrowser.selectedBrowser, { fnc, args }, function*({
fnc,
args
args,
}) {
return content.wrappedJSObject[fnc](...args);
});
@ -1051,7 +1051,7 @@ const keyMappings = {
ShiftEnter: { code: "VK_RETURN", modifiers: shiftOrAlt },
AltEnter: {
code: "VK_RETURN",
modifiers: { altKey: true }
modifiers: { altKey: true },
},
Up: { code: "VK_UP" },
Down: { code: "VK_DOWN" },
@ -1068,8 +1068,8 @@ const keyMappings = {
stepInKey: { code: "VK_F11", modifiers: { ctrlKey: isLinux } },
stepOutKey: {
code: "VK_F11",
modifiers: { ctrlKey: isLinux, shiftKey: true }
}
modifiers: { ctrlKey: isLinux, shiftKey: true },
},
};
/**
@ -1195,7 +1195,7 @@ const selectors = {
enableOthers: "#node-menu-enable-others",
remove: "#node-menu-delete-self",
removeOthers: "#node-menu-delete-other",
removeCondition: "#node-menu-remove-condition"
removeCondition: "#node-menu-remove-condition",
},
columnBreakpoints: ".column-breakpoint",
scopes: ".scopes-list",
@ -1263,7 +1263,7 @@ const selectors = {
threadsPaneItems: ".workers-pane .worker",
threadsPaneItem: i => `.workers-pane .worker:nth-child(${i})`,
threadsPaneItemPause: i => `${selectors.threadsPaneItem(i)} .pause-badge`,
CodeMirrorLines: ".CodeMirror-lines"
CodeMirrorLines: ".CodeMirror-lines",
};
function getSelector(elementName, ...args) {
@ -1512,7 +1512,7 @@ async function hoverAtPos(dbg, { line, ch }) {
new MouseEvent("mouseover", {
bubbles: true,
cancelable: true,
view: dbg.win
view: dbg.win,
})
);
@ -1597,18 +1597,18 @@ async function assertPreviews(dbg, previews) {
await assertPreviewPopup(dbg, line, column, {
expression,
field,
value
value,
});
}
} else {
await assertPreviewTextValue(dbg, line, column, {
expression,
text: result
text: result,
});
}
const { target } = dbg.selectors.getPreview(getContext(dbg));
InspectorUtils.removePseudoClassLock(target, ':hover')
InspectorUtils.removePseudoClassLock(target, ":hover");
dbg.actions.clearPreview(getContext(dbg));
}
}
@ -1773,3 +1773,19 @@ async function hasConsoleMessage(dbg, msg) {
return messages.length > 0;
});
}
function evaluateExpressionInConsole(hud, expression) {
const onResult = new Promise(res => {
const onNewMessage = messages => {
for (let message of messages) {
if (message.node.classList.contains("result")) {
hud.ui.off("new-messages", onNewMessage);
res(message.node);
}
}
};
hud.ui.on("new-messages", onNewMessage);
});
hud.ui.wrapper.dispatchEvaluateExpression(expression);
return onResult;
}

View File

@ -36,12 +36,21 @@ add_task(async function() {
.then(console => {
// This is for checking Browser Toolbox doesn't have a close button.
const hasCloseButton = !!toolbox.doc.getElementById("toolbox-close");
const { jsterm } = console.hud;
const js =
"Services.obs.notifyObservers(null, 'browser-toolbox-console-works', " +
hasCloseButton +
");";
return jsterm.execute(js);
const { wrapper } = console.hud.ui;
const js = `Services.obs.notifyObservers(null, 'browser-toolbox-console-works', ${hasCloseButton} )`;
const onResult = new Promise(resolve => {
const onNewMessages = messages => {
for (const message of messages) {
if (message.node.classList.contains("result")) {
console.hud.ui.off("new-messages", onNewMessages);
resolve();
}
}
};
console.hud.ui.on("new-messages", onNewMessages);
});
wrapper.dispatchEvaluateExpression(js);
return onResult;
})
.then(() => toolbox.destroy());
};

View File

@ -75,7 +75,20 @@ async function testScript() {
// Switch to the webconsole to send the result to the main test.
const webconsole = await toolbox.selectTool("webconsole");
const js = `Services.obs.notifyObservers(null, "browser-toolbox-inspector-dir", "${dir}");`;
await webconsole.hud.jsterm.execute(js);
const onResult = new Promise(resolve => {
const onNewMessages = messages => {
for (const message of messages) {
if (message.node.classList.contains("result")) {
webconsole.hud.ui.off("new-messages", onNewMessages);
resolve();
}
}
};
webconsole.hud.ui.on("new-messages", onNewMessages);
});
webconsole.hud.ui.wrapper.dispatchEvaluateExpression(js);
await onResult;
// Destroy the toolbox.
await toolbox.destroy();

View File

@ -47,9 +47,11 @@ add_task(async function() {
info("Veryify we are inspecting the new document");
const console = await toolbox.selectTool("webconsole");
const { jsterm } = console.hud;
const url = await jsterm.execute("document.location.href");
// Uses includes as the old console frontend prints a timestamp
const { ui } = console.hud;
ui.wrapper.dispatchEvaluateExpression("document.location.href");
await waitUntil(() => ui.outputNode.querySelector(".result"));
const url = ui.outputNode.querySelector(".result");
ok(
url.textContent.includes(URL_2),
"The console inspects the second document"

View File

@ -344,11 +344,8 @@ class MarkupContextMenu {
*/
_showDOMProperties() {
this.toolbox.openSplitConsole().then(() => {
const panel = this.toolbox.getPanel("webconsole");
const jsterm = panel.hud.jsterm;
jsterm.execute("inspect($0)");
jsterm.focus();
const { hud } = this.toolbox.getPanel("webconsole");
hud.ui.wrapper.dispatchEvaluateExpression("inspect($0)");
});
}

View File

@ -26,14 +26,17 @@ add_task(async function() {
await inspector.once("console-var-ready");
const hud = toolbox.getPanel("webconsole").hud;
const jsterm = hud.jsterm;
const getConsoleResults = () =>
hud.ui.outputNode.querySelectorAll(".result");
is(hud.getInputValue(), "temp0", "first console variable is named temp0");
hud.ui.wrapper.dispatchEvaluateExpression();
let result = await jsterm.execute();
isnot(
result.textContent.indexOf('<p id="console-var">'),
-1,
await waitUntil(() => getConsoleResults().length === 1);
let result = getConsoleResults()[0];
ok(
result.textContent.includes('<p id="console-var">'),
"variable temp0 references correct node"
);
@ -42,11 +45,12 @@ add_task(async function() {
await inspector.once("console-var-ready");
is(hud.getInputValue(), "temp1", "second console variable is named temp1");
hud.ui.wrapper.dispatchEvaluateExpression();
result = await jsterm.execute();
isnot(
result.textContent.indexOf('<p id="console-var-multi">'),
-1,
await waitUntil(() => getConsoleResults().length === 2);
result = getConsoleResults()[1];
ok(
result.textContent.includes('<p id="console-var-multi">'),
"variable temp1 references correct node"
);

View File

@ -81,11 +81,10 @@ exports.initConsoleInTab = async function({ tab }) {
const consoleMethod = async function(method, label, event) {
const performanceFront = await toolbox.target.getFront("performance");
const recordingEventReceived = once(performanceFront, event);
if (label === undefined) {
await panel.hud.jsterm.execute(`console.${method}()`);
} else {
await panel.hud.jsterm.execute(`console.${method}("${label}")`);
}
const expression = label
? `console.${method}("${label}")`
: `console.${method}()`;
await panel.hud.ui.wrapper.dispatchEvaluateExpression(expression);
await recordingEventReceived;
};

View File

@ -24,12 +24,9 @@ add_task(async function testNormalExecution() {
WORKER_URL
);
const jsterm = await getSplitConsole(toolbox);
const executed = await jsterm.execute("this.location.toString()");
ok(
executed.textContent.includes(WORKER_URL),
"Evaluating the global's location works"
);
const hud = await getSplitConsole(toolbox);
await executeAndWaitForMessage(hud, "this.location.toString()", WORKER_URL);
ok(true, "Evaluating the global's location works");
terminateWorkerInTab(tab, WORKER_URL);
await waitForWorkerClose(workerTargetFront);

View File

@ -24,12 +24,9 @@ add_task(async function testWhilePaused() {
const workerThreadFront = await workerTargetFront.getFront("thread");
// Execute some basic math to make sure evaluations are working.
const jsterm = await getSplitConsole(toolbox);
let executed = await jsterm.execute("10000+1");
ok(
executed.textContent.includes("10001"),
"Text for message appeared correct"
);
const hud = await getSplitConsole(toolbox);
await executeAndWaitForMessage(hud, "10000+1", "10001");
ok(true, "Text for message appeared correct");
await clickElement(dbg, "pause");
workerThreadFront.once("willInterrupt").then(() => {
@ -38,24 +35,27 @@ add_task(async function testWhilePaused() {
});
await waitForPaused(dbg);
const command1 = jsterm.execute("10000+2");
const command2 = jsterm.execute("10000+3");
const command3 = jsterm.execute("foobar"); // throw an error
const command1 = executeAndWaitForMessage(hud, "10000+2", "10002");
const command2 = executeAndWaitForMessage(hud, "10000+3", "10003");
// throw an error
const command3 = executeAndWaitForMessage(
hud,
"foobar",
"ReferenceError: foobar is not defined",
"error"
);
info("Trying to get the result of command1");
executed = await command1;
ok(executed.textContent.includes("10002"), "command1 executed successfully");
let executed = await command1;
ok(executed, "command1 executed successfully");
info("Trying to get the result of command2");
executed = await command2;
ok(executed.textContent.includes("10003"), "command2 executed successfully");
ok(executed, "command2 executed successfully");
info("Trying to get the result of command3");
executed = await command3;
ok(
executed.textContent.includes("ReferenceError: foobar is not defined"),
"command3 executed successfully"
);
ok(executed, "command3 executed successfully");
await resume(dbg);

View File

@ -23,34 +23,25 @@ add_task(async function testPausedByConsole() {
const dbg = await initWorkerDebugger(TAB_URL, WORKER_URL);
const { client, tab, workerTargetFront, toolbox } = dbg;
const jsterm = await getSplitConsole(toolbox);
let executed = await jsterm.execute("10000+1");
ok(
executed.textContent.includes("10001"),
"Text for message appeared correct"
);
const console = await getSplitConsole(toolbox);
let executed = await executeAndWaitForMessage(console, "10000+1", "10001");
ok(executed, "Text for message appeared correct");
await clickElement(dbg, "pause");
const pausedExecution = jsterm.execute("10000+2");
const pausedExecution = executeAndWaitForMessage(console, "10000+2", "10002");
info("Executed a command with 'break on next' active, waiting for pause");
await waitForPaused(dbg);
executed = await jsterm.execute("10000+3");
ok(
executed.textContent.includes("10003"),
"Text for message appeared correct"
);
executed = await executeAndWaitForMessage(console, "10000+3", "10003");
ok(executed, "Text for message appeared correct");
info("Waiting for a resume");
await clickElement(dbg, "resume");
executed = await pausedExecution;
ok(
executed.textContent.includes("10002"),
"Text for message appeared correct"
);
ok(executed, "Text for message appeared correct");
terminateWorkerInTab(tab, WORKER_URL);
await waitForWorkerClose(workerTargetFront);

View File

@ -36,19 +36,21 @@ add_task(async function testPausedByConsole() {
);
info("Check Date objects can be used in the console");
const jsterm = await getSplitConsole(toolbox);
let executed = await jsterm.execute("new Date(2013, 3, 1)");
ok(
executed.textContent.includes("Mon Apr 01 2013 00:00:00"),
"Date object has expected text content"
const console = await getSplitConsole(toolbox);
let executed = await executeAndWaitForMessage(
console,
"new Date(2013, 3, 1)",
"Mon Apr 01 2013 00:00:00"
);
ok(executed, "Date object has expected text content");
info("Check RegExp objects can be used in the console");
executed = await jsterm.execute("new RegExp('.*')");
ok(
executed.textContent.includes("/.*/"),
"Text for message appeared correct"
executed = await executeAndWaitForMessage(
console,
"new RegExp('.*')",
"/.*/"
);
ok(executed, "Text for message appeared correct");
terminateWorkerInTab(tab, WORKER_URL);
await waitForWorkerClose(workerTargetFront);

View File

@ -139,10 +139,10 @@ async function waitForWorkerClose(workerTargetFront) {
info("Worker did close.");
}
// Return a promise with a reference to jsterm, opening the split
// Return a promise with a reference to webconsole, opening the split
// console if necessary. This cleans up the split console pref so
// it won't pollute other tests.
function getSplitConsole(toolbox, win) {
async function getSplitConsole(toolbox, win) {
if (!win) {
win = toolbox.win;
}
@ -151,12 +151,32 @@ function getSplitConsole(toolbox, win) {
EventUtils.synthesizeKey("VK_ESCAPE", {}, win);
}
await toolbox.getPanelWhenReady("webconsole");
ok(toolbox.splitConsole, "Split console is shown.");
return toolbox.getPanel("webconsole");
}
function executeAndWaitForMessage(
webconsole,
expression,
expectedTextContent,
className = "result"
) {
const { ui } = webconsole.hud;
return new Promise(resolve => {
toolbox.getPanelWhenReady("webconsole").then(() => {
ok(toolbox.splitConsole, "Split console is shown.");
const jsterm = toolbox.getPanel("webconsole").hud.jsterm;
resolve(jsterm);
});
const onNewMessages = messages => {
for (const message of messages) {
if (
message.node.classList.contains(className) &&
message.node.textContent.includes(expectedTextContent)
) {
ui.off("new-messages", onNewMessages);
resolve(message.node);
}
}
};
ui.on("new-messages", onNewMessages);
ui.wrapper.dispatchEvaluateExpression(expression);
});
}

View File

@ -210,7 +210,7 @@ class JSTerm extends Component {
return this.acceptProposedCompletion();
}
this.execute();
this._execute();
return null;
};
@ -243,7 +243,7 @@ class JSTerm extends Component {
}
if (!this.props.editorMode) {
this.execute();
this._execute();
return null;
}
return "CodeMirror.Pass";
@ -581,14 +581,9 @@ class JSTerm extends Component {
/**
* 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()|.
*/
execute(executeString) {
// attempt to execute the content of the inputNode
executeString = executeString || this._getValue();
_execute() {
const executeString = this._getValue();
if (!executeString) {
return;
}
@ -597,7 +592,6 @@ class JSTerm extends Component {
this._setValue("");
}
this.clearCompletion();
this.props.evaluateExpression(executeString);
}
@ -839,7 +833,7 @@ class JSTerm extends Component {
if (this.hasAutocompletionSuggestion()) {
this.acceptProposedCompletion();
} else if (this.props.editorMode) {
this.execute();
this._execute();
}
event.preventDefault();
}
@ -852,7 +846,7 @@ class JSTerm extends Component {
if (this.hasAutocompletionSuggestion()) {
this.acceptProposedCompletion();
} else if (this.props.editorMode) {
this.execute();
this._execute();
}
event.preventDefault();
}
@ -888,7 +882,7 @@ class JSTerm extends Component {
if (this.hasAutocompletionSuggestion()) {
this.acceptProposedCompletion();
} else if (!props.editorMode) {
this.execute();
this._execute();
} else {
this.insertStringAtCursor("\n");
}
@ -1223,7 +1217,6 @@ class JSTerm extends Component {
} else if (items.length < minimumAutoCompleteLength && popup.isOpen) {
popup.hidePopup();
}
this.emit("autocomplete-updated");
}
@ -1275,8 +1268,8 @@ class JSTerm extends Component {
});
this.autocompletePopup.hidePopup();
}
this.emit("autocomplete-updated");
}
this.emit("autocomplete-updated");
}
/**

View File

@ -77,10 +77,11 @@ async function testMessages(hud) {
});
// Test eval.
hud.jsterm.execute("document.location.href");
execute(hud, "document.location.href");
// Test eval frame script
hud.jsterm.execute(
execute(
hud,
`gBrowser.selectedBrowser.messageManager.loadFrameScript(` +
`'data:application/javascript,console.log("framescript-message")', false);` +
`"framescript-eval";`

View File

@ -12,17 +12,20 @@ add_task(async function() {
const hud = await HUDService.toggleBrowserConsole();
await hud.ui.clearOutput();
await openNewTabAndConsole(
`data:text/html,<script>console.log("hello from content")</script>`
);
const expectedMessages = [
`Cu.reportError`, // bug 1561930
];
const jsterm = hud.jsterm;
await jsterm.execute(`Cu.reportError("Cu.reportError");`); // bug 1561930
execute(hud, `Cu.reportError("Cu.reportError");`); // bug 1561930
info("Wait for expected message are shown on browser console");
await waitFor(() =>
expectedMessages.every(expectedMessage => findMessage(hud, expectedMessage))
);
await waitFor(() => findMessage(hud, "hello from content"));
ok(true, "Expected messages are displayed in the browser console");
@ -31,14 +34,13 @@ add_task(async function() {
".webconsole-filterbar-primary .filter-checkbox"
);
checkbox.click();
// Wait one second for hiding the content message
await jsterm.execute(`await new Promise(res => setTimeout(res, 1000));`);
await waitFor(() => !findMessage(hud, "hello from content"));
info("Check the expected messages are still visiable in the browser console");
for (const expectedMessage of expectedMessages) {
ok(
findMessage(hud, expectedMessage),
`"${expectedMessage}" should be still visiable`
`"${expectedMessage}" should be still visible`
);
}
});

View File

@ -18,25 +18,23 @@ add_task(async function() {
const hud = await HUDService.toggleBrowserConsole();
ok(hud, "browser console opened");
const jsterm = hud.jsterm;
// Add the reference to the nuked sandbox.
await jsterm.execute(
"window.nukedSandbox = Cu.Sandbox(null);" + "Cu.nukeSandbox(nukedSandbox);"
execute(
hud,
"window.nukedSandbox = Cu.Sandbox(null); Cu.nukeSandbox(nukedSandbox);"
);
await jsterm.execute("nukedSandbox");
await waitFor(() => findMessage(hud, "DeadObject", ".objectTitle"));
jsterm.execute("nukedSandbox.hello");
const msg = await waitFor(() => findMessage(hud, "can't access dead object"));
await executeAndWaitForMessage(hud, "nukedSandbox", "DeadObject");
const msg = await executeAndWaitForMessage(
hud,
"nukedSandbox.hello",
"can't access dead object"
);
// Check that the link contains an anchor. We can't click on the link because
// clicking links from tests attempts to access an external URL and crashes
// Firefox.
const anchor = msg.querySelector("a");
// clicking links from tests attempts to access an external URL and crashes Firefox.
const anchor = msg.node.querySelector("a");
is(anchor.textContent, "[Learn More]", "Link text is correct");
await jsterm.execute("delete window.nukedSandbox; 2013-26");
await waitFor(() => findMessage(hud, "1987"));
await executeAndWaitForMessage(hud, "delete window.nukedSandbox; 1 + 1", "2");
});

View File

@ -22,7 +22,6 @@ add_task(async function() {
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
const { jsterm } = hud;
ok(!getInputValue(hud), "console input is empty");
checkInputCursorPosition(hud, 0, "Cursor is at expected position");
@ -33,7 +32,8 @@ async function performTests() {
EventUtils.synthesizeKey("KEY_ArrowDown");
is(getInputValue(hud), '"first item"', "null test history down");
await jsterm.execute();
EventUtils.synthesizeKey("KEY_Enter");
await waitFor(() => findMessage(hud, "first item", ".result"));
is(getInputValue(hud), "", "cleared input line after submit");
setInputValue(hud, '"editing input 1"');
@ -47,7 +47,9 @@ async function performTests() {
);
setInputValue(hud, '"second item"');
await jsterm.execute();
EventUtils.synthesizeKey("KEY_Enter");
await waitFor(() => findMessage(hud, "second item", ".result"));
setInputValue(hud, '"editing input 2"');
EventUtils.synthesizeKey("KEY_ArrowUp");
is(getInputValue(hud), '"second item"', "test history up");
@ -65,8 +67,14 @@ async function performTests() {
// Appending the same value again should not impact the history.
// Let's also use some spaces around to check that the input value
// is properly trimmed.
await jsterm.execute('"second item"');
await jsterm.execute(' "second item" ');
setInputValue(hud, '"second item"');
EventUtils.synthesizeKey("KEY_Enter");
await waitFor(() => findMessage(hud, "second item", ".result"));
setInputValue(hud, '"second item" ');
EventUtils.synthesizeKey("KEY_Enter");
await waitFor(() => findMessage(hud, "second item", ".result"));
EventUtils.synthesizeKey("KEY_ArrowUp");
is(
getInputValue(hud),

View File

@ -7,7 +7,7 @@
// Test that properties starting with underscores or dollars can be
// autocompleted (bug 967468).
const TEST_URI = "data:text/html;charset=utf8,test autocompletion with $ or _";
const TEST_URI = `data:text/html;charset=utf8,test autocompletion with $ or _`;
add_task(async function() {
// Run test with legacy JsTerm
@ -20,9 +20,8 @@ add_task(async function() {
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
const { jsterm } = hud;
await jsterm.execute("var testObject = {$$aaab: '', $$aaac: ''}");
execute(hud, "var testObject = {$$aaab: '', $$aaac: ''}");
// Should work with bug 967468.
await testAutocomplete(hud, "Object.__d");
@ -33,7 +32,7 @@ async function performTests() {
await testAutocomplete(hud, "testObject.$$aa");
// Should work with bug 1207868.
await jsterm.execute("let foobar = {a: ''}; const blargh = {a: 1};");
execute(hud, "let foobar = {a: ''}; const blargh = {a: 1};");
await testAutocomplete(hud, "foobar");
await testAutocomplete(hud, "blargh");
await testAutocomplete(hud, "foobar.a");

View File

@ -112,12 +112,15 @@ async function performTests() {
);
info("Ensure filtering from the cache does work");
await jsterm.execute(`
execute(
hud,
`
window.testObject = Object.create(null);
window.testObject.zz = "zz";
window.testObject.zzz = "zzz";
window.testObject.zzzz = "zzzz";
`);
`
);
await jstermComplete("window.testObject.");
await jstermComplete("window.testObject.z");
is(

View File

@ -45,7 +45,9 @@ async function performTests() {
"completion node has expected :screenshot value"
);
onAutocompleUpdated = jsterm.once("autocomplete-updated");
EventUtils.synthesizeKey("KEY_Tab");
await onAutocompleUpdated;
is(
getInputValue(hud),
":screenshot",
@ -55,7 +57,7 @@ async function performTests() {
ok(!autocompletePopup.isOpen, "popup is closed after Tab");
info("Test :hel completion");
setInputValue(hud, ":he");
await setInputValue(hud, ":he");
onAutocompleUpdated = jsterm.once("autocomplete-updated");
EventUtils.sendString("l");

View File

@ -21,11 +21,13 @@ add_task(async function() {
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
const { jsterm } = hud;
const onParentTitle = waitForMessage(hud, "iframe parent");
jsterm.execute("document.title");
await onParentTitle;
await executeAndWaitForMessage(
hud,
"document.title",
"iframe parent",
".result"
);
ok(true, "root document's title is accessible");
// Make sure we don't throw when trying to autocomplete
@ -43,8 +45,11 @@ async function performTests() {
"A message error is shown when trying to inspect window[0]"
);
const onParentLocation = waitForMessage(hud, "test-iframe-parent.html");
hud.jsterm.execute("window.location");
await onParentLocation;
await executeAndWaitForMessage(
hud,
"window.location",
"test-iframe-parent.html",
".result"
);
ok(true, "root document's location is accessible");
}

View File

@ -24,21 +24,29 @@ async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
info("Check that declaring a let variable does not create a global property");
await hud.jsterm.execute(
`let bazA = await new Promise(r => setTimeout(() => r("local-bazA"), 10))`
await executeAndWaitForMessage(
hud,
`let bazA = await new Promise(r => setTimeout(() => r("local-bazA"), 10))`,
"local-bazA",
".result"
);
await checkVariable(hud, "bazA");
info(
"Check that declaring a const variable does not create a global property"
);
await hud.jsterm.execute(
`const bazB = await new Promise(r => setTimeout(() => r("local-bazB"), 10))`
await executeAndWaitForMessage(
hud,
`const bazB = await new Promise(r => setTimeout(() => r("local-bazB"), 10))`,
"local-bazB",
".result"
);
await checkVariable(hud, "bazB");
info("Check that complex variable declarations work as expected");
await hud.jsterm.execute(`
await executeAndWaitForMessage(
hud,
`
let bazC = "local-bazC", bazD, bazE = "local-bazE";
bazD = await new Promise(r => setTimeout(() => r("local-bazD"), 10));
let {
@ -59,7 +67,10 @@ async function performTests() {
e: ["local-bazI"]
}
}
});`);
});`,
"",
".result"
);
await checkVariable(hud, "bazC");
await checkVariable(hud, "bazD");
await checkVariable(hud, "bazE");
@ -72,8 +83,13 @@ async function performTests() {
}
async function checkVariable(hud, varName) {
await executeAndWaitForMessage(hud, `window.${varName}`, `undefined`);
await executeAndWaitForMessage(
hud,
`window.${varName}`,
`undefined`,
".result"
);
ok(true, `The ${varName} assignment did not create a global variable`);
await executeAndWaitForMessage(hud, varName, `"local-${varName}"`);
await executeAndWaitForMessage(hud, varName, `"local-${varName}"`, ".result");
ok(true, `"${varName}" has the expected value`);
}

View File

@ -22,7 +22,6 @@ add_task(async function() {
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
const { jsterm } = hud;
hud.ui.clearOutput();
const delays = [3000, 500, 9000, 6000];
@ -38,7 +37,7 @@ async function performTests() {
".message.result"
);
for (const input of inputs) {
jsterm.execute(input);
execute(hud, input);
}
await onMessage;

View File

@ -22,7 +22,6 @@ add_task(async function() {
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
const { jsterm } = hud;
const executeAndWaitForResultMessage = (input, expectedOutput) =>
executeAndWaitForMessage(hud, input, expectedOutput, ".result");
@ -79,7 +78,7 @@ async function performTests() {
".message.result"
);
for (const input of inputs) {
jsterm.execute(input);
execute(hud, input);
}
await onMessage;

View File

@ -23,7 +23,6 @@ async function performTests() {
// Force the split console to be closed.
await pushPref("devtools.toolbox.splitconsoleEnabled", false);
const hud = await openNewTabAndConsole(TEST_URI);
const { jsterm } = hud;
const pauseExpression = `(() => {
var foo = ["bar"];
@ -31,7 +30,7 @@ async function performTests() {
debugger;
return "pauseExpression-res";
})()`;
jsterm.execute(pauseExpression);
execute(hud, pauseExpression);
// wait for the debugger to be opened and paused.
const target = await TargetFactory.forTab(gBrowser.selectedTab);
@ -52,11 +51,11 @@ async function performTests() {
`[ "res", "bar" ]`,
".message.result"
);
jsterm.execute(awaitExpression);
execute(hud, awaitExpression);
// We send an evaluation just after the await one to ensure the await evaluation was
// done. We can't await on the previous execution because it waits for the result to
// be send, which won't happen until we resume the debugger.
await jsterm.execute(`"smoke"`);
await executeAndWaitForMessage(hud, `"smoke"`, `"smoke"`, ".result");
// Give the engine some time to evaluate the await expression before resuming.
await waitForTick();

View File

@ -90,7 +90,8 @@ async function performTests() {
checkInputCompletionValue(hud, " ment", "'docu' completion");
let onAutocompletUpdated = jsterm.once("autocomplete-updated");
await jsterm.execute();
EventUtils.synthesizeKey("KEY_Enter");
await onAutocompletUpdated;
checkInputCompletionValue(hud, "", "clear completion on execute()");
// Test multi-line completion works. We can't use setInputValueForAutocompletion because

View File

@ -32,10 +32,14 @@ async function performTests() {
is(autocompletePopup.isOpen, false, "autocomplete popup is not open");
info("Populate $_ by executing a command");
await jsterm.execute(`Object.create(null, Object.getOwnPropertyDescriptors({
await executeAndWaitForMessage(
hud,
`Object.create(null, Object.getOwnPropertyDescriptors({
x: 1,
y: "hello"
}))`);
}))`,
`Object { x: 1, y: "hello" }`
);
await setInputValueForAutocompletion(hud, "$_.");
checkInputCompletionValue(hud, " x", "'$_.' completion (completeNode)");

View File

@ -38,14 +38,14 @@ add_task(async function() {
});
async function performTests() {
const { jsterm } = await openNewTabAndConsole(TEST_URI);
const hud = await openNewTabAndConsole(TEST_URI);
const random = Math.random();
const string = "Text: " + random;
const obj = { a: 1, b: "foo", c: random };
await testCopy(jsterm, random, random.toString());
await testCopy(jsterm, JSON.stringify(string), string);
await testCopy(jsterm, obj.toSource(), JSON.stringify(obj, null, " "));
await testCopy(hud, random, random.toString());
await testCopy(hud, JSON.stringify(string), string);
await testCopy(hud, obj.toSource(), JSON.stringify(obj, null, " "));
const outerHTML = await ContentTask.spawn(
gBrowser.selectedBrowser,
@ -54,14 +54,14 @@ async function performTests() {
return content.document.getElementById(elementId).outerHTML;
}
);
await testCopy(jsterm, `$("#${id}")`, outerHTML);
await testCopy(hud, `$("#${id}")`, outerHTML);
}
function testCopy(jsterm, stringToCopy, expectedResult) {
function testCopy(hud, stringToCopy, expectedResult) {
return waitForClipboardPromise(() => {
info(`Attempting to copy: "${stringToCopy}"`);
const command = `copy(${stringToCopy})`;
info(`Executing command: "${command}"`);
jsterm.execute(command);
execute(hud, command);
}, expectedResult);
}

View File

@ -242,8 +242,10 @@ async function testNavWithHistory(hud) {
// submit to history
for (const value of values) {
const onResult = waitForMessage(hud, "", ".result");
setInputValue(hud, value);
await hud.jsterm.execute();
EventUtils.synthesizeKey("KEY_Enter");
await onResult;
}
checkInput("|", "caret location at start of empty line");

View File

@ -16,11 +16,13 @@ add_task(async function() {
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
const { jsterm } = hud;
// check for occurrences of Object XRayWrapper, bug 604430
const onMessage = waitForMessage(hud, "HTMLDocument");
jsterm.execute("document");
const { node } = await onMessage;
const { node } = await executeAndWaitForMessage(
hud,
"document",
"HTMLDocument",
".result"
);
is(node.textContent.includes("xray"), false, "document - no XrayWrapper");
}

View File

@ -23,10 +23,9 @@ add_task(async function() {
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
const { jsterm } = hud;
const expression = `x = 10`;
setInputValue(hud, expression);
await jsterm.execute();
await executeAndWaitForMessage(hud, undefined, "", ".result");
is(getInputValue(hud), expression, "input line is not cleared after submit");
}

View File

@ -16,7 +16,6 @@ add_task(async function() {
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
const { jsterm } = hud;
// Check that errors with entries in errordocs.js display links next to their messages.
const ErrorDocs = require("devtools/server/actors/errordocs");
@ -35,9 +34,11 @@ async function performTests() {
const title = errorUrl.split("?")[0];
hud.ui.clearOutput();
const onMessage = waitForMessage(hud, "RangeError:");
jsterm.execute(expression);
const { node } = await onMessage;
const { node } = await executeAndWaitForMessage(
hud,
expression,
"RangeError:"
);
const learnMoreLink = node.querySelector(".learn-more-link");
ok(
learnMoreLink,

View File

@ -19,14 +19,16 @@ add_task(async function() {
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
const { jsterm } = hud;
const text =
"TypeError: 'redirect' member of RequestInit 'foo' is not a valid value " +
"for enumeration RequestRedirect";
const onErrorMessage = waitForMessage(hud, text, ".message.error");
jsterm.execute("new Request('',{redirect:'foo'})");
await onErrorMessage;
await executeAndWaitForMessage(
hud,
"new Request('',{redirect:'foo'})",
text,
".message.error"
);
ok(
true,
"Error message displayed as expected, without crashing the console."

View File

@ -26,7 +26,7 @@ async function performTests() {
const onCleared = waitFor(
() => hud.ui.outputNode.querySelector(".message") === null
);
hud.jsterm.execute("clear()");
execute(hud, "clear()");
await onCleared;
ok(true, "Console was cleared");
}

View File

@ -26,25 +26,31 @@ add_task(async function() {
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
const jsterm = hud.jsterm;
let onMessage = waitForMessage(hud, "<main>");
jsterm.execute("$('main')");
let message = await onMessage;
let message = await executeAndWaitForMessage(
hud,
"$('main')",
"<main>",
".result"
);
ok(message, "`$('main')` worked");
onMessage = waitForMessage(hud, "<li>");
jsterm.execute("$('main > ul > li')");
message = await onMessage;
message = await executeAndWaitForMessage(
hud,
"$('main > ul > li')",
"<li>",
".result"
);
ok(message, "`$('main > ul > li')` worked");
onMessage = waitForMessage(hud, "LI");
jsterm.execute("$('main > ul > li').tagName");
message = await onMessage;
message = await executeAndWaitForMessage(
hud,
"$('main > ul > li').tagName",
"LI",
".result"
);
ok(message, "`$` result can be used right away");
onMessage = waitForMessage(hud, "null");
jsterm.execute("$('div')");
message = await onMessage;
message = await executeAndWaitForMessage(hud, "$('div')", "null", ".result");
ok(message, "`$('div')` does return null");
}

View File

@ -26,25 +26,36 @@ add_task(async function() {
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
const jsterm = hud.jsterm;
let onMessage = waitForMessage(hud, "Array [ main ]");
jsterm.execute("$$('main')");
let message = await onMessage;
let message = await executeAndWaitForMessage(
hud,
"$$('main')",
"Array [ main ]",
".result"
);
ok(message, "`$$('main')` worked");
onMessage = waitForMessage(hud, "Array [ li, li ]");
jsterm.execute("$$('main > ul > li')");
message = await onMessage;
message = await executeAndWaitForMessage(
hud,
"$$('main > ul > li')",
"Array [ li, li ]",
".result"
);
ok(message, "`$$('main > ul > li')` worked");
onMessage = waitForMessage(hud, "LI - LI");
jsterm.execute("$$('main > ul > li').map(el => el.tagName).join(' - ')");
message = await onMessage;
message = await executeAndWaitForMessage(
hud,
"$$('main > ul > li').map(el => el.tagName).join(' - ')",
"LI - LI",
".result"
);
ok(message, "`$$` result can be used right away");
onMessage = waitForMessage(hud, "Array []");
jsterm.execute("$$('div')");
message = await onMessage;
message = await executeAndWaitForMessage(
hud,
"$$('div')",
"Array []",
".result"
);
ok(message, "`$$('div')` returns an empty array");
}

View File

@ -26,84 +26,91 @@ add_task(async function() {
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
const jsterm = hud.jsterm;
let onMessage = waitForMessage(hud, "Array [ li, li ]");
jsterm.execute("$x('.//li')");
let message = await onMessage;
let message = await executeAndWaitForMessage(
hud,
"$x('.//li')",
"Array [ li, li ]"
);
ok(message, "`$x` worked");
onMessage = waitForMessage(hud, "<li>");
jsterm.execute("$x('.//li', document.body)[0]");
message = await onMessage;
message = await executeAndWaitForMessage(
hud,
"$x('.//li', document.body)[0]",
"<li>"
);
ok(message, "`$x()` result can be used right away");
onMessage = waitForMessage(hud, "2");
jsterm.execute("$x('count(.//li)', document.body, XPathResult.NUMBER_TYPE)");
message = await onMessage;
message = await executeAndWaitForMessage(
hud,
"$x('count(.//li)', document.body, XPathResult.NUMBER_TYPE)",
"2"
);
ok(message, "$x works as expected with XPathResult.NUMBER_TYPE");
onMessage = waitForMessage(hud, "First");
jsterm.execute("$x('.//li', document.body, XPathResult.STRING_TYPE)");
message = await onMessage;
message = await executeAndWaitForMessage(
hud,
"$x('.//li', document.body, XPathResult.STRING_TYPE)",
"First"
);
ok(message, "$x works as expected with XPathResult.STRING_TYPE");
onMessage = waitForMessage(hud, "true");
jsterm.execute(
"$x('//li[not(@foo)]', document.body, XPathResult.BOOLEAN_TYPE)"
message = await executeAndWaitForMessage(
hud,
"$x('//li[not(@foo)]', document.body, XPathResult.BOOLEAN_TYPE)",
"true"
);
message = await onMessage;
ok(message, "$x works as expected with XPathResult.BOOLEAN_TYPE");
onMessage = waitForMessage(hud, "Array [ li, li ]");
jsterm.execute(
"$x('.//li', document.body, XPathResult.UNORDERED_NODE_ITERATOR_TYPE)"
message = await executeAndWaitForMessage(
hud,
"$x('.//li', document.body, XPathResult.UNORDERED_NODE_ITERATOR_TYPE)",
"Array [ li, li ]"
);
message = await onMessage;
ok(
message,
"$x works as expected with XPathResult.UNORDERED_NODE_ITERATOR_TYPE"
);
onMessage = waitForMessage(hud, "Array [ li, li ]");
jsterm.execute(
"$x('.//li', document.body, XPathResult.ORDERED_NODE_ITERATOR_TYPE)"
message = await executeAndWaitForMessage(
hud,
"$x('.//li', document.body, XPathResult.ORDERED_NODE_ITERATOR_TYPE)",
"Array [ li, li ]"
);
message = await onMessage;
ok(
message,
"$x works as expected with XPathResult.ORDERED_NODE_ITERATOR_TYPE"
);
onMessage = waitForMessage(hud, "<li>");
jsterm.execute(
"$x('.//li', document.body, XPathResult.ANY_UNORDERED_NODE_TYPE)"
message = await executeAndWaitForMessage(
hud,
"$x('.//li', document.body, XPathResult.ANY_UNORDERED_NODE_TYPE)",
"<li>"
);
message = await onMessage;
ok(message, "$x works as expected with XPathResult.ANY_UNORDERED_NODE_TYPE");
onMessage = waitForMessage(hud, "<li>");
jsterm.execute(
"$x('.//li', document.body, XPathResult.FIRST_ORDERED_NODE_TYPE)"
message = await executeAndWaitForMessage(
hud,
"$x('.//li', document.body, XPathResult.FIRST_ORDERED_NODE_TYPE)",
"<li>"
);
message = await onMessage;
ok(message, "$x works as expected with XPathResult.FIRST_ORDERED_NODE_TYPE");
onMessage = waitForMessage(hud, "Array [ li, li ]");
jsterm.execute(
"$x('.//li', document.body, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE)"
message = await executeAndWaitForMessage(
hud,
"$x('.//li', document.body, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE)",
"Array [ li, li ]"
);
message = await onMessage;
ok(
message,
"$x works as expected with XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE"
);
onMessage = waitForMessage(hud, "Array [ li, li ]");
jsterm.execute(
"$x('.//li', document.body, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE)"
message = await executeAndWaitForMessage(
hud,
"$x('.//li', document.body, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE)",
"Array [ li, li ]"
);
message = await onMessage;
ok(
message,
"$x works as expected with XPathResult.ORDERED_NODE_SNAPSHOT_TYPE"

View File

@ -17,7 +17,6 @@ add_task(async function() {
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
const jsterm = hud.jsterm;
let openedLinks = 0;
const oldOpenLink = hud.openLink;
@ -28,15 +27,22 @@ async function performTests() {
};
hud.ui.clearOutput();
await jsterm.execute("help()");
await jsterm.execute("help");
await jsterm.execute("?");
execute(hud, "help()");
execute(hud, "help");
execute(hud, "?");
// Wait for a simple message to be displayed so we know the different help commands
// were processed.
await executeAndWaitForMessage(hud, "smoke", "", ".result");
const messages = Array.from(hud.ui.outputNode.querySelectorAll(".message"));
ok(
messages.every(msg => msg.classList.contains("command")),
const messages = hud.ui.outputNode.querySelectorAll(".message");
is(messages.length, 5, "There is the expected number of messages");
const resultMessages = hud.ui.outputNode.querySelectorAll(".result");
is(
resultMessages.length,
1,
"There is no results shown for the help commands"
);
is(openedLinks, 3, "correct number of pages opened by the help calls");
hud.openLink = oldOpenLink;
}

View File

@ -17,20 +17,28 @@ add_task(async function() {
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
const jsterm = hud.jsterm;
let onMessage = waitForMessage(hud, `Array [ "a", "b" ]`);
jsterm.execute("keys({a: 2, b:1})");
let message = await onMessage;
let message = await executeAndWaitForMessage(
hud,
"keys({a: 2, b:1})",
`Array [ "a", "b" ]`,
".result"
);
ok(message, "`keys()` worked");
onMessage = waitForMessage(hud, "Array [ 2, 1 ]");
jsterm.execute("values({a: 2, b:1})");
message = await onMessage;
message = await executeAndWaitForMessage(
hud,
"values({a: 2, b:1})",
"Array [ 2, 1 ]",
".result"
);
ok(message, "`values()` worked");
onMessage = waitForMessage(hud, "Array");
jsterm.execute("keys(window)");
message = await onMessage;
message = await executeAndWaitForMessage(
hud,
"keys(window)",
"Array",
".result"
);
ok(message, "`keys(window)` worked");
}

View File

@ -16,28 +16,39 @@ add_task(async function() {
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
const { jsterm } = hud;
let onMessage = waitForMessage(hud, `" b: 2\n a: 1"`);
jsterm.execute("pprint({b:2, a:1})");
let message = await onMessage;
let message = await executeAndWaitForMessage(
hud,
"pprint({b:2, a:1})",
`" b: 2\n a: 1"`,
".result"
);
ok(message, "`pprint()` worked");
// check that pprint(window) does not throw (see Bug 608358).
onMessage = waitForMessage(hud, `window:`);
jsterm.execute("pprint(window)");
message = await onMessage;
message = await executeAndWaitForMessage(
hud,
"pprint(window)",
`window:`,
".result"
);
ok(message, "`pprint(window)` worked");
// check that calling pprint with a string does not throw (See Bug 614561).
onMessage = waitForMessage(hud, `" 0: \\"h\\"\n 1: \\"i\\""`);
jsterm.execute("pprint('hi')");
message = await onMessage;
message = await executeAndWaitForMessage(
hud,
"pprint('hi')",
`" 0: \\"h\\"\n 1: \\"i\\""`,
".result"
);
ok(message, "`pprint('hi')` worked");
// check that pprint(function) shows function source (See Bug 618344).
onMessage = waitForMessage(hud, `"function() { var someCanaryValue = 42; }`);
jsterm.execute("pprint(function() { var someCanaryValue = 42; })");
message = await onMessage;
message = await executeAndWaitForMessage(
hud,
"pprint(function() { var someCanaryValue = 42; })",
`"function() { var someCanaryValue = 42; }`,
".result"
);
ok(message, "`pprint(function)` shows function source");
}

View File

@ -71,11 +71,13 @@ async function performTests() {
}
async function logObject(hud) {
const { jsterm } = hud;
const prop = "browser_console_hide_jsterm_test";
const onMessage = waitForMessage(hud, prop, ".result");
jsterm.execute(`new Object({ ${prop}: true })`);
const { node } = await onMessage;
const { node } = await executeAndWaitForMessage(
hud,
`new Object({ ${prop}: true })`,
prop,
".result"
);
return node.querySelector(".tree");
}

View File

@ -25,7 +25,7 @@ async function testHistory() {
for (const command of COMMANDS) {
info(`Executing command ${command}`);
await jsterm.execute(command);
await executeAndWaitForMessage(hud, command, "", ".result");
}
for (let x = COMMANDS.length - 1; x != -1; x--) {

View File

@ -40,8 +40,7 @@ async function performTests() {
info("Execute each test value in the console");
for (const value of TEST_VALUES) {
setInputValue(hud, value);
await jsterm.execute();
await executeAndWaitForMessage(hud, value, "", ".result");
}
EventUtils.synthesizeKey("KEY_ArrowUp");

View File

@ -33,15 +33,25 @@ async function testHistory() {
};
popup.on("popup-opened", onShown);
await jsterm.execute(`window.foobarBug660806 = {
await executeAndWaitForMessage(
hud,
`window.foobarBug660806 = {
'location': 'value0',
'locationbar': 'value1'
}`);
}`,
"",
".result"
);
ok(!popup.isOpen, "popup is not open");
// Let's add this expression in the input history. We don't use setInputValue since
// it _does_ trigger an autocompletion request in codeMirror JsTerm.
await jsterm.execute("window.foobarBug660806.location");
await executeAndWaitForMessage(
hud,
"window.foobarBug660806.location",
"",
".result"
);
const onSetInputValue = jsterm.once("set-input-value");
EventUtils.synthesizeKey("KEY_ArrowUp");

View File

@ -89,7 +89,12 @@ async function testHistory() {
// Set input value separately from execute so UP arrow accurately navigates
// history.
setInputValue(hud3, '"hello from third tab"');
await hud3.jsterm.execute();
await executeAndWaitForMessage(
hud3,
'"hello from third tab"',
'"hello from third tab"',
".result"
);
state1 = hud1.ui.wrapper.getStore().getState();
is(
@ -153,12 +158,9 @@ async function testHistory() {
* [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
*/
async function populateInputHistory(hud) {
const jsterm = hud.jsterm;
for (let i = 0; i < INPUT_HISTORY_COUNT; i++) {
// Set input value separately from execute so UP arrow accurately navigates history.
setInputValue(hud, i.toString());
await jsterm.execute();
const input = i.toString();
await executeAndWaitForMessage(hud, input, input, ".result");
}
}

View File

@ -21,12 +21,10 @@ add_task(async function() {
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
const jsterm = hud.jsterm;
info("Test `inspect(window)`");
// Add a global value so we can check it later.
await jsterm.execute("testProp = 'testValue'");
await jsterm.execute("inspect(window)");
execute(hud, "testProp = 'testValue'");
execute(hud, "inspect(window)");
const inspectWindowNode = await waitFor(() =>
findInspectResultMessage(hud.ui.outputNode, 1)
@ -71,7 +69,7 @@ async function performTests() {
/* Check that a primitive value can be inspected, too */
info("Test `inspect(1)`");
await jsterm.execute("inspect(1)");
execute(hud, "inspect(1)");
const inspectPrimitiveNode = await waitFor(() =>
findInspectResultMessage(hud.ui.outputNode, 2)

View File

@ -17,20 +17,28 @@ add_task(async function() {
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
const { jsterm } = hud;
let onMessage = waitForMessage(hud, "true");
jsterm.execute("[] instanceof Array");
let message = await onMessage;
let message = await executeAndWaitForMessage(
hud,
"[] instanceof Array",
"true",
".result"
);
ok(message, "`instanceof Array` is correct");
onMessage = waitForMessage(hud, "true");
jsterm.execute("({}) instanceof Object");
message = await onMessage;
message = await executeAndWaitForMessage(
hud,
"({}) instanceof Object",
"true",
".result"
);
ok(message, "`instanceof Object` is correct");
onMessage = waitForMessage(hud, "false");
jsterm.execute("({}) instanceof Array");
message = await onMessage;
message = await executeAndWaitForMessage(
hud,
"({}) instanceof Array",
"false",
".result"
);
ok(message, "`instanceof Array` has expected result");
}

View File

@ -94,7 +94,6 @@ async function performTests() {
ok(!snapshot.parent, "No events have been logged for the main process");
const hud = await openNewTabAndConsole(TEST_URI);
const { jsterm } = hud;
for (const { input, shiftKey } of SHOULD_ENTER_MULTILINE) {
setInputValue(hud, input);
@ -114,7 +113,12 @@ async function performTests() {
is(getInputValue(hud), "", "Input is cleared");
}
await jsterm.execute("document.\nlocation.\nhref");
await executeAndWaitForMessage(
hud,
"document.\nlocation.\nhref",
TEST_URI,
".result"
);
checkEventTelemetry();
}

View File

@ -16,22 +16,16 @@ add_task(async function() {
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
const jsterm = hud.jsterm;
// Check that an evaluated null produces "null". See Bug 650780.
let onMessage = waitForMessages({
hud,
messages: [{ text: "null" }, { text: "null" }],
});
jsterm.execute("null");
let message = await onMessage;
let message = await executeAndWaitForMessage(hud, "null", "null", ".result");
ok(message, "`null` returned the expected value");
onMessage = waitForMessages({
message = await executeAndWaitForMessage(
hud,
messages: [{ text: "undefined" }, { text: "undefined" }],
});
jsterm.execute("undefined");
message = await onMessage;
"undefined",
"undefined",
".result"
);
ok(message, "`undefined` returned the expected value");
}

View File

@ -37,9 +37,7 @@ async function performTests() {
async function testClipboard(hud) {
const command = `:screenshot --clipboard ${dpr}`;
const onMessage = waitForMessage(hud, "Screenshot copied to clipboard.");
hud.jsterm.execute(command);
await onMessage;
await executeScreenshotClipboardCommand(hud, command);
const contentSize = await getContentSize();
const imgSize = await getImageSizeFromClipboard();
@ -57,9 +55,7 @@ async function testClipboard(hud) {
async function testFullpageClipboard(hud) {
const command = `:screenshot --fullpage --clipboard ${dpr}`;
const onMessage = waitForMessage(hud, "Screenshot copied to clipboard.");
hud.jsterm.execute(command);
await onMessage;
await executeScreenshotClipboardCommand(hud, command);
const contentSize = await getContentSize();
const imgSize = await getImageSizeFromClipboard();
@ -77,12 +73,8 @@ async function testFullpageClipboard(hud) {
async function testSelectorClipboard(hud) {
const command = `:screenshot --selector "img#testImage" --clipboard ${dpr}`;
const messageReceived = waitForMessage(
hud,
"Screenshot copied to clipboard."
);
hud.jsterm.execute(command);
await messageReceived;
await executeScreenshotClipboardCommand(hud, command);
const imgSize1 = await getImageSizeFromClipboard();
await ContentTask.spawn(gBrowser.selectedBrowser, imgSize1, function(
imgSize
@ -103,9 +95,7 @@ async function testSelectorClipboard(hud) {
async function testFullpageClipboardScrollbar(hud) {
const command = `:screenshot --fullpage --clipboard ${dpr}`;
const onMessage = waitForMessage(hud, "Screenshot copied to clipboard.");
hud.jsterm.execute(command);
await onMessage;
await executeScreenshotClipboardCommand(hud, command);
const contentSize = await getContentSize();
const scrollbarSize = await getScrollbarSize();
const imgSize = await getImageSizeFromClipboard();
@ -128,6 +118,21 @@ async function testFullpageClipboardScrollbar(hud) {
);
}
/**
* Executes the command string and returns a Promise that resolves when the message
* saying that the screenshot was copied to clipboard is rendered in the console.
*
* @param {WebConsole} hud
* @param {String} command
*/
function executeScreenshotClipboardCommand(hud, command) {
return executeAndWaitForMessage(
hud,
command,
"Screenshot copied to clipboard."
);
}
async function createScrollbarOverflow() {
// Trigger scrollbars by forcing document to overflow
// This only affects results on OSes with scrollbars that reduce document size

View File

@ -38,9 +38,7 @@ async function testFile(hud) {
// Test capture to file
const file = FileUtils.getFile("TmpD", ["TestScreenshotFile.png"]);
const command = `:screenshot ${file.path} ${dpr}`;
const onMessage = waitForMessage(hud, `Saved to ${file.path}`);
hud.jsterm.execute(command);
await onMessage;
await executeAndWaitForMessage(hud, command, `Saved to ${file.path}`);
ok(file.exists(), "Screenshot file exists");

View File

@ -7,7 +7,7 @@
const TEST_URI = `data:text/html,<meta charset=utf8><script>
function screenshot() {
console.log(\"user screenshot function\");
console.log("contextScreen");
}
</script>`;
@ -23,9 +23,11 @@ add_task(async function() {
async function testCommand(hud) {
const command = `:screenshot --clipboard`;
const onMessage = waitForMessage(hud, "Screenshot copied to clipboard.");
hud.jsterm.execute(command);
await onMessage;
await executeAndWaitForMessage(
hud,
command,
"Screenshot copied to clipboard."
);
ok(true, ":screenshot was executed as expected");
}
@ -33,9 +35,7 @@ async function testCommand(hud) {
// command should not overwrite the screenshot function
async function testUserScreenshotFunction(hud) {
const command = `screenshot()`;
const onMessage = waitForMessage(hud, "user screenshot function");
hud.jsterm.execute(command);
await onMessage;
await executeAndWaitForMessage(hud, command, "contextScreen");
ok(
true,
"content screenshot function is not overidden and was executed as expected"

View File

@ -29,7 +29,7 @@ add_task(async function() {
async function performTest() {
await pushPref("devtools.selfxss.count", 0);
const hud = await openNewTabAndConsole(TEST_URI);
const { jsterm, ui } = hud;
const { ui } = hud;
const { document } = ui;
info("Self-xss paste tests");
@ -38,9 +38,9 @@ async function performTest() {
// Input some commands to check if usage counting is working
for (let i = 0; i <= 3; i++) {
setInputValue(hud, i.toString());
jsterm.execute();
await executeAndWaitForMessage(hud, i.toString(), i, ".result");
}
is(WebConsoleUtils.usageCount, 4, "Usage count incremented");
WebConsoleUtils.usageCount = 0;

View File

@ -15,7 +15,6 @@ add_task(async function() {
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
const jsterm = hud.jsterm;
// Syntax highlighting is implemented with a Custom Element:
ok(
@ -26,7 +25,7 @@ async function performTests() {
// Check that we syntax highlight output to look like the inputed text.
// See Bug 1463669.
const onMessage = waitForMessage(hud, `var a = 'str';`);
jsterm.execute("var a = 'str';");
execute(hud, "var a = 'str';");
const message = await onMessage;
const highlighted = message.node.querySelectorAll("syntax-highlighted");
let expectedMarkup;

View File

@ -18,24 +18,24 @@ add_task(async function() {
await executeWindowTest(hud, "parent");
info("cd() into the iframe using a selector");
await hud.jsterm.execute(`cd("iframe")`);
execute(hud, `cd("iframe")`);
await executeWindowTest(hud, "child");
info("cd() out of the iframe, reset to default window");
await hud.jsterm.execute("cd()");
execute(hud, "cd()");
await executeWindowTest(hud, "parent");
info("cd() into the iframe using an iframe DOM element");
await hud.jsterm.execute(`cd($("iframe"))`);
execute(hud, `cd($("iframe"))`);
await executeWindowTest(hud, "child");
info("cd(window.parent)");
await hud.jsterm.execute("cd(window.parent)");
execute(hud, "cd(window.parent)");
await executeWindowTest(hud, "parent");
info("call cd() with unexpected arguments");
let onCdErrorMessage = waitForMessage(hud, "Cannot cd()");
hud.jsterm.execute("cd(document)");
execute(hud, "cd(document)");
let cdErrorMessage = await onCdErrorMessage;
ok(
cdErrorMessage.node.classList.contains("error"),
@ -43,7 +43,7 @@ add_task(async function() {
);
onCdErrorMessage = waitForMessage(hud, "Cannot cd()");
hud.jsterm.execute(`cd("p")`);
execute(hud, `cd("p")`);
cdErrorMessage = await onCdErrorMessage;
ok(
cdErrorMessage.node.classList.contains("error"),
@ -68,9 +68,9 @@ async function executeWindowTest(hud, iframeRole) {
],
});
hud.jsterm.execute(`document.title`);
hud.jsterm.execute(`"p: " + document.querySelector("p").textContent`);
hud.jsterm.execute(`"obj: " + window.foobar`);
execute(hud, `document.title`);
execute(hud, `"p: " + document.querySelector("p").textContent`);
execute(hud, `"obj: " + window.foobar`);
const messages = await onMessages;
ok(

View File

@ -15,20 +15,24 @@ const SECOND_LOG_MESSAGE = "fooBug773466b";
add_task(async function() {
const hud = await openNewTabAndConsole(TEST_URI);
const { jsterm } = hud;
info("Logging a first message to make sure everything is working");
let onLogMessage = waitForMessage(hud, FIRST_LOG_MESSAGE);
jsterm.execute(`console.log("${FIRST_LOG_MESSAGE}")`);
await onLogMessage;
await executeAndWaitForMessage(
hud,
`console.log("${FIRST_LOG_MESSAGE}")`,
FIRST_LOG_MESSAGE,
".message.log"
);
info("console.dir on an uninspectable object");
const onDirMessage = waitForMessage(hud, "Object { }");
jsterm.execute("console.dir(Object.create(null))");
await onDirMessage;
await executeAndWaitForMessage(
hud,
"console.dir(Object.create(null))",
"Object { }"
);
info("Logging a second message to make sure the console is not broken");
onLogMessage = waitForMessage(hud, SECOND_LOG_MESSAGE);
const onLogMessage = waitForMessage(hud, SECOND_LOG_MESSAGE);
// Logging from content to make sure the console API is working.
ContentTask.spawn(gBrowser.selectedBrowser, SECOND_LOG_MESSAGE, string => {
content.console.log(string);

View File

@ -11,7 +11,7 @@ add_task(async function() {
// We open the console and an empty tab, as we only want to evaluate something.
const hud = await openNewTabAndConsole(TEST_URI);
// We execute `console.timeStamp('test')` from the console input.
await hud.jsterm.execute("console.timeStamp('test')");
execute(hud, "console.timeStamp('test')");
info(`Checking size`);
await waitFor(() => findMessages(hud, "").length == 2);
const [first, second] = findMessages(hud, "").map(message =>

View File

@ -47,9 +47,12 @@ add_task(async function() {
);
// Triggering the Violation via JS
hud.ui.clearOutput();
hud.jsterm.execute("window.violate()");
msg = await waitFor(() => findMessage(hud, CSP_VIOLATION));
locationNode = msg.querySelector(".message-location");
msg = await executeAndWaitForMessage(
hud,
"window.violate()",
CSP_VIOLATION
);
locationNode = msg.node.querySelector(".message-location");
info(`EXPECT ${VIOLATION_LOCATION_JS} GOT: ${locationNode.textContent}`);
ok(
locationNode.textContent == VIOLATION_LOCATION_JS,
@ -69,9 +72,12 @@ add_task(async function() {
ok(msg, "Base-URI validation was Printed");
// Triggering the Violation via JS
hud.ui.clearOutput();
hud.jsterm.execute("window.violate()");
msg = await waitFor(() => findMessage(hud, CSP_VIOLATION));
const locationNode = msg.querySelector(".message-location");
msg = await executeAndWaitForMessage(
hud,
"window.violate()",
CSP_VIOLATION
);
const locationNode = msg.node.querySelector(".message-location");
console.log(locationNode.textContent);
ok(
locationNode.textContent == VIOLATION_LOCATION,

View File

@ -15,22 +15,25 @@ const TEST_URI =
add_task(async function() {
const hud = await openNewTabAndConsole(TEST_URI);
hud.jsterm.execute("throwErrorObject()");
execute(hud, "throwErrorObject()");
await checkMessageStack(hud, "ThrowErrorObject", [6, 1]);
hud.jsterm.execute("throwValue(40 + 2)");
execute(hud, "throwValue(40 + 2)");
await checkMessageStack(hud, "42", [14, 10, 1]);
hud.jsterm.execute(`
execute(
hud,
`
a = () => {throw "bloop"};
b = () => a();
c = () => b();
d = () => c();
d();
`);
`
);
await checkMessageStack(hud, "Error: bloop", [2, 3, 4, 5, 6]);
hud.jsterm.execute(`1 + @`);
execute(hud, `1 + @`);
const messageNode = await waitFor(() =>
findMessage(hud, "illegal character")
);

View File

@ -16,18 +16,18 @@ const TEST_URI =
add_task(async function() {
info("open the console");
const hud = await openNewTabAndConsole(TEST_URI);
const { jsterm } = hud;
info("Check `foo` value");
let onResultMessage = waitForMessage(hud, "globalFooBug783499");
jsterm.execute("foo");
await onResultMessage;
executeAndWaitForMessage(hud, "foo", "globalFooBug783499", ".result");
ok(true, "|foo| value is correct");
info("Assign and check `foo2` value");
onResultMessage = waitForMessage(hud, "newFoo");
jsterm.execute("foo2 = 'newFoo'; window.foo2");
await onResultMessage;
executeAndWaitForMessage(
hud,
"foo2 = 'newFoo'; window.foo2",
"newFoo",
".result"
);
ok(true, "'newFoo' is displayed after adding `foo2`");
info("Open the debugger and then select the console again");
@ -38,9 +38,12 @@ add_task(async function() {
await openConsole();
info("Check `foo + foo2` value");
onResultMessage = waitForMessage(hud, "globalFooBug783499newFoo");
jsterm.execute("foo + foo2");
await onResultMessage;
executeAndWaitForMessage(
hud,
"foo + foo2",
"globalFooBug783499newFoo",
".result"
);
info("Select the debugger again");
await openDebugger();
@ -52,8 +55,12 @@ add_task(async function() {
await openConsole();
info("Check `foo + foo2` value when paused");
onResultMessage = waitForMessage(hud, "globalFooBug783499foo2SecondCall");
jsterm.execute("foo + foo2");
executeAndWaitForMessage(
hud,
"foo + foo2",
"globalFooBug783499foo2SecondCall",
".result"
);
ok(true, "`foo + foo2` from `secondCall()`");
info("select the debugger and select the frame (1)");
@ -64,14 +71,20 @@ add_task(async function() {
await openConsole();
info("Check `foo + foo2 + foo3` value when paused on a given frame");
onResultMessage = waitForMessage(hud, "fooFirstCallnewFoofoo3FirstCall");
jsterm.execute("foo + foo2 + foo3");
await onResultMessage;
executeAndWaitForMessage(
hud,
"foo + foo2 + foo3",
"fooFirstCallnewFoofoo3FirstCall",
".result"
);
ok(true, "`foo + foo2 + foo3` from `firstCall()`");
onResultMessage = waitForMessage(hud, "abbabug783499");
jsterm.execute("foo = 'abba'; foo3 = 'bug783499'; foo + foo3");
await onResultMessage;
executeAndWaitForMessage(
hud,
"foo = 'abba'; foo3 = 'bug783499'; foo + foo3",
"abbabug783499",
".result"
);
ok(true, "`foo + foo3` updated in `firstCall()`");
await ContentTask.spawn(gBrowser.selectedBrowser, null, function() {

View File

@ -16,7 +16,6 @@ const TEST_URI =
add_task(async function() {
info("open the console");
const hud = await openNewTabAndConsole(TEST_URI);
const { jsterm } = hud;
info("open the debugger");
await openDebugger();
@ -32,7 +31,7 @@ add_task(async function() {
onFirstCallMessageReceived.then(message => {
firstCallEvaluationResult = message;
});
jsterm.execute("firstCall()");
execute(hud, "firstCall()");
info("Waiting for a frame to be added");
await waitForPaused(dbg);
@ -41,16 +40,17 @@ add_task(async function() {
await openConsole();
info("Executing basic command while paused");
let onMessageReceived = waitForMessage(hud, "3");
jsterm.execute("1 + 2");
let message = await onMessageReceived;
ok(message, "`1 + 2` was evaluated whith debugger paused");
await executeAndWaitForMessage(hud, "1 + 2", "3", ".result");
ok(true, "`1 + 2` was evaluated whith debugger paused");
info("Executing command using scoped variables while paused");
onMessageReceived = waitForMessage(hud, `"globalFooBug783499foo2SecondCall"`);
jsterm.execute("foo + foo2");
message = await onMessageReceived;
ok(message, "`foo + foo2` was evaluated as expected with debugger paused");
await executeAndWaitForMessage(
hud,
"foo + foo2",
`"globalFooBug783499foo2SecondCall"`,
".result"
);
ok(true, "`foo + foo2` was evaluated as expected with debugger paused");
info(
"Checking the first command, which is the last to resolve since it paused"
@ -63,7 +63,7 @@ add_task(async function() {
info("Resuming the thread");
dbg.actions.resume(dbg.selectors.getThreadContext());
message = await onFirstCallMessageReceived;
await onFirstCallMessageReceived;
ok(
firstCallEvaluationResult !== unresolvedSymbol,
"firstCall() returned correct value"

View File

@ -13,7 +13,6 @@ const TEST_URI =
add_task(async function() {
const hud = await openNewTabAndConsole(TEST_URI);
const { jsterm } = hud;
hud.ui.clearOutput();
const onInputMessage = waitForMessage(
@ -26,7 +25,7 @@ add_task(async function() {
TEST_URI,
".message.result"
);
jsterm.execute("window.location.href;");
execute(hud, "window.location.href;");
let message = await onInputMessage;
ok(message, "Input message is displayed with the expected class");

View File

@ -28,21 +28,21 @@ add_task(async function() {
info("Picker mode stopped, <h1> selected, now switching to the console");
const hud = await openConsole();
const { jsterm } = hud;
hud.ui.clearOutput();
const onEvaluationResult = waitForMessage(hud, "<h1>");
jsterm.execute("$0");
await onEvaluationResult;
await executeAndWaitForMessage(hud, "$0", "<h1>", ".result");
ok(true, "correct output for $0");
hud.ui.clearOutput();
const newH1Content = "newH1Content";
const onAssignmentResult = waitForMessage(hud, "<h1>");
jsterm.execute(`$0.textContent = "${newH1Content}";$0`);
await onAssignmentResult;
await executeAndWaitForMessage(
hud,
`$0.textContent = "${newH1Content}";$0`,
"<h1>",
".result"
);
ok(true, "correct output for $0 after setting $0.textContent");
const { textContent } = await testActor.getNodeInfo("h1");

View File

@ -115,7 +115,7 @@ async function testKeyOrder(hud, command, expectedKeys) {
"Wait for a new .result message with an object inspector to be displayed"
);
const resultsCount = findMessages(hud, "", ".result").length;
hud.jsterm.execute(command);
execute(hud, command);
const oi = await waitFor(() => {
const results = findMessages(hud, "", ".result");
if (results.length == resultsCount + 1) {

View File

@ -31,11 +31,12 @@ add_task(async function() {
await gDevTools.showToolbox(target, "webconsole");
info("Test logging and inspecting objects while on a breakpoint.");
const jsterm = hud.jsterm;
const onMessage = waitForMessage(hud, '{ testProp2: "testValue2" }');
jsterm.execute("fooObj");
const message = await onMessage;
const message = await executeAndWaitForMessage(
hud,
"fooObj",
'{ testProp2: "testValue2" }',
".result"
);
const objectInspectors = [...message.node.querySelectorAll(".tree")];
is(objectInspectors.length, 1, "There should be one object inspector");

View File

@ -30,12 +30,8 @@ add_task(async function() {
await toolbox.selectTool("webconsole");
// This is the meat of the test: evaluate the optimized out variable.
const onMessage = waitForMessage(hud, "optimized out");
hud.jsterm.execute("upvar");
info("Waiting for optimized out message");
await onMessage;
await executeAndWaitForMessage(hud, "upvar", "optimized out", ".result");
ok(true, "Optimized out message logged");
info("Open the debugger");

View File

@ -22,7 +22,7 @@ add_task(async function() {
messages: messages.map(text => ({ text })),
});
hud.jsterm.execute("console.log('foo', 'bar');");
execute(hud, "console.log('foo', 'bar');");
const [fncallNode, consoleMessageNode, resultNode] = (await onMessages).map(
msg => msg.node

View File

@ -59,7 +59,7 @@ add_task(async function() {
// Check that expected output and actual trimmed output match
for (const { name, command, expected } of TEST_ITEMS) {
hud.ui.clearOutput();
await hud.jsterm.execute(command);
await executeAndWaitForMessage(hud, command, "", ".result");
const result = await waitFor(() => getDisplayedInput(hud));

View File

@ -29,7 +29,7 @@ add_task(async function() {
messages: [{ text: `"a" + "😎"` }, { text: `"a😎"` }],
});
for (const input of jstermHistory) {
await hud.jsterm.execute(input);
execute(hud, input);
}
await onLastMessage;

View File

@ -30,9 +30,9 @@ async function performTests() {
`"😎"`,
];
const onLastMessage = waitForMessage(hud, `"😎"`);
const onLastMessage = waitForMessage(hud, `"😎"`, ".result");
for (const input of jstermHistory) {
await jsterm.execute(input);
execute(hud, input);
}
await onLastMessage;

View File

@ -22,7 +22,7 @@ add_task(async function() {
const onLastMessage = waitForMessage(hud, `"Snoopy"`);
for (const input of jstermHistory) {
await hud.jsterm.execute(input);
execute(hud, input);
}
await onLastMessage;

View File

@ -21,7 +21,7 @@ add_task(async function() {
const onLastMessage = waitForMessage(hud, `"Snoopy"`);
for (const input of jstermHistory) {
await hud.jsterm.execute(input);
execute(hud, input);
}
await onLastMessage;

View File

@ -19,15 +19,12 @@ add_task(async function() {
const hud = await openNewTabAndConsole(TEST_URI1);
let onMessages = waitForMessages({
await executeAndWaitForMessage(
hud,
messages: [{ text: "window.location.href" }, { text: TEST_URI1 }],
});
hud.jsterm.execute("window.location.href");
info("wait for window.location.href");
await onMessages;
"window.location.href",
TEST_URI1,
".result"
);
// load second url
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, TEST_URI2);
@ -35,16 +32,14 @@ add_task(async function() {
ok(!findMessage(hud, "Permission denied"), "no permission denied errors");
onMessages = waitForMessages({
hud,
messages: [{ text: "window.location.href" }, { text: TEST_URI2 }],
});
hud.ui.clearOutput();
hud.jsterm.execute("window.location.href");
info("wait for window.location.href after page navigation");
await onMessages;
hud.ui.clearOutput();
await executeAndWaitForMessage(
hud,
"window.location.href",
TEST_URI2,
".result"
);
ok(!findMessage(hud, "Permission denied"), "no permission denied errors");
@ -59,16 +54,12 @@ add_task(async function() {
await cleared;
info("Messages cleared after navigation; checking location");
onMessages = waitForMessages({
await executeAndWaitForMessage(
hud,
messages: [{ text: "window.location.href" }, { text: TEST_URI1 }],
});
hud.jsterm.execute("window.location.href");
info("wait for window.location.href after goBack()");
await onMessages;
"window.location.href",
TEST_URI1,
".result"
);
ok(!findMessage(hud, "Permission denied"), "no permission denied errors");
});

View File

@ -77,9 +77,7 @@ add_task(async function() {
is(outputContainer.scrollTop, 0, "The console stayed scrolled to the top");
info("Evaluate a command to check that the console scrolls to the bottom");
onMessage = waitForMessage(hud, "42");
ui.jsterm.execute("21 + 21");
await onMessage;
await executeAndWaitForMessage(hud, "21 + 21", "42", ".result");
ok(hasVerticalOverflow(outputContainer), "There is a vertical overflow");
ok(
isScrolledToBottom(outputContainer),
@ -103,12 +101,15 @@ add_task(async function() {
info(
"Evaluate an Error object to check that the console scrolls to the bottom"
);
onMessage = waitForMessage(hud, "myErrorObject", ".message.result");
ui.jsterm.execute(`
message = await executeAndWaitForMessage(
hud,
`
x = new Error("myErrorObject");
x.stack = "a@b/c.js:1:2\\nd@e/f.js:3:4";
x;`);
message = await onMessage;
x;`,
"myErrorObject",
".result"
);
ok(
isScrolledToBottom(outputContainer),
"The console is scrolled to the bottom"

View File

@ -20,16 +20,11 @@ add_task(async function testSelectAll() {
});
async function testSelectionWhenMovingBetweenBoxes(hud) {
const jsterm = hud.jsterm;
// Fill the console with some output.
hud.ui.clearOutput();
await jsterm.execute("1 + 2");
await waitFor(() => findMessage(hud, "3"));
await jsterm.execute("3 + 4");
await waitFor(() => findMessage(hud, "7"));
await jsterm.execute("5 + 6");
await waitFor(() => findMessage(hud, "11"));
await executeAndWaitForMessage(hud, "1 + 2", "3", ".result");
await executeAndWaitForMessage(hud, "3 + 4", "7", ".result");
await executeAndWaitForMessage(hud, "5 + 6", "11", ".result");
}
function testBrowserMenuSelectAll(hud) {

View File

@ -30,11 +30,17 @@ add_task(async function() {
await receivedMessages;
info("evaluating a string constant");
const jsterm = hud.jsterm;
await jsterm.execute('"string\\nconstant"');
const msg = await waitFor(() => findMessage(hud, "constant"));
const body = msg.querySelector(".message-body");
const msg = await executeAndWaitForMessage(
hud,
'"string\\nconstant"',
"constant",
".result"
);
const body = msg.node.querySelector(".message-body");
// On the other hand, a string constant result should be quoted, but
// newlines should be let through.
ok(body.textContent.includes('"string\nconstant"'), "found expected text");
ok(
body.textContent.includes('"string\nconstant"'),
`found expected text - "${body.textContent}"`
);
});

View File

@ -29,22 +29,24 @@ add_task(async function() {
info(
"Evaluating an expression resulting in the same error increments the sum"
);
let onMessage = waitForMessage(hud, "window is not a function");
hud.jsterm.execute("window()");
await onMessage;
await executeAndWaitForMessage(hud, "window()", "window is not a function");
checkErrorDisplayedTelemetry("JSMSG_NOT_FUNCTION", 3);
info(
"Evaluating an expression resulting in another error is logged in telemetry"
);
onMessage = waitForMessage(hud, "repeat count must be non-negative");
hud.jsterm.execute(`"a".repeat(-1)`);
await onMessage;
await executeAndWaitForMessage(
hud,
`"a".repeat(-1)`,
"repeat count must be non-negative"
);
checkErrorDisplayedTelemetry("JSMSG_NEGATIVE_REPETITION_COUNT", 1);
onMessage = waitForMessage(hud, "repeat count must be non-negative");
hud.jsterm.execute(`"b".repeat(-1)`);
await onMessage;
await executeAndWaitForMessage(
hud,
`"b".repeat(-1)`,
"repeat count must be non-negative"
);
checkErrorDisplayedTelemetry("JSMSG_NEGATIVE_REPETITION_COUNT", 2);
});

View File

@ -14,20 +14,16 @@ const TEST_URI =
add_task(async function() {
const hud = await openNewTabAndConsole(TEST_URI);
const { jsterm } = hud;
await openDebugger();
const toolbox = gDevTools.getToolbox(hud.target);
const dbg = createDebuggerContext(toolbox);
jsterm.execute("pauseInWorker(42)");
execute(hud, "pauseInWorker(42)");
await waitForPaused(dbg);
await openConsole();
const onMessage = waitForMessage(hud, "42");
jsterm.execute("data");
await onMessage;
await executeAndWaitForMessage(hud, "data", "42", ".result");
ok(true, "Evaluated console message in worker thread");
});

View File

@ -220,6 +220,16 @@ async function waitForMessage(hud, text, selector) {
return messages[0];
}
/**
* Execute an input expression.
*
* @param {Object} hud : The webconsole.
* @param {String} input : The input expression to execute.
*/
function execute(hud, input) {
return hud.ui.wrapper.dispatchEvaluateExpression(input);
}
/**
* Execute an input expression and wait for a message with the expected text (and an
* optional selector) to be displayed in the output.
@ -236,7 +246,7 @@ function executeAndWaitForMessage(
selector = ".message"
) {
const onMessage = waitForMessage(hud, matchingText, selector);
hud.jsterm.execute(input);
execute(hud, input);
return onMessage;
}
@ -501,7 +511,9 @@ function getInputValue(hud) {
* @param {String} value : The value to set the console input to.
*/
function setInputValue(hud, value) {
return hud.jsterm._setValue(value);
const onValueSet = hud.jsterm.once("set-input-value");
hud.jsterm._setValue(value);
return onValueSet;
}
/**

View File

@ -652,6 +652,14 @@ class WebConsoleWrapper {
store.dispatch(actions.clearHistory());
}
/**
*
* @param {String} expression: The expression to evaluate
*/
dispatchEvaluateExpression(expression) {
store.dispatch(actions.evaluateExpression(expression));
}
/**
* Returns a Promise that resolves once any async dispatch is finally dispatched.
*/