Backed out 5 changesets (bug 1384527, bug 1734786, bug 1734782, bug 1734592, bug 1734785) for causing mochitest failures. CLOSED TREE

Backed out changeset fd5088801f6d (bug 1384527)
Backed out changeset 0752e08d7ec9 (bug 1734786)
Backed out changeset 038d15951e1a (bug 1734782)
Backed out changeset a6a1a9b835f4 (bug 1734785)
Backed out changeset aca421f634ea (bug 1734592)
This commit is contained in:
Cristian Tuns
2021-10-11 11:06:16 -04:00
parent 9a4508b875
commit efc1b74179
30 changed files with 140 additions and 134 deletions

View File

@@ -19,6 +19,7 @@ const HTML_NS = "http://www.w3.org/1999/xhtml";
const REGEX_4XX_5XX = /^[4,5]\d\d$/;
var { Ci, Cc } = require("chrome");
var promise = require("promise");
const { debounce } = require("devtools/shared/debounce");
const { throttle } = require("devtools/shared/throttle");
const { safeAsyncMethod } = require("devtools/shared/async-utils");
@@ -908,7 +909,7 @@ Toolbox.prototype = {
// Wait until the original tool is selected so that the split
// console input will receive focus.
let splitConsolePromise = Promise.resolve();
let splitConsolePromise = promise.resolve();
if (Services.prefs.getBoolPref(SPLITCONSOLE_ENABLED_PREF)) {
splitConsolePromise = this.openSplitConsole();
this.telemetry.addEventProperty(
@@ -930,7 +931,7 @@ Toolbox.prototype = {
);
}
await Promise.all([
await promise.all([
splitConsolePromise,
framesPromise,
onResourcesWatched,
@@ -2541,7 +2542,7 @@ Toolbox.prototype = {
}
// Wait till the panel is fully ready and fire 'ready' events.
Promise.resolve(built).then(panel => {
promise.resolve(built).then(panel => {
this._toolPanels.set(id, panel);
// Make sure to decorate panel object with event API also in case
@@ -2682,12 +2683,12 @@ Toolbox.prototype = {
this.focusTool(id);
// Return the existing panel in order to have a consistent return value.
return Promise.resolve(panel);
return promise.resolve(panel);
}
// Otherwise, if there is no panel instance, it is still loading,
// so we are racing another call to selectTool with the same id.
return this.once("select").then(() =>
Promise.resolve(this._toolPanels.get(id))
promise.resolve(this._toolPanels.get(id))
);
}
@@ -2905,7 +2906,7 @@ Toolbox.prototype = {
if (this._lastFocusedElement) {
this._lastFocusedElement.focus();
}
return Promise.resolve();
return promise.resolve();
},
/**
@@ -2922,7 +2923,7 @@ Toolbox.prototype = {
: this.openSplitConsole();
}
return Promise.resolve();
return promise.resolve();
},
/**
@@ -3150,7 +3151,7 @@ Toolbox.prototype = {
if (!this.target.getTrait("frames")) {
// We are not targetting a regular WindowGlobalTargetActor
// it can be either an addon or browser toolbox actor
return Promise.resolve();
return promise.resolve();
}
try {

View File

@@ -4,6 +4,7 @@
"use strict";
const promise = require("promise");
const flags = require("devtools/shared/flags");
const ToolDefinitions = require("devtools/client/definitions").Tools;
const CssLogic = require("devtools/shared/inspector/css-logic");
@@ -332,7 +333,7 @@ CssComputedView.prototype = {
* The highlighted node to get styles for.
* @returns a promise that will be resolved when highlighting is complete.
*/
selectElement: function(element) {
selectElement: async function(element) {
if (!element) {
if (this.viewedElementPageStyle) {
this.viewedElementPageStyle.off(
@@ -351,11 +352,11 @@ CssComputedView.prototype = {
for (const propView of this.propertyViews) {
propView.refresh();
}
return Promise.resolve(undefined);
return promise.resolve(undefined);
}
if (element === this._viewedElement) {
return Promise.resolve(undefined);
return promise.resolve(undefined);
}
if (this.viewedElementPageStyle) {
@@ -559,24 +560,25 @@ CssComputedView.prototype = {
*/
refreshPanel: function() {
if (!this._viewedElement || !this.isPanelVisible()) {
return Promise.resolve();
return promise.resolve();
}
// Capture the current viewed element to return from the promise handler
// early if it changed
const viewedElement = this._viewedElement;
return Promise.all([
this._createPropertyViews(),
this.viewedElementPageStyle.getComputed(this._viewedElement, {
filter: this._sourceFilter,
onlyMatched: !this.includeBrowserStyles,
markMatched: true,
}),
])
return promise
.all([
this._createPropertyViews(),
this.viewedElementPageStyle.getComputed(this._viewedElement, {
filter: this._sourceFilter,
onlyMatched: !this.includeBrowserStyles,
markMatched: true,
}),
])
.then(([, computed]) => {
if (viewedElement !== this._viewedElement) {
return Promise.resolve();
return promise.resolve();
}
this._matchedProperties = new Set();
@@ -1245,7 +1247,7 @@ PropertyView.prototype = {
STYLE_INSPECTOR_L10N.getStr("rule.twistyExpand.label")
);
this.tree.inspector.emit("computed-view-property-collapsed");
return Promise.resolve(undefined);
return promise.resolve(undefined);
},
get matchedSelectors() {

View File

@@ -4,6 +4,7 @@
"use strict";
const promise = require("promise");
const { KeyCodes } = require("devtools/client/shared/keycodes");
const EventEmitter = require("devtools/shared/event-emitter");
@@ -43,6 +44,10 @@ function InspectorSearch(inspector, input, clearBtn) {
this.searchBox.addEventListener("input", this._onInput, true);
this.searchClearButton.addEventListener("click", this._onClearSearch);
// For testing, we need to be able to wait for the most recent node request
// to finish. Tests can watch this promise for that.
this._lastQuery = promise.resolve(null);
this.autocompleter = new SelectorAutocompleter(inspector, input);
EventEmitter.decorate(this);
}
@@ -172,6 +177,9 @@ function SelectorAutocompleter(inspector, inputNode) {
this.searchBox.addEventListener("keypress", this._onSearchKeypress, true);
this.inspector.on("markupmutation", this._onMarkupMutation);
// For testing, we need to be able to wait for the most recent node request
// to finish. Tests can watch this promise for that.
this._lastQuery = promise.resolve(null);
EventEmitter.decorate(this);
}
@@ -335,7 +343,7 @@ SelectorAutocompleter.prototype = {
// When tab is pressed with focus on searchbox and closed popup,
// do not prevent the default to avoid a keyboard trap and move focus
// to next/previous element.
this.emitForTests("processing-done");
this.emit("processing-done");
return;
}
break;
@@ -358,7 +366,7 @@ SelectorAutocompleter.prototype = {
if (popup.isOpen) {
this.hidePopup();
} else {
this.emitForTests("processing-done");
this.emit("processing-done");
return;
}
break;
@@ -369,7 +377,7 @@ SelectorAutocompleter.prototype = {
event.preventDefault();
event.stopPropagation();
this.emitForTests("processing-done");
this.emit("processing-done");
},
/**
@@ -474,8 +482,6 @@ SelectorAutocompleter.prototype = {
*/
showSuggestions: async function() {
let query = this.searchBox.value;
const originalQuery = this.searchBox.value;
const state = this.state;
let firstPart = "";
@@ -484,7 +490,6 @@ SelectorAutocompleter.prototype = {
// suggest all nodes) or if it is an attribute selector (because
// it would give a lot of useless results).
this.hidePopup();
this.emitForTests("processing-done", { query: originalQuery });
return;
}
@@ -508,27 +513,26 @@ SelectorAutocompleter.prototype = {
query += "*";
}
let suggestions = await this.inspector.commands.inspectorCommand.getSuggestionsForQuery(
query,
firstPart,
state
);
this._lastQuery = this.inspector.commands.inspectorCommand
.getSuggestionsForQuery(query, firstPart, state)
.then(suggestions => {
this.emit("processing-done");
if (state === this.States.CLASS) {
firstPart = "." + firstPart;
} else if (state === this.States.ID) {
firstPart = "#" + firstPart;
}
if (state === this.States.CLASS) {
firstPart = "." + firstPart;
} else if (state === this.States.ID) {
firstPart = "#" + firstPart;
}
// If there is a single tag match and it's what the user typed, then
// don't need to show a popup.
if (suggestions.length === 1 && suggestions[0][0] === firstPart) {
suggestions = [];
}
// If there is a single tag match and it's what the user typed, then
// don't need to show a popup.
if (suggestions.length === 1 && suggestions[0][0] === firstPart) {
suggestions = [];
}
// Wait for the autocomplete-popup to fire its popup-opened event, to make sure
// the autoSelect item has been selected.
await this._showPopup(suggestions, state);
this.emitForTests("processing-done", { query: originalQuery });
// Wait for the autocomplete-popup to fire its popup-opened event, to make sure
// the autoSelect item has been selected.
return this._showPopup(suggestions, state);
});
},
};

View File

@@ -5,6 +5,7 @@
"use strict";
const Services = require("Services");
const promise = require("promise");
const EventEmitter = require("devtools/shared/event-emitter");
const flags = require("devtools/shared/flags");
const { executeSoon } = require("devtools/shared/DevToolsUtils");
@@ -1873,7 +1874,7 @@ Inspector.prototype = {
parents: hierarchical,
});
}
return Promise.resolve();
return promise.resolve();
},
/**

View File

@@ -5,6 +5,7 @@
"use strict";
const Services = require("Services");
const promise = require("promise");
const { PSEUDO_CLASSES } = require("devtools/shared/css/constants");
const { LocalizationHelper } = require("devtools/shared/l10n");
@@ -286,7 +287,7 @@ class MarkupContextMenu {
_pasteAdjacentHTML(position) {
const content = this._getClipboardContentForPaste();
if (!content) {
return Promise.reject("No clipboard content for paste");
return promise.reject("No clipboard content for paste");
}
const node = this.selection.nodeFront;
@@ -299,7 +300,7 @@ class MarkupContextMenu {
_pasteInnerHTML() {
const content = this._getClipboardContentForPaste();
if (!content) {
return Promise.reject("No clipboard content for paste");
return promise.reject("No clipboard content for paste");
}
const node = this.selection.nodeFront;
@@ -314,7 +315,7 @@ class MarkupContextMenu {
_pasteOuterHTML() {
const content = this._getClipboardContentForPaste();
if (!content) {
return Promise.reject("No clipboard content for paste");
return promise.reject("No clipboard content for paste");
}
const node = this.selection.nodeFront;

View File

@@ -4,6 +4,7 @@
"use strict";
const promise = require("promise");
const Services = require("Services");
const MarkupContainer = require("devtools/client/inspector/markup/views/markup-container");
const ElementEditor = require("devtools/client/inspector/markup/views/element-editor");
@@ -112,7 +113,7 @@ MarkupElementContainer.prototype = extend(MarkupContainer.prototype, {
*/
_getPreview: function() {
if (!this.isPreviewable()) {
return Promise.reject("_getPreview called on a non-previewable element.");
return promise.reject("_getPreview called on a non-previewable element.");
}
if (this.tooltipDataPromise) {

View File

@@ -5,6 +5,7 @@
"use strict";
const Services = require("Services");
const promise = require("promise");
const Rule = require("devtools/client/inspector/rules/models/rule");
const UserProperties = require("devtools/client/inspector/rules/models/user-properties");
const {
@@ -128,7 +129,7 @@ class ElementStyle {
})
.then(entries => {
if (this.destroyed || this.populated !== populated) {
return Promise.resolve(undefined);
return promise.resolve(undefined);
}
// Store the current list of rules (if any) during the population
@@ -166,7 +167,7 @@ class ElementStyle {
// populate is often called after a setTimeout,
// the connection may already be closed.
if (this.destroyed) {
return Promise.resolve(undefined);
return promise.resolve(undefined);
}
return promiseWarn(e);
});

View File

@@ -4,6 +4,7 @@
"use strict";
const promise = require("promise");
const {
style: { ELEMENT_STYLE },
} = require("devtools/shared/constants");
@@ -473,7 +474,8 @@ class Rule {
applyProperties(modifier) {
// If there is already a pending modification, we have to wait
// until it settles before applying the next modification.
const resultPromise = Promise.resolve(this._applyingModifications)
const resultPromise = promise
.resolve(this._applyingModifications)
.then(() => {
const modifications = this.domRule.startModifyingProperties(
this.cssProperties

View File

@@ -4,6 +4,7 @@
"use strict";
const promise = require("promise");
const Services = require("Services");
const flags = require("devtools/shared/flags");
const { l10n } = require("devtools/shared/inspector/css-logic");
@@ -647,7 +648,7 @@ CssRuleView.prototype = {
// request to complete, and then focus the new rule's selector.
const eventPromise = this.once("ruleview-refreshed");
const newRulePromise = this.pageStyle.addNewRule(element, pseudoClasses);
Promise.all([eventPromise, newRulePromise]).then(values => {
promise.all([eventPromise, newRulePromise]).then(values => {
const options = values[1];
// Be sure the reference the correct |rules| here.
for (const rule of this._elementStyle.rules) {
@@ -928,7 +929,7 @@ CssRuleView.prototype = {
selectElement: function(element, allowRefresh = false) {
const refresh = this._viewedElement === element;
if (refresh && !allowRefresh) {
return Promise.resolve(undefined);
return promise.resolve(undefined);
}
if (this._popup && this.popup.isOpen) {
@@ -950,7 +951,7 @@ CssRuleView.prototype = {
this.pageStyle.off("stylesheet-updated", this.refreshPanel);
this.pageStyle = null;
}
return Promise.resolve(undefined);
return promise.resolve(undefined);
}
this.pageStyle = element.inspectorFront.pageStyle;
@@ -959,7 +960,8 @@ CssRuleView.prototype = {
// To figure out how shorthand properties are interpreted by the
// engine, we will set properties on a dummy element and observe
// how their .style attribute reflects them as computed values.
const dummyElementPromise = Promise.resolve(this.styleDocument)
const dummyElementPromise = promise
.resolve(this.styleDocument)
.then(document => {
// ::before and ::after do not have a namespaceURI
const namespaceURI =
@@ -1015,7 +1017,7 @@ CssRuleView.prototype = {
refreshPanel: function() {
// Ignore refreshes when the panel is hidden, or during editing or when no element is selected.
if (!this.isPanelVisible() || this.isEditing || !this._elementStyle) {
return Promise.resolve(undefined);
return promise.resolve(undefined);
}
// Repopulate the element style once the current modifications are done.
@@ -1026,7 +1028,7 @@ CssRuleView.prototype = {
}
}
return Promise.all(promises).then(() => {
return promise.all(promises).then(() => {
return this._populate();
});
},
@@ -1308,7 +1310,7 @@ CssRuleView.prototype = {
let container = null;
if (!this._elementStyle.rules) {
return Promise.resolve();
return promise.resolve();
}
const editorReadyPromises = [];
@@ -1381,7 +1383,7 @@ CssRuleView.prototype = {
this.searchValue && !seenSearchTerm
);
return Promise.all(editorReadyPromises);
return promise.all(editorReadyPromises);
},
/**

View File

@@ -45,10 +45,7 @@ async function testImageTooltipAfterColorChange(swatch, url, ruleView) {
const spectrum = picker.spectrum;
const onHidden = picker.tooltip.once("hidden");
// On "RETURN", `ruleview-changed` is triggered when the SwatchBasedEditorTooltip calls
// its `commit` method, and then another event is emitted when the editor is hidden.
const onModifications = waitForNEvents(ruleView, "ruleview-changed", 2);
const onModifications = ruleView.once("ruleview-changed");
focusAndSendKey(spectrum.element.ownerDocument.defaultView, "RETURN");
await onHidden;
await onModifications;

View File

@@ -28,6 +28,7 @@ const {
SELECTOR_ELEMENT,
SELECTOR_PSEUDO_CLASS,
} = require("devtools/shared/css/parsing-utils");
const promise = require("promise");
const Services = require("Services");
const EventEmitter = require("devtools/shared/event-emitter");
const CssLogic = require("devtools/shared/inspector/css-logic");
@@ -363,7 +364,7 @@ RuleEditor.prototype = {
this._onToolChanged();
}
Promise.resolve().then(() => {
promise.resolve().then(() => {
this.emit("source-link-updated");
});
},

View File

@@ -78,7 +78,7 @@ add_task(async function() {
}
info("Waiting for search query to complete");
promises.push(inspector.searchSuggestions.once("processing-done"));
promises.push(inspector.searchSuggestions._lastQuery);
EventUtils.synthesizeKey(key, {}, inspector.panelWin);

View File

@@ -118,14 +118,11 @@ add_task(async function() {
info("Pressing " + key + " to get " + formatSuggestions(suggestions));
const command = once(searchBox, "input");
const onSearchProcessingDone = inspector.searchSuggestions.once(
"processing-done"
);
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
await command;
info("Waiting for search query to complete");
await onSearchProcessingDone;
await inspector.searchSuggestions._lastQuery;
info(
"Query completed. Performing checks for input '" +

View File

@@ -194,14 +194,11 @@ add_task(async function() {
info("Pressing " + key + " to get " + formatSuggestions(suggestions));
const command = once(searchBox, "input");
const onSearchProcessingDone = inspector.searchSuggestions.once(
"processing-done"
);
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
await command;
info("Waiting for search query to complete");
await onSearchProcessingDone;
await inspector.searchSuggestions._lastQuery;
info(
"Query completed. Performing checks for input '" + searchBox.value + "'"

View File

@@ -81,14 +81,11 @@ add_task(async function() {
info("Pressing " + key + " to get " + formatSuggestions(suggestions));
const command = once(searchBox, "input");
const onSearchProcessingDone = inspector.searchSuggestions.once(
"processing-done"
);
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
await command;
info("Waiting for search query to complete");
await onSearchProcessingDone;
await inspector.searchSuggestions._lastQuery;
info(
"Query completed. Performing checks for input '" + searchBox.value + "'"

View File

@@ -18,9 +18,10 @@ add_task(async function() {
info("Enter # to search for all ids");
let processingDone = once(inspector.searchSuggestions, "processing-done");
EventUtils.synthesizeKey("#", {}, inspector.panelWin);
await processingDone;
info("Wait for search query to complete");
await processingDone;
await inspector.searchSuggestions._lastQuery;
info("Press tab to fill the search input with the first suggestion");
processingDone = once(inspector.searchSuggestions, "processing-done");

View File

@@ -77,13 +77,10 @@ async function synthesizeKeys(keys, inspector) {
for (const key of keys) {
info("Synthesizing key " + key + " in the search box");
const eventHandled = once(inspector.searchBox, "keypress", true);
const onSearchProcessingDone = inspector.searchSuggestions.once(
"processing-done"
);
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
await eventHandled;
info("Waiting for the search query to complete");
await onSearchProcessingDone;
await inspector.searchSuggestions._lastQuery;
}
}

View File

@@ -34,14 +34,11 @@ add_task(async function() {
info("Pressing " + key + " to get " + suggestions);
const command = once(searchBox, "input");
const onSearchProcessingDone = inspector.searchSuggestions.once(
"processing-done"
);
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
await command;
info("Waiting for search query to complete and getting the suggestions");
await onSearchProcessingDone;
await inspector.searchSuggestions._lastQuery;
const actualSuggestions = popup.getItems();
is(

View File

@@ -49,14 +49,11 @@ add_task(async function() {
info("Pressing " + key + " to get " + suggestions.join(", "));
const command = once(searchBox, "input");
const onSearchProcessingDone = inspector.searchSuggestions.once(
"processing-done"
);
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
await command;
info("Waiting for search query to complete and getting the suggestions");
await onSearchProcessingDone;
await inspector.searchSuggestions._lastQuery;
const actualSuggestions = popup.getItems();
is(

View File

@@ -56,23 +56,20 @@ add_task(async function() {
let index = 0;
for (const [key, id, isTextNode, isValid] of KEY_STATES) {
info(index + ": Pressing key " + key + " to get id " + id + ".");
const onSearchProcessingDone = inspector.searchSuggestions.once(
"processing-done"
);
const onSearchResult = inspector.search.once("search-result");
EventUtils.synthesizeKey(
key,
{ shiftKey: key === "*" },
inspector.panelWin
);
info("Got processing-done event");
if (key === "VK_RETURN") {
info("Waiting for " + (isValid ? "NO " : "") + "results");
await onSearchResult;
await inspector.search.once("search-result");
}
info("Waiting for search query to complete");
await onSearchProcessingDone;
await inspector.searchSuggestions._lastQuery;
if (isTextNode) {
info(

View File

@@ -32,26 +32,22 @@ add_task(async function() {
info("Type d and the clear button will be shown");
const command = once(searchBox, "input");
let onSearchProcessingDone = inspector.searchSuggestions.once(
"processing-done"
);
EventUtils.synthesizeKey("c", {}, inspector.panelWin);
await command;
info("Waiting for search query to complete and getting the suggestions");
await onSearchProcessingDone;
await inspector.searchSuggestions._lastQuery;
ok(
!searchClearButton.hidden,
"The clear button is shown when some word is in searchBox"
);
onSearchProcessingDone = inspector.searchSuggestions.once("processing-done");
EventUtils.synthesizeKey("VK_BACK_SPACE", {}, inspector.panelWin);
await command;
info("Waiting for search query to complete and getting the suggestions");
await onSearchProcessingDone;
await inspector.searchSuggestions._lastQuery;
ok(
searchClearButton.hidden,

View File

@@ -54,17 +54,10 @@ add_task(async function() {
await onContextMenuClose;
info("Copy text in search field using the context menu");
const onSearchProcessingDone = inspector.searchSuggestions.once(
"processing-done"
);
searchBox.setUserInput(TEST_INPUT);
searchBox.select();
searchBox.focus();
// We have to wait for search query to avoid test failure.
info("Waiting for search query to complete and getting the suggestions");
await onSearchProcessingDone;
onContextMenuOpen = toolbox.once("menu-open");
synthesizeContextMenuEvent(searchBox);
await onContextMenuOpen;
@@ -107,4 +100,8 @@ add_task(async function() {
const onContextMenuHidden = toolbox.once("menu-close");
searchContextMenu.hidePopup();
await onContextMenuHidden;
// We have to wait for search query to avoid test failure.
info("Waiting for search query to complete and getting the suggestions");
await inspector.searchSuggestions._lastQuery;
});

View File

@@ -64,9 +64,10 @@ add_task(async function() {
const done = inspector.searchSuggestions.once("processing-done");
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
await done;
info("Waiting for search query to complete");
await done;
await inspector.searchSuggestions._lastQuery;
is(inspector.searchBox.value, query, "The searchbox value is correct");
}

View File

@@ -103,14 +103,11 @@ add_task(async function() {
info("Pressing " + key + " to get " + formatSuggestions(suggestions));
const command = once(searchBox, "input");
const onSearchProcessingDone = inspector.searchSuggestions.once(
"processing-done"
);
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
await command;
info("Waiting for search query to complete");
await onSearchProcessingDone;
await inspector.searchSuggestions._lastQuery;
info(
"Query completed. Performing checks for input '" + searchBox.value + "'"

View File

@@ -14,20 +14,12 @@ add_task(async function() {
await focusSearchBoxUsingShortcut(inspector.panelWin);
info("Enter body > p to search");
const searchText = "body > p";
// EventUtils.sendString will trigger multiple updates, so wait until the final one.
const processingDone = new Promise(resolve => {
const off = inspector.searchSuggestions.on("processing-done", data => {
if (data.query == searchText) {
resolve();
off();
}
});
});
EventUtils.sendString(searchText, inspector.panelWin);
const processingDone = once(inspector.searchSuggestions, "processing-done");
EventUtils.sendString("body > p", inspector.panelWin);
await processingDone;
info("Wait for search query to complete");
await processingDone;
await inspector.searchSuggestions._lastQuery;
let msg = "Press enter and expect a new selection";
await sendKeyAndCheck(inspector, msg, "VK_RETURN", {}, "#p1");

View File

@@ -128,14 +128,11 @@ add_task(async function() {
);
const onCommand = once(searchBox, "input", true);
const onSearchProcessingDone = inspector.searchSuggestions.once(
"processing-done"
);
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
await onCommand;
info("Waiting for the suggestions to be retrieved");
await onSearchProcessingDone;
await inspector.searchSuggestions._lastQuery;
const actualSuggestions = popup.getItems();
is(

View File

@@ -65,6 +65,15 @@ function DevToolsLoader({
"toolkit/locales": "chrome://global/locale",
};
// When creating a Loader invisible to the Debugger, we have to ensure
// using only modules and not depend on any JSM. As everything that is
// not loaded with Loader isn't going to respect `invisibleToDebugger`.
// But we have to keep using Promise.jsm for other loader to prevent
// breaking unhandled promise rejection in tests.
if (invisibleToDebugger) {
paths.promise = "resource://gre/modules/Promise-backend.js";
}
// DAMP tests use a dynamic path. If DEBUG_DEVTOOLS_DAMP_TEST_PATH was set as
// a custom preference, add a corresponding path mapping entry.
// DAMP runner and tests are under testing/talos/talos/tests/devtools
@@ -109,6 +118,13 @@ function DevToolsLoader({
// Fetch custom pseudo modules and globals
const { modules, globals } = this.require("devtools/shared/builtin-modules");
// When creating a Loader for the browser toolbox, we have to use
// Promise-backend.js, as a Loader module. Instead of Promise.jsm which
// can't be flagged as invisible to debugger.
if (invisibleToDebugger) {
delete modules.promise;
}
// Register custom pseudo modules to the current loader instance
for (const id in modules) {
const uri = resolveURI(id, this.loader.mapping);

View File

@@ -14,6 +14,7 @@
*/
const { Cu, Cc, Ci } = require("chrome");
const promise = require("resource://gre/modules/Promise.jsm").Promise;
const jsmScope = require("resource://devtools/shared/Loader.jsm");
const { Services } = require("resource://gre/modules/Services.jsm");
@@ -209,6 +210,7 @@ exports.modules = {
DebuggerNotificationObserver,
HeapSnapshot,
InspectorUtils,
promise,
// Expose "chrome" Promise, which aren't related to any document
// and so are never frozen, even if the browser loader module which
// pull it is destroyed. See bug 1402779.

View File

@@ -32,6 +32,12 @@ function visible_loader() {
} catch (e) {
do_throw("debugger could not add visible value");
}
// Check that for common loader used for tabs, promise modules is Promise.jsm
// Which is required to support unhandled promises rejection in mochitests
const promise = ChromeUtils.import("resource://gre/modules/Promise.jsm")
.Promise;
Assert.equal(loader.require("promise"), promise);
}
function invisible_loader() {
@@ -49,4 +55,12 @@ function invisible_loader() {
} catch (e) {
Assert.ok(true);
}
// But for browser toolbox loader, promise is loaded as a regular modules out
// of Promise-backend.js, that to be invisible to the debugger and not step
// into it.
const promise = loader.require("promise");
const promiseModule =
loader.loader.modules["resource://gre/modules/Promise-backend.js"];
Assert.equal(promise, promiseModule.exports);
}

View File

@@ -26,6 +26,7 @@
"resource://devtools/shared/Loader.jsm"
);
this.isWorker = false;
this.Promise = require("resource://gre/modules/Promise.jsm").Promise;
this.console = console;
factory.call(
this,