mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-02 22:37:50 +00:00
Merge autoland to mozilla-central. a=merge
This commit is contained in:
commit
b12fccca4a
@ -454,7 +454,9 @@ DocAccessible* DocManager::CreateDocOrRootAccessible(Document* aDocument) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Ignore documents without presshell and not having root frame.
|
||||
// Ignore documents without presshell. We must not ignore documents with no
|
||||
// root frame because DOM focus can hit such documents and ignoring them would
|
||||
// prevent a11y focus.
|
||||
PresShell* presShell = aDocument->GetPresShell();
|
||||
if (!presShell || presShell->IsDestroying()) {
|
||||
return nullptr;
|
||||
|
@ -74,8 +74,9 @@ void TextAttrsMgr::GetAttributes(AccAttributes* aAttributes,
|
||||
}
|
||||
|
||||
nsIFrame* rootFrame = mHyperTextAcc->GetFrame();
|
||||
MOZ_ASSERT(rootFrame, "No frame for accessible!");
|
||||
if (!rootFrame) return;
|
||||
if (!rootFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsIContent *offsetNode = nullptr, *offsetElm = nullptr;
|
||||
nsIFrame* frame = nullptr;
|
||||
|
@ -35,6 +35,15 @@ Note that scenario 1 or 2 could happen for a child document as well.
|
||||
|
||||
Scenario 3 would then apply for any child documents encountered while building the accessibility trees for these top level DocAccessibles.
|
||||
|
||||
### Scenario 5: Document gets focus before layout begins
|
||||
It is possible for a document to get focus before layout has begun and before DOM loading is complete.
|
||||
In that case, there will be a PresShell, but it will have no root frame.
|
||||
Despite this, it is necessary to create the document because otherwise, a11y focus would go nowhere while the document had DOM focus.
|
||||
|
||||
1. [a11y::FocusManager gets notified of a DOM focus change (FocusManager::NotifyOfDOMFocus)](https://searchfox.org/mozilla-central/rev/04dbb1a865894aec20eb02585aa75acccc0b72d5/accessible/base/FocusManager.cpp#126).
|
||||
2. It gets the DocAccessible for the child document (DocManager::GetDocAccessible).
|
||||
3. Because it doesn't exist yet, [the DocAccessible gets created (DocManager::CreateDocOrRootAccessible)](https://searchfox.org/mozilla-central/rev/4e87b5392eafe1f1d49017e76f7317b06ec0b1d8/accessible/base/DocManager.cpp#62).
|
||||
|
||||
## 2. Initial tree creation
|
||||
1. When a DocAccessible is created, it [creates a refresh observer (NotificationController)](https://searchfox.org/mozilla-central/rev/36f79bed679ad7ec46f7cd05868a8f6dc823e1be/accessible/generic/DocAccessible.cpp#368) which performs various processing asynchronously.
|
||||
2. When the NotificationController is created, it [schedules processing for the next possible refresh tick](https://searchfox.org/mozilla-central/rev/36f79bed679ad7ec46f7cd05868a8f6dc823e1be/accessible/base/NotificationController.cpp#39).
|
||||
@ -42,6 +51,9 @@ Scenario 3 would then apply for any child documents encountered while building t
|
||||
4. For a top level document, the [DocAccessibleChild IPC actor is created](https://searchfox.org/mozilla-central/rev/36f79bed679ad7ec46f7cd05868a8f6dc823e1be/accessible/generic/DocAccessible.cpp#1752). See the section on IPC actor creation below.
|
||||
5. The [DOM tree is walked and the accessibility tree is built for the document down (DocAccessible::CacheChildrenInSubtree)](https://searchfox.org/mozilla-central/rev/36f79bed679ad7ec46f7cd05868a8f6dc823e1be/accessible/generic/DocAccessible.cpp#1789).
|
||||
|
||||
Note that the document might still have no layout frame if the PresShell still has no frame; see scenario 5 in DocAccessible creation above.
|
||||
Nevertheless, DoInitialUpdate must be called because otherwise, we wouldn't create the IPC actor, which would in turn mean remote documents in this state couldn't get a11y focus.
|
||||
|
||||
## 3. Child document binding
|
||||
Child document here refers to a child document in the same process; e.g. an in-process iframe or a parent process document such as an about: page.
|
||||
|
||||
|
@ -103,6 +103,9 @@ class LocalAccessible : public nsISupports, public Accessible {
|
||||
|
||||
/**
|
||||
* Return frame for this accessible.
|
||||
* Note that this will return null for display: contents. Also,
|
||||
* DocAccessible::GetFrame can return null if the frame tree hasn't been
|
||||
* created yet.
|
||||
*/
|
||||
virtual nsIFrame* GetFrame() const;
|
||||
|
||||
|
@ -511,6 +511,9 @@ pref("browser.urlbar.merino.clientVariants", "");
|
||||
// Whether the best match feature in the urlbar is enabled.
|
||||
pref("browser.urlbar.bestMatch.enabled", false);
|
||||
|
||||
// Whether best match results can be blocked.
|
||||
pref("browser.urlbar.bestMatch.blockingEnabled", false);
|
||||
|
||||
pref("browser.altClickSave", false);
|
||||
|
||||
// Enable logging downloads operations to the Console.
|
||||
|
@ -399,6 +399,12 @@ var SidebarUI = {
|
||||
* @return {Promise}
|
||||
*/
|
||||
toggle(commandID = this.lastOpenedId, triggerNode) {
|
||||
if (
|
||||
CustomizationHandler.isCustomizing() ||
|
||||
CustomizationHandler.isExitingCustomizeMode
|
||||
) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
// First priority for a default value is this.lastOpenedId which is set during show()
|
||||
// and not reset in hide(), unlike currentID. If show() hasn't been called and we don't
|
||||
// have a persisted command either, or the command doesn't exist anymore, then
|
||||
|
@ -22,3 +22,87 @@ add_task(async function test_sidebar_keys() {
|
||||
let options = { accelKey: true, shiftKey: AppConstants.platform == "macosx" };
|
||||
await testSidebarKeyToggle("h", options, "viewHistorySidebar");
|
||||
});
|
||||
|
||||
add_task(async function test_sidebar_in_customize_mode() {
|
||||
// Test bug 1756385 - widgets to appear unchecked in customize mode. Test that
|
||||
// the sidebar button widget doesn't appear checked, and that the sidebar
|
||||
// button toggle is inert while in customize mode.
|
||||
let { CustomizableUI } = ChromeUtils.import(
|
||||
"resource:///modules/CustomizableUI.jsm"
|
||||
);
|
||||
registerCleanupFunction(() => SidebarUI.hide());
|
||||
|
||||
let placement = CustomizableUI.getPlacementOfWidget("sidebar-button");
|
||||
if (!(placement?.area == CustomizableUI.AREA_NAVBAR)) {
|
||||
CustomizableUI.addWidgetToArea(
|
||||
"sidebar-button",
|
||||
CustomizableUI.AREA_NAVBAR,
|
||||
0
|
||||
);
|
||||
CustomizableUI.ensureWidgetPlacedInWindow("sidebar-button", window);
|
||||
registerCleanupFunction(function() {
|
||||
CustomizableUI.removeWidgetFromArea("sidebar-button");
|
||||
});
|
||||
}
|
||||
|
||||
let widgetIcon = CustomizableUI.getWidget("sidebar-button")
|
||||
.forWindow(window)
|
||||
.node?.querySelector(".toolbarbutton-icon");
|
||||
// Get the alpha value of the sidebar toggle widget's background
|
||||
let getBGAlpha = () =>
|
||||
InspectorUtils.colorToRGBA(
|
||||
getComputedStyle(widgetIcon).getPropertyValue("background-color")
|
||||
).a;
|
||||
|
||||
let promiseShown = BrowserTestUtils.waitForEvent(window, "SidebarShown");
|
||||
SidebarUI.show("viewBookmarksSidebar");
|
||||
await promiseShown;
|
||||
|
||||
Assert.greater(
|
||||
getBGAlpha(),
|
||||
0,
|
||||
"Sidebar widget background should appear checked"
|
||||
);
|
||||
|
||||
// Enter customize mode. This should disable the toggle and make the sidebar
|
||||
// toggle widget appear unchecked.
|
||||
let customizationReadyPromise = BrowserTestUtils.waitForEvent(
|
||||
gNavToolbox,
|
||||
"customizationready"
|
||||
);
|
||||
gCustomizeMode.enter();
|
||||
await customizationReadyPromise;
|
||||
|
||||
Assert.equal(
|
||||
getBGAlpha(),
|
||||
0,
|
||||
"Sidebar widget background should appear unchecked"
|
||||
);
|
||||
|
||||
// Attempt toggle - should fail in customize mode.
|
||||
await SidebarUI.toggle();
|
||||
ok(SidebarUI.isOpen, "Sidebar is still open");
|
||||
|
||||
// Exit customize mode. This should re-enable the toggle and make the sidebar
|
||||
// toggle widget appear checked again, since toggle() didn't hide the sidebar.
|
||||
let afterCustomizationPromise = BrowserTestUtils.waitForEvent(
|
||||
gNavToolbox,
|
||||
"aftercustomization"
|
||||
);
|
||||
gCustomizeMode.exit();
|
||||
await afterCustomizationPromise;
|
||||
|
||||
Assert.greater(
|
||||
getBGAlpha(),
|
||||
0,
|
||||
"Sidebar widget background should appear checked again"
|
||||
);
|
||||
|
||||
await SidebarUI.toggle();
|
||||
ok(!SidebarUI.isOpen, "Sidebar is closed");
|
||||
Assert.equal(
|
||||
getBGAlpha(),
|
||||
0,
|
||||
"Sidebar widget background should appear unchecked"
|
||||
);
|
||||
});
|
||||
|
@ -26,18 +26,11 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
ShellService: "resource:///modules/ShellService.jsm",
|
||||
UpdatePing: "resource://gre/modules/UpdatePing.jsm",
|
||||
});
|
||||
XPCOMUtils.defineLazyServiceGetter(
|
||||
this,
|
||||
"WindowsUIUtils",
|
||||
"@mozilla.org/windows-ui-utils;1",
|
||||
"nsIWindowsUIUtils"
|
||||
);
|
||||
XPCOMUtils.defineLazyServiceGetter(
|
||||
this,
|
||||
"UpdateManager",
|
||||
"@mozilla.org/updates/update-manager;1",
|
||||
"nsIUpdateManager"
|
||||
);
|
||||
XPCOMUtils.defineLazyServiceGetters(this, {
|
||||
UpdateManager: ["@mozilla.org/updates/update-manager;1", "nsIUpdateManager"],
|
||||
WinTaskbar: ["@mozilla.org/windows-taskbar;1", "nsIWinTaskbar"],
|
||||
WindowsUIUtils: ["@mozilla.org/windows-ui-utils;1", "nsIWindowsUIUtils"],
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gSystemPrincipal", () =>
|
||||
Services.scriptSecurityManager.getSystemPrincipal()
|
||||
@ -48,6 +41,11 @@ XPCOMUtils.defineLazyGlobalGetters(this, [URL]);
|
||||
const ONCE_DOMAINS = ["mozilla.org", "firefox.com"];
|
||||
const ONCE_PREF = "browser.startup.homepage_override.once";
|
||||
|
||||
// Index of Private Browsing icon in firefox.exe
|
||||
// Must line up with the one in nsNativeAppSupportWin.h.
|
||||
const PRIVATE_BROWSING_ICON_INDEX = 5;
|
||||
const PRIVACY_SEGMENTATION_PREF = "browser.privacySegmentation.enabled";
|
||||
|
||||
function shouldLoadURI(aURI) {
|
||||
if (aURI && !aURI.schemeIs("chrome")) {
|
||||
return true;
|
||||
@ -276,6 +274,20 @@ function openBrowserWindow(
|
||||
win.docShell.QueryInterface(
|
||||
Ci.nsILoadContext
|
||||
).usePrivateBrowsing = true;
|
||||
if (Services.prefs.getBoolPref(PRIVACY_SEGMENTATION_PREF)) {
|
||||
// TODO: Changing this after the Window has been painted causes it to
|
||||
// change Taskbar icons if the original one had a different AUMID.
|
||||
// This must stay pref'ed off until this is resolved.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1751010
|
||||
WinTaskbar.setGroupIdForWindow(win, WinTaskbar.defaultPrivateGroupId);
|
||||
WindowsUIUtils.setWindowIconFromExe(
|
||||
win,
|
||||
Services.dirsvc.get("XREExeF", Ci.nsIFile).path,
|
||||
// This corresponds to the definitions in
|
||||
// nsNativeAppSupportWin.h
|
||||
PRIVATE_BROWSING_ICON_INDEX
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let openTime = win.openTime;
|
||||
|
@ -29,33 +29,6 @@
|
||||
* dispatches the commands that apply to individual items.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A few words on focus and focusrings
|
||||
*
|
||||
* We do quite a few hacks in the Downloads Panel for focusrings. In fact, we
|
||||
* basically suppress most if not all XUL-level focusrings, and style/draw
|
||||
* them ourselves (using :focus instead of -moz-focusring). There are a few
|
||||
* reasons for this:
|
||||
*
|
||||
* 1) Richlists on OSX don't have focusrings; instead, they are shown as
|
||||
* selected. This makes for some ambiguity when we have a focused/selected
|
||||
* item in the list, and the mouse is hovering a completed download (which
|
||||
* highlights).
|
||||
* 2) Windows doesn't show focusrings until after the first time that tab is
|
||||
* pressed (and by then you're focusing the second item in the panel).
|
||||
* 3) Richlistbox sets -moz-focusring even when we select it with a mouse.
|
||||
*
|
||||
* In general, the desired behaviour is to focus the first item after pressing
|
||||
* tab/down, and show that focus with a ring. Then, if the mouse moves over
|
||||
* the panel, to hide that focus ring; essentially resetting us to the state
|
||||
* before pressing the key.
|
||||
*
|
||||
* We end up capturing the tab/down key events, and preventing their default
|
||||
* behaviour. We then set a "keyfocus" attribute on the panel, which allows
|
||||
* us to draw a ring around the currently focused element. If the panel is
|
||||
* closed or the mouse moves over the panel, we remove the attribute.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
var { XPCOMUtils } = ChromeUtils.import(
|
||||
@ -249,6 +222,9 @@ var DownloadsPanel = {
|
||||
Services.telemetry.scalarAdd("downloads.panel_shown", 1);
|
||||
DownloadsCommon.log("Opening the downloads panel.");
|
||||
|
||||
this._openedManually = openedManually;
|
||||
this._preventFocusRing = !openedManually || !isKeyPress;
|
||||
|
||||
if (this.isPanelShowing) {
|
||||
DownloadsCommon.log("Panel is already showing - focusing instead.");
|
||||
this._focusPanel();
|
||||
@ -263,7 +239,7 @@ var DownloadsPanel = {
|
||||
// called while another window is closing (like the window for selecting
|
||||
// whether to save or open the file), and that would cause the panel to
|
||||
// close immediately.
|
||||
setTimeout(() => this._openPopupIfDataReady(openedManually, isKeyPress), 0);
|
||||
setTimeout(() => this._openPopupIfDataReady(), 0);
|
||||
|
||||
DownloadsCommon.log("Waiting for the downloads panel to appear.");
|
||||
this._state = this.kStateWaitingData;
|
||||
@ -299,36 +275,17 @@ var DownloadsPanel = {
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns whether the user has started keyboard navigation.
|
||||
*/
|
||||
get keyFocusing() {
|
||||
return this.panel.hasAttribute("keyfocus");
|
||||
},
|
||||
|
||||
/**
|
||||
* Set to true if the user has started keyboard navigation, and we should be
|
||||
* showing focusrings in the panel. Also adds a mousemove event handler to
|
||||
* the panel which disables keyFocusing.
|
||||
*/
|
||||
set keyFocusing(aValue) {
|
||||
if (aValue) {
|
||||
this.panel.setAttribute("keyfocus", "true");
|
||||
this.panel.addEventListener("mousemove", this);
|
||||
} else {
|
||||
this.panel.removeAttribute("keyfocus");
|
||||
this.panel.removeEventListener("mousemove", this);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the mousemove event for the panel, which disables focusring
|
||||
* visualization.
|
||||
*/
|
||||
handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "mousemove":
|
||||
this.keyFocusing = false;
|
||||
if (this.panel.contains(document.activeElement)) {
|
||||
// Let mouse movement remove focus rings and reset focus in the panel.
|
||||
// This behavior is copied from PanelMultiView.
|
||||
document.activeElement.blur();
|
||||
DownloadsView.richListBox.removeAttribute("force-focus-visible");
|
||||
this._preventFocusRing = true;
|
||||
this._focusPanel();
|
||||
}
|
||||
break;
|
||||
case "keydown":
|
||||
this._onKeyDown(aEvent);
|
||||
@ -395,9 +352,7 @@ var DownloadsPanel = {
|
||||
this._delayTimeout = null;
|
||||
}
|
||||
|
||||
// Removes the keyfocus attribute so that we stop handling keyboard
|
||||
// navigation.
|
||||
this.keyFocusing = false;
|
||||
DownloadsView.richListBox.removeAttribute("force-focus-visible");
|
||||
|
||||
// Since at most one popup is open at any given time, we can set globally.
|
||||
DownloadsCommon.getIndicatorData(
|
||||
@ -438,6 +393,7 @@ var DownloadsPanel = {
|
||||
// Handle keypress to be able to preventDefault() events before they reach
|
||||
// the richlistbox, for keyboard navigation.
|
||||
this.panel.addEventListener("keypress", this);
|
||||
this.panel.addEventListener("mousemove", this);
|
||||
DownloadsView.richListBox.addEventListener("focus", this);
|
||||
DownloadsView.richListBox.addEventListener("select", this);
|
||||
},
|
||||
@ -449,6 +405,7 @@ var DownloadsPanel = {
|
||||
_unattachEventListeners() {
|
||||
this.panel.removeEventListener("keydown", this);
|
||||
this.panel.removeEventListener("keypress", this);
|
||||
this.panel.removeEventListener("mousemove", this);
|
||||
DownloadsView.richListBox.removeEventListener("focus", this);
|
||||
DownloadsView.richListBox.removeEventListener("select", this);
|
||||
},
|
||||
@ -475,20 +432,21 @@ var DownloadsPanel = {
|
||||
this._handlePotentiallySpammyDownloadActivation(aEvent);
|
||||
return;
|
||||
}
|
||||
// If the user has pressed the tab, up, or down cursor key, start keyboard
|
||||
// navigation, thus enabling focusrings in the panel. Keyboard navigation
|
||||
// is automatically disabled if the user moves the mouse on the panel, or
|
||||
// if the panel is closed.
|
||||
if (
|
||||
(aEvent.keyCode == aEvent.DOM_VK_TAB ||
|
||||
aEvent.keyCode == aEvent.DOM_VK_UP ||
|
||||
aEvent.keyCode == aEvent.DOM_VK_DOWN) &&
|
||||
!this.keyFocusing
|
||||
) {
|
||||
this.keyFocusing = true;
|
||||
}
|
||||
|
||||
let richListBox = DownloadsView.richListBox;
|
||||
|
||||
// If the user has pressed the up or down cursor key, force-enable focus
|
||||
// indicators for the richlistbox. :focus-visible doesn't work in this case
|
||||
// because the the focused element may not change here if the richlistbox
|
||||
// already had focus. The force-focus-visible attribute will be removed
|
||||
// again if the user moves the mouse on the panel or if the panel is closed.
|
||||
if (
|
||||
aEvent.keyCode == aEvent.DOM_VK_UP ||
|
||||
aEvent.keyCode == aEvent.DOM_VK_DOWN
|
||||
) {
|
||||
richListBox.setAttribute("force-focus-visible", "true");
|
||||
}
|
||||
|
||||
// If the footer is focused and the downloads list has at least 1 element
|
||||
// in it, focus the last element in the list when going up.
|
||||
if (aEvent.keyCode == aEvent.DOM_VK_UP && richListBox.firstElementChild) {
|
||||
@ -575,17 +533,15 @@ var DownloadsPanel = {
|
||||
return;
|
||||
}
|
||||
|
||||
let element = document.commandDispatcher.focusedElement;
|
||||
while (element && element != this.panel) {
|
||||
element = element.parentNode;
|
||||
if (document.activeElement && this.panel.contains(document.activeElement)) {
|
||||
return;
|
||||
}
|
||||
if (!element) {
|
||||
if (DownloadsView.richListBox.itemCount > 0) {
|
||||
DownloadsView.richListBox.selectedIndex = 0;
|
||||
DownloadsView.richListBox.focus();
|
||||
} else {
|
||||
DownloadsFooter.focus();
|
||||
}
|
||||
let focusOptions = { preventFocusRing: !!this._preventFocusRing };
|
||||
if (DownloadsView.richListBox.itemCount > 0) {
|
||||
DownloadsView.richListBox.selectedIndex = 0;
|
||||
DownloadsView.richListBox.focus(focusOptions);
|
||||
} else {
|
||||
DownloadsFooter.focus(focusOptions);
|
||||
}
|
||||
},
|
||||
|
||||
@ -636,7 +592,7 @@ var DownloadsPanel = {
|
||||
/**
|
||||
* Opens the downloads panel when data is ready to be displayed.
|
||||
*/
|
||||
_openPopupIfDataReady(openedManually, isKeyPress) {
|
||||
_openPopupIfDataReady() {
|
||||
// We don't want to open the popup if we already displayed it, or if we are
|
||||
// still loading data.
|
||||
if (this._state != this.kStateWaitingData || DownloadsView.loading) {
|
||||
@ -675,11 +631,6 @@ var DownloadsPanel = {
|
||||
|
||||
DownloadsCommon.log("Opening downloads panel popup.");
|
||||
|
||||
if (isKeyPress) {
|
||||
// If the panel was opened via a keypress, enable focus indicators.
|
||||
this.keyFocusing = true;
|
||||
}
|
||||
|
||||
// Delay displaying the panel because this function will sometimes be
|
||||
// called while another window is closing (like the window for selecting
|
||||
// whether to save or open the file), and that would cause the panel to
|
||||
@ -698,7 +649,7 @@ var DownloadsPanel = {
|
||||
this._state = this.kStateHidden;
|
||||
});
|
||||
|
||||
if (!openedManually) {
|
||||
if (!this._openedManually) {
|
||||
this._delayPopupItems();
|
||||
}
|
||||
}, 0);
|
||||
@ -1528,9 +1479,9 @@ var DownloadsSummary = {
|
||||
/**
|
||||
* Focuses the root element of the summary.
|
||||
*/
|
||||
focus() {
|
||||
focus(focusOptions) {
|
||||
if (this._summaryNode) {
|
||||
this._summaryNode.focus();
|
||||
this._summaryNode.focus(focusOptions);
|
||||
}
|
||||
},
|
||||
|
||||
@ -1624,11 +1575,11 @@ var DownloadsFooter = {
|
||||
* is visible, focus it. If not, focus the "Show all downloads"
|
||||
* button.
|
||||
*/
|
||||
focus() {
|
||||
focus(focusOptions) {
|
||||
if (this._showingSummary) {
|
||||
DownloadsSummary.focus();
|
||||
DownloadsSummary.focus(focusOptions);
|
||||
} else {
|
||||
DownloadsView.downloadsHistory.focus({ preventFocusRing: true });
|
||||
DownloadsView.downloadsHistory.focus(focusOptions);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -152,21 +152,9 @@ add_task(async function test_downloads_keynav() {
|
||||
EventUtils.synthesizeMouseAtCenter(listbox.getItemAtIndex(1), {
|
||||
type: "mousemove",
|
||||
});
|
||||
is(listbox.selectedIndex, 1, "downloads list selected index after mousemove");
|
||||
is(listbox.selectedIndex, 0, "downloads list selected index after mousemove");
|
||||
|
||||
checkTabbing(listbox, 1);
|
||||
|
||||
EventUtils.synthesizeKey("VK_UP", {});
|
||||
is(
|
||||
document.activeElement,
|
||||
listbox,
|
||||
"downloads list is focused after up to index 0"
|
||||
);
|
||||
is(
|
||||
listbox.selectedIndex,
|
||||
0,
|
||||
"downloads list selected index after up to index 0"
|
||||
);
|
||||
checkTabbing(listbox, 0);
|
||||
|
||||
EventUtils.synthesizeKey("VK_UP", {});
|
||||
is(
|
||||
|
@ -35,6 +35,8 @@ XPCOMUtils.defineLazyPreferenceGetter(
|
||||
* @property {string} title
|
||||
* The title of the group, this may be automatically generated or
|
||||
* user assigned.
|
||||
* @property {boolean} hidden
|
||||
* Whether the group is hidden or not.
|
||||
* @property {string} builder
|
||||
* The builder that was used to create the group (e.g. "domain", "pinned").
|
||||
* @property {object} builderMetadata
|
||||
@ -104,24 +106,46 @@ const SnapshotGroups = new (class SnapshotGroups {
|
||||
* Modifies the metadata for a snapshot group.
|
||||
*
|
||||
* @param {SnapshotGroup} group
|
||||
* The details of the group to modify. If lastAccessed and SnapshotCount are specified, then they are ignored.
|
||||
* The partial details of the group to modify. Must include the group's id. Any other properties
|
||||
* update those properties of the group. If builder, imageUrl, lastAccessed or snapshotCount are
|
||||
* specified then they are ignored.
|
||||
*/
|
||||
async updateMetadata(group) {
|
||||
await PlacesUtils.withConnectionWrapper(
|
||||
"SnapshotsGroups.jsm:updateMetadata",
|
||||
db => {
|
||||
return db.executeCached(
|
||||
`
|
||||
UPDATE moz_places_metadata_snapshots_groups
|
||||
SET title = :title, builder = :builder, builder_data = :builder_data
|
||||
WHERE id = :id
|
||||
`,
|
||||
{
|
||||
id: group.id,
|
||||
title: group.title,
|
||||
builder: group.builder,
|
||||
builder_data: JSON.stringify(group.builderMetadata),
|
||||
async db => {
|
||||
let params = { id: group.id };
|
||||
let updates = {
|
||||
title: group.title,
|
||||
builder_data:
|
||||
"builderMetadata" in group
|
||||
? JSON.stringify(group.builderMetadata)
|
||||
: undefined,
|
||||
};
|
||||
|
||||
if ("hidden" in group) {
|
||||
updates.hidden = group.hidden ? 1 : 0;
|
||||
}
|
||||
|
||||
let setters = [];
|
||||
for (let [key, value] of Object.entries(updates)) {
|
||||
if (value !== undefined) {
|
||||
setters.push(`${key} = :${key}`);
|
||||
params[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
if (!setters.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
await db.executeCached(
|
||||
`
|
||||
UPDATE moz_places_metadata_snapshots_groups
|
||||
SET ${setters.join(", ")}
|
||||
WHERE id = :id
|
||||
`,
|
||||
params
|
||||
);
|
||||
}
|
||||
);
|
||||
@ -189,6 +213,8 @@ const SnapshotGroups = new (class SnapshotGroups {
|
||||
* @param {number} [options.limit]
|
||||
* A numerical limit to the number of snapshots to retrieve, defaults to 50.
|
||||
* Use -1 to specify no limit.
|
||||
* @param {boolean} [options.hidden]
|
||||
* Pass true to also return hidden groups.
|
||||
* @param {string} [options.builder]
|
||||
* Limit searching snapshot groups to results from a particular builder.
|
||||
* @param {boolean} [options.skipMinimum]
|
||||
@ -198,10 +224,15 @@ const SnapshotGroups = new (class SnapshotGroups {
|
||||
* @returns {SnapshotGroup[]}
|
||||
* An array of snapshot groups, in descending order of last access time.
|
||||
*/
|
||||
async query({ limit = 50, builder = "", skipMinimum = false } = {}) {
|
||||
async query({
|
||||
limit = 50,
|
||||
builder = undefined,
|
||||
hidden = false,
|
||||
skipMinimum = false,
|
||||
} = {}) {
|
||||
let db = await PlacesUtils.promiseDBConnection();
|
||||
|
||||
let params = { builder };
|
||||
let params = {};
|
||||
let sizeFragment = "";
|
||||
let limitFragment = "";
|
||||
if (!skipMinimum) {
|
||||
@ -213,9 +244,22 @@ const SnapshotGroups = new (class SnapshotGroups {
|
||||
limitFragment = "LIMIT :limit";
|
||||
}
|
||||
|
||||
let whereTerms = [];
|
||||
|
||||
if (builder) {
|
||||
whereTerms.push("builder = :builder");
|
||||
params.builder = builder;
|
||||
}
|
||||
|
||||
if (!hidden) {
|
||||
whereTerms.push("hidden = 0");
|
||||
}
|
||||
|
||||
let where = whereTerms.length ? `WHERE ${whereTerms.join(" AND ")}` : "";
|
||||
|
||||
let rows = await db.executeCached(
|
||||
`
|
||||
SELECT g.id, g.title, g.builder, g.builder_data,
|
||||
SELECT g.id, g.title, g.hidden, g.builder, g.builder_data,
|
||||
COUNT(s.group_id) AS snapshot_count,
|
||||
MAX(sn.last_interaction_at) AS last_access,
|
||||
(SELECT group_concat(IFNULL(preview_image_url, ''), '|')
|
||||
@ -233,7 +277,7 @@ const SnapshotGroups = new (class SnapshotGroups {
|
||||
FROM moz_places_metadata_snapshots_groups g
|
||||
LEFT JOIN moz_places_metadata_groups_to_snapshots s ON s.group_id = g.id
|
||||
LEFT JOIN moz_places_metadata_snapshots sn ON sn.place_id = s.place_id
|
||||
WHERE builder = :builder OR :builder = ""
|
||||
${where}
|
||||
GROUP BY g.id ${sizeFragment}
|
||||
ORDER BY last_access DESC
|
||||
${limitFragment}
|
||||
@ -398,6 +442,7 @@ const SnapshotGroups = new (class SnapshotGroups {
|
||||
id: row.getResultByName("id"),
|
||||
imageUrl,
|
||||
title: row.getResultByName("title"),
|
||||
hidden: row.getResultByName("hidden") == 1,
|
||||
builder: row.getResultByName("builder"),
|
||||
builderMetadata: JSON.parse(row.getResultByName("builder_data")),
|
||||
snapshotCount: row.getResultByName("snapshot_count"),
|
||||
|
@ -67,83 +67,103 @@ add_task(async function test_change_location_from_Toolbar() {
|
||||
|
||||
let toolbarNode = getToolbarNodeForItemGuid(toolbarBookmark.guid);
|
||||
|
||||
await withBookmarksDialog(
|
||||
false,
|
||||
async function openPropertiesDialog() {
|
||||
let placesContext = document.getElementById("placesContext");
|
||||
let promisePopup = BrowserTestUtils.waitForEvent(
|
||||
placesContext,
|
||||
"popupshown"
|
||||
);
|
||||
EventUtils.synthesizeMouseAtCenter(toolbarNode, {
|
||||
button: 2,
|
||||
type: "contextmenu",
|
||||
add_task(
|
||||
async function change_location_from_toolbar_dialog_instantEditBookmark() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.bookmarks.editDialog.delayedApply.enabled", false]],
|
||||
});
|
||||
await promisePopup;
|
||||
await withBookmarksDialog(
|
||||
false,
|
||||
async function openPropertiesDialog() {
|
||||
let placesContext = document.getElementById("placesContext");
|
||||
let promisePopup = BrowserTestUtils.waitForEvent(
|
||||
placesContext,
|
||||
"popupshown"
|
||||
);
|
||||
EventUtils.synthesizeMouseAtCenter(toolbarNode, {
|
||||
button: 2,
|
||||
type: "contextmenu",
|
||||
});
|
||||
await promisePopup;
|
||||
|
||||
let properties = document.getElementById(
|
||||
"placesContext_show_bookmark:info"
|
||||
);
|
||||
placesContext.activateItem(properties);
|
||||
},
|
||||
async function test(dialogWin) {
|
||||
// Check the initial location.
|
||||
let locationPicker = dialogWin.document.getElementById(
|
||||
"editBMPanel_locationField"
|
||||
);
|
||||
Assert.equal(
|
||||
locationPicker.value,
|
||||
TEST_URL,
|
||||
"The location is the expected one."
|
||||
);
|
||||
let properties = document.getElementById(
|
||||
"placesContext_show_bookmark:info"
|
||||
);
|
||||
placesContext.activateItem(properties);
|
||||
},
|
||||
async function test(dialogWin) {
|
||||
// Check the initial location.
|
||||
let locationPicker = dialogWin.document.getElementById(
|
||||
"editBMPanel_locationField"
|
||||
);
|
||||
Assert.equal(
|
||||
locationPicker.value,
|
||||
TEST_URL,
|
||||
"InstantEditBookmark: The location is the expected one."
|
||||
);
|
||||
|
||||
let promiseLocationChange = PlacesTestUtils.waitForNotification(
|
||||
"bookmark-url-changed",
|
||||
events => events.some(e => e.url === TEST_URL2),
|
||||
"places"
|
||||
);
|
||||
// Update the "location" field.
|
||||
fillBookmarkTextField(
|
||||
"editBMPanel_locationField",
|
||||
TEST_URL2,
|
||||
dialogWin,
|
||||
false
|
||||
);
|
||||
await TestUtils.waitForCondition(
|
||||
() => locationPicker.value === TEST_URL2,
|
||||
"The location is correct after update."
|
||||
);
|
||||
locationPicker.blur();
|
||||
await promiseLocationChange;
|
||||
Assert.equal(
|
||||
dialogWin.gEditItemOverlay.uri.spec,
|
||||
TEST_URL2,
|
||||
"The location is the expected one."
|
||||
);
|
||||
locationPicker.focus();
|
||||
// Confirm and close the dialog.
|
||||
EventUtils.synthesizeKey("VK_RETURN", {}, dialogWin);
|
||||
let promiseLocationChange = PlacesTestUtils.waitForNotification(
|
||||
"bookmark-url-changed",
|
||||
events => events.some(e => e.url === TEST_URL2),
|
||||
"places"
|
||||
);
|
||||
// Update the "location" field.
|
||||
fillBookmarkTextField(
|
||||
"editBMPanel_locationField",
|
||||
TEST_URL2,
|
||||
dialogWin,
|
||||
false
|
||||
);
|
||||
await TestUtils.waitForCondition(
|
||||
() => locationPicker.value === TEST_URL2,
|
||||
"InstantEditBookmark: The location is correct after update."
|
||||
);
|
||||
locationPicker.blur();
|
||||
await promiseLocationChange;
|
||||
Assert.equal(
|
||||
dialogWin.gEditItemOverlay.uri.spec,
|
||||
TEST_URL2,
|
||||
"InstantEditBookmark: The location is the expected one."
|
||||
);
|
||||
locationPicker.focus();
|
||||
// Confirm and close the dialog.
|
||||
EventUtils.synthesizeKey("VK_RETURN", {}, dialogWin);
|
||||
|
||||
let updatedBm = await PlacesUtils.bookmarks.fetch(toolbarBookmark.guid);
|
||||
Assert.equal(
|
||||
updatedBm.url,
|
||||
TEST_URL2,
|
||||
"Should have updated the bookmark location in the database."
|
||||
let updatedBm = await PlacesUtils.bookmarks.fetch(
|
||||
toolbarBookmark.guid
|
||||
);
|
||||
Assert.equal(
|
||||
updatedBm.url,
|
||||
TEST_URL2,
|
||||
"InstantEditBookmark: Should have updated the bookmark location in the database."
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function test_change_location_from_Sidebar() {
|
||||
let bm = await PlacesUtils.bookmarks.fetch({ url: TEST_URL2 });
|
||||
|
||||
await withSidebarTree("bookmarks", async function(tree) {
|
||||
tree.selectItems([bm.guid]);
|
||||
|
||||
add_task(async function change_location_from_toolbar_dialog_editBookmark() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.bookmarks.editDialog.delayedApply.enabled", true]],
|
||||
});
|
||||
await withBookmarksDialog(
|
||||
false,
|
||||
function openPropertiesDialog() {
|
||||
tree.controller.doCommand("placesCmd_show:info");
|
||||
async function openPropertiesDialog() {
|
||||
let placesContext = document.getElementById("placesContext");
|
||||
let promisePopup = BrowserTestUtils.waitForEvent(
|
||||
placesContext,
|
||||
"popupshown"
|
||||
);
|
||||
EventUtils.synthesizeMouseAtCenter(toolbarNode, {
|
||||
button: 2,
|
||||
type: "contextmenu",
|
||||
});
|
||||
await promisePopup;
|
||||
|
||||
let properties = document.getElementById(
|
||||
"placesContext_show_bookmark:info"
|
||||
);
|
||||
placesContext.activateItem(properties);
|
||||
},
|
||||
async function test(dialogWin) {
|
||||
// Check the initial location.
|
||||
@ -153,13 +173,7 @@ add_task(async function test_change_location_from_Sidebar() {
|
||||
Assert.equal(
|
||||
locationPicker.value,
|
||||
TEST_URL2,
|
||||
"The location is the expected one."
|
||||
);
|
||||
|
||||
let promiseLocationChange = PlacesTestUtils.waitForNotification(
|
||||
"bookmark-url-changed",
|
||||
events => events.some(e => e.url === TEST_URL3),
|
||||
"places"
|
||||
"EditBookmark: The current location is the expected one."
|
||||
);
|
||||
|
||||
// Update the "location" field.
|
||||
@ -169,22 +183,140 @@ add_task(async function test_change_location_from_Sidebar() {
|
||||
dialogWin,
|
||||
false
|
||||
);
|
||||
await TestUtils.waitForCondition(
|
||||
() => locationPicker.value === TEST_URL3,
|
||||
"The location is correct after update."
|
||||
|
||||
locationPicker.blur();
|
||||
|
||||
Assert.equal(
|
||||
locationPicker.value,
|
||||
TEST_URL3,
|
||||
"EditBookmark: The changed location is the expected one."
|
||||
);
|
||||
|
||||
locationPicker.focus();
|
||||
// Confirm and close the dialog.
|
||||
EventUtils.synthesizeKey("VK_RETURN", {}, dialogWin);
|
||||
await promiseLocationChange;
|
||||
|
||||
let updatedBm = await PlacesUtils.bookmarks.fetch(bm.guid);
|
||||
Assert.equal(
|
||||
updatedBm.url,
|
||||
TEST_URL3,
|
||||
"Should have updated the bookmark location in the database."
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
let updatedBm = await PlacesUtils.bookmarks.fetch(toolbarBookmark.guid);
|
||||
Assert.equal(
|
||||
updatedBm.url,
|
||||
TEST_URL3,
|
||||
"EditBookmark: Should have updated the bookmark location in the database."
|
||||
);
|
||||
});
|
||||
|
||||
add_task(
|
||||
async function instantEditBookmark_test_change_location_from_Sidebar() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.bookmarks.editDialog.delayedApply.enabled", false]],
|
||||
});
|
||||
let bm = await PlacesUtils.bookmarks.fetch({ url: TEST_URL });
|
||||
|
||||
await withSidebarTree("bookmarks", async function(tree) {
|
||||
tree.selectItems([bm.guid]);
|
||||
|
||||
await withBookmarksDialog(
|
||||
false,
|
||||
function openPropertiesDialog() {
|
||||
tree.controller.doCommand("placesCmd_show:info");
|
||||
},
|
||||
async function test(dialogWin) {
|
||||
// Check the initial location.
|
||||
let locationPicker = dialogWin.document.getElementById(
|
||||
"editBMPanel_locationField"
|
||||
);
|
||||
Assert.equal(
|
||||
locationPicker.value,
|
||||
TEST_URL,
|
||||
"Sidebar - InstantEditBookmark: The current location is the expected one."
|
||||
);
|
||||
|
||||
let promiseLocationChange = PlacesTestUtils.waitForNotification(
|
||||
"bookmark-url-changed",
|
||||
events => events.some(e => e.url === TEST_URL3),
|
||||
"places"
|
||||
);
|
||||
|
||||
// Update the "location" field.
|
||||
fillBookmarkTextField(
|
||||
"editBMPanel_locationField",
|
||||
TEST_URL3,
|
||||
dialogWin,
|
||||
false
|
||||
);
|
||||
await TestUtils.waitForCondition(
|
||||
() => locationPicker.value === TEST_URL3,
|
||||
"Sidebar - InstantEditBookmark: The location is correct after update."
|
||||
);
|
||||
|
||||
// Confirm and close the dialog.
|
||||
EventUtils.synthesizeKey("VK_RETURN", {}, dialogWin);
|
||||
await promiseLocationChange;
|
||||
|
||||
let updatedBm = await PlacesUtils.bookmarks.fetch(bm.guid);
|
||||
Assert.equal(
|
||||
updatedBm.url,
|
||||
TEST_URL3,
|
||||
"Sidebar - InstantEditBookmark: Should have updated the bookmark location in the database."
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
add_task(async function editBookmark_test_change_location_from_Sidebar() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.bookmarks.editDialog.delayedApply.enabled", true]],
|
||||
});
|
||||
let bm = await PlacesUtils.bookmarks.fetch({ url: TEST_URL3 });
|
||||
|
||||
await withSidebarTree("bookmarks", async function(tree) {
|
||||
tree.selectItems([bm.guid]);
|
||||
|
||||
await withBookmarksDialog(
|
||||
false,
|
||||
function openPropertiesDialog() {
|
||||
tree.controller.doCommand("placesCmd_show:info");
|
||||
},
|
||||
async function test(dialogWin) {
|
||||
// Check the initial location.
|
||||
let locationPicker = dialogWin.document.getElementById(
|
||||
"editBMPanel_locationField"
|
||||
);
|
||||
|
||||
Assert.equal(
|
||||
locationPicker.value,
|
||||
TEST_URL3,
|
||||
"Sidebar - EditBookmark: The current location is the expected one."
|
||||
);
|
||||
|
||||
// Update the "location" field.
|
||||
fillBookmarkTextField(
|
||||
"editBMPanel_locationField",
|
||||
TEST_URL2,
|
||||
dialogWin,
|
||||
false
|
||||
);
|
||||
|
||||
Assert.equal(
|
||||
locationPicker.value,
|
||||
TEST_URL2,
|
||||
"Sidebar - EditBookmark: The location is changed in dialog for prefered one."
|
||||
);
|
||||
|
||||
// Confirm and close the dialog.
|
||||
EventUtils.synthesizeKey("VK_RETURN", {}, dialogWin);
|
||||
}
|
||||
);
|
||||
|
||||
let updatedBm = await PlacesUtils.bookmarks.fetch(bm.guid);
|
||||
Assert.equal(
|
||||
updatedBm.url,
|
||||
TEST_URL2,
|
||||
"Sidebar - EditBookmark: Should have updated the bookmark location in the database."
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -308,6 +308,43 @@ function assertSnapshotGroup(group, expected) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the list of snapshot groups match the expected values.
|
||||
*
|
||||
* @param {SnapshotGroup[]} received
|
||||
* The received snapshots.
|
||||
* @param {SnapshotGroup[]} expected
|
||||
* The expected snapshots.
|
||||
*/
|
||||
async function assertSnapshotGroupList(received, expected) {
|
||||
info(
|
||||
`Found ${received.length} snapshot groups:\n ${JSON.stringify(received)}`
|
||||
);
|
||||
Assert.equal(
|
||||
received.length,
|
||||
expected.length,
|
||||
"Should have the expected number of snapshots"
|
||||
);
|
||||
for (let i = 0; i < expected.length; i++) {
|
||||
assertSnapshotGroup(received[i], expected[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of snapshot groups and a list of ids returns the groups in that
|
||||
* order.
|
||||
*
|
||||
* @param {SnapshotGroup[]} list
|
||||
* The list of groups.
|
||||
* @param {string[]} order
|
||||
* The ids of groups.
|
||||
* @returns {SnapshotGroup[]} The list of groups in the order expected.
|
||||
*/
|
||||
function orderedGroups(list, order) {
|
||||
let groups = Object.fromEntries(list.map(g => [g.id, g]));
|
||||
return order.map(id => groups[id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries overlapping snapshots from the database and asserts their expected values.
|
||||
*
|
||||
|
@ -81,6 +81,7 @@ add_task(async function test_add_and_query() {
|
||||
assertSnapshotGroup(groups[0], {
|
||||
title: "Test Group",
|
||||
builder: "domain",
|
||||
hidden: false,
|
||||
snapshotCount: data.length,
|
||||
lastAccessed: now - 10000,
|
||||
imageUrl: getPageThumbURL(TEST_URL1),
|
||||
@ -96,6 +97,7 @@ add_task(async function test_add_and_query() {
|
||||
assertSnapshotGroup(groups[0], {
|
||||
title: "Test Group",
|
||||
builder: "domain",
|
||||
hidden: false,
|
||||
snapshotCount: data.length,
|
||||
lastAccessed: now - 10000,
|
||||
imageUrl: previewImageURL,
|
||||
@ -111,6 +113,7 @@ add_task(async function test_add_and_query() {
|
||||
assertSnapshotGroup(groups[0], {
|
||||
title: "Test Group",
|
||||
builder: "domain",
|
||||
hidden: false,
|
||||
snapshotCount: data.length,
|
||||
lastAccessed: now - 10000,
|
||||
imageUrl: previewImageURL,
|
||||
@ -134,6 +137,7 @@ add_task(async function test_add_and_query_builderMetadata() {
|
||||
assertSnapshotGroup(groups[0], {
|
||||
title: "Test Group",
|
||||
builder: "domain",
|
||||
hidden: false,
|
||||
builderMetadata: { domain: "example.com" },
|
||||
snapshotCount: urls.length,
|
||||
});
|
||||
@ -179,14 +183,57 @@ add_task(async function test_update_metadata() {
|
||||
);
|
||||
|
||||
groups[0].title = "Modified title";
|
||||
// This should be ignored.
|
||||
groups[0].builder = "pinned";
|
||||
await SnapshotGroups.updateMetadata(groups[0]);
|
||||
|
||||
let updated_groups = await SnapshotGroups.query({ skipMinimum: true });
|
||||
Assert.equal(updated_groups.length, 1, "Should return 1 SnapshotGroup");
|
||||
assertSnapshotGroup(groups[0], {
|
||||
assertSnapshotGroup(updated_groups[0], {
|
||||
title: "Modified title",
|
||||
builder: "pinned",
|
||||
builder: "domain",
|
||||
snapshotCount: [TEST_URL3, TEST_URL2, TEST_URL1].length,
|
||||
});
|
||||
|
||||
await SnapshotGroups.updateMetadata({
|
||||
id: groups[0].id,
|
||||
title: "Only changed title",
|
||||
});
|
||||
|
||||
updated_groups = await SnapshotGroups.query({ skipMinimum: true });
|
||||
Assert.equal(updated_groups.length, 1, "Should return 1 SnapshotGroup");
|
||||
assertSnapshotGroup(updated_groups[0], {
|
||||
title: "Only changed title",
|
||||
builder: "domain",
|
||||
snapshotCount: [TEST_URL3, TEST_URL2, TEST_URL1].length,
|
||||
});
|
||||
|
||||
await SnapshotGroups.updateMetadata({
|
||||
id: groups[0].id,
|
||||
builderMetadata: { foo: "bar" },
|
||||
});
|
||||
|
||||
updated_groups = await SnapshotGroups.query({ skipMinimum: true });
|
||||
Assert.equal(updated_groups.length, 1, "Should return 1 SnapshotGroup");
|
||||
assertSnapshotGroup(updated_groups[0], {
|
||||
title: "Only changed title",
|
||||
builder: "domain",
|
||||
builderMetadata: { foo: "bar" },
|
||||
snapshotCount: [TEST_URL3, TEST_URL2, TEST_URL1].length,
|
||||
});
|
||||
|
||||
await SnapshotGroups.updateMetadata({
|
||||
id: groups[0].id,
|
||||
title: "Modified title",
|
||||
builderMetadata: null,
|
||||
});
|
||||
|
||||
updated_groups = await SnapshotGroups.query({ skipMinimum: true });
|
||||
Assert.equal(updated_groups.length, 1, "Should return 1 SnapshotGroup");
|
||||
assertSnapshotGroup(updated_groups[0], {
|
||||
title: "Modified title",
|
||||
builder: "domain",
|
||||
builderMetadata: null,
|
||||
snapshotCount: [TEST_URL3, TEST_URL2, TEST_URL1].length,
|
||||
});
|
||||
});
|
||||
@ -194,11 +241,11 @@ add_task(async function test_update_metadata() {
|
||||
add_task(async function test_update_urls() {
|
||||
let groups = await SnapshotGroups.query({ skipMinimum: true });
|
||||
Assert.equal(groups.length, 1, "Should return 1 snapshot group");
|
||||
Assert.equal(
|
||||
groups[0].title,
|
||||
"Modified title",
|
||||
"SnapshotGroup title should be retrieved"
|
||||
);
|
||||
assertSnapshotGroup(groups[0], {
|
||||
title: "Modified title",
|
||||
builder: "domain",
|
||||
snapshotCount: [TEST_URL3, TEST_URL2, TEST_URL1].length,
|
||||
});
|
||||
|
||||
await SnapshotGroups.updateUrls(groups[0].id, [
|
||||
TEST_URL5,
|
||||
@ -210,7 +257,7 @@ add_task(async function test_update_urls() {
|
||||
Assert.equal(updated_groups.length, 1, "Should return 1 SnapshotGroup");
|
||||
assertSnapshotGroup(groups[0], {
|
||||
title: "Modified title",
|
||||
builder: "pinned",
|
||||
builder: "domain",
|
||||
snapshotCount: [TEST_URL5, TEST_URL3, TEST_URL1].length,
|
||||
});
|
||||
});
|
||||
@ -380,3 +427,127 @@ add_task(async function test_minimum_size() {
|
||||
snapshotCount: 4,
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_hidden_groups() {
|
||||
await delete_all_groups();
|
||||
|
||||
let group1 = await SnapshotGroups.add(
|
||||
{
|
||||
title: "Test Group 1",
|
||||
builder: "domain",
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
let group2 = await SnapshotGroups.add(
|
||||
{
|
||||
title: "Test Group 2",
|
||||
builder: "domain",
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
let groups = await SnapshotGroups.query({ skipMinimum: true });
|
||||
Assert.equal(groups.length, 2, "Should return all groups.");
|
||||
assertSnapshotGroupList(orderedGroups(groups, [group1, group2]), [
|
||||
{
|
||||
title: "Test Group 1",
|
||||
builder: "domain",
|
||||
hidden: false,
|
||||
snapshotCount: 0,
|
||||
},
|
||||
{
|
||||
title: "Test Group 2",
|
||||
builder: "domain",
|
||||
hidden: false,
|
||||
snapshotCount: 0,
|
||||
},
|
||||
]);
|
||||
|
||||
await SnapshotGroups.updateMetadata({
|
||||
id: group1,
|
||||
hidden: true,
|
||||
});
|
||||
|
||||
groups = await SnapshotGroups.query({ skipMinimum: true });
|
||||
Assert.equal(groups.length, 1, "Should be only one visible group.");
|
||||
assertSnapshotGroup(groups[0], {
|
||||
title: "Test Group 2",
|
||||
builder: "domain",
|
||||
hidden: false,
|
||||
snapshotCount: 0,
|
||||
});
|
||||
|
||||
groups = await SnapshotGroups.query({ hidden: true, skipMinimum: true });
|
||||
Assert.equal(groups.length, 2, "Should be two total groups.");
|
||||
assertSnapshotGroupList(orderedGroups(groups, [group1, group2]), [
|
||||
{
|
||||
title: "Test Group 1",
|
||||
builder: "domain",
|
||||
hidden: true,
|
||||
snapshotCount: 0,
|
||||
},
|
||||
{
|
||||
title: "Test Group 2",
|
||||
builder: "domain",
|
||||
hidden: false,
|
||||
snapshotCount: 0,
|
||||
},
|
||||
]);
|
||||
|
||||
await SnapshotGroups.updateMetadata({
|
||||
id: group1,
|
||||
hidden: false,
|
||||
});
|
||||
|
||||
groups = await SnapshotGroups.query({ skipMinimum: true });
|
||||
Assert.equal(groups.length, 2, "Should be two visible groups.");
|
||||
assertSnapshotGroupList(orderedGroups(groups, [group1, group2]), [
|
||||
{
|
||||
title: "Test Group 1",
|
||||
builder: "domain",
|
||||
hidden: false,
|
||||
snapshotCount: 0,
|
||||
},
|
||||
{
|
||||
title: "Test Group 2",
|
||||
builder: "domain",
|
||||
hidden: false,
|
||||
snapshotCount: 0,
|
||||
},
|
||||
]);
|
||||
|
||||
groups = await SnapshotGroups.query({ hidden: true, skipMinimum: true });
|
||||
Assert.equal(groups.length, 2, "Should be two total groups.");
|
||||
|
||||
await SnapshotGroups.updateMetadata({
|
||||
id: group2,
|
||||
hidden: true,
|
||||
});
|
||||
|
||||
groups = await SnapshotGroups.query({ skipMinimum: true });
|
||||
Assert.equal(groups.length, 1, "Should be only one visible group.");
|
||||
assertSnapshotGroup(groups[0], {
|
||||
title: "Test Group 1",
|
||||
builder: "domain",
|
||||
hidden: false,
|
||||
snapshotCount: 0,
|
||||
});
|
||||
|
||||
groups = await SnapshotGroups.query({ hidden: true, skipMinimum: true });
|
||||
Assert.equal(groups.length, 2, "Should be two total groups.");
|
||||
assertSnapshotGroupList(orderedGroups(groups, [group1, group2]), [
|
||||
{
|
||||
title: "Test Group 1",
|
||||
builder: "domain",
|
||||
hidden: false,
|
||||
snapshotCount: 0,
|
||||
},
|
||||
{
|
||||
title: "Test Group 2",
|
||||
builder: "domain",
|
||||
hidden: true,
|
||||
snapshotCount: 0,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
@ -68,6 +68,7 @@ async function renderInfo({
|
||||
infoLinkUrl ||
|
||||
RPMGetFormatURLPref("app.support.baseURL") + "private-browsing-myths"
|
||||
);
|
||||
linkEl.setAttribute("target", "_blank");
|
||||
|
||||
linkEl.addEventListener("click", () => {
|
||||
window.PrivateBrowsingRecordClick("info_link");
|
||||
@ -111,6 +112,7 @@ async function renderPromo({
|
||||
|
||||
if (vpnPromoUrl) {
|
||||
linkEl.setAttribute("href", vpnPromoUrl);
|
||||
linkEl.setAttribute("target", "_blank");
|
||||
linkEl.addEventListener("click", () => {
|
||||
window.PrivateBrowsingRecordClick("promo_link");
|
||||
});
|
||||
|
@ -539,9 +539,14 @@ add_task(async function test_experiment_messaging_system() {
|
||||
"should format the infoLinkUrl url"
|
||||
);
|
||||
is(
|
||||
content.document.querySelector(".promo a").getAttribute("href"),
|
||||
"http://bar.example.com/" + locale,
|
||||
"should format the promoLinkUrl url"
|
||||
content.document.querySelector(".info a").getAttribute("target"),
|
||||
"_blank",
|
||||
"should open info url in new tab"
|
||||
);
|
||||
is(
|
||||
content.document.querySelector(".promo a").getAttribute("target"),
|
||||
"_blank",
|
||||
"should open promo url in new tab"
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -54,6 +54,9 @@ const PREF_URLBAR_DEFAULTS = new Map([
|
||||
// this value. See UrlbarProviderPlaces.
|
||||
["autoFill.stddevMultiplier", [0.0, "float"]],
|
||||
|
||||
// Whether best match results can be blocked.
|
||||
["bestMatch.blockingEnabled", false],
|
||||
|
||||
// Whether the best match feature is enabled.
|
||||
["bestMatch.enabled", true],
|
||||
|
||||
|
@ -99,9 +99,7 @@ class ProviderQuickSuggest extends UrlbarProvider {
|
||||
* @returns {string} The help URL for the Quick Suggest best match feature.
|
||||
*/
|
||||
get bestMatchHelpUrl() {
|
||||
return (
|
||||
Services.urlFormatter.formatURLPref("app.support.baseURL") + "top-pick"
|
||||
);
|
||||
return this.helpUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -294,6 +292,11 @@ class ProviderQuickSuggest extends UrlbarProvider {
|
||||
* Whether the result was blocked.
|
||||
*/
|
||||
blockResult(result) {
|
||||
if (!UrlbarPrefs.get("bestMatch.blockingEnabled")) {
|
||||
this.logger.info("Blocking disabled, ignoring key shortcut");
|
||||
return false;
|
||||
}
|
||||
|
||||
this.logger.info("Blocking result: " + JSON.stringify(result));
|
||||
this.blockSuggestion(result.payload.originalUrl);
|
||||
return true;
|
||||
|
@ -1285,7 +1285,9 @@ class UrlbarView {
|
||||
body.appendChild(bottom);
|
||||
item._elements.set("bottom", bottom);
|
||||
|
||||
this._addRowButton(item, "block", "firefox-suggest-urlbar-block");
|
||||
if (UrlbarPrefs.get("bestMatch.blockingEnabled")) {
|
||||
this._addRowButton(item, "block", "firefox-suggest-urlbar-block");
|
||||
}
|
||||
if (result.payload.helpUrl) {
|
||||
this._addRowButton(item, "help", result.payload.helpL10nId);
|
||||
}
|
||||
|
@ -1,7 +1,13 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests best match rows in the view.
|
||||
// Tests best match rows in the view. See also:
|
||||
//
|
||||
// browser_quicksuggest_bestMatch.js
|
||||
// UI test for quick suggest best matches specifically
|
||||
// test_quicksuggest_bestMatch.js
|
||||
// Tests triggering quick suggest best matches and things that don't depend on
|
||||
// the view
|
||||
|
||||
"use strict";
|
||||
|
||||
@ -31,6 +37,27 @@ add_task(async function nonsponsoredHelpButton() {
|
||||
});
|
||||
});
|
||||
|
||||
// Tests a non-sponsored best match row with help and block buttons.
|
||||
add_task(async function nonsponsoredHelpAndBlockButtons() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.urlbar.bestMatch.blockingEnabled", true]],
|
||||
});
|
||||
let result = makeBestMatchResult({ helpUrl: "https://example.com/help" });
|
||||
await withProvider(result, async () => {
|
||||
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||
window,
|
||||
value: "test",
|
||||
});
|
||||
await checkBestMatchRow({
|
||||
result,
|
||||
hasHelpButton: true,
|
||||
hasBlockButton: true,
|
||||
});
|
||||
await UrlbarTestUtils.promisePopupClose(window);
|
||||
});
|
||||
await SpecialPowers.popPrefEnv();
|
||||
});
|
||||
|
||||
// Tests a sponsored best match row.
|
||||
add_task(async function sponsored() {
|
||||
let result = makeBestMatchResult({ isSponsored: true });
|
||||
@ -60,84 +87,121 @@ add_task(async function sponsoredHelpButton() {
|
||||
});
|
||||
});
|
||||
|
||||
// Tests keyboard selection using the arrow keys.
|
||||
add_task(async function arrowKeys() {
|
||||
await doKeySelectionTest(false);
|
||||
// Tests a sponsored best match row with help and block buttons.
|
||||
add_task(async function sponsoredHelpAndBlockButtons() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.urlbar.bestMatch.blockingEnabled", true]],
|
||||
});
|
||||
let result = makeBestMatchResult({
|
||||
isSponsored: true,
|
||||
helpUrl: "https://example.com/help",
|
||||
});
|
||||
await withProvider(result, async () => {
|
||||
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||
window,
|
||||
value: "test",
|
||||
});
|
||||
await checkBestMatchRow({
|
||||
result,
|
||||
isSponsored: true,
|
||||
hasHelpButton: true,
|
||||
hasBlockButton: true,
|
||||
});
|
||||
await UrlbarTestUtils.promisePopupClose(window);
|
||||
});
|
||||
await SpecialPowers.popPrefEnv();
|
||||
});
|
||||
|
||||
// Tests keyboard selection using the tab key.
|
||||
add_task(async function tabKey() {
|
||||
await doKeySelectionTest(true);
|
||||
});
|
||||
|
||||
async function doKeySelectionTest(useTabKey) {
|
||||
info(`Starting key selection test with useTabKey=${useTabKey}`);
|
||||
|
||||
// Tests keyboard selection.
|
||||
add_task(async function keySelection() {
|
||||
let result = makeBestMatchResult({
|
||||
isSponsored: true,
|
||||
helpUrl: "https://example.com/help",
|
||||
});
|
||||
|
||||
await withProvider(result, async () => {
|
||||
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||
window,
|
||||
value: "test",
|
||||
});
|
||||
|
||||
await checkBestMatchRow({ result, isSponsored: true, hasHelpButton: true });
|
||||
|
||||
// Ordered list of class names of the elements that should be selected as
|
||||
// the tab key is pressed.
|
||||
// Ordered list of class names of the elements that should be selected.
|
||||
let expectedClassNames = [
|
||||
"urlbarView-row-inner",
|
||||
"urlbarView-button-block",
|
||||
"urlbarView-button-help",
|
||||
];
|
||||
|
||||
let sendKey = reverse => {
|
||||
if (useTabKey) {
|
||||
EventUtils.synthesizeKey("KEY_Tab", { shiftKey: reverse });
|
||||
} else if (reverse) {
|
||||
EventUtils.synthesizeKey("KEY_ArrowUp");
|
||||
} else {
|
||||
EventUtils.synthesizeKey("KEY_ArrowDown");
|
||||
}
|
||||
};
|
||||
// Test with and without the block button.
|
||||
for (let showBlockButton of [false, true]) {
|
||||
UrlbarPrefs.set("bestMatch.blockingEnabled", showBlockButton);
|
||||
|
||||
// First tab in forward order and then in reverse order.
|
||||
for (let reverse of [false, true]) {
|
||||
info(`Doing key selection with reverse=${reverse}`);
|
||||
// The block button is not immediately removed or added when
|
||||
// `bestMatch.blockingEnabled` is toggled while the panel is open, so we
|
||||
// need to do a new search each time we change it.
|
||||
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||
window,
|
||||
value: "test",
|
||||
});
|
||||
await checkBestMatchRow({
|
||||
result,
|
||||
isSponsored: true,
|
||||
hasHelpButton: true,
|
||||
hasBlockButton: showBlockButton,
|
||||
});
|
||||
|
||||
let classNames = [...expectedClassNames];
|
||||
if (reverse) {
|
||||
classNames.reverse();
|
||||
// Test with the tab key vs. arrow keys and in order vs. reverse order.
|
||||
for (let useTabKey of [false, true]) {
|
||||
for (let reverse of [false, true]) {
|
||||
info(
|
||||
"Doing key selection: " +
|
||||
JSON.stringify({ showBlockButton, useTabKey, reverse })
|
||||
);
|
||||
|
||||
let classNames = [...expectedClassNames];
|
||||
if (!showBlockButton) {
|
||||
classNames.splice(classNames.indexOf("urlbarView-button-block"), 1);
|
||||
}
|
||||
if (reverse) {
|
||||
classNames.reverse();
|
||||
}
|
||||
|
||||
let sendKey = () => {
|
||||
if (useTabKey) {
|
||||
EventUtils.synthesizeKey("KEY_Tab", { shiftKey: reverse });
|
||||
} else if (reverse) {
|
||||
EventUtils.synthesizeKey("KEY_ArrowUp");
|
||||
} else {
|
||||
EventUtils.synthesizeKey("KEY_ArrowDown");
|
||||
}
|
||||
};
|
||||
|
||||
// Move selection through each expected element.
|
||||
for (let className of classNames) {
|
||||
info("Expecting selection: " + className);
|
||||
sendKey();
|
||||
Assert.ok(gURLBar.view.isOpen, "View remains open");
|
||||
let { selectedElement } = gURLBar.view;
|
||||
Assert.ok(selectedElement, "Selected element exists");
|
||||
Assert.ok(
|
||||
selectedElement.classList.contains(className),
|
||||
"Expected element is selected"
|
||||
);
|
||||
}
|
||||
sendKey();
|
||||
Assert.ok(
|
||||
gURLBar.view.isOpen,
|
||||
"View remains open after keying through best match row"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (let className of classNames) {
|
||||
sendKey(reverse);
|
||||
Assert.ok(gURLBar.view.isOpen, "View remains open");
|
||||
let { selectedElement } = gURLBar.view;
|
||||
Assert.ok(selectedElement, "Selected element exists");
|
||||
Assert.ok(
|
||||
selectedElement.classList.contains(className),
|
||||
"Expected element is selected"
|
||||
);
|
||||
}
|
||||
sendKey(reverse);
|
||||
Assert.ok(
|
||||
gURLBar.view.isOpen,
|
||||
"View remains open after keying through best match row"
|
||||
);
|
||||
await UrlbarTestUtils.promisePopupClose(window);
|
||||
UrlbarPrefs.clear("bestMatch.blockingEnabled");
|
||||
}
|
||||
|
||||
await UrlbarTestUtils.promisePopupClose(window);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
async function checkBestMatchRow({
|
||||
result,
|
||||
isSponsored = false,
|
||||
hasHelpButton = false,
|
||||
hasBlockButton = false,
|
||||
}) {
|
||||
Assert.equal(
|
||||
UrlbarTestUtils.getResultCount(window),
|
||||
@ -189,7 +253,11 @@ async function checkBestMatchRow({
|
||||
}
|
||||
|
||||
let blockButton = row._buttons.get("block");
|
||||
Assert.ok(blockButton, "Row has a block button");
|
||||
if (hasBlockButton) {
|
||||
Assert.ok(blockButton, "Row has a block button");
|
||||
} else {
|
||||
Assert.ok(!blockButton, "Row does not have a block button");
|
||||
}
|
||||
|
||||
let helpButton = row._buttons.get("help");
|
||||
Assert.equal(
|
||||
|
@ -291,11 +291,20 @@ class QSTestUtils {
|
||||
this.Assert.ok(helpButton, "The help button should be present");
|
||||
this.Assert.equal(result.payload.helpUrl, LEARN_MORE_URL, "Result helpURL");
|
||||
|
||||
this.Assert.equal(
|
||||
!!row._buttons.get("block"),
|
||||
isBestMatch,
|
||||
"The block button is present iff the suggestion is a best match"
|
||||
);
|
||||
let blockButton = row._buttons.get("block");
|
||||
if (!isBestMatch) {
|
||||
this.Assert.ok(
|
||||
!blockButton,
|
||||
"The block button is not present since the row is not a best match"
|
||||
);
|
||||
} else if (!UrlbarPrefs.get("bestMatch.blockingEnabled")) {
|
||||
this.Assert.ok(
|
||||
!blockButton,
|
||||
"The block button is not present since blocking is disabled"
|
||||
);
|
||||
} else {
|
||||
this.Assert.ok(blockButton, "The block button is present");
|
||||
}
|
||||
|
||||
return details;
|
||||
}
|
||||
|
@ -29,7 +29,10 @@ const SUGGESTIONS = [1, 2, 3].map(i => ({
|
||||
|
||||
add_task(async function init() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.urlbar.bestMatch.enabled", true]],
|
||||
set: [
|
||||
["browser.urlbar.bestMatch.enabled", true],
|
||||
["browser.urlbar.bestMatch.blockingEnabled", true],
|
||||
],
|
||||
});
|
||||
|
||||
await PlacesUtils.history.clear();
|
||||
@ -44,15 +47,31 @@ add_task(async function init() {
|
||||
|
||||
// Picks the block button with the keyboard.
|
||||
add_task(async function basicBlock_keyboard() {
|
||||
await doBasicBlockTest(true);
|
||||
await doBasicBlockTest(() => {
|
||||
// Arrow down twice to select the block button: once to select the main
|
||||
// part of the best match row, once to select the block button.
|
||||
EventUtils.synthesizeKey("KEY_ArrowDown", { repeat: 2 });
|
||||
EventUtils.synthesizeKey("KEY_Enter");
|
||||
});
|
||||
});
|
||||
|
||||
// Picks the block button with the mouse.
|
||||
add_task(async function basicBlock_mouse() {
|
||||
await doBasicBlockTest(false);
|
||||
await doBasicBlockTest(blockButton => {
|
||||
EventUtils.synthesizeMouseAtCenter(blockButton, {});
|
||||
});
|
||||
});
|
||||
|
||||
async function doBasicBlockTest(useKeyboard) {
|
||||
// Uses the key shortcut to block a best match.
|
||||
add_task(async function basicBlock_keyShortcut() {
|
||||
await doBasicBlockTest(() => {
|
||||
// Arrow down once to select the best match row.
|
||||
EventUtils.synthesizeKey("KEY_ArrowDown");
|
||||
EventUtils.synthesizeKey("KEY_Delete", { shiftKey: true });
|
||||
});
|
||||
});
|
||||
|
||||
async function doBasicBlockTest(doBlock) {
|
||||
// Do a search that triggers the best match.
|
||||
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||
window,
|
||||
@ -70,18 +89,9 @@ async function doBasicBlockTest(useKeyboard) {
|
||||
isBestMatch: true,
|
||||
});
|
||||
|
||||
// Pick the block button.
|
||||
if (useKeyboard) {
|
||||
// Arrow down twice to select the block button: once to select the main part
|
||||
// of the best match row, once to select the block button.
|
||||
EventUtils.synthesizeKey("KEY_ArrowDown", { repeat: 2 });
|
||||
EventUtils.synthesizeKey("KEY_Enter");
|
||||
} else {
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
details.element.row._buttons.get("block"),
|
||||
{}
|
||||
);
|
||||
}
|
||||
// Block the suggestion.
|
||||
let blockButton = details.element.row._buttons.get("block");
|
||||
doBlock(blockButton);
|
||||
|
||||
// The row should have been removed.
|
||||
Assert.ok(
|
||||
@ -144,3 +154,63 @@ add_task(async function blockMultiple() {
|
||||
await UrlbarTestUtils.promisePopupClose(window);
|
||||
await UrlbarProviderQuickSuggest.clearBlockedSuggestions();
|
||||
});
|
||||
|
||||
// Tests with blocking disabled.
|
||||
add_task(async function blockingDisabled() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.urlbar.bestMatch.blockingEnabled", false]],
|
||||
});
|
||||
|
||||
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||
window,
|
||||
value: SUGGESTIONS[0].keywords[0],
|
||||
});
|
||||
|
||||
let expectedResultCount = 2;
|
||||
Assert.equal(
|
||||
UrlbarTestUtils.getResultCount(window),
|
||||
expectedResultCount,
|
||||
"Two rows are present after searching (heuristic + best match)"
|
||||
);
|
||||
|
||||
// `assertIsQuickSuggest()` asserts that the block button is not present when
|
||||
// `bestMatch.blockingEnabled` is false, but check it again here since it's
|
||||
// central to this test.
|
||||
let details = await QuickSuggestTestUtils.assertIsQuickSuggest({
|
||||
window,
|
||||
originalUrl: SUGGESTIONS[0].url,
|
||||
isBestMatch: true,
|
||||
});
|
||||
Assert.ok(
|
||||
!details.element.row._buttons.get("block"),
|
||||
"Block button is not present"
|
||||
);
|
||||
|
||||
// Arrow down once to select the best match row and then press the key
|
||||
// shortcut to block.
|
||||
EventUtils.synthesizeKey("KEY_ArrowDown");
|
||||
EventUtils.synthesizeKey("KEY_Delete", { shiftKey: true });
|
||||
|
||||
// Nothing should happen.
|
||||
Assert.ok(
|
||||
UrlbarTestUtils.isPopupOpen(window),
|
||||
"View remains open after key shortcut"
|
||||
);
|
||||
Assert.equal(
|
||||
UrlbarTestUtils.getResultCount(window),
|
||||
expectedResultCount,
|
||||
"Same number of results after key shortcut"
|
||||
);
|
||||
await QuickSuggestTestUtils.assertIsQuickSuggest({
|
||||
window,
|
||||
originalUrl: SUGGESTIONS[0].url,
|
||||
isBestMatch: true,
|
||||
});
|
||||
Assert.ok(
|
||||
!(await UrlbarProviderQuickSuggest.isSuggestionBlocked(SUGGESTIONS[0].url)),
|
||||
"Suggestion is not blocked"
|
||||
);
|
||||
|
||||
await UrlbarTestUtils.promisePopupClose(window);
|
||||
await SpecialPowers.popPrefEnv();
|
||||
});
|
||||
|
@ -141,52 +141,34 @@ let privateWindowTask = {
|
||||
|
||||
// Implementation
|
||||
|
||||
var WinTaskbarJumpList = {
|
||||
_builder: null,
|
||||
_tasks: null,
|
||||
_shuttingDown: false,
|
||||
var Builder = class {
|
||||
constructor(builder) {
|
||||
this._builder = builder;
|
||||
this._tasks = null;
|
||||
this._pendingStatements = {};
|
||||
this._shuttingDown = false;
|
||||
// These are ultimately controlled by prefs, so we disable
|
||||
// everything until is read from there
|
||||
this._showTasks = false;
|
||||
this._showFrequent = false;
|
||||
this._showRecent = false;
|
||||
this._maxItemCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Startup, shutdown, and update
|
||||
*/
|
||||
refreshPrefs(showTasks, showFrequent, showRecent, maxItemCount) {
|
||||
this._showTasks = showTasks;
|
||||
this._showFrequent = showFrequent;
|
||||
this._showRecent = showRecent;
|
||||
this._maxItemCount = maxItemCount;
|
||||
}
|
||||
|
||||
startup: function WTBJL_startup() {
|
||||
// exit if this isn't win7 or higher.
|
||||
if (!this._initTaskbar()) {
|
||||
return;
|
||||
}
|
||||
updateShutdownState(shuttingDown) {
|
||||
this._shuttingDown = shuttingDown;
|
||||
}
|
||||
|
||||
// Store our task list config data
|
||||
this._tasks = tasksCfg;
|
||||
|
||||
if (PrivateBrowsingUtils.enabled) {
|
||||
tasksCfg.push(privateWindowTask);
|
||||
}
|
||||
|
||||
// retrieve taskbar related prefs.
|
||||
this._refreshPrefs();
|
||||
|
||||
// observer for private browsing and our prefs branch
|
||||
this._initObs();
|
||||
|
||||
// jump list refresh timer
|
||||
this._updateTimer();
|
||||
},
|
||||
|
||||
update: function WTBJL_update() {
|
||||
// are we disabled via prefs? don't do anything!
|
||||
if (!this._enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// do what we came here to do, update the taskbar jumplist
|
||||
this._buildList();
|
||||
},
|
||||
|
||||
_shutdown: function WTBJL__shutdown() {
|
||||
this._shuttingDown = true;
|
||||
this._free();
|
||||
},
|
||||
delete() {
|
||||
delete this._builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* List building
|
||||
@ -198,13 +180,15 @@ var WinTaskbarJumpList = {
|
||||
* commitBuild() will commit for real.
|
||||
*/
|
||||
|
||||
_pendingStatements: {},
|
||||
_hasPendingStatements: function WTBJL__hasPendingStatements() {
|
||||
_hasPendingStatements() {
|
||||
return !!Object.keys(this._pendingStatements).length;
|
||||
},
|
||||
}
|
||||
|
||||
async _buildList() {
|
||||
if (this._hasPendingStatements()) {
|
||||
async buildList() {
|
||||
if (
|
||||
(this._showFrequent || this._showRecent) &&
|
||||
this._hasPendingStatements()
|
||||
) {
|
||||
// We were requested to update the list while another update was in
|
||||
// progress, this could happen at shutdown, idle or privatebrowsing.
|
||||
// Abort the current list building.
|
||||
@ -238,7 +222,7 @@ var WinTaskbarJumpList = {
|
||||
}
|
||||
|
||||
this._commitBuild();
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Taskbar api wrappers
|
||||
@ -251,10 +235,13 @@ var WinTaskbarJumpList = {
|
||||
// Prior to building, delete removed items from history.
|
||||
this._clearHistory(URIsToRemove);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_commitBuild: function WTBJL__commitBuild() {
|
||||
if (this._hasPendingStatements()) {
|
||||
_commitBuild() {
|
||||
if (
|
||||
(this._showFrequent || this._showRecent) &&
|
||||
this._hasPendingStatements()
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -263,9 +250,9 @@ var WinTaskbarJumpList = {
|
||||
this._builder.abortListBuild();
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_buildTasks: function WTBJL__buildTasks() {
|
||||
_buildTasks() {
|
||||
var items = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
|
||||
this._tasks.forEach(function(task) {
|
||||
if (
|
||||
@ -290,9 +277,9 @@ var WinTaskbarJumpList = {
|
||||
items
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_buildCustom: function WTBJL__buildCustom(title, items) {
|
||||
_buildCustom(title, items) {
|
||||
if (items.length) {
|
||||
this._builder.addListToBuild(
|
||||
this._builder.JUMPLIST_CATEGORY_CUSTOMLIST,
|
||||
@ -300,9 +287,9 @@ var WinTaskbarJumpList = {
|
||||
title
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_buildFrequent: function WTBJL__buildFrequent() {
|
||||
_buildFrequent() {
|
||||
// Windows supports default frequent and recent lists,
|
||||
// but those depend on internal windows visit tracking
|
||||
// which we don't populate. So we build our own custom
|
||||
@ -339,9 +326,9 @@ var WinTaskbarJumpList = {
|
||||
},
|
||||
this
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
_buildRecent: function WTBJL__buildRecent() {
|
||||
_buildRecent() {
|
||||
var items = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
|
||||
// Frequent items will be skipped, so we select a double amount of
|
||||
// entries and stop fetching results at _maxItemCount.
|
||||
@ -385,23 +372,17 @@ var WinTaskbarJumpList = {
|
||||
},
|
||||
this
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
_deleteActiveJumpList: function WTBJL__deleteAJL() {
|
||||
_deleteActiveJumpList() {
|
||||
this._builder.deleteActiveList();
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Jump list item creation helpers
|
||||
*/
|
||||
|
||||
_getHandlerAppItem: function WTBJL__getHandlerAppItem(
|
||||
name,
|
||||
description,
|
||||
args,
|
||||
iconIndex,
|
||||
faviconPageUri
|
||||
) {
|
||||
_getHandlerAppItem(name, description, args, iconIndex, faviconPageUri) {
|
||||
var file = Services.dirsvc.get("XREExeF", Ci.nsIFile);
|
||||
|
||||
var handlerApp = Cc[
|
||||
@ -422,25 +403,13 @@ var WinTaskbarJumpList = {
|
||||
item.iconIndex = iconIndex;
|
||||
item.faviconPageUri = faviconPageUri;
|
||||
return item;
|
||||
},
|
||||
|
||||
_getSeparatorItem: function WTBJL__getSeparatorItem() {
|
||||
var item = Cc["@mozilla.org/windows-jumplistseparator;1"].createInstance(
|
||||
Ci.nsIJumpListSeparator
|
||||
);
|
||||
return item;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Nav history helpers
|
||||
*/
|
||||
|
||||
_getHistoryResults: function WTBLJL__getHistoryResults(
|
||||
aSortingMode,
|
||||
aLimit,
|
||||
aCallback,
|
||||
aScope
|
||||
) {
|
||||
_getHistoryResults(aSortingMode, aLimit, aCallback, aScope) {
|
||||
var options = PlacesUtils.history.getNewQueryOptions();
|
||||
options.maxResults = aLimit;
|
||||
options.sortingMode = aSortingMode;
|
||||
@ -464,12 +433,12 @@ var WinTaskbarJumpList = {
|
||||
);
|
||||
},
|
||||
handleCompletion(aReason) {
|
||||
aCallback.call(WinTaskbarJumpList, null);
|
||||
aCallback.call(aScope, null);
|
||||
},
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_clearHistory: function WTBJL__clearHistory(uriSpecsToRemove) {
|
||||
_clearHistory(uriSpecsToRemove) {
|
||||
let URIsToRemove = uriSpecsToRemove
|
||||
.map(spec => {
|
||||
try {
|
||||
@ -484,6 +453,66 @@ var WinTaskbarJumpList = {
|
||||
if (URIsToRemove.length) {
|
||||
PlacesUtils.history.remove(URIsToRemove).catch(Cu.reportError);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var WinTaskbarJumpList = {
|
||||
// We build two separate jump lists -- one for the regular Firefox icon
|
||||
// and one for the Private Browsing icon
|
||||
_builder: null,
|
||||
_pbBuilder: null,
|
||||
_builtPb: false,
|
||||
_shuttingDown: false,
|
||||
|
||||
/**
|
||||
* Startup, shutdown, and update
|
||||
*/
|
||||
|
||||
startup: function WTBJL_startup() {
|
||||
// exit if this isn't win7 or higher.
|
||||
if (!this._initTaskbar()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (PrivateBrowsingUtils.enabled) {
|
||||
tasksCfg.push(privateWindowTask);
|
||||
}
|
||||
// Store our task list config data
|
||||
this._builder._tasks = tasksCfg;
|
||||
this._pbBuilder._tasks = tasksCfg;
|
||||
|
||||
// retrieve taskbar related prefs.
|
||||
this._refreshPrefs();
|
||||
|
||||
// observer for private browsing and our prefs branch
|
||||
this._initObs();
|
||||
|
||||
// jump list refresh timer
|
||||
this._updateTimer();
|
||||
},
|
||||
|
||||
update: function WTBJL_update() {
|
||||
// are we disabled via prefs? don't do anything!
|
||||
if (!this._enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we only need to do this once, but we do it here
|
||||
// to avoid main thread io on startup
|
||||
if (!this._builtPb) {
|
||||
this._pbBuilder.buildList();
|
||||
this._builtPb = true;
|
||||
}
|
||||
|
||||
// do what we came here to do, update the taskbar jumplist
|
||||
this._builder.buildList();
|
||||
},
|
||||
|
||||
_shutdown: function WTBJL__shutdown() {
|
||||
this._builder.updateShutdownState(true);
|
||||
this._pbBuilder.updateShutdownState(true);
|
||||
this._shuttingDown = true;
|
||||
this._free();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -492,10 +521,17 @@ var WinTaskbarJumpList = {
|
||||
|
||||
_refreshPrefs: function WTBJL__refreshPrefs() {
|
||||
this._enabled = _prefs.getBoolPref(PREF_TASKBAR_ENABLED);
|
||||
this._showFrequent = _prefs.getBoolPref(PREF_TASKBAR_FREQUENT);
|
||||
this._showRecent = _prefs.getBoolPref(PREF_TASKBAR_RECENT);
|
||||
this._showTasks = _prefs.getBoolPref(PREF_TASKBAR_TASKS);
|
||||
this._maxItemCount = _prefs.getIntPref(PREF_TASKBAR_ITEMCOUNT);
|
||||
var showTasks = _prefs.getBoolPref(PREF_TASKBAR_TASKS);
|
||||
this._builder.refreshPrefs(
|
||||
showTasks,
|
||||
_prefs.getBoolPref(PREF_TASKBAR_FREQUENT),
|
||||
_prefs.getBoolPref(PREF_TASKBAR_RECENT),
|
||||
_prefs.getIntPref(PREF_TASKBAR_ITEMCOUNT)
|
||||
);
|
||||
// showTasks is the only relevant pref for the Private Browsing Jump List
|
||||
// the others are are related to frequent/recent entries, which are
|
||||
// explicitly disabled for it
|
||||
this._pbBuilder.refreshPrefs(showTasks, false, false, 0);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -503,11 +539,15 @@ var WinTaskbarJumpList = {
|
||||
*/
|
||||
|
||||
_initTaskbar: function WTBJL__initTaskbar() {
|
||||
this._builder = _taskbarService.createJumpListBuilder();
|
||||
if (!this._builder || !this._builder.available) {
|
||||
var builder = _taskbarService.createJumpListBuilder(false);
|
||||
var pbBuilder = _taskbarService.createJumpListBuilder(true);
|
||||
if (!builder || !builder.available || !pbBuilder || !pbBuilder.available) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this._builder = new Builder(builder, true, true, true);
|
||||
this._pbBuilder = new Builder(pbBuilder, true, false, false);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
@ -571,7 +611,8 @@ var WinTaskbarJumpList = {
|
||||
this._freeObs();
|
||||
this._updateTimer();
|
||||
this._updateIdleObserver();
|
||||
delete this._builder;
|
||||
this._builder.delete();
|
||||
this._pbBuilder.delete();
|
||||
},
|
||||
|
||||
notify: function WTBJL_notify(aTimer) {
|
||||
|
@ -12,9 +12,3 @@
|
||||
--downloads-item-details-opacity: 0.6;
|
||||
--downloads-item-disabled-opacity: 0.6;
|
||||
}
|
||||
|
||||
#downloadsPanel[keyfocus] :is(#downloadsListBox:focus > richlistitem[selected], #downloadsSummary:focus),
|
||||
.downloadButton:focus {
|
||||
outline: 1px -moz-dialogtext dotted;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
@ -10,10 +10,3 @@
|
||||
--downloads-item-details-opacity: 0.7;
|
||||
--downloads-item-disabled-opacity: 0.7;
|
||||
}
|
||||
|
||||
.downloadButton:focus > .button-box,
|
||||
#downloadsPanel[keyfocus] #downloadsListBox:focus > richlistitem[selected],
|
||||
#downloadsPanel[keyfocus] #downloadsSummary:focus {
|
||||
outline: var(--focus-outline);
|
||||
outline-offset: calc(var(--focus-outline-width) * -1);
|
||||
}
|
||||
|
@ -180,6 +180,12 @@ toolbarpaletteitem toolbarbutton[disabled] {
|
||||
color: inherit !important;
|
||||
}
|
||||
|
||||
#PersonalToolbar toolbarpaletteitem toolbarbutton[checked="true"],
|
||||
toolbar toolbarpaletteitem toolbarbutton[checked="true"]
|
||||
> :where(.toolbarbutton-icon, .toolbarbutton-text, .toolbarbutton-badge-stack) {
|
||||
background-color: revert !important;
|
||||
}
|
||||
|
||||
toolbarpaletteitem > toolbarbutton > .toolbarbutton-icon,
|
||||
toolbarpaletteitem > toolbarbutton > .toolbarbutton-badge-stack > .toolbarbutton-icon,
|
||||
toolbarpaletteitem > #search-container,
|
||||
|
@ -52,19 +52,26 @@
|
||||
#downloadsListBox > richlistitem.openWhenFinished.hoveringMainArea:hover,
|
||||
#downloadsListBox > richlistitem[verdict]:hover,
|
||||
#downloadsListBox > richlistitem.openWhenFinished:hover,
|
||||
.downloadsPanelFooterButton:hover,
|
||||
#downloadsPanel[keyfocus] #downloadsListBox:focus > richlistitem[selected],
|
||||
#downloadsHistory:focus {
|
||||
.downloadsPanelFooterButton:hover {
|
||||
background-color: var(--panel-item-hover-bgcolor);
|
||||
}
|
||||
|
||||
#downloadsListBox > richlistitem[state="1"][exists].hoveringMainArea:hover:active,
|
||||
#downloadsListBox > richlistitem.openWhenFinished.hoveringMainArea:hover:active,
|
||||
.downloadsPanelFooterButton[open="true"],
|
||||
#downloadsListBox > richlistitem[verdict]:hover:active {
|
||||
#downloadsListBox > richlistitem[verdict]:hover:active,
|
||||
.downloadsPanelFooterButton[open="true"] {
|
||||
background-color: var(--panel-item-active-bgcolor);
|
||||
}
|
||||
|
||||
#downloadsListBox:focus-visible > richlistitem[selected],
|
||||
#downloadsListBox[force-focus-visible]:focus > richlistitem[selected],
|
||||
.downloadButton:focus-visible,
|
||||
#downloadsSummary:focus-visible,
|
||||
.downloadsPanelFooterButton:focus-visible {
|
||||
outline: var(--focus-outline);
|
||||
outline-offset: calc(var(--focus-outline-width) * -1);
|
||||
}
|
||||
|
||||
#downloadsListBox > richlistitem[verdict="Insecure"] .downloadDetails,
|
||||
#downloadsListBox > richlistitem[verdict="Malware"] .downloadDetails {
|
||||
color: #C50042;
|
||||
@ -87,18 +94,11 @@
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
#downloadsPanel:not([keyfocus]) .downloadsPanelFooterButton:-moz-focusring {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#downloadsSummary {
|
||||
background: var(--arrowpanel-dimmed);
|
||||
border-top: 1px solid var(--panel-separator-color);
|
||||
/* Reserve the same space as the button and separator in download items. */
|
||||
padding-inline-end: 59px;
|
||||
}
|
||||
|
||||
#downloadsSummary {
|
||||
-moz-user-focus: normal;
|
||||
}
|
||||
|
||||
|
@ -10,14 +10,6 @@
|
||||
border: 0;
|
||||
}
|
||||
|
||||
#downloadsSummary:focus-visible {
|
||||
outline-offset: -5px;
|
||||
}
|
||||
|
||||
#downloadsPanel:not([keyfocus]) #downloadsSummary:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/*** List items and similar elements in the summary ***/
|
||||
|
||||
:root {
|
||||
@ -27,17 +19,6 @@
|
||||
--downloads-item-disabled-opacity: 0.6;
|
||||
}
|
||||
|
||||
#downloadsPanel:not([keyfocus]) .downloadButton:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/*** Highlighted list items ***/
|
||||
|
||||
#downloadsPanel[keyfocus] #downloadsListBox:focus > richlistitem[selected] {
|
||||
outline: 1px -moz-dialogtext dotted;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
/*** Progress bars ***/
|
||||
|
||||
@media (prefers-contrast) {
|
||||
|
@ -1203,7 +1203,12 @@
|
||||
"../node_modules/parse-script-tags/node_modules/@babel/types/lib/validators/isSpecifierDefault.js": 1051,
|
||||
"../node_modules/parse-script-tags/node_modules/@babel/types/lib/validators/isValidES3Identifier.js": 1052,
|
||||
"../node_modules/parse-script-tags/node_modules/@babel/types/lib/validators/isVar.js": 1053,
|
||||
"../node_modules/parse-script-tags/node_modules/@babel/parser/lib/index.js": 1054
|
||||
"../node_modules/parse-script-tags/node_modules/@babel/parser/lib/index.js": 1054,
|
||||
"../node_modules/babel-loader/lib/index.js??ref--1!../../shared/worker-handler.js": 1055,
|
||||
"../node_modules/babel-loader/lib/index.js??ref--1!../packages/devtools-source-map/src/utils/network-request.js": 1056,
|
||||
"../node_modules/babel-loader/lib/index.js??ref--1!../../shared/worker-dispatcher.js": 1057,
|
||||
"../node_modules/babel-loader/lib/index.js??ref--1!../packages/devtools-source-map/src/utils/privileged-network-request.js": 1058,
|
||||
"../node_modules/babel-loader/lib/index.js??ref--1!../../shared/worker-utils.js": 1059
|
||||
},
|
||||
"usedIds": {
|
||||
"0": 0,
|
||||
@ -2260,7 +2265,12 @@
|
||||
"1051": 1051,
|
||||
"1052": 1052,
|
||||
"1053": 1053,
|
||||
"1054": 1054
|
||||
"1054": 1054,
|
||||
"1055": 1055,
|
||||
"1056": 1056,
|
||||
"1057": 1057,
|
||||
"1058": 1058,
|
||||
"1059": 1059
|
||||
}
|
||||
},
|
||||
"chunks": {
|
||||
|
415
devtools/client/debugger/dist/parser-worker.js
vendored
415
devtools/client/debugger/dist/parser-worker.js
vendored
@ -6026,22 +6026,7 @@ function isSpreadProperty(node, opts) {
|
||||
}
|
||||
|
||||
/***/ }),
|
||||
/* 560 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
const networkRequest = __webpack_require__(567);
|
||||
|
||||
const workerUtils = __webpack_require__(568);
|
||||
|
||||
module.exports = {
|
||||
networkRequest,
|
||||
workerUtils
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
/* 560 */,
|
||||
/* 561 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
@ -7923,213 +7908,8 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 567 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
function networkRequest(url, opts) {
|
||||
const UNSUPPORTED_PROTOCOLS = ["chrome://", "resource://"];
|
||||
|
||||
if (UNSUPPORTED_PROTOCOLS.some(protocol => url.startsWith(protocol))) {
|
||||
return Promise.reject(`unsupported protocol for sourcemap request ${url}`);
|
||||
}
|
||||
|
||||
return fetch(url, {
|
||||
cache: opts.loadFromCache ? "default" : "no-cache"
|
||||
}).then(res => {
|
||||
if (res.status >= 200 && res.status < 300) {
|
||||
if (res.headers.get("Content-Type") === "application/wasm") {
|
||||
return res.arrayBuffer().then(buffer => ({
|
||||
content: buffer,
|
||||
isDwarf: true
|
||||
}));
|
||||
}
|
||||
|
||||
return res.text().then(text => ({
|
||||
content: text
|
||||
}));
|
||||
}
|
||||
|
||||
return Promise.reject(`request failed with status ${res.status}`);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = networkRequest;
|
||||
|
||||
/***/ }),
|
||||
/* 568 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
function WorkerDispatcher() {
|
||||
this.msgId = 1;
|
||||
this.worker = null; // Map of message ids -> promise resolution functions, for dispatching worker responses
|
||||
|
||||
this.pendingCalls = new Map();
|
||||
this._onMessage = this._onMessage.bind(this);
|
||||
}
|
||||
|
||||
WorkerDispatcher.prototype = {
|
||||
start(url, win = window) {
|
||||
this.worker = new win.Worker(url);
|
||||
|
||||
this.worker.onerror = err => {
|
||||
console.error(`Error in worker ${url}`, err.message);
|
||||
};
|
||||
|
||||
this.worker.addEventListener("message", this._onMessage);
|
||||
},
|
||||
|
||||
stop() {
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.worker.removeEventListener("message", this._onMessage);
|
||||
this.worker.terminate();
|
||||
this.worker = null;
|
||||
this.pendingCalls.clear();
|
||||
},
|
||||
|
||||
task(method, {
|
||||
queue = false
|
||||
} = {}) {
|
||||
const calls = [];
|
||||
|
||||
const push = args => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (queue && calls.length === 0) {
|
||||
Promise.resolve().then(flush);
|
||||
}
|
||||
|
||||
calls.push({
|
||||
args,
|
||||
resolve,
|
||||
reject
|
||||
});
|
||||
|
||||
if (!queue) {
|
||||
flush();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const flush = () => {
|
||||
const items = calls.slice();
|
||||
calls.length = 0;
|
||||
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
const id = this.msgId++;
|
||||
this.worker.postMessage({
|
||||
id,
|
||||
method,
|
||||
calls: items.map(item => item.args)
|
||||
});
|
||||
this.pendingCalls.set(id, items);
|
||||
};
|
||||
|
||||
return (...args) => push(args);
|
||||
},
|
||||
|
||||
invoke(method, ...args) {
|
||||
return this.task(method)(...args);
|
||||
},
|
||||
|
||||
_onMessage({
|
||||
data: result
|
||||
}) {
|
||||
const items = this.pendingCalls.get(result.id);
|
||||
this.pendingCalls.delete(result.id);
|
||||
|
||||
if (!items) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
result.results.forEach((resultData, i) => {
|
||||
const {
|
||||
resolve,
|
||||
reject
|
||||
} = items[i];
|
||||
|
||||
if (resultData.error) {
|
||||
const err = new Error(resultData.message);
|
||||
err.metadata = resultData.metadata;
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(resultData.response);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function workerHandler(publicInterface) {
|
||||
return function (msg) {
|
||||
const {
|
||||
id,
|
||||
method,
|
||||
calls
|
||||
} = msg.data;
|
||||
Promise.all(calls.map(args => {
|
||||
try {
|
||||
const response = publicInterface[method].apply(undefined, args);
|
||||
|
||||
if (response instanceof Promise) {
|
||||
return response.then(val => ({
|
||||
response: val
|
||||
}), err => asErrorMessage(err));
|
||||
}
|
||||
|
||||
return {
|
||||
response
|
||||
};
|
||||
} catch (error) {
|
||||
return asErrorMessage(error);
|
||||
}
|
||||
})).then(results => {
|
||||
globalThis.postMessage({
|
||||
id,
|
||||
results
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function asErrorMessage(error) {
|
||||
if (typeof error === "object" && error && "message" in error) {
|
||||
// Error can't be sent via postMessage, so be sure to convert to
|
||||
// string.
|
||||
return {
|
||||
error: true,
|
||||
message: error.message,
|
||||
metadata: error.metadata
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
error: true,
|
||||
message: error == null ? error : error.toString(),
|
||||
metadata: undefined
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
WorkerDispatcher,
|
||||
workerHandler
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
/* 567 */,
|
||||
/* 568 */,
|
||||
/* 569 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
@ -32245,7 +32025,7 @@ var _validate = __webpack_require__(895);
|
||||
|
||||
var _mapExpression = _interopRequireDefault(__webpack_require__(896));
|
||||
|
||||
var _devtoolsUtils = __webpack_require__(560);
|
||||
var _workerUtils = __webpack_require__(1059);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
@ -32256,10 +32036,6 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
const {
|
||||
workerHandler
|
||||
} = _devtoolsUtils.workerUtils;
|
||||
|
||||
function clearState() {
|
||||
(0, _ast.clearASTs)();
|
||||
(0, _getScopes.clearScopes)();
|
||||
@ -32267,7 +32043,7 @@ function clearState() {
|
||||
(0, _getSymbols.clearSymbols)();
|
||||
}
|
||||
|
||||
self.onmessage = workerHandler({
|
||||
self.onmessage = (0, _workerUtils.workerHandler)({
|
||||
findOutOfScopeLocations: _findOutOfScopeLocations.default,
|
||||
getSymbols: _getSymbols.getSymbols,
|
||||
getScopes: _getScopes.default,
|
||||
@ -76505,6 +76281,187 @@ exports.tokTypes = types;
|
||||
//# sourceMappingURL=index.js.map
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 1055 */,
|
||||
/* 1056 */,
|
||||
/* 1057 */,
|
||||
/* 1058 */,
|
||||
/* 1059 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
|
||||
function WorkerDispatcher() {
|
||||
this.msgId = 1;
|
||||
this.worker = null; // Map of message ids -> promise resolution functions, for dispatching worker responses
|
||||
|
||||
this.pendingCalls = new Map();
|
||||
this._onMessage = this._onMessage.bind(this);
|
||||
}
|
||||
|
||||
WorkerDispatcher.prototype = {
|
||||
start(url, win = window) {
|
||||
this.worker = new win.Worker(url);
|
||||
|
||||
this.worker.onerror = err => {
|
||||
console.error(`Error in worker ${url}`, err.message);
|
||||
};
|
||||
|
||||
this.worker.addEventListener("message", this._onMessage);
|
||||
},
|
||||
|
||||
stop() {
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.worker.removeEventListener("message", this._onMessage);
|
||||
this.worker.terminate();
|
||||
this.worker = null;
|
||||
this.pendingCalls.clear();
|
||||
},
|
||||
|
||||
task(method, {
|
||||
queue = false
|
||||
} = {}) {
|
||||
const calls = [];
|
||||
|
||||
const push = args => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (queue && calls.length === 0) {
|
||||
Promise.resolve().then(flush);
|
||||
}
|
||||
|
||||
calls.push({
|
||||
args,
|
||||
resolve,
|
||||
reject
|
||||
});
|
||||
|
||||
if (!queue) {
|
||||
flush();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const flush = () => {
|
||||
const items = calls.slice();
|
||||
calls.length = 0;
|
||||
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
const id = this.msgId++;
|
||||
this.worker.postMessage({
|
||||
id,
|
||||
method,
|
||||
calls: items.map(item => item.args)
|
||||
});
|
||||
this.pendingCalls.set(id, items);
|
||||
};
|
||||
|
||||
return (...args) => push(args);
|
||||
},
|
||||
|
||||
invoke(method, ...args) {
|
||||
return this.task(method)(...args);
|
||||
},
|
||||
|
||||
_onMessage({
|
||||
data: result
|
||||
}) {
|
||||
const items = this.pendingCalls.get(result.id);
|
||||
this.pendingCalls.delete(result.id);
|
||||
|
||||
if (!items) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
result.results.forEach((resultData, i) => {
|
||||
const {
|
||||
resolve,
|
||||
reject
|
||||
} = items[i];
|
||||
|
||||
if (resultData.error) {
|
||||
const err = new Error(resultData.message);
|
||||
err.metadata = resultData.metadata;
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(resultData.response);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function workerHandler(publicInterface) {
|
||||
return function (msg) {
|
||||
const {
|
||||
id,
|
||||
method,
|
||||
calls
|
||||
} = msg.data;
|
||||
Promise.all(calls.map(args => {
|
||||
try {
|
||||
const response = publicInterface[method].apply(undefined, args);
|
||||
|
||||
if (response instanceof Promise) {
|
||||
return response.then(val => ({
|
||||
response: val
|
||||
}), err => asErrorMessage(err));
|
||||
}
|
||||
|
||||
return {
|
||||
response
|
||||
};
|
||||
} catch (error) {
|
||||
return asErrorMessage(error);
|
||||
}
|
||||
})).then(results => {
|
||||
globalThis.postMessage({
|
||||
id,
|
||||
results
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function asErrorMessage(error) {
|
||||
if (typeof error === "object" && error && "message" in error) {
|
||||
// Error can't be sent via postMessage, so be sure to convert to
|
||||
// string.
|
||||
return {
|
||||
error: true,
|
||||
message: error.message,
|
||||
metadata: error.metadata
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
error: true,
|
||||
message: error == null ? error : error.toString(),
|
||||
metadata: undefined
|
||||
};
|
||||
} // Might be loaded within a worker thread where `module` isn't available.
|
||||
|
||||
|
||||
if (true) {
|
||||
module.exports = {
|
||||
WorkerDispatcher,
|
||||
workerHandler
|
||||
};
|
||||
}
|
||||
|
||||
/***/ })
|
||||
/******/ ]);
|
||||
});
|
390
devtools/client/debugger/dist/pretty-print-worker.js
vendored
390
devtools/client/debugger/dist/pretty-print-worker.js
vendored
@ -79,21 +79,182 @@ return /******/ (function(modules) { // webpackBootstrap
|
||||
/************************************************************************/
|
||||
/******/ ({
|
||||
|
||||
/***/ 560:
|
||||
/***/ 1059:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
const networkRequest = __webpack_require__(567);
|
||||
|
||||
const workerUtils = __webpack_require__(568);
|
||||
|
||||
module.exports = {
|
||||
networkRequest,
|
||||
workerUtils
|
||||
function WorkerDispatcher() {
|
||||
this.msgId = 1;
|
||||
this.worker = null; // Map of message ids -> promise resolution functions, for dispatching worker responses
|
||||
|
||||
this.pendingCalls = new Map();
|
||||
this._onMessage = this._onMessage.bind(this);
|
||||
}
|
||||
|
||||
WorkerDispatcher.prototype = {
|
||||
start(url, win = window) {
|
||||
this.worker = new win.Worker(url);
|
||||
|
||||
this.worker.onerror = err => {
|
||||
console.error(`Error in worker ${url}`, err.message);
|
||||
};
|
||||
|
||||
this.worker.addEventListener("message", this._onMessage);
|
||||
},
|
||||
|
||||
stop() {
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.worker.removeEventListener("message", this._onMessage);
|
||||
this.worker.terminate();
|
||||
this.worker = null;
|
||||
this.pendingCalls.clear();
|
||||
},
|
||||
|
||||
task(method, {
|
||||
queue = false
|
||||
} = {}) {
|
||||
const calls = [];
|
||||
|
||||
const push = args => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (queue && calls.length === 0) {
|
||||
Promise.resolve().then(flush);
|
||||
}
|
||||
|
||||
calls.push({
|
||||
args,
|
||||
resolve,
|
||||
reject
|
||||
});
|
||||
|
||||
if (!queue) {
|
||||
flush();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const flush = () => {
|
||||
const items = calls.slice();
|
||||
calls.length = 0;
|
||||
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
const id = this.msgId++;
|
||||
this.worker.postMessage({
|
||||
id,
|
||||
method,
|
||||
calls: items.map(item => item.args)
|
||||
});
|
||||
this.pendingCalls.set(id, items);
|
||||
};
|
||||
|
||||
return (...args) => push(args);
|
||||
},
|
||||
|
||||
invoke(method, ...args) {
|
||||
return this.task(method)(...args);
|
||||
},
|
||||
|
||||
_onMessage({
|
||||
data: result
|
||||
}) {
|
||||
const items = this.pendingCalls.get(result.id);
|
||||
this.pendingCalls.delete(result.id);
|
||||
|
||||
if (!items) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
result.results.forEach((resultData, i) => {
|
||||
const {
|
||||
resolve,
|
||||
reject
|
||||
} = items[i];
|
||||
|
||||
if (resultData.error) {
|
||||
const err = new Error(resultData.message);
|
||||
err.metadata = resultData.metadata;
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(resultData.response);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function workerHandler(publicInterface) {
|
||||
return function (msg) {
|
||||
const {
|
||||
id,
|
||||
method,
|
||||
calls
|
||||
} = msg.data;
|
||||
Promise.all(calls.map(args => {
|
||||
try {
|
||||
const response = publicInterface[method].apply(undefined, args);
|
||||
|
||||
if (response instanceof Promise) {
|
||||
return response.then(val => ({
|
||||
response: val
|
||||
}), err => asErrorMessage(err));
|
||||
}
|
||||
|
||||
return {
|
||||
response
|
||||
};
|
||||
} catch (error) {
|
||||
return asErrorMessage(error);
|
||||
}
|
||||
})).then(results => {
|
||||
globalThis.postMessage({
|
||||
id,
|
||||
results
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function asErrorMessage(error) {
|
||||
if (typeof error === "object" && error && "message" in error) {
|
||||
// Error can't be sent via postMessage, so be sure to convert to
|
||||
// string.
|
||||
return {
|
||||
error: true,
|
||||
message: error.message,
|
||||
metadata: error.metadata
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
error: true,
|
||||
message: error == null ? error : error.toString(),
|
||||
metadata: undefined
|
||||
};
|
||||
} // Might be loaded within a worker thread where `module` isn't available.
|
||||
|
||||
|
||||
if (true) {
|
||||
module.exports = {
|
||||
WorkerDispatcher,
|
||||
workerHandler
|
||||
};
|
||||
}
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 566:
|
||||
@ -518,215 +679,6 @@ function compareByGeneratedPositionsInflated(mappingA, mappingB) {
|
||||
exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 567:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
function networkRequest(url, opts) {
|
||||
const UNSUPPORTED_PROTOCOLS = ["chrome://", "resource://"];
|
||||
|
||||
if (UNSUPPORTED_PROTOCOLS.some(protocol => url.startsWith(protocol))) {
|
||||
return Promise.reject(`unsupported protocol for sourcemap request ${url}`);
|
||||
}
|
||||
|
||||
return fetch(url, {
|
||||
cache: opts.loadFromCache ? "default" : "no-cache"
|
||||
}).then(res => {
|
||||
if (res.status >= 200 && res.status < 300) {
|
||||
if (res.headers.get("Content-Type") === "application/wasm") {
|
||||
return res.arrayBuffer().then(buffer => ({
|
||||
content: buffer,
|
||||
isDwarf: true
|
||||
}));
|
||||
}
|
||||
|
||||
return res.text().then(text => ({
|
||||
content: text
|
||||
}));
|
||||
}
|
||||
|
||||
return Promise.reject(`request failed with status ${res.status}`);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = networkRequest;
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 568:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
function WorkerDispatcher() {
|
||||
this.msgId = 1;
|
||||
this.worker = null; // Map of message ids -> promise resolution functions, for dispatching worker responses
|
||||
|
||||
this.pendingCalls = new Map();
|
||||
this._onMessage = this._onMessage.bind(this);
|
||||
}
|
||||
|
||||
WorkerDispatcher.prototype = {
|
||||
start(url, win = window) {
|
||||
this.worker = new win.Worker(url);
|
||||
|
||||
this.worker.onerror = err => {
|
||||
console.error(`Error in worker ${url}`, err.message);
|
||||
};
|
||||
|
||||
this.worker.addEventListener("message", this._onMessage);
|
||||
},
|
||||
|
||||
stop() {
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.worker.removeEventListener("message", this._onMessage);
|
||||
this.worker.terminate();
|
||||
this.worker = null;
|
||||
this.pendingCalls.clear();
|
||||
},
|
||||
|
||||
task(method, {
|
||||
queue = false
|
||||
} = {}) {
|
||||
const calls = [];
|
||||
|
||||
const push = args => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (queue && calls.length === 0) {
|
||||
Promise.resolve().then(flush);
|
||||
}
|
||||
|
||||
calls.push({
|
||||
args,
|
||||
resolve,
|
||||
reject
|
||||
});
|
||||
|
||||
if (!queue) {
|
||||
flush();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const flush = () => {
|
||||
const items = calls.slice();
|
||||
calls.length = 0;
|
||||
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
const id = this.msgId++;
|
||||
this.worker.postMessage({
|
||||
id,
|
||||
method,
|
||||
calls: items.map(item => item.args)
|
||||
});
|
||||
this.pendingCalls.set(id, items);
|
||||
};
|
||||
|
||||
return (...args) => push(args);
|
||||
},
|
||||
|
||||
invoke(method, ...args) {
|
||||
return this.task(method)(...args);
|
||||
},
|
||||
|
||||
_onMessage({
|
||||
data: result
|
||||
}) {
|
||||
const items = this.pendingCalls.get(result.id);
|
||||
this.pendingCalls.delete(result.id);
|
||||
|
||||
if (!items) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
result.results.forEach((resultData, i) => {
|
||||
const {
|
||||
resolve,
|
||||
reject
|
||||
} = items[i];
|
||||
|
||||
if (resultData.error) {
|
||||
const err = new Error(resultData.message);
|
||||
err.metadata = resultData.metadata;
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(resultData.response);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function workerHandler(publicInterface) {
|
||||
return function (msg) {
|
||||
const {
|
||||
id,
|
||||
method,
|
||||
calls
|
||||
} = msg.data;
|
||||
Promise.all(calls.map(args => {
|
||||
try {
|
||||
const response = publicInterface[method].apply(undefined, args);
|
||||
|
||||
if (response instanceof Promise) {
|
||||
return response.then(val => ({
|
||||
response: val
|
||||
}), err => asErrorMessage(err));
|
||||
}
|
||||
|
||||
return {
|
||||
response
|
||||
};
|
||||
} catch (error) {
|
||||
return asErrorMessage(error);
|
||||
}
|
||||
})).then(results => {
|
||||
globalThis.postMessage({
|
||||
id,
|
||||
results
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function asErrorMessage(error) {
|
||||
if (typeof error === "object" && error && "message" in error) {
|
||||
// Error can't be sent via postMessage, so be sure to convert to
|
||||
// string.
|
||||
return {
|
||||
error: true,
|
||||
message: error.message,
|
||||
metadata: error.metadata
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
error: true,
|
||||
message: error == null ? error : error.toString(),
|
||||
metadata: undefined
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
WorkerDispatcher,
|
||||
workerHandler
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 581:
|
||||
@ -3366,17 +3318,13 @@ module.exports = __webpack_require__(901);
|
||||
|
||||
var _prettyFast = _interopRequireDefault(__webpack_require__(902));
|
||||
|
||||
var _devtoolsUtils = __webpack_require__(560);
|
||||
var _workerUtils = __webpack_require__(1059);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
const {
|
||||
workerHandler
|
||||
} = _devtoolsUtils.workerUtils;
|
||||
|
||||
function prettyPrint({
|
||||
url,
|
||||
indent,
|
||||
@ -3414,7 +3362,7 @@ function invertMappings(mappings) {
|
||||
});
|
||||
}
|
||||
|
||||
self.onmessage = workerHandler({
|
||||
self.onmessage = (0, _workerUtils.workerHandler)({
|
||||
prettyPrint
|
||||
});
|
||||
|
||||
|
75
devtools/client/debugger/dist/search-worker.js
vendored
75
devtools/client/debugger/dist/search-worker.js
vendored
@ -79,66 +79,15 @@ return /******/ (function(modules) { // webpackBootstrap
|
||||
/************************************************************************/
|
||||
/******/ ({
|
||||
|
||||
/***/ 560:
|
||||
/***/ 1059:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
const networkRequest = __webpack_require__(567);
|
||||
|
||||
const workerUtils = __webpack_require__(568);
|
||||
|
||||
module.exports = {
|
||||
networkRequest,
|
||||
workerUtils
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 567:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
function networkRequest(url, opts) {
|
||||
const UNSUPPORTED_PROTOCOLS = ["chrome://", "resource://"];
|
||||
|
||||
if (UNSUPPORTED_PROTOCOLS.some(protocol => url.startsWith(protocol))) {
|
||||
return Promise.reject(`unsupported protocol for sourcemap request ${url}`);
|
||||
}
|
||||
|
||||
return fetch(url, {
|
||||
cache: opts.loadFromCache ? "default" : "no-cache"
|
||||
}).then(res => {
|
||||
if (res.status >= 200 && res.status < 300) {
|
||||
if (res.headers.get("Content-Type") === "application/wasm") {
|
||||
return res.arrayBuffer().then(buffer => ({
|
||||
content: buffer,
|
||||
isDwarf: true
|
||||
}));
|
||||
}
|
||||
|
||||
return res.text().then(text => ({
|
||||
content: text
|
||||
}));
|
||||
}
|
||||
|
||||
return Promise.reject(`request failed with status ${res.status}`);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = networkRequest;
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 568:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
function WorkerDispatcher() {
|
||||
this.msgId = 1;
|
||||
this.worker = null; // Map of message ids -> promise resolution functions, for dispatching worker responses
|
||||
@ -296,12 +245,15 @@ function asErrorMessage(error) {
|
||||
message: error == null ? error : error.toString(),
|
||||
metadata: undefined
|
||||
};
|
||||
}
|
||||
} // Might be loaded within a worker thread where `module` isn't available.
|
||||
|
||||
module.exports = {
|
||||
WorkerDispatcher,
|
||||
workerHandler
|
||||
};
|
||||
|
||||
if (true) {
|
||||
module.exports = {
|
||||
WorkerDispatcher,
|
||||
workerHandler
|
||||
};
|
||||
}
|
||||
|
||||
/***/ }),
|
||||
|
||||
@ -574,17 +526,14 @@ var _getMatches = _interopRequireDefault(__webpack_require__(701));
|
||||
|
||||
var _projectSearch = __webpack_require__(909);
|
||||
|
||||
var _devtoolsUtils = __webpack_require__(560);
|
||||
var _workerUtils = __webpack_require__(1059);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
const {
|
||||
workerHandler
|
||||
} = _devtoolsUtils.workerUtils;
|
||||
self.onmessage = workerHandler({
|
||||
self.onmessage = (0, _workerUtils.workerHandler)({
|
||||
getMatches: _getMatches.default,
|
||||
findSourceMatches: _projectSearch.findSourceMatches
|
||||
});
|
||||
|
229
devtools/client/debugger/dist/vendors.js
vendored
229
devtools/client/debugger/dist/vendors.js
vendored
@ -93,232 +93,6 @@ module.exports = __WEBPACK_EXTERNAL_MODULE_112__;
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 560:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
const networkRequest = __webpack_require__(567);
|
||||
|
||||
const workerUtils = __webpack_require__(568);
|
||||
|
||||
module.exports = {
|
||||
networkRequest,
|
||||
workerUtils
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 567:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
function networkRequest(url, opts) {
|
||||
const UNSUPPORTED_PROTOCOLS = ["chrome://", "resource://"];
|
||||
|
||||
if (UNSUPPORTED_PROTOCOLS.some(protocol => url.startsWith(protocol))) {
|
||||
return Promise.reject(`unsupported protocol for sourcemap request ${url}`);
|
||||
}
|
||||
|
||||
return fetch(url, {
|
||||
cache: opts.loadFromCache ? "default" : "no-cache"
|
||||
}).then(res => {
|
||||
if (res.status >= 200 && res.status < 300) {
|
||||
if (res.headers.get("Content-Type") === "application/wasm") {
|
||||
return res.arrayBuffer().then(buffer => ({
|
||||
content: buffer,
|
||||
isDwarf: true
|
||||
}));
|
||||
}
|
||||
|
||||
return res.text().then(text => ({
|
||||
content: text
|
||||
}));
|
||||
}
|
||||
|
||||
return Promise.reject(`request failed with status ${res.status}`);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = networkRequest;
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 568:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
function WorkerDispatcher() {
|
||||
this.msgId = 1;
|
||||
this.worker = null; // Map of message ids -> promise resolution functions, for dispatching worker responses
|
||||
|
||||
this.pendingCalls = new Map();
|
||||
this._onMessage = this._onMessage.bind(this);
|
||||
}
|
||||
|
||||
WorkerDispatcher.prototype = {
|
||||
start(url, win = window) {
|
||||
this.worker = new win.Worker(url);
|
||||
|
||||
this.worker.onerror = err => {
|
||||
console.error(`Error in worker ${url}`, err.message);
|
||||
};
|
||||
|
||||
this.worker.addEventListener("message", this._onMessage);
|
||||
},
|
||||
|
||||
stop() {
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.worker.removeEventListener("message", this._onMessage);
|
||||
this.worker.terminate();
|
||||
this.worker = null;
|
||||
this.pendingCalls.clear();
|
||||
},
|
||||
|
||||
task(method, {
|
||||
queue = false
|
||||
} = {}) {
|
||||
const calls = [];
|
||||
|
||||
const push = args => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (queue && calls.length === 0) {
|
||||
Promise.resolve().then(flush);
|
||||
}
|
||||
|
||||
calls.push({
|
||||
args,
|
||||
resolve,
|
||||
reject
|
||||
});
|
||||
|
||||
if (!queue) {
|
||||
flush();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const flush = () => {
|
||||
const items = calls.slice();
|
||||
calls.length = 0;
|
||||
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
const id = this.msgId++;
|
||||
this.worker.postMessage({
|
||||
id,
|
||||
method,
|
||||
calls: items.map(item => item.args)
|
||||
});
|
||||
this.pendingCalls.set(id, items);
|
||||
};
|
||||
|
||||
return (...args) => push(args);
|
||||
},
|
||||
|
||||
invoke(method, ...args) {
|
||||
return this.task(method)(...args);
|
||||
},
|
||||
|
||||
_onMessage({
|
||||
data: result
|
||||
}) {
|
||||
const items = this.pendingCalls.get(result.id);
|
||||
this.pendingCalls.delete(result.id);
|
||||
|
||||
if (!items) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
result.results.forEach((resultData, i) => {
|
||||
const {
|
||||
resolve,
|
||||
reject
|
||||
} = items[i];
|
||||
|
||||
if (resultData.error) {
|
||||
const err = new Error(resultData.message);
|
||||
err.metadata = resultData.metadata;
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(resultData.response);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function workerHandler(publicInterface) {
|
||||
return function (msg) {
|
||||
const {
|
||||
id,
|
||||
method,
|
||||
calls
|
||||
} = msg.data;
|
||||
Promise.all(calls.map(args => {
|
||||
try {
|
||||
const response = publicInterface[method].apply(undefined, args);
|
||||
|
||||
if (response instanceof Promise) {
|
||||
return response.then(val => ({
|
||||
response: val
|
||||
}), err => asErrorMessage(err));
|
||||
}
|
||||
|
||||
return {
|
||||
response
|
||||
};
|
||||
} catch (error) {
|
||||
return asErrorMessage(error);
|
||||
}
|
||||
})).then(results => {
|
||||
globalThis.postMessage({
|
||||
id,
|
||||
results
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function asErrorMessage(error) {
|
||||
if (typeof error === "object" && error && "message" in error) {
|
||||
// Error can't be sent via postMessage, so be sure to convert to
|
||||
// string.
|
||||
return {
|
||||
error: true,
|
||||
message: error.message,
|
||||
metadata: error.metadata
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
error: true,
|
||||
message: error == null ? error : error.toString(),
|
||||
metadata: undefined
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
WorkerDispatcher,
|
||||
workerHandler
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 6:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
@ -1283,8 +1057,6 @@ Object.defineProperty(exports, "__esModule", {
|
||||
});
|
||||
exports.vendored = void 0;
|
||||
|
||||
var devtoolsUtils = _interopRequireWildcard(__webpack_require__(560));
|
||||
|
||||
var fuzzaldrinPlus = _interopRequireWildcard(__webpack_require__(931));
|
||||
|
||||
var transition = _interopRequireWildcard(__webpack_require__(934));
|
||||
@ -1321,7 +1093,6 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
|
||||
// !!! Should remain synchronized with .babel/transform-mc.js !!!
|
||||
const vendored = {
|
||||
classnames: _classnames.default,
|
||||
"devtools-utils": devtoolsUtils,
|
||||
"fuzzaldrin-plus": fuzzaldrinPlus,
|
||||
"react-aria-components/src/tabs": reactAriaComponentsTabs,
|
||||
"react-transition-group/Transition": transition
|
||||
|
@ -18,7 +18,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"babel-plugin-transform-async-to-generator": "^6.22.0",
|
||||
"devtools-utils": "0.0.14",
|
||||
"devtools-wasm-dwarf": "0.0.1",
|
||||
"md5": "^2.2.1",
|
||||
"regenerator-runtime": "^0.13.0",
|
||||
|
@ -2,9 +2,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
const {
|
||||
workerUtils: { WorkerDispatcher },
|
||||
} = require("devtools-utils");
|
||||
const { WorkerDispatcher } = require("devtools/client/shared/worker-utils");
|
||||
|
||||
export const dispatcher = new WorkerDispatcher();
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* @module utils/source-map-worker
|
||||
*/
|
||||
|
||||
const { networkRequest } = require("devtools-utils");
|
||||
const { networkRequest } = require("./utils/network-request");
|
||||
const { SourceMapConsumer, SourceMapGenerator } = require("source-map");
|
||||
|
||||
const { createConsumer } = require("./utils/createConsumer");
|
||||
|
@ -30,10 +30,12 @@ async function setupBundleFixtureAndData(name) {
|
||||
sourceMapBaseURL: `http://example.com/${name}.js`,
|
||||
};
|
||||
|
||||
require("devtools-utils/src/network-request").mockImplementationOnce(() => {
|
||||
const content = getMap(`fixtures/${name}.js.map`);
|
||||
return { content };
|
||||
});
|
||||
require("../utils/network-request").networkRequest.mockImplementationOnce(
|
||||
() => {
|
||||
const content = getMap(`fixtures/${name}.js.map`);
|
||||
return { content };
|
||||
}
|
||||
);
|
||||
|
||||
return getOriginalURLs(source);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
jest.mock("devtools-utils/src/network-request");
|
||||
jest.mock("../utils/network-request");
|
||||
const {
|
||||
getOriginalLocation,
|
||||
getGeneratedLocation,
|
||||
|
@ -2,8 +2,8 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
jest.mock("devtools-utils/src/network-request");
|
||||
const networkRequest = require("devtools-utils/src/network-request");
|
||||
jest.mock("../utils/network-request");
|
||||
const { networkRequest } = require("../utils/network-request");
|
||||
|
||||
const {
|
||||
getOriginalURLs,
|
||||
|
@ -7,7 +7,7 @@
|
||||
const { WasmRemap } = require("../utils/wasmRemap");
|
||||
const { createConsumer } = require("../utils/createConsumer");
|
||||
|
||||
jest.mock("devtools-utils/src/network-request");
|
||||
jest.mock("../utils/network-request");
|
||||
|
||||
describe("wasm source maps", () => {
|
||||
test("smoke test", async () => {
|
||||
@ -96,16 +96,18 @@ describe("wasm source maps", () => {
|
||||
isWasm: true,
|
||||
};
|
||||
|
||||
require("devtools-utils/src/network-request").mockImplementationOnce(() => {
|
||||
const content = JSON.stringify({
|
||||
version: 3,
|
||||
file: "min.js",
|
||||
names: [],
|
||||
sources: ["one.js"],
|
||||
mappings: "CAAC,IAAM",
|
||||
});
|
||||
return { content };
|
||||
});
|
||||
require("../utils/network-request").networkRequest.mockImplementationOnce(
|
||||
() => {
|
||||
const content = JSON.stringify({
|
||||
version: 3,
|
||||
file: "min.js",
|
||||
names: [],
|
||||
sources: ["one.js"],
|
||||
mappings: "CAAC,IAAM",
|
||||
});
|
||||
return { content };
|
||||
}
|
||||
);
|
||||
|
||||
const { getOriginalURLs, getOriginalLocation } = require("../source-map");
|
||||
|
||||
|
@ -2,7 +2,8 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
const { networkRequest } = require("devtools-utils");
|
||||
const { networkRequest } = require("./network-request");
|
||||
|
||||
const { getSourceMap, setSourceMap } = require("./sourceMapRequests");
|
||||
const { WasmRemap } = require("./wasmRemap");
|
||||
const { convertToJSON } = require("devtools-wasm-dwarf");
|
||||
|
@ -32,4 +32,4 @@ function networkRequest(url, opts) {
|
||||
]);
|
||||
}
|
||||
|
||||
module.exports = networkRequest;
|
||||
module.exports = { networkRequest };
|
@ -24,4 +24,4 @@ function networkRequest(url, opts) {
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = networkRequest;
|
||||
module.exports = { networkRequest };
|
@ -21,9 +21,7 @@ const {
|
||||
const { getOriginalStackFrames } = require("./utils/getOriginalStackFrames");
|
||||
const { setAssetRootURL } = require("./utils/assetRoot");
|
||||
|
||||
const {
|
||||
workerUtils: { workerHandler },
|
||||
} = require("devtools-utils");
|
||||
const { workerHandler } = require("devtools/client/shared/worker-utils");
|
||||
|
||||
// The interface is implemented in source-map to be
|
||||
// easier to unit test.
|
||||
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"presets": ["stage-3"]
|
||||
}
|
@ -1,362 +0,0 @@
|
||||
Mozilla Public License, version 2.0
|
||||
|
||||
1. Definitions
|
||||
|
||||
1.1. "Contributor"
|
||||
|
||||
means each individual or legal entity that creates, contributes to the
|
||||
creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
|
||||
means the combination of the Contributions of others (if any) used by a
|
||||
Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
|
||||
means Source Code Form to which the initial Contributor has attached the
|
||||
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
||||
Modifications of such Source Code Form, in each case including portions
|
||||
thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
a. that the initial Contributor has attached the notice described in
|
||||
Exhibit B to the Covered Software; or
|
||||
|
||||
b. that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the terms of
|
||||
a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
|
||||
means a work that combines Covered Software with other material, in a
|
||||
separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
|
||||
means having the right to grant, to the maximum extent possible, whether
|
||||
at the time of the initial grant or subsequently, any and all of the
|
||||
rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
|
||||
means any of the following:
|
||||
|
||||
a. any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered Software; or
|
||||
|
||||
b. any new file in Source Code Form that contains any Covered Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the License,
|
||||
by the making, using, selling, offering for sale, having made, import,
|
||||
or transfer of either its Contributions or its Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
|
||||
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
||||
General Public License, Version 2.1, the GNU Affero General Public
|
||||
License, Version 3.0, or any later versions of those licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that controls, is
|
||||
controlled by, or is under common control with You. For purposes of this
|
||||
definition, "control" means (a) the power, direct or indirect, to cause
|
||||
the direction or management of such entity, whether by contract or
|
||||
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
||||
outstanding shares or beneficial ownership of such entity.
|
||||
|
||||
|
||||
2. License Grants and Conditions
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
a. under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
||||
sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
a. for any code that a Contributor has removed from Covered Software; or
|
||||
|
||||
b. for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
c. under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights to
|
||||
grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
||||
Section 2.1.
|
||||
|
||||
|
||||
3. Responsibilities
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
a. such Covered Software must also be made available in Source Code Form,
|
||||
as described in Section 3.1, and You must inform recipients of the
|
||||
Executable Form how they can obtain a copy of such Source Code Form by
|
||||
reasonable means in a timely manner, at a charge no more than the cost
|
||||
of distribution to the recipient; and
|
||||
|
||||
b. You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter the
|
||||
recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty, or
|
||||
limitations of liability) contained within the Source Code Form of the
|
||||
Covered Software, except that You may alter any license notices to the
|
||||
extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this License
|
||||
with respect to some or all of the Covered Software due to statute,
|
||||
judicial order, or regulation then You must: (a) comply with the terms of
|
||||
this License to the maximum extent possible; and (b) describe the
|
||||
limitations and the code they affect. Such description must be placed in a
|
||||
text file included with all distributions of the Covered Software under
|
||||
this License. Except to the extent prohibited by statute or regulation,
|
||||
such description must be sufficiently detailed for a recipient of ordinary
|
||||
skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically if You
|
||||
fail to comply with any of its terms. However, if You become compliant,
|
||||
then the rights granted under this License from a particular Contributor
|
||||
are reinstated (a) provisionally, unless and until such Contributor
|
||||
explicitly and finally terminates Your grants, and (b) on an ongoing
|
||||
basis, if such Contributor fails to notify You of the non-compliance by
|
||||
some reasonable means prior to 60 days after You have come back into
|
||||
compliance. Moreover, Your grants from a particular Contributor are
|
||||
reinstated on an ongoing basis if such Contributor notifies You of the
|
||||
non-compliance by some reasonable means, this is the first time You have
|
||||
received notice of non-compliance with this License from such
|
||||
Contributor, and You become compliant prior to 30 days after Your receipt
|
||||
of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
||||
license agreements (excluding distributors and resellers) which have been
|
||||
validly granted by You or Your distributors under this License prior to
|
||||
termination shall survive termination.
|
||||
|
||||
6. Disclaimer of Warranty
|
||||
|
||||
Covered Software is provided under this License on an "as is" basis,
|
||||
without warranty of any kind, either expressed, implied, or statutory,
|
||||
including, without limitation, warranties that the Covered Software is free
|
||||
of defects, merchantable, fit for a particular purpose or non-infringing.
|
||||
The entire risk as to the quality and performance of the Covered Software
|
||||
is with You. Should any Covered Software prove defective in any respect,
|
||||
You (not any Contributor) assume the cost of any necessary servicing,
|
||||
repair, or correction. This disclaimer of warranty constitutes an essential
|
||||
part of this License. No use of any Covered Software is authorized under
|
||||
this License except under this disclaimer.
|
||||
|
||||
7. Limitation of Liability
|
||||
|
||||
Under no circumstances and under no legal theory, whether tort (including
|
||||
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
||||
distributes Covered Software as permitted above, be liable to You for any
|
||||
direct, indirect, special, incidental, or consequential damages of any
|
||||
character including, without limitation, damages for lost profits, loss of
|
||||
goodwill, work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses, even if such party shall have been
|
||||
informed of the possibility of such damages. This limitation of liability
|
||||
shall not apply to liability for death or personal injury resulting from
|
||||
such party's negligence to the extent applicable law prohibits such
|
||||
limitation. Some jurisdictions do not allow the exclusion or limitation of
|
||||
incidental or consequential damages, so this exclusion and limitation may
|
||||
not apply to You.
|
||||
|
||||
8. Litigation
|
||||
|
||||
Any litigation relating to this License may be brought only in the courts
|
||||
of a jurisdiction where the defendant maintains its principal place of
|
||||
business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions. Nothing
|
||||
in this Section shall prevent a party's ability to bring cross-claims or
|
||||
counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides that
|
||||
the language of a contract shall be construed against the drafter shall not
|
||||
be used to construe this License against a Contributor.
|
||||
|
||||
|
||||
10. Versions of the License
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses If You choose to distribute Source Code Form that is
|
||||
Incompatible With Secondary Licenses under the terms of this version of
|
||||
the License, the notice described in Exhibit B of this License must be
|
||||
attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular file,
|
||||
then You may include the notice in a location (such as a LICENSE file in a
|
||||
relevant directory) where a recipient would be likely to look for such a
|
||||
notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
|
||||
This Source Code Form is "Incompatible
|
||||
With Secondary Licenses", as defined by
|
||||
the Mozilla Public License, v. 2.0.
|
@ -1,4 +0,0 @@
|
||||
## Devtools Utils
|
||||
|
||||
* _networkRequest_ - CORS network requests
|
||||
* _workerUtils_ - worker task communication
|
@ -1,11 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
const networkRequest = require("./src/network-request");
|
||||
const workerUtils = require("./src/worker-utils");
|
||||
|
||||
module.exports = {
|
||||
networkRequest,
|
||||
workerUtils,
|
||||
};
|
@ -1,16 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
const { resolve } = require("path");
|
||||
const rootDir = resolve(__dirname, "src");
|
||||
module.exports = {
|
||||
rootDir,
|
||||
displayName: "devtools-utils test",
|
||||
testMatch: ["**/tests/**/*.js"],
|
||||
testPathIgnorePatterns: [],
|
||||
testURL: "http://localhost/",
|
||||
transformIgnorePatterns: [],
|
||||
setupFiles: [],
|
||||
moduleNameMapper: {},
|
||||
};
|
@ -1,15 +0,0 @@
|
||||
{
|
||||
"name": "devtools-utils",
|
||||
"version": "0.0.14",
|
||||
"description": "DevTools Utils",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"license-check": "devtools-license-check",
|
||||
"test": "jest --projects jest.config.js"
|
||||
},
|
||||
"author": "",
|
||||
"license": "MPL-2.0",
|
||||
"dependencies": {
|
||||
"babel-preset-stage-3": "^6.22.0"
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"globals": {
|
||||
"jest": true
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
jest.useFakeTimers();
|
||||
const networkRequest = require("../network-request");
|
||||
|
||||
describe("network request", () => {
|
||||
beforeEach(() => {
|
||||
global.fetch = jest.fn();
|
||||
});
|
||||
|
||||
it("successful fetch", async () => {
|
||||
global.fetch.mockImplementation(async () => ({
|
||||
status: 200,
|
||||
headers: { get: () => "application/json" },
|
||||
text: async () => "Yay",
|
||||
}));
|
||||
const res = await networkRequest("foo");
|
||||
expect(res).toEqual({ content: "Yay" });
|
||||
});
|
||||
|
||||
it("wasm successful fetch", async () => {
|
||||
global.fetch.mockImplementation(async () => ({
|
||||
status: 200,
|
||||
headers: { get: () => "application/wasm" },
|
||||
arrayBuffer: async () => "Yay",
|
||||
}));
|
||||
const res = await networkRequest("foo");
|
||||
expect(res).toEqual({ content: "Yay", isDwarf: true });
|
||||
});
|
||||
|
||||
it("failed fetch", async () => {
|
||||
global.fetch.mockImplementation(async () => ({
|
||||
status: 400,
|
||||
headers: { get: () => "application/json" },
|
||||
text: async () => "Sad",
|
||||
}));
|
||||
|
||||
await expect(networkRequest("foo")).rejects.toThrow(
|
||||
expect.objectContaining({ message: "failed to request foo" })
|
||||
);
|
||||
});
|
||||
|
||||
it("timed out fetch", async () => {
|
||||
global.fetch.mockImplementation(async () => {});
|
||||
|
||||
// eslint-disable-next-line jest/valid-expect-in-promise
|
||||
networkRequest("foo").catch(e => {
|
||||
expect(e.message).toEqual("Connect timeout error");
|
||||
});
|
||||
|
||||
jest.runAllTimers();
|
||||
});
|
||||
});
|
@ -1,128 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
const { WorkerDispatcher, workerHandler } = require("../worker-utils");
|
||||
|
||||
describe("worker utils", () => {
|
||||
it("starts a worker", () => {
|
||||
const dispatcher = new WorkerDispatcher();
|
||||
global.Worker = jest.fn(function() {
|
||||
this.addEventListener = jest.fn();
|
||||
});
|
||||
dispatcher.start("foo", globalThis);
|
||||
expect(dispatcher.worker).toEqual(global.Worker.mock.instances[0]);
|
||||
});
|
||||
|
||||
it("stops a worker", () => {
|
||||
const dispatcher = new WorkerDispatcher();
|
||||
const terminateMock = jest.fn();
|
||||
|
||||
global.Worker = jest.fn(() => ({
|
||||
addEventListener: jest.fn(),
|
||||
removeEventListener: jest.fn(),
|
||||
terminate: terminateMock,
|
||||
}));
|
||||
|
||||
dispatcher.start("", globalThis);
|
||||
dispatcher.stop();
|
||||
|
||||
expect(dispatcher.worker).toEqual(null);
|
||||
expect(terminateMock.mock.calls).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("dispatches a task", () => {
|
||||
const dispatcher = new WorkerDispatcher();
|
||||
const postMessageMock = jest.fn();
|
||||
const addEventListenerMock = jest.fn();
|
||||
|
||||
global.Worker = jest.fn(() => {
|
||||
return {
|
||||
postMessage: postMessageMock,
|
||||
addEventListener: addEventListenerMock,
|
||||
};
|
||||
});
|
||||
|
||||
dispatcher.start("", globalThis);
|
||||
const task = dispatcher.task("foo");
|
||||
task("bar");
|
||||
|
||||
const postMessageMockCall = postMessageMock.mock.calls[0][0];
|
||||
|
||||
expect(postMessageMockCall).toEqual({
|
||||
calls: [["bar"]],
|
||||
id: 1,
|
||||
method: "foo",
|
||||
});
|
||||
|
||||
expect(addEventListenerMock.mock.calls).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("dispatches a queued task", async () => {
|
||||
const dispatcher = new WorkerDispatcher();
|
||||
let postMessageMock;
|
||||
const postMessagePromise = new Promise(resolve => {
|
||||
postMessageMock = jest.fn(resolve);
|
||||
});
|
||||
|
||||
const addEventListenerMock = jest.fn();
|
||||
|
||||
global.Worker = jest.fn(() => {
|
||||
return {
|
||||
postMessage: postMessageMock,
|
||||
addEventListener: addEventListenerMock,
|
||||
};
|
||||
});
|
||||
|
||||
dispatcher.start("", globalThis);
|
||||
const task = dispatcher.task("foo", { queue: true });
|
||||
task("bar");
|
||||
task("baz");
|
||||
|
||||
expect(postMessageMock).not.toHaveBeenCalled();
|
||||
|
||||
await postMessagePromise;
|
||||
|
||||
const postMessageMockCall = postMessageMock.mock.calls[0][0];
|
||||
|
||||
expect(postMessageMockCall).toEqual({
|
||||
calls: [["bar"], ["baz"]],
|
||||
id: 1,
|
||||
method: "foo",
|
||||
});
|
||||
|
||||
expect(addEventListenerMock.mock.calls).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("test workerHandler error case", async () => {
|
||||
let postMessageMock;
|
||||
const postMessagePromise = new Promise(resolve => {
|
||||
postMessageMock = jest.fn(resolve);
|
||||
});
|
||||
|
||||
globalThis.postMessage = postMessageMock;
|
||||
|
||||
const callee = {
|
||||
doSomething: () => {
|
||||
throw new Error("failed");
|
||||
},
|
||||
};
|
||||
|
||||
const handler = workerHandler(callee);
|
||||
|
||||
handler({ data: { id: 53, method: "doSomething", calls: [[]] } });
|
||||
|
||||
await postMessagePromise;
|
||||
|
||||
expect(postMessageMock.mock.calls[0][0]).toEqual({
|
||||
id: 53,
|
||||
results: [
|
||||
{
|
||||
error: true,
|
||||
message: "failed",
|
||||
metadata: undefined,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
@ -14,7 +14,6 @@
|
||||
* Both are fine, but cannot be mixed for the same module.
|
||||
*/
|
||||
|
||||
import * as devtoolsUtils from "devtools-utils";
|
||||
import * as fuzzaldrinPlus from "fuzzaldrin-plus";
|
||||
import * as transition from "react-transition-group/Transition";
|
||||
import * as reactAriaComponentsTabs from "react-aria-components/src/tabs";
|
||||
@ -28,7 +27,6 @@ import classnames from "classnames";
|
||||
// !!! Should remain synchronized with .babel/transform-mc.js !!!
|
||||
export const vendored = {
|
||||
classnames,
|
||||
"devtools-utils": devtoolsUtils,
|
||||
"fuzzaldrin-plus": fuzzaldrinPlus,
|
||||
"react-aria-components/src/tabs": reactAriaComponentsTabs,
|
||||
"react-transition-group/Transition": transition,
|
||||
|
@ -2,8 +2,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
import { workerUtils } from "devtools-utils";
|
||||
const { WorkerDispatcher } = workerUtils;
|
||||
import { WorkerDispatcher } from "devtools/client/shared/worker-utils";
|
||||
|
||||
export class ParserDispatcher extends WorkerDispatcher {
|
||||
async findOutOfScopeLocations(sourceId, position) {
|
||||
|
@ -11,8 +11,7 @@ import { getNextStep } from "./steps";
|
||||
import { hasSyntaxError } from "./validate";
|
||||
import mapExpression from "./mapExpression";
|
||||
|
||||
import { workerUtils } from "devtools-utils";
|
||||
const { workerHandler } = workerUtils;
|
||||
import { workerHandler } from "devtools/client/shared/worker-utils";
|
||||
|
||||
function clearState() {
|
||||
clearASTs();
|
||||
|
@ -3,8 +3,7 @@
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
import { prefs } from "../../utils/prefs";
|
||||
import { workerUtils } from "devtools-utils";
|
||||
const { WorkerDispatcher } = workerUtils;
|
||||
import { WorkerDispatcher } from "devtools/client/shared/worker-utils";
|
||||
|
||||
let dispatcher;
|
||||
let workerPath;
|
||||
|
@ -4,8 +4,7 @@
|
||||
|
||||
import prettyFast from "pretty-fast";
|
||||
|
||||
import { workerUtils } from "devtools-utils";
|
||||
const { workerHandler } = workerUtils;
|
||||
import { workerHandler } from "devtools/client/shared/worker-utils";
|
||||
|
||||
function prettyPrint({ url, indent, sourceText }) {
|
||||
const prettified = prettyFast(sourceText, {
|
||||
|
@ -2,8 +2,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
import { workerUtils } from "devtools-utils";
|
||||
const { WorkerDispatcher } = workerUtils;
|
||||
import { WorkerDispatcher } from "devtools/client/shared/worker-utils";
|
||||
|
||||
let startArgs;
|
||||
let dispatcher;
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
import getMatches from "./get-matches";
|
||||
import { findSourceMatches } from "./project-search";
|
||||
import { workerUtils } from "devtools-utils";
|
||||
const { workerHandler } = workerUtils;
|
||||
import { workerHandler } from "devtools/client/shared/worker-utils";
|
||||
|
||||
self.onmessage = workerHandler({ getMatches, findSourceMatches });
|
||||
|
@ -60,8 +60,14 @@ module.exports = {
|
||||
new ObjectRestSpreadPlugin(),
|
||||
new ExtractTextPlugin("[name].css"),
|
||||
new webpack.NormalModuleReplacementPlugin(
|
||||
/.\/src\/network-request/,
|
||||
"./src/privileged-network-request"
|
||||
/\.\/utils\/network-request/,
|
||||
"./utils/privileged-network-request"
|
||||
),
|
||||
// This additional NormalModuleReplacementPlugin is for files in the same
|
||||
// folder as network-request which use require("./network-request");
|
||||
new webpack.NormalModuleReplacementPlugin(
|
||||
/\.\/network-request/,
|
||||
"./privileged-network-request"
|
||||
),
|
||||
new webpack.DefinePlugin({
|
||||
"process.env": {
|
||||
|
@ -36,11 +36,11 @@ add_task(async function() {
|
||||
"resource://devtools/client/shared/vendor/fluent-react.js",
|
||||
"resource://devtools/client/shared/vendor/react-dom.js",
|
||||
"resource://devtools/client/shared/vendor/react.js",
|
||||
"resource://devtools/client/debugger/dist/vendors.js",
|
||||
"resource://devtools/client/shared/vendor/react-prop-types.js",
|
||||
"resource://devtools/client/shared/vendor/react-dom-factories.js",
|
||||
"resource://devtools/client/shared/vendor/react-redux.js",
|
||||
"resource://devtools/client/shared/vendor/redux.js",
|
||||
"resource://devtools/client/shared/worker-utils.js",
|
||||
"resource://devtools/client/debugger/src/workers/parser/index.js",
|
||||
"resource://devtools/client/shared/source-map/index.js",
|
||||
"resource://devtools/client/shared/components/menu/MenuButton.js",
|
||||
|
@ -78,7 +78,7 @@ add_task(async function() {
|
||||
// "resource://devtools/client/netmonitor/src/actions/messages.js",
|
||||
// "resource://devtools/client/netmonitor/src/actions/search.js",
|
||||
// "resource://devtools/client/netmonitor/src/workers/search/index.js",
|
||||
// "resource://devtools/client/netmonitor/src/workers/worker-utils.js",
|
||||
// "resource://devtools/client/shared/worker-utils",
|
||||
// ];
|
||||
// runDuplicatedModulesTest(loaders, allowedDupes);
|
||||
|
||||
|
@ -79,7 +79,7 @@ function initUserSettings() {
|
||||
|
||||
try {
|
||||
const [defaultTargetBrowsers, targetBrowsers] = await Promise.all([
|
||||
UserSettings.getDefaultTargetBrowsers(),
|
||||
UserSettings.getBrowsersList(),
|
||||
UserSettings.getTargetBrowsers(),
|
||||
]);
|
||||
|
||||
|
@ -5,13 +5,13 @@
|
||||
// Test for the default browsers of user settings.
|
||||
|
||||
const {
|
||||
getDefaultTargetBrowsers,
|
||||
getBrowsersList,
|
||||
} = require("devtools/client/inspector/shared/compatibility-user-settings");
|
||||
|
||||
add_task(async () => {
|
||||
info("Check whether each default browsers data are unique by id and status");
|
||||
|
||||
const defaultBrowsers = await getDefaultTargetBrowsers();
|
||||
const defaultBrowsers = await getBrowsersList();
|
||||
|
||||
for (const target of defaultBrowsers) {
|
||||
const count = defaultBrowsers.reduce(
|
||||
|
@ -216,8 +216,11 @@ class Rule {
|
||||
*/
|
||||
async getCompatibilityIssues() {
|
||||
if (!this.compatibilityIssues) {
|
||||
const targetBrowsers = await getTargetBrowsers();
|
||||
const compatibility = await this.inspector.inspectorFront.getCompatibilityFront();
|
||||
const [targetBrowsers, compatibility] = await Promise.all([
|
||||
getTargetBrowsers(),
|
||||
this.inspector.inspectorFront.getCompatibilityFront(),
|
||||
]);
|
||||
|
||||
this.compatibilityIssues = await compatibility.getCSSDeclarationBlockIssues(
|
||||
this.domRule.declarations,
|
||||
targetBrowsers
|
||||
|
@ -18,12 +18,12 @@ const TARGET_BROWSERS = [
|
||||
{
|
||||
// Chrome doesn't need any prefix for both user-select and text-size-adjust.
|
||||
id: "chrome",
|
||||
version: "84",
|
||||
status: "current",
|
||||
},
|
||||
{
|
||||
// The safari_ios needs -webkit prefix for both properties.
|
||||
id: "safari_ios",
|
||||
version: "13",
|
||||
status: "current",
|
||||
},
|
||||
];
|
||||
|
||||
@ -40,7 +40,6 @@ const TEST_URI = `
|
||||
|
||||
const TEST_DATA_INITIAL = [
|
||||
{
|
||||
selector: "div",
|
||||
rules: [
|
||||
{},
|
||||
{
|
||||
@ -61,7 +60,6 @@ const TEST_DATA_INITIAL = [
|
||||
|
||||
const TEST_DATA_FIX_USER_SELECT = [
|
||||
{
|
||||
selector: "div",
|
||||
rules: [
|
||||
{},
|
||||
{
|
||||
@ -83,7 +81,6 @@ const TEST_DATA_FIX_USER_SELECT = [
|
||||
// still show an inline warning for its experimental status.
|
||||
const TEST_DATA_FIX_EXPERIMENTAL_SUPPORTED = [
|
||||
{
|
||||
selector: "div",
|
||||
rules: [
|
||||
{},
|
||||
{
|
||||
@ -112,6 +109,11 @@ add_task(async function() {
|
||||
await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
|
||||
const { inspector, view } = await openRuleView();
|
||||
|
||||
// We're only looking for properties on this single node so select it here instead of
|
||||
// passing `selector` to `runCSSCompatibilityTests` (otherwise addition requests are sent
|
||||
// to the server and we may end up with pending promises when the toolbox closes).
|
||||
await selectNode("div", inspector);
|
||||
|
||||
await runCSSCompatibilityTests(view, inspector, TEST_DATA_INITIAL);
|
||||
|
||||
info(
|
||||
|
@ -27,10 +27,16 @@ const TARGET_BROWSER_STATUS = ["esr", "current", "beta", "nightly"];
|
||||
const TARGET_BROWSER_PREF = "devtools.inspector.compatibility.target-browsers";
|
||||
|
||||
/**
|
||||
* Returns the full list of browsers in the RemoteSetting devtools-compatibility-browsers
|
||||
* collection (which is a flat copy of MDN compat data), sorted by browser and version.
|
||||
*
|
||||
* @returns Promise<Array<Object>>
|
||||
* @returns Promise<Array<Object>> : Objects in the array have the following shape:
|
||||
* - {string} id: The browser id (e.g. `firefox`,`safari_ios`). Should be one of TARGET_BROWSER_ID
|
||||
* - {string} name: The browser display name (e.g. `Firefox`,`Safari for IOS`, …)
|
||||
* - {string} version: The browser version (e.g. `99`,`15.3`, `1.0.4`, …)
|
||||
* - {string} status: The browser status (e.g. `current`,`beta`, …). Should be one of TARGET_BROWSER_STATUS
|
||||
*/
|
||||
async function getDefaultTargetBrowsers() {
|
||||
async function getBrowsersList() {
|
||||
const records = await RemoteSettings("devtools-compatibility-browsers", {
|
||||
filterFunc: record => {
|
||||
if (
|
||||
@ -77,20 +83,56 @@ async function getDefaultTargetBrowsers() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of browsers for which we should check compatibility issues.
|
||||
*
|
||||
* @returns Promise<Array<Object>>
|
||||
* @returns Promise<Array<Object>> : Objects in the array have the following shape:
|
||||
* - {string} id: The browser id (e.g. `firefox`,`safari_ios`). Should be one of TARGET_BROWSER_ID
|
||||
* - {string} name: The browser display name (e.g. `Firefox`,`Safari for IOS`, …)
|
||||
* - {string} version: The browser version (e.g. `99`,`15.3`, `1.0.4`, …)
|
||||
* - {string} status: The browser status (e.g. `current`,`beta`, …). Should be one of TARGET_BROWSER_STATUS
|
||||
*/
|
||||
async function getTargetBrowsers() {
|
||||
const targetsString = Services.prefs.getCharPref(TARGET_BROWSER_PREF, "");
|
||||
return targetsString ? JSON.parse(targetsString) : getDefaultTargetBrowsers();
|
||||
const browsers = await getBrowsersList();
|
||||
|
||||
// If not value are stored in the pref, it means the user did not chose specific browsers,
|
||||
// so we need to return the full list.
|
||||
if (!targetsString) {
|
||||
return browsers;
|
||||
}
|
||||
|
||||
const selectedBrowsersAndStatuses = JSON.parse(targetsString);
|
||||
return browsers.filter(
|
||||
browser =>
|
||||
!!selectedBrowsersAndStatuses.find(
|
||||
({ id, status }) => browser.id == id && browser.status == status
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function setTargetBrowsers(targets) {
|
||||
Services.prefs.setCharPref(TARGET_BROWSER_PREF, JSON.stringify(targets));
|
||||
/**
|
||||
* Store the list of browser id and status that should be used for checking compatibility
|
||||
* issues.
|
||||
*
|
||||
* @param {Object[]} browsers
|
||||
* @param {string} browsers[].id: The browser id. Should be one of TARGET_BROWSER_ID
|
||||
* @param {string} browsers[].status: The browser status. Should be one of TARGET_BROWSER_STATUS
|
||||
*/
|
||||
function setTargetBrowsers(browsers) {
|
||||
Services.prefs.setCharPref(
|
||||
TARGET_BROWSER_PREF,
|
||||
JSON.stringify(
|
||||
// Only store the id and the status
|
||||
browsers.map(browser => ({
|
||||
id: browser.id,
|
||||
status: browser.status,
|
||||
}))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getDefaultTargetBrowsers,
|
||||
getBrowsersList,
|
||||
getTargetBrowsers,
|
||||
setTargetBrowsers,
|
||||
};
|
||||
|
@ -6,7 +6,3 @@
|
||||
DIRS += [
|
||||
"search",
|
||||
]
|
||||
|
||||
DevToolsModules(
|
||||
"worker-utils.js",
|
||||
)
|
||||
|
@ -4,9 +4,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
WorkerDispatcher,
|
||||
} = require("devtools/client/netmonitor/src/workers/worker-utils");
|
||||
const { WorkerDispatcher } = require("devtools/client/shared/worker-utils");
|
||||
|
||||
let startArgs;
|
||||
let dispatcher;
|
||||
|
@ -7,7 +7,7 @@
|
||||
/* eslint-disable no-undef*/
|
||||
importScripts(
|
||||
"resource://devtools/client/netmonitor/src/workers/search/search.js",
|
||||
"resource://devtools/client/netmonitor/src/workers/worker-utils.js"
|
||||
"resource://devtools/client/shared/worker-utils.js"
|
||||
);
|
||||
|
||||
// Implementation of search worker (runs in worker scope).
|
||||
|
@ -1,128 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
"use strict";
|
||||
|
||||
function WorkerDispatcher() {
|
||||
this.msgId = 1;
|
||||
this.worker = null;
|
||||
}
|
||||
|
||||
WorkerDispatcher.prototype = {
|
||||
start(url, win) {
|
||||
this.worker = new win.Worker(url);
|
||||
this.worker.onerror = () => {
|
||||
console.error(`Error in worker ${url}`);
|
||||
};
|
||||
},
|
||||
|
||||
stop() {
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.worker.terminate();
|
||||
this.worker = null;
|
||||
},
|
||||
|
||||
task(method, { queue = false } = {}) {
|
||||
const calls = [];
|
||||
const push = args => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (queue && calls.length === 0) {
|
||||
Promise.resolve().then(flush);
|
||||
}
|
||||
|
||||
calls.push([args, resolve, reject]);
|
||||
|
||||
if (!queue) {
|
||||
flush();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const flush = () => {
|
||||
const items = calls.slice();
|
||||
calls.length = 0;
|
||||
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
const id = this.msgId++;
|
||||
this.worker.postMessage({
|
||||
id,
|
||||
method,
|
||||
calls: items.map(item => item[0]),
|
||||
});
|
||||
|
||||
const listener = ({ data: result }) => {
|
||||
if (result.id !== id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.worker.removeEventListener("message", listener);
|
||||
|
||||
result.results.forEach((resultData, i) => {
|
||||
const [, resolve, reject] = items[i];
|
||||
|
||||
if (resultData.error) {
|
||||
reject(resultData.error);
|
||||
} else {
|
||||
resolve(resultData.response);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
this.worker.addEventListener("message", listener);
|
||||
};
|
||||
|
||||
return (...args) => push(args);
|
||||
},
|
||||
|
||||
invoke(method, ...args) {
|
||||
return this.task(method)(...args);
|
||||
},
|
||||
};
|
||||
|
||||
function workerHandler(publicInterface) {
|
||||
return function(msg) {
|
||||
const { id, method, calls } = msg.data;
|
||||
|
||||
Promise.all(
|
||||
calls.map(args => {
|
||||
try {
|
||||
const response = publicInterface[method].apply(undefined, args);
|
||||
if (response instanceof Promise) {
|
||||
return response.then(
|
||||
val => ({ response: val }),
|
||||
// Error can't be sent via postMessage, so be sure to
|
||||
// convert to string.
|
||||
err => ({ error: err.toString() })
|
||||
);
|
||||
}
|
||||
return { response };
|
||||
} catch (error) {
|
||||
// Error can't be sent via postMessage, so be sure to convert to
|
||||
// string.
|
||||
return { error: error.toString() };
|
||||
}
|
||||
})
|
||||
).then(results => {
|
||||
self.postMessage({ id, results });
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// Might be loaded within a worker thread where `module` isn't available.
|
||||
if (typeof module !== "undefined") {
|
||||
module.exports = {
|
||||
WorkerDispatcher,
|
||||
workerHandler,
|
||||
};
|
||||
}
|
@ -41,7 +41,6 @@ function isRequire(t, node) {
|
||||
const VENDORS = [
|
||||
"classnames",
|
||||
"devtools-environment",
|
||||
"devtools-utils",
|
||||
"fuzzaldrin-plus",
|
||||
"react-aria-components/src/tabs",
|
||||
"react-transition-group/Transition",
|
||||
|
@ -56,6 +56,7 @@ DevToolsModules(
|
||||
"view-source.js",
|
||||
"WeakMapMap.js",
|
||||
"webgl-utils.js",
|
||||
"worker-utils.js",
|
||||
"workers-listener.js",
|
||||
"zoom-keys.js",
|
||||
)
|
||||
|
@ -79,66 +79,15 @@ return /******/ (function(modules) { // webpackBootstrap
|
||||
/************************************************************************/
|
||||
/******/ ({
|
||||
|
||||
/***/ 560:
|
||||
/***/ 1059:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
const networkRequest = __webpack_require__(567);
|
||||
|
||||
const workerUtils = __webpack_require__(568);
|
||||
|
||||
module.exports = {
|
||||
networkRequest,
|
||||
workerUtils
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 567:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
function networkRequest(url, opts) {
|
||||
const UNSUPPORTED_PROTOCOLS = ["chrome://", "resource://"];
|
||||
|
||||
if (UNSUPPORTED_PROTOCOLS.some(protocol => url.startsWith(protocol))) {
|
||||
return Promise.reject(`unsupported protocol for sourcemap request ${url}`);
|
||||
}
|
||||
|
||||
return fetch(url, {
|
||||
cache: opts.loadFromCache ? "default" : "no-cache"
|
||||
}).then(res => {
|
||||
if (res.status >= 200 && res.status < 300) {
|
||||
if (res.headers.get("Content-Type") === "application/wasm") {
|
||||
return res.arrayBuffer().then(buffer => ({
|
||||
content: buffer,
|
||||
isDwarf: true
|
||||
}));
|
||||
}
|
||||
|
||||
return res.text().then(text => ({
|
||||
content: text
|
||||
}));
|
||||
}
|
||||
|
||||
return Promise.reject(`request failed with status ${res.status}`);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = networkRequest;
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 568:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
function WorkerDispatcher() {
|
||||
this.msgId = 1;
|
||||
this.worker = null; // Map of message ids -> promise resolution functions, for dispatching worker responses
|
||||
@ -296,12 +245,15 @@ function asErrorMessage(error) {
|
||||
message: error == null ? error : error.toString(),
|
||||
metadata: undefined
|
||||
};
|
||||
}
|
||||
} // Might be loaded within a worker thread where `module` isn't available.
|
||||
|
||||
module.exports = {
|
||||
WorkerDispatcher,
|
||||
workerHandler
|
||||
};
|
||||
|
||||
if (true) {
|
||||
module.exports = {
|
||||
WorkerDispatcher,
|
||||
workerHandler
|
||||
};
|
||||
}
|
||||
|
||||
/***/ }),
|
||||
|
||||
@ -798,10 +750,8 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
const {
|
||||
workerUtils: {
|
||||
WorkerDispatcher
|
||||
}
|
||||
} = __webpack_require__(560);
|
||||
WorkerDispatcher
|
||||
} = __webpack_require__(1059);
|
||||
|
||||
const dispatcher = new WorkerDispatcher();
|
||||
exports.dispatcher = dispatcher;
|
||||
|
@ -79,72 +79,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
||||
/************************************************************************/
|
||||
/******/ ({
|
||||
|
||||
/***/ 533:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
module.exports =
|
||||
(() => {
|
||||
let factory;
|
||||
function define(...args) {
|
||||
if (factory) {
|
||||
throw new Error("expected a single define call");
|
||||
}
|
||||
|
||||
if (
|
||||
args.length !== 2 ||
|
||||
!Array.isArray(args[0]) ||
|
||||
args[0].length !== 0 ||
|
||||
typeof args[1] !== "function"
|
||||
) {
|
||||
throw new Error("whatwg-url had unexpected factory arguments.");
|
||||
}
|
||||
|
||||
factory = args[1];
|
||||
}
|
||||
define.amd = true;
|
||||
|
||||
const existingDefine = Object.getOwnPropertyDescriptor(globalThis, "define");
|
||||
globalThis.define = define;
|
||||
let err;
|
||||
try {
|
||||
importScripts("resource://devtools/client/shared/vendor/whatwg-url.js");
|
||||
|
||||
if (!factory) {
|
||||
throw new Error("Failed to load whatwg-url factory");
|
||||
}
|
||||
} finally {
|
||||
if (existingDefine) {
|
||||
Object.defineProperty(globalThis, "define", existingDefine);
|
||||
} else {
|
||||
delete globalThis.define;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return factory();
|
||||
})()
|
||||
;
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 560:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
const networkRequest = __webpack_require__(567);
|
||||
|
||||
const workerUtils = __webpack_require__(568);
|
||||
|
||||
module.exports = {
|
||||
networkRequest,
|
||||
workerUtils
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 567:
|
||||
/***/ 1058:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
@ -177,16 +112,21 @@ function networkRequest(url, opts) {
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = networkRequest;
|
||||
module.exports = {
|
||||
networkRequest
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 568:
|
||||
/***/ (function(module, exports) {
|
||||
/***/ 1059:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
|
||||
function WorkerDispatcher() {
|
||||
this.msgId = 1;
|
||||
this.worker = null; // Map of message ids -> promise resolution functions, for dispatching worker responses
|
||||
@ -344,12 +284,63 @@ function asErrorMessage(error) {
|
||||
message: error == null ? error : error.toString(),
|
||||
metadata: undefined
|
||||
};
|
||||
} // Might be loaded within a worker thread where `module` isn't available.
|
||||
|
||||
|
||||
if (true) {
|
||||
module.exports = {
|
||||
WorkerDispatcher,
|
||||
workerHandler
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
WorkerDispatcher,
|
||||
workerHandler
|
||||
};
|
||||
/***/ }),
|
||||
|
||||
/***/ 533:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
module.exports =
|
||||
(() => {
|
||||
let factory;
|
||||
function define(...args) {
|
||||
if (factory) {
|
||||
throw new Error("expected a single define call");
|
||||
}
|
||||
|
||||
if (
|
||||
args.length !== 2 ||
|
||||
!Array.isArray(args[0]) ||
|
||||
args[0].length !== 0 ||
|
||||
typeof args[1] !== "function"
|
||||
) {
|
||||
throw new Error("whatwg-url had unexpected factory arguments.");
|
||||
}
|
||||
|
||||
factory = args[1];
|
||||
}
|
||||
define.amd = true;
|
||||
|
||||
const existingDefine = Object.getOwnPropertyDescriptor(globalThis, "define");
|
||||
globalThis.define = define;
|
||||
let err;
|
||||
try {
|
||||
importScripts("resource://devtools/client/shared/vendor/whatwg-url.js");
|
||||
|
||||
if (!factory) {
|
||||
throw new Error("Failed to load whatwg-url factory");
|
||||
}
|
||||
} finally {
|
||||
if (existingDefine) {
|
||||
Object.defineProperty(globalThis, "define", existingDefine);
|
||||
} else {
|
||||
delete globalThis.define;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return factory();
|
||||
})()
|
||||
;
|
||||
|
||||
/***/ }),
|
||||
|
||||
@ -2125,10 +2116,8 @@ const {
|
||||
} = __webpack_require__(927);
|
||||
|
||||
const {
|
||||
workerUtils: {
|
||||
workerHandler
|
||||
}
|
||||
} = __webpack_require__(560); // The interface is implemented in source-map to be
|
||||
workerHandler
|
||||
} = __webpack_require__(1059); // The interface is implemented in source-map to be
|
||||
// easier to unit test.
|
||||
|
||||
|
||||
@ -2165,7 +2154,7 @@ self.onmessage = workerHandler({
|
||||
*/
|
||||
const {
|
||||
networkRequest
|
||||
} = __webpack_require__(560);
|
||||
} = __webpack_require__(1058);
|
||||
|
||||
const {
|
||||
SourceMapConsumer,
|
||||
@ -4543,7 +4532,7 @@ module.exports = assert;
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
const {
|
||||
networkRequest
|
||||
} = __webpack_require__(560);
|
||||
} = __webpack_require__(1058);
|
||||
|
||||
const {
|
||||
getSourceMap,
|
||||
|
@ -2,6 +2,8 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
"use strict";
|
||||
|
||||
function WorkerDispatcher() {
|
||||
this.msgId = 1;
|
||||
this.worker = null;
|
||||
@ -139,7 +141,10 @@ function asErrorMessage(error) {
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
WorkerDispatcher,
|
||||
workerHandler,
|
||||
};
|
||||
// Might be loaded within a worker thread where `module` isn't available.
|
||||
if (typeof module !== "undefined") {
|
||||
module.exports = {
|
||||
WorkerDispatcher,
|
||||
workerHandler,
|
||||
};
|
||||
}
|
@ -15,6 +15,16 @@ In order to download up-to-date data, you need to run the following commands:
|
||||
- `yarn install --no-lockfile` and select the latest package version for the `@mdn/browser-compat-data` package
|
||||
- `yarn update`
|
||||
|
||||
This should save the JSON files directly in `devtools/shared/compatibility/dataset/`.
|
||||
This should save the `css-properties.json` JSON file directly in `devtools/shared/compatibility/dataset/`.
|
||||
|
||||
For the browsers data, we need to update the RemoteSettings collection.
|
||||
While connected to the Mozilla Corporate VPN (See https://mana.mozilla.org/wiki/display/SD/VPN), log into https://settings-writer.stage.mozaws.net/v1/admin/#/buckets/main/collections/devtools-compatibility-browsers/records (Using `OpenID Connect (LDAP)`). Then copy the authentication header using the icon in the top toolbar.
|
||||
You can then run `SERVER=stage AUTH='XXX' yarn update-rs-records`, replacing `XXX` with the value of the authentication header.
|
||||
|
||||
The logs should indicate if the collection was updated, and if so, provide a short summary of the modifications.
|
||||
If the collection was updated, then run Firefox, and use the [RemoteSettings DevTools WebExtension](https://github.com/mozilla-extensions/remote-settings-devtools) to use the `Stage (preview)` environment.
|
||||
Then open the compatibility panel and make sure that the updated browsers do appear in the `Settings` panel.
|
||||
|
||||
If everything looks right, you can run the same command, on the prod server this time: `SERVER=prod AUTH='XXX' yarn update-rs-records`
|
||||
|
||||
Check that all tests still pass. It is possible that changes in the structure or contents of the latest dataset will cause tests to fail. If that is the case, fix the tests. **Do not manually change the contents or structure of the local dataset** because any changes will be overwritten by the next update from the official dataset.
|
||||
|
@ -7,11 +7,10 @@
|
||||
// This dataset needs to be manually synchronized periodically
|
||||
|
||||
// The subsets from the dataset required by the Compatibility panel are:
|
||||
// * browsers: https://github.com/mdn/browser-compat-data/tree/master/browsers
|
||||
// * css.properties: https://github.com/mdn/browser-compat-data/tree/master/css
|
||||
|
||||
// The MDN compatibility data is available as a node package ("@mdn/browser-compat-data").
|
||||
// This node script downloads `browsers.json` and `css-properties.json` and updates the relevant files.
|
||||
// The MDN compatibility data is available as a node package ("@mdn/browser-compat-data"),
|
||||
// which is used here to update `../dataset/css-properties.json`.
|
||||
|
||||
/* global __dirname */
|
||||
|
||||
@ -19,7 +18,6 @@
|
||||
|
||||
const compatData = require("@mdn/browser-compat-data");
|
||||
exportData(compatData.css.properties, "css-properties.json");
|
||||
exportData(compatData.browsers, "browsers.json");
|
||||
|
||||
function exportData(data, fileName) {
|
||||
const fs = require("fs");
|
||||
|
File diff suppressed because one or more lines are too long
@ -5,6 +5,5 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DevToolsModules(
|
||||
"browsers.json",
|
||||
"css-properties.json",
|
||||
)
|
||||
|
@ -39,6 +39,7 @@ const BROWSER_BASED_DIRS = [
|
||||
"resource://devtools/client/shared/source-map",
|
||||
"resource://devtools/client/shared/redux",
|
||||
"resource://devtools/client/shared/vendor",
|
||||
"resource://devtools/client/shared/worker-utils",
|
||||
];
|
||||
|
||||
const COMMON_LIBRARY_DIRS = ["resource://devtools/client/shared/vendor"];
|
||||
|
@ -2297,7 +2297,11 @@ bool nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel) {
|
||||
|
||||
/* static */
|
||||
bool nsContentUtils::UseStandinsForNativeColors() {
|
||||
return ShouldResistFingerprinting() ||
|
||||
return ShouldResistFingerprinting(
|
||||
"we want to have consistent colors across the browser if RFP is "
|
||||
"enabled, so we check the global preference"
|
||||
"not excluding chrome browsers or webpages, so we call the legacy "
|
||||
"RFP function to prevent that") ||
|
||||
StaticPrefs::ui_use_standins_for_native_colors();
|
||||
}
|
||||
|
||||
|
@ -920,6 +920,7 @@ nsGlobalWindowInner::nsGlobalWindowInner(nsGlobalWindowOuter* aOuterWindow,
|
||||
mHasSeenGamepadInput(false),
|
||||
mHintedWasLoading(false),
|
||||
mHasOpenedExternalProtocolFrame(false),
|
||||
mScrollMarksOnHScrollbar(false),
|
||||
mStorageAllowedReasonCache(0),
|
||||
mSuspendDepth(0),
|
||||
mFreezeDepth(0),
|
||||
@ -7707,9 +7708,10 @@ ContentMediaController* nsGlobalWindowInner::GetContentMediaController() {
|
||||
return mContentMediaController;
|
||||
}
|
||||
|
||||
void nsGlobalWindowInner::SetScrollMarks(
|
||||
const nsTArray<uint32_t>& aScrollMarks) {
|
||||
void nsGlobalWindowInner::SetScrollMarks(const nsTArray<uint32_t>& aScrollMarks,
|
||||
bool aOnHScrollbar) {
|
||||
mScrollMarks.Assign(aScrollMarks);
|
||||
mScrollMarksOnHScrollbar = aOnHScrollbar;
|
||||
|
||||
// Mark the scrollbar for repainting.
|
||||
if (mDoc) {
|
||||
@ -7717,7 +7719,7 @@ void nsGlobalWindowInner::SetScrollMarks(
|
||||
if (presShell) {
|
||||
nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable();
|
||||
if (sf) {
|
||||
sf->InvalidateVerticalScrollbar();
|
||||
sf->InvalidateScrollbars();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1316,7 +1316,9 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
|
||||
}
|
||||
|
||||
nsTArray<uint32_t>& GetScrollMarks() { return mScrollMarks; }
|
||||
void SetScrollMarks(const nsTArray<uint32_t>& aScrollMarks);
|
||||
bool GetScrollMarksOnHScrollbar() const { return mScrollMarksOnHScrollbar; }
|
||||
void SetScrollMarks(const nsTArray<uint32_t>& aScrollMarks,
|
||||
bool aOnHScrollbar);
|
||||
|
||||
// Don't use this value directly, call StorageAccess::StorageAllowedForWindow
|
||||
// instead.
|
||||
@ -1411,6 +1413,8 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
|
||||
// activation once already. Only relevant for top windows.
|
||||
bool mHasOpenedExternalProtocolFrame : 1;
|
||||
|
||||
bool mScrollMarksOnHScrollbar : 1;
|
||||
|
||||
nsCheapSet<nsUint32HashKey> mGamepadIndexSet;
|
||||
nsRefPtrHashtable<nsGenericHashKey<mozilla::dom::GamepadHandle>,
|
||||
mozilla::dom::Gamepad>
|
||||
|
10
dom/base/test/file_delazification_strategy.html
Normal file
10
dom/base/test/file_delazification_strategy.html
Normal file
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Add a tag script to check delazification strategy</title>
|
||||
</head>
|
||||
<body>
|
||||
<!-- <script id="watchme" src="file_delazification_strategy.js"></script> -->
|
||||
</body>
|
||||
</html>
|
91
dom/base/test/file_delazification_strategy.js
Normal file
91
dom/base/test/file_delazification_strategy.js
Normal file
@ -0,0 +1,91 @@
|
||||
function baz() {}
|
||||
function bar() {}
|
||||
function foo() {
|
||||
bar();
|
||||
}
|
||||
foo();
|
||||
|
||||
// For testing, we require the script to be parsed off-htread. To schedule a
|
||||
// script off-thread, we require the script to be at least 5 KB. Thus, here is
|
||||
// one comment which is used to trick this heuristics:
|
||||
//
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWX0Oxoc;,.... ....,;coxO0XWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0kdlc;'.. ..';:ldk0XWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNKkoc,.. ..,cok0NWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKko:'. .':okKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKkl,. .,lkKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOo;. .;oONMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXkl'. 'lkXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOl' 'lONMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMWKo, ,oKWMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMNk:. .:kNMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMXx, ,xXMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMWXd' 'dXWMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMXd' 'dXMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMNx' 'xNMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMWO; ;OWMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMKl. .lXMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMWk, ,kWMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMXo. .lXMMMMMMMMMMMM
|
||||
// MMMMMMMMMMW0; ...... ;0WMMMMMMMMMM
|
||||
// MMMMMMMMMWk' ..,:loxxkOOkxdo:,. 'kWMMMMMMMMM
|
||||
// MMMMMMMMWx. .':lxO000000000000000ko;. .xWMMMMMMMM
|
||||
// MMMMMMMNd. .'cdk00000000000000000000000x;. ..',;ccloodddddddollc:;,'.. .dNMMMMMMM
|
||||
// MMMMMMNd. ,dO000000000000000000000000000Oo' ..;coxk00000000000000000000000Okdlc;'. .dNMMMMMM
|
||||
// MMMMMNd. .cO000000000000000000000000000000k; .;lxO0000000000000000000000000000000000Okoc,. .dWMMMMM
|
||||
// MMMMWx. .'cO0000000000000000000000000000Oc. .;ok0000K00000000000000000000000000000000000000ko, .kWMMMM
|
||||
// MMMMO' ,kK0000000000000000000000000000Oc. .:x000000000000000OkdoollcccllodxkO0000K00000000000k' 'OMMMM
|
||||
// MMMK; .'lO000000000000000000000000000000Ol'... 'd000000000000Odl;'.. ..',:ldkO00000000KO, ;KMMM
|
||||
// MMNo ,dkO0K00000000000000000000000000000000OOkxdoc;,,ck0000000000Oo;. .'ck000000KO; oNMM
|
||||
// MMk. .o0000000000000000000000000000000000000000000000000000000000d, .o000000K0: .OMM
|
||||
// MX: .o00000000000000000000000000000000000000000000000000000000Oc. c000000K0l. :XM
|
||||
// Wx. .c00000000000000000000000000000000000000000000000000000000x, :OK000000o. .xW
|
||||
// X: .:dxO00000000000000000000000000000000000000000000000000000Oo' ,k0000000d. :X
|
||||
// O. .:xOO0000000000000000000000000000000000000000000000000000Ol. .x000000Kd. .O
|
||||
// o ..'''''''',,:lx000000000000000000000000000000000000000000x, .lOOOOkkko. o
|
||||
// ; .:x00000000000000000000000000000000000000000O:. ......... ;
|
||||
// . 'd00000000000000000000000000000000000000000Ol. .
|
||||
// . ,k000000000000000000000000000000000000000000o. .
|
||||
// .o0000000000000000000000000000000000000000000d.
|
||||
// c00000000000000000000000000000000000000000000o.
|
||||
// ;OK0000000000000000000000000000000000000000000o.
|
||||
// ,kK00000000000000000000000000000000000000000000xoc:,'..
|
||||
// .x00000000000000000000000000000000000000000000000000Okxolc;,'..
|
||||
// .d000000000000000K000000000000000000000000000000000000000000OOxdl:,..
|
||||
// . .o00000000000000OO0000000000000000000000000000000000000000000000000Oxo:'. .
|
||||
// . .l0000000000000Oc:k0000000000000000000000000000000000000000000000000000Oxl,. .
|
||||
// ; c000000000000Kk, ,x000000000000000000000000000000xodkO00000000000000000000xc. ;
|
||||
// o ..''.. :000000000000Kx' ,k0000000000000000000000000000Oc. ..';codkO000000000000000k:. o
|
||||
// O. .,lxO00Okxl:,. :O000000000000d. ;k0000000000000000000000000000l. ..,cok0000000000000d' .O
|
||||
// X: ,d000000000000kdc;. :O000000000000l. .c0000000000000000000000000000o. .;oO00000000000k; :X
|
||||
// Wx. 'x00000000000000000Oxl;..:O00000000000O: .x000000000000000000000000000d. 'oO00000K0000k, .kW
|
||||
// MX: c0000000000000000000000Oxk00000000000Kk, cO00000000000000000000000000d. ;k0000000000d. :XM
|
||||
// MMO. :O000000000000000000000000000000000000x. cO00000000000000000000000000d. ,k000000000O: .OMM
|
||||
// MMNo .d000000000000000000000000000000000000l. .d000000000000000000000000000o. cO000000000o. .oNMM
|
||||
// MMMK; 'd00000000000000000000000000000000000c ,k000000000000000000000000000l. 'x000000000d. ;KMMM
|
||||
// MMMMO' .lO000000000000000000000000000000000kl;. .o00000000000000000000000000K0c .d000000000d. 'OMMMM
|
||||
// MMMMWx. ;x00000000000000000000000000000000000ko:lO000000000000000000000000000O; .x000000000d. .xWMMMM
|
||||
// MMMMMWd. .ck00000000000000000000000000000000000000000000000000000000000000000k, ;kK00000000l. .dWMMMMM
|
||||
// MMMMMMNd. .:x000000000000000000000000000000000000000000000000000000000000000d. .o000000000O; .dNMMMMMM
|
||||
// MMMMMMMNd. .;dO000000000000000000000000000000000000000000000000000000000000l. .o0000000000d. .dNMMMMMMM
|
||||
// MMMMMMMMWx. .,,'.. 'cx00000000000000000000000000000000000000000000000000000000KO: .;d0000000000x, .xWMMMMMMMM
|
||||
// MMMMMMMMMWk' 'd00Oxdl;'. .,lx000000000000000000000000000000000000000000000000000000k' .:dO0000000000x, 'kWMMMMMMMMM
|
||||
// MMMMMMMMMMW0; .:x000000kd:'. .,lk000000000000000000000000000000000000000000000000000d. ..,cdk0K000000000Oo. :0WMMMMMMMMMM
|
||||
// MMMMMMMMMMMMXo. .,ok000000Odc. ,x000000000000000000000000000000000000000000000000000d,...'',;:cldxO000000000000K0d;. .oXMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMWk, .:x0000000Oo;.. .,oO000000000000000000000000000000000000000000000000000000OOOO00000000000000000000Od;. ,kWMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMXl. .;dO0000000Oxdoooxk0000000000OxxO0000000000000000000000000000000000000000000000000000000000000000Oxc' .lXMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMWO; 'lk00000000000000000000Oxc' ..:oxO0K000000000000000000000000000000000000000000000000000000Oko:'. ;OWMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMNx, .;ok00000000000000kdc'. ..;cdxO00000000000000000000000000000000000000000000Okxdoc;'. ,xNMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMXd' .,:ldxkkkkxdl:,. ..,:cldxkkkO000000000000Okkxdlc:;;;:::::;;;,,'... 'dXMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMXd' ...... ....'',,,,,,,,'.... 'dXWMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMXx,. ,xXMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMNk:. .:kNMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMWKo,. .,oKWMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOl' 'lONMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXkl'. .'lkXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOo;. .;oONMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKkl;. .,lkKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKko:'. .':okKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNKkoc,.. ..,cok0NWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0kdlc;'.. ..';:ldk0XWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWX0Oxoc;,.... ....,;coxO0XNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
@ -755,6 +755,11 @@ support-files =
|
||||
file_js_cache_save_after_load.js
|
||||
file_js_cache_syntax_error.html
|
||||
file_js_cache_syntax_error.js
|
||||
[test_delazification_strategy.html]
|
||||
skip-if = verify
|
||||
support-files =
|
||||
file_delazification_strategy.html
|
||||
file_delazification_strategy.js
|
||||
[test_setInterval_from_start.html]
|
||||
[test_setInterval_uncatchable_exception.html]
|
||||
skip-if = debug == false
|
||||
|
175
dom/base/test/test_delazification_strategy.html
Normal file
175
dom/base/test/test_delazification_strategy.html
Normal file
@ -0,0 +1,175 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=1753709 -->
|
||||
<!-- Script delazification strategy is not supposed to have any observable
|
||||
side-effect. To make it observable, the ScriptLoader is instrumented to
|
||||
trigger events on the script tag. These events are used to validate that
|
||||
the strategy is used as execpected. This does not garantee that all
|
||||
functions are delazified properly, but this should be checked in the JS
|
||||
engine test suite.
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for triggering eager delazification.</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script type="application/javascript">
|
||||
async function WaitForScriptTagEvent() {
|
||||
var url = "file_delazification_strategy.html";
|
||||
var iframe = document.createElement("iframe");
|
||||
|
||||
// Call the resolve function when the event is one of the expected events.
|
||||
// This is made to be used by a promise and provided to event listeners.
|
||||
function resolve_with_event(resolve, evt) {
|
||||
// If we have multiple script tags in the loaded source, make sure
|
||||
// we only watch a single one.
|
||||
if (evt.target.id != "watchme")
|
||||
return;
|
||||
|
||||
switch (evt.type) {
|
||||
case "delazification_on_demand_only":
|
||||
case "delazification_concurrent_depth_first":
|
||||
case "delazification_parse_everything_eagerly":
|
||||
resolve(evt.type.split('_').slice(1).join('_'));
|
||||
break;
|
||||
case "scriptloader_main_thread_compile":
|
||||
resolve(evt.type);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Create an event listener, which resolves a promise.
|
||||
let log_event;
|
||||
let scriptLoaderTrace = new Promise((resolve, reject) => {
|
||||
log_event = resolve_with_event.bind(this, resolve);
|
||||
});
|
||||
|
||||
// Wait until the iframe is fully loaded.
|
||||
await new Promise(resolve => {
|
||||
iframe.onload = resolve;
|
||||
iframe.src = url;
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
|
||||
// Register all events.
|
||||
let events = [
|
||||
"delazification_on_demand_only",
|
||||
"delazification_concurrent_depth_first",
|
||||
"delazification_parse_everything_eagerly",
|
||||
"scriptloader_main_thread_compile"
|
||||
];
|
||||
let iwin = iframe.contentWindow;
|
||||
for (let evt of events) {
|
||||
iwin.addEventListener(evt, log_event);
|
||||
}
|
||||
|
||||
// Add a script tag, which will trigger one of the previous events.
|
||||
let script = document.createElement("script");
|
||||
script.setAttribute("id", "watchme");
|
||||
script.setAttribute("src", "file_delazification_strategy.js");
|
||||
iframe.contentDocument.body.appendChild(script);
|
||||
|
||||
// Wait for the event emitted by ScriptLoader, while processing the
|
||||
// previous script.
|
||||
let result = await scriptLoaderTrace;
|
||||
|
||||
// Remove the events and the iframe.
|
||||
for (let evt of events) {
|
||||
iwin.removeEventListener(evt, log_event);
|
||||
}
|
||||
document.body.removeChild(iframe);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Setting dom.expose_test_interfaces pref causes the
|
||||
// nsScriptLoadRequest to fire event on script tags, with information
|
||||
// about its internal state. The ScriptLoader source send events to
|
||||
// trace these and resolve a promise with the path taken by the
|
||||
// script loader.
|
||||
//
|
||||
// Setting dom.script_loader.bytecode_cache.enabled to false in order
|
||||
// to prevent the bytecode cache to perturb this test case.
|
||||
//
|
||||
// Setting dom.script_loader.external_scripts.speculate_* are used to
|
||||
// force off-main-thread compilation, while hoping that we have enough
|
||||
// processors to run the test case
|
||||
//
|
||||
// Setting dom.delazification.* are used to select the delazification
|
||||
// strategy and to check that it is well selected.
|
||||
promise_test(async function() {
|
||||
await SpecialPowers.pushPrefEnv({set: [
|
||||
['dom.expose_test_interfaces', true],
|
||||
['dom.script_loader.bytecode_cache.enabled', false],
|
||||
['dom.script_loader.external_scripts.speculate_non_parser_inserted.enable', true],
|
||||
['dom.script_loader.external_scripts.speculate_async.enabled', true],
|
||||
['dom.script_loader.external_scripts.speculate_link_preload.enabled', true],
|
||||
// Parse everything eagerly
|
||||
['dom.script_loader.delazification.strategy', 255],
|
||||
['dom.script_loader.delazification.max_size', 0],
|
||||
['dom.script_loader.delazification.min_mem', 0],
|
||||
]});
|
||||
|
||||
assert_equals(await WaitForScriptTagEvent(), "on_demand_only",
|
||||
"[1] AttemptAsyncScriptCompile: On demand only");
|
||||
}, "Check that max_size can disable delazification strategy");
|
||||
|
||||
promise_test(async function() {
|
||||
await SpecialPowers.pushPrefEnv({set: [
|
||||
['dom.expose_test_interfaces', true],
|
||||
['dom.script_loader.bytecode_cache.enabled', false],
|
||||
// Enable OffMainThread compilation for everything, and cross-fingers
|
||||
// about the number of CPU.
|
||||
['dom.script_loader.external_scripts.speculate_non_parser_inserted.enable', true],
|
||||
['dom.script_loader.external_scripts.speculate_async.enabled', true],
|
||||
['dom.script_loader.external_scripts.speculate_link_preload.enabled', true],
|
||||
// Parse everything eagerly
|
||||
['dom.script_loader.delazification.strategy', 255],
|
||||
['dom.script_loader.delazification.max_size', 10485760],
|
||||
// 4 TB should of RAM be enough.
|
||||
['dom.script_loader.delazification.min_mem', 4096],
|
||||
]});
|
||||
|
||||
assert_equals(await WaitForScriptTagEvent(), "on_demand_only",
|
||||
"[2] AttemptAsyncScriptCompile: On demand only");
|
||||
}, "Check that min_mem can disable delazification strategy");
|
||||
|
||||
promise_test(async function() {
|
||||
await SpecialPowers.pushPrefEnv({set: [
|
||||
['dom.expose_test_interfaces', true],
|
||||
['dom.script_loader.bytecode_cache.enabled', false],
|
||||
// Enable OffMainThread compilation for everything, and cross-fingers
|
||||
// about the number of CPU.
|
||||
['dom.script_loader.external_scripts.speculate_non_parser_inserted.enable', true],
|
||||
['dom.script_loader.external_scripts.speculate_async.enabled', true],
|
||||
['dom.script_loader.external_scripts.speculate_link_preload.enabled', true],
|
||||
['dom.script_loader.delazification.max_size', 10485760],
|
||||
['dom.script_loader.delazification.min_mem', 0],
|
||||
]});
|
||||
|
||||
await SpecialPowers.pushPrefEnv({set: [
|
||||
['dom.script_loader.delazification.strategy', 0],
|
||||
]});
|
||||
assert_equals(await WaitForScriptTagEvent(), "on_demand_only",
|
||||
"[3] AttemptAsyncScriptCompile: On demand only");
|
||||
|
||||
await SpecialPowers.pushPrefEnv({set: [
|
||||
['dom.script_loader.delazification.strategy', 1],
|
||||
]});
|
||||
assert_equals(await WaitForScriptTagEvent(), "concurrent_depth_first",
|
||||
"[3] AttemptAsyncScriptCompile: Concurrent Depth First");
|
||||
|
||||
await SpecialPowers.pushPrefEnv({set: [
|
||||
['dom.script_loader.delazification.strategy', 255],
|
||||
]});
|
||||
assert_equals(await WaitForScriptTagEvent(), "parse_everything_eagerly",
|
||||
"[3] AttemptAsyncScriptCompile: Parse Everything Eagerly");
|
||||
}, "Check enabling delazification strategy works");
|
||||
|
||||
done();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1753709">Mozilla Bug 1753709</a>
|
||||
</body>
|
||||
</html>
|
@ -627,7 +627,6 @@ DOMInterfaces = {
|
||||
'PeerConnectionImpl': {
|
||||
'nativeType': 'mozilla::PeerConnectionImpl',
|
||||
'headerFile': 'PeerConnectionImpl.h',
|
||||
'wrapperCache': False
|
||||
},
|
||||
|
||||
'PerformanceResourceTiming' : {
|
||||
|
@ -501,9 +501,8 @@ class AdjustedTargetForShadow {
|
||||
int32_t blurRadius = state.ShadowBlurRadius();
|
||||
bounds.Inflate(blurRadius);
|
||||
bounds.RoundOut();
|
||||
bounds.ToIntRect(&mTempRect);
|
||||
|
||||
if (!mFinalTarget->CanCreateSimilarDrawTarget(mTempRect.Size(),
|
||||
if (!bounds.ToIntRect(&mTempRect) ||
|
||||
!mFinalTarget->CanCreateSimilarDrawTarget(mTempRect.Size(),
|
||||
SurfaceFormat::B8G8R8A8)) {
|
||||
mTarget = mFinalTarget;
|
||||
mCtx = nullptr;
|
||||
@ -595,7 +594,7 @@ class AdjustedTarget {
|
||||
bounds = bounds.Intersect(*aBounds);
|
||||
}
|
||||
gfx::Rect boundsAfterFilter = BoundsAfterFilter(bounds, aCtx);
|
||||
if (!aCtx->IsTargetValid()) {
|
||||
if (!aCtx->IsTargetValid() || !boundsAfterFilter.IsFinite()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -179,17 +179,19 @@ void FetchService::FetchInstance::OnResponseEnd(
|
||||
}
|
||||
|
||||
// Get PerformanceTimingData from FetchDriver.
|
||||
IPCPerformanceTimingData ipcPerformanceTiming;
|
||||
nsString initiatorType;
|
||||
nsString entryName;
|
||||
UniquePtr<PerformanceTimingData> performanceTiming(
|
||||
mFetchDriver->GetPerformanceTimingData(initiatorType, entryName));
|
||||
MOZ_ASSERT(performanceTiming);
|
||||
if (performanceTiming != nullptr) {
|
||||
ipcPerformanceTiming = performanceTiming->ToIPC();
|
||||
}
|
||||
|
||||
initiatorType = u"navigation"_ns;
|
||||
|
||||
FetchServiceResponse response =
|
||||
MakeTuple(std::move(mResponse), performanceTiming->ToIPC(), initiatorType,
|
||||
entryName);
|
||||
FetchServiceResponse response = MakeTuple(
|
||||
std::move(mResponse), ipcPerformanceTiming, initiatorType, entryName);
|
||||
|
||||
// Resolve the FetchServiceResponsePromise
|
||||
mResponsePromiseHolder.ResolveIfExists(std::move(response), __func__);
|
||||
|
@ -1132,10 +1132,9 @@ int32_t HTMLFormElement::CompareFormControlPosition(Element* aElement1,
|
||||
/* static */
|
||||
void HTMLFormElement::AssertDocumentOrder(
|
||||
const nsTArray<nsGenericHTMLFormElement*>& aControls, nsIContent* aForm) {
|
||||
// TODO: remove the return statement with bug 598468.
|
||||
// TODO: remove the if directive with bug 598468.
|
||||
// This is done to prevent asserts in some edge cases.
|
||||
return;
|
||||
|
||||
# if 0
|
||||
// Only iterate if aControls is not empty, since otherwise
|
||||
// |aControls.Length() - 1| will be a very large unsigned number... not what
|
||||
// we want here.
|
||||
@ -1146,6 +1145,7 @@ void HTMLFormElement::AssertDocumentOrder(
|
||||
"Form controls not ordered correctly");
|
||||
}
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1158,10 +1158,9 @@ void HTMLFormElement::AssertDocumentOrder(
|
||||
void HTMLFormElement::AssertDocumentOrder(
|
||||
const nsTArray<RefPtr<nsGenericHTMLFormElement>>& aControls,
|
||||
nsIContent* aForm) {
|
||||
// TODO: remove the return statement with bug 598468.
|
||||
// TODO: remove the if directive with bug 598468.
|
||||
// This is done to prevent asserts in some edge cases.
|
||||
return;
|
||||
|
||||
# if 0
|
||||
// Only iterate if aControls is not empty, since otherwise
|
||||
// |aControls.Length() - 1| will be a very large unsigned number... not what
|
||||
// we want here.
|
||||
@ -1172,6 +1171,7 @@ void HTMLFormElement::AssertDocumentOrder(
|
||||
"Form controls not ordered correctly");
|
||||
}
|
||||
}
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -28,11 +28,11 @@ void VsyncParent::UpdateVsyncSource(
|
||||
}
|
||||
|
||||
if (mObservingVsync && mVsyncDispatcher) {
|
||||
mVsyncDispatcher->RemoveChildRefreshTimer(this);
|
||||
mVsyncDispatcher->RemoveVsyncObserver(this);
|
||||
}
|
||||
mVsyncDispatcher = mVsyncSource->GetRefreshTimerVsyncDispatcher();
|
||||
if (mObservingVsync) {
|
||||
mVsyncDispatcher->AddChildRefreshTimer(this);
|
||||
mVsyncDispatcher->AddVsyncObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,7 +69,7 @@ mozilla::ipc::IPCResult VsyncParent::RecvObserve() {
|
||||
AssertIsOnInitialThread();
|
||||
if (!mObservingVsync) {
|
||||
if (mVsyncDispatcher) {
|
||||
mVsyncDispatcher->AddChildRefreshTimer(this);
|
||||
mVsyncDispatcher->AddVsyncObserver(this);
|
||||
}
|
||||
mObservingVsync = true;
|
||||
return IPC_OK();
|
||||
@ -81,7 +81,7 @@ mozilla::ipc::IPCResult VsyncParent::RecvUnobserve() {
|
||||
AssertIsOnInitialThread();
|
||||
if (mObservingVsync) {
|
||||
if (mVsyncDispatcher) {
|
||||
mVsyncDispatcher->RemoveChildRefreshTimer(this);
|
||||
mVsyncDispatcher->RemoveVsyncObserver(this);
|
||||
}
|
||||
mObservingVsync = false;
|
||||
return IPC_OK();
|
||||
@ -93,7 +93,7 @@ void VsyncParent::ActorDestroy(ActorDestroyReason aActorDestroyReason) {
|
||||
MOZ_ASSERT(!mDestroyed);
|
||||
AssertIsOnInitialThread();
|
||||
if (mObservingVsync && mVsyncDispatcher) {
|
||||
mVsyncDispatcher->RemoveChildRefreshTimer(this);
|
||||
mVsyncDispatcher->RemoveVsyncObserver(this);
|
||||
}
|
||||
mVsyncDispatcher = nullptr;
|
||||
mDestroyed = true;
|
||||
|
@ -567,7 +567,7 @@ class RTCPeerConnection {
|
||||
// Add a reference to the PeerConnection to global list (before init).
|
||||
_globalPCList.addPC(this);
|
||||
|
||||
this._impl.initialize(observer, this._win, Services.tm.currentThread);
|
||||
this._impl.initialize(observer, this._win);
|
||||
|
||||
this.setConfiguration(rtcConfig);
|
||||
|
||||
|
@ -629,6 +629,10 @@ nsresult MediaTransportHandlerSTS::SetIceConfig(
|
||||
mInitPromise->Then(
|
||||
mStsThread, __func__,
|
||||
[=, self = RefPtr<MediaTransportHandlerSTS>(this)]() {
|
||||
if (!mIceCtx) {
|
||||
CSFLogError(LOGTAG, "%s: mIceCtx is null", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
NrIceCtx::Config config;
|
||||
config.mPolicy = toNrIcePolicy(aIcePolicy);
|
||||
if (config.mPolicy == NrIceCtx::ICE_POLICY_ALL && mForceNoHost) {
|
||||
|
@ -9,38 +9,45 @@
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
PacketDumper::PacketDumper(PeerConnectionImpl* aPc) : mPc(aPc) {}
|
||||
|
||||
PacketDumper::PacketDumper(const std::string& aPcHandle) {
|
||||
if (!aPcHandle.empty()) {
|
||||
PeerConnectionWrapper pcw(aPcHandle);
|
||||
mPc = pcw.impl();
|
||||
/* static */
|
||||
RefPtr<PacketDumper> PacketDumper::GetPacketDumper(
|
||||
const std::string& aPcHandle) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
PeerConnectionWrapper pcw(aPcHandle);
|
||||
if (pcw.impl()) {
|
||||
return pcw.impl()->GetPacketDumper();
|
||||
}
|
||||
|
||||
return new PacketDumper("");
|
||||
}
|
||||
|
||||
PacketDumper::~PacketDumper() {
|
||||
RefPtr<Runnable> pcDisposeRunnable = media::NewRunnableFrom(std::bind(
|
||||
[](RefPtr<PeerConnectionImpl> pc) { return NS_OK; }, mPc.forget()));
|
||||
NS_DispatchToMainThread(pcDisposeRunnable);
|
||||
}
|
||||
PacketDumper::PacketDumper(const std::string& aPcHandle)
|
||||
: mPcHandle(aPcHandle),
|
||||
mPacketDumpEnabled(false),
|
||||
mPacketDumpFlagsMutex("Packet dump flags mutex") {}
|
||||
|
||||
void PacketDumper::Dump(size_t level, dom::mozPacketDumpType type, bool sending,
|
||||
const void* data, size_t size) {
|
||||
void PacketDumper::Dump(size_t aLevel, dom::mozPacketDumpType aType,
|
||||
bool aSending, const void* aData, size_t aSize) {
|
||||
// Optimization; avoids making a copy of the buffer, but we need to lock a
|
||||
// mutex and check the flags. Could be optimized further, if we really want to
|
||||
if (!mPc || !mPc->ShouldDumpPacket(level, type, sending)) {
|
||||
if (!ShouldDumpPacket(aLevel, aType, aSending)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<PeerConnectionImpl> pc = mPc;
|
||||
|
||||
UniquePtr<uint8_t[]> ownedPacket = MakeUnique<uint8_t[]>(size);
|
||||
memcpy(ownedPacket.get(), data, size);
|
||||
UniquePtr<uint8_t[]> ownedPacket = MakeUnique<uint8_t[]>(aSize);
|
||||
memcpy(ownedPacket.get(), aData, aSize);
|
||||
|
||||
RefPtr<Runnable> dumpRunnable = media::NewRunnableFrom(std::bind(
|
||||
[pc, level, type, sending,
|
||||
size](UniquePtr<uint8_t[]>& packet) -> nsresult {
|
||||
pc->DumpPacket_m(level, type, sending, packet, size);
|
||||
[this, self = RefPtr<PacketDumper>(this), aLevel, aType, aSending,
|
||||
aSize](UniquePtr<uint8_t[]>& aPacket) -> nsresult {
|
||||
// Check again; packet dump might have been disabled since the dispatch
|
||||
if (ShouldDumpPacket(aLevel, aType, aSending)) {
|
||||
PeerConnectionWrapper pcw(mPcHandle);
|
||||
RefPtr<PeerConnectionImpl> pc = pcw.impl();
|
||||
if (pc) {
|
||||
pc->DumpPacket_m(aLevel, aType, aSending, aPacket, aSize);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
},
|
||||
std::move(ownedPacket)));
|
||||
@ -48,4 +55,70 @@ void PacketDumper::Dump(size_t level, dom::mozPacketDumpType type, bool sending,
|
||||
NS_DispatchToMainThread(dumpRunnable);
|
||||
}
|
||||
|
||||
nsresult PacketDumper::EnablePacketDump(unsigned long aLevel,
|
||||
dom::mozPacketDumpType aType,
|
||||
bool aSending) {
|
||||
mPacketDumpEnabled = true;
|
||||
std::vector<unsigned>* packetDumpFlags;
|
||||
if (aSending) {
|
||||
packetDumpFlags = &mSendPacketDumpFlags;
|
||||
} else {
|
||||
packetDumpFlags = &mRecvPacketDumpFlags;
|
||||
}
|
||||
|
||||
unsigned flag = 1 << (unsigned)aType;
|
||||
|
||||
MutexAutoLock lock(mPacketDumpFlagsMutex);
|
||||
if (aLevel >= packetDumpFlags->size()) {
|
||||
packetDumpFlags->resize(aLevel + 1);
|
||||
}
|
||||
|
||||
(*packetDumpFlags)[aLevel] |= flag;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult PacketDumper::DisablePacketDump(unsigned long aLevel,
|
||||
dom::mozPacketDumpType aType,
|
||||
bool aSending) {
|
||||
std::vector<unsigned>* packetDumpFlags;
|
||||
if (aSending) {
|
||||
packetDumpFlags = &mSendPacketDumpFlags;
|
||||
} else {
|
||||
packetDumpFlags = &mRecvPacketDumpFlags;
|
||||
}
|
||||
|
||||
unsigned flag = 1 << (unsigned)aType;
|
||||
|
||||
MutexAutoLock lock(mPacketDumpFlagsMutex);
|
||||
if (aLevel < packetDumpFlags->size()) {
|
||||
(*packetDumpFlags)[aLevel] &= ~flag;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool PacketDumper::ShouldDumpPacket(size_t aLevel, dom::mozPacketDumpType aType,
|
||||
bool aSending) const {
|
||||
if (!mPacketDumpEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MutexAutoLock lock(mPacketDumpFlagsMutex);
|
||||
|
||||
const std::vector<unsigned>* packetDumpFlags;
|
||||
|
||||
if (aSending) {
|
||||
packetDumpFlags = &mSendPacketDumpFlags;
|
||||
} else {
|
||||
packetDumpFlags = &mRecvPacketDumpFlags;
|
||||
}
|
||||
|
||||
if (aLevel < packetDumpFlags->size()) {
|
||||
unsigned flag = 1 << (unsigned)aType;
|
||||
return flag & packetDumpFlags->at(aLevel);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -14,18 +14,35 @@ class PeerConnectionImpl;
|
||||
|
||||
class PacketDumper {
|
||||
public:
|
||||
explicit PacketDumper(PeerConnectionImpl* aPc);
|
||||
explicit PacketDumper(const std::string& aPcHandle);
|
||||
PacketDumper(const PacketDumper&) = delete;
|
||||
~PacketDumper();
|
||||
static RefPtr<PacketDumper> GetPacketDumper(const std::string& aPcHandle);
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PacketDumper)
|
||||
|
||||
PacketDumper(const PacketDumper&) = delete;
|
||||
PacketDumper& operator=(const PacketDumper&) = delete;
|
||||
|
||||
void Dump(size_t level, dom::mozPacketDumpType type, bool sending,
|
||||
const void* data, size_t size);
|
||||
void Dump(size_t aLevel, dom::mozPacketDumpType aType, bool aSending,
|
||||
const void* aData, size_t aSize);
|
||||
|
||||
nsresult EnablePacketDump(unsigned long aLevel, dom::mozPacketDumpType aType,
|
||||
bool aSending);
|
||||
|
||||
nsresult DisablePacketDump(unsigned long aLevel, dom::mozPacketDumpType aType,
|
||||
bool aSending);
|
||||
|
||||
private:
|
||||
RefPtr<PeerConnectionImpl> mPc;
|
||||
friend class PeerConnectionImpl;
|
||||
explicit PacketDumper(const std::string& aPcHandle);
|
||||
~PacketDumper() = default;
|
||||
bool ShouldDumpPacket(size_t aLevel, dom::mozPacketDumpType aType,
|
||||
bool aSending) const;
|
||||
|
||||
// This class is not cycle-collected, so it cannot hold onto a strong ref
|
||||
const std::string mPcHandle;
|
||||
std::vector<unsigned> mSendPacketDumpFlags;
|
||||
std::vector<unsigned> mRecvPacketDumpFlags;
|
||||
Atomic<bool> mPacketDumpEnabled;
|
||||
mutable Mutex mPacketDumpFlagsMutex;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -207,7 +207,7 @@ class PeerConnectionCtxObserver : public nsIObserver {
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
rv = observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID,
|
||||
rv = observerService->AddObserver(this, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID,
|
||||
false);
|
||||
MOZ_ALWAYS_SUCCEEDS(rv);
|
||||
rv = observerService->AddObserver(this, NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
|
||||
@ -218,7 +218,7 @@ class PeerConnectionCtxObserver : public nsIObserver {
|
||||
|
||||
NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
|
||||
const char16_t* aData) override {
|
||||
if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
|
||||
if (strcmp(aTopic, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID) == 0) {
|
||||
CSFLogDebug(LOGTAG, "Shutting down PeerConnectionCtx");
|
||||
PeerConnectionCtx::Destroy();
|
||||
|
||||
@ -229,7 +229,8 @@ class PeerConnectionCtxObserver : public nsIObserver {
|
||||
nsresult rv = observerService->RemoveObserver(
|
||||
this, NS_IOSERVICE_OFFLINE_STATUS_TOPIC);
|
||||
MOZ_ALWAYS_SUCCEEDS(rv);
|
||||
rv = observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
||||
rv = observerService->RemoveObserver(this,
|
||||
NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID);
|
||||
MOZ_ALWAYS_SUCCEEDS(rv);
|
||||
|
||||
// Make sure we're not deleted while still inside ::Observe()
|
||||
@ -257,7 +258,7 @@ class PeerConnectionCtxObserver : public nsIObserver {
|
||||
services::GetObserverService();
|
||||
if (observerService) {
|
||||
observerService->RemoveObserver(this, NS_IOSERVICE_OFFLINE_STATUS_TOPIC);
|
||||
observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
||||
observerService->RemoveObserver(this, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -265,16 +266,10 @@ class PeerConnectionCtxObserver : public nsIObserver {
|
||||
NS_IMPL_ISUPPORTS(PeerConnectionCtxObserver, nsIObserver);
|
||||
|
||||
PeerConnectionCtx* PeerConnectionCtx::gInstance;
|
||||
nsIThread* PeerConnectionCtx::gMainThread;
|
||||
StaticRefPtr<PeerConnectionCtxObserver>
|
||||
PeerConnectionCtx::gPeerConnectionCtxObserver;
|
||||
|
||||
nsresult PeerConnectionCtx::InitializeGlobal(nsIThread* mainThread) {
|
||||
if (!gMainThread) {
|
||||
gMainThread = mainThread;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(gMainThread == mainThread);
|
||||
nsresult PeerConnectionCtx::InitializeGlobal() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsresult res;
|
||||
@ -542,8 +537,8 @@ static void GMPReady_m() {
|
||||
};
|
||||
|
||||
static void GMPReady() {
|
||||
PeerConnectionCtx::gMainThread->Dispatch(WrapRunnableNM(&GMPReady_m),
|
||||
NS_DISPATCH_NORMAL);
|
||||
GetMainThreadEventTarget()->Dispatch(WrapRunnableNM(&GMPReady_m),
|
||||
NS_DISPATCH_NORMAL);
|
||||
};
|
||||
|
||||
void PeerConnectionCtx::initGMP() {
|
||||
|
@ -80,7 +80,7 @@ class SharedWebrtcState {
|
||||
// * Upstream webrtc state shared across all Calls (processing thread)
|
||||
class PeerConnectionCtx {
|
||||
public:
|
||||
static nsresult InitializeGlobal(nsIThread* mainThread);
|
||||
static nsresult InitializeGlobal();
|
||||
static PeerConnectionCtx* GetInstance();
|
||||
static bool isActive();
|
||||
static void Destroy();
|
||||
@ -165,7 +165,6 @@ class PeerConnectionCtx {
|
||||
static PeerConnectionCtx* gInstance;
|
||||
|
||||
public:
|
||||
static nsIThread* gMainThread;
|
||||
static mozilla::StaticRefPtr<mozilla::PeerConnectionCtxObserver>
|
||||
gPeerConnectionCtxObserver;
|
||||
};
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user