Merge autoland to mozilla-central. a=merge

This commit is contained in:
Butkovits Atila 2021-10-20 00:48:21 +03:00
Родитель 47821a8f76 8ecb76d03a
Коммит b24799980a
157 изменённых файлов: 2286 добавлений и 1887 удалений

Просмотреть файл

@ -1208,6 +1208,16 @@ pref("dom.ipc.shims.enabledWarnings", false);
// content process is killed when all windows are closed, so a change will
// take effect when the 1st window is opened.
pref("security.sandbox.content.level", 3);
// Disconnect content processes from the window server. Depends on
// out-of-process WebGL and non-native theming. i.e., both in-process WebGL
// and native theming depend on content processes having a connection to the
// window server. Window server disconnection is automatically disabled (and
// this pref overridden) if OOP WebGL is disabled. OOP WebGL is disabled
// for some tests.
#if defined(NIGHTLY_BUILD)
pref("security.sandbox.content.mac.disconnect-windowserver", true);
#endif
#endif
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)

Просмотреть файл

@ -1349,15 +1349,6 @@ toolbarpaletteitem:not([place="palette"]) > #stop-reload-button {
animation-duration: 2s;
}
/* This effectively simulates a focus outline. */
#UITourHighlight[active="focus-outline"] {
background-color: transparent;
border: 2px solid var(--focus-outline-color);
border-radius: 4px;
animation-name: none;
}
/* Combined context-menu items */
#context-navigation > .menuitem-iconic > .menu-iconic-text,
#context-navigation > .menuitem-iconic > .menu-accel-container {

Просмотреть файл

@ -89,7 +89,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
TelemetryUtils: "resource://gre/modules/TelemetryUtils.jsm",
TRRRacer: "resource:///modules/TRRPerformance.jsm",
UIState: "resource://services-sync/UIState.jsm",
UITour: "resource:///modules/UITour.jsm",
UrlbarQuickSuggest: "resource:///modules/UrlbarQuickSuggest.jsm",
UrlbarPrefs: "resource:///modules/UrlbarPrefs.jsm",
WebChannel: "resource://gre/modules/WebChannel.jsm",
@ -2189,6 +2188,39 @@ BrowserGlue.prototype = {
Services.wm.addListener(windowListener);
},
_monitorGPCPref() {
const FEATURE_PREF_ENABLED = "privacy.globalprivacycontrol.enabled";
const FUNCTIONALITY_PREF_ENABLED =
"privacy.globalprivacycontrol.functionality.enabled";
const PREF_WAS_ENABLED = "privacy.globalprivacycontrol.was_ever_enabled";
const _checkGPCPref = async () => {
const feature_enabled = Services.prefs.getBoolPref(
FEATURE_PREF_ENABLED,
false
);
const functionality_enabled = Services.prefs.getBoolPref(
FUNCTIONALITY_PREF_ENABLED,
false
);
const was_enabled = Services.prefs.getBoolPref(PREF_WAS_ENABLED, false);
let value = 0;
if (feature_enabled && functionality_enabled) {
value = 1;
Services.prefs.setBoolPref(PREF_WAS_ENABLED, true);
} else if (was_enabled) {
value = 2;
}
Services.telemetry.scalarSet(
"security.global_privacy_control_enabled",
value
);
};
Services.prefs.addObserver(FEATURE_PREF_ENABLED, _checkGPCPref);
Services.prefs.addObserver(FUNCTIONALITY_PREF_ENABLED, _checkGPCPref);
_checkGPCPref();
},
// All initial windows have opened.
_onWindowsRestored: function BG__onWindowsRestored() {
if (this._windowsWereRestored) {
@ -2266,6 +2298,7 @@ BrowserGlue.prototype = {
if (AppConstants.NIGHTLY_BUILD) {
this._monitorTranslationsPref();
}
this._monitorGPCPref();
},
/**
@ -4071,11 +4104,10 @@ BrowserGlue.prototype = {
{
"l10n-id": "restore-session-startup-suggestion-button",
callback: () => {
UITour.getTarget(win, "history").then(historyMenu => {
UITour.showHighlight(win, historyMenu, "focus-outline", {
autohide: true,
});
});
win.PanelUI.selectAndMarkItem([
"appMenu-history-button",
"appMenu-restoreSession",
]);
},
},
];

Просмотреть файл

@ -1216,7 +1216,11 @@ var PanelMultiView = class extends AssociatedToNode {
currentView.keyNavigation(aEvent);
break;
case "mousemove":
this.openViews.forEach(panelView => panelView.clearNavigation());
this.openViews.forEach(panelView => {
if (!panelView.ignoreMouseMove) {
panelView.clearNavigation();
}
});
break;
case "popupshowing": {
this._viewContainer.setAttribute("panelopen", "true");
@ -1807,6 +1811,8 @@ var PanelView = class extends AssociatedToNode {
return popup && popup.state == "open";
};
this.ignoreMouseMove = false;
let keyCode = event.code;
switch (keyCode) {
case "ArrowDown":

Просмотреть файл

@ -717,6 +717,87 @@ const PanelUI = {
}
},
/**
* Selects and marks an item by id from the main view. The ids are an array,
* the first in the main view and the later ids in subsequent subviews that
* become marked when the user opens the subview. The subview marking is
* cancelled if a different subview is opened.
*/
async selectAndMarkItem(itemIds) {
// This shouldn't really occur, but return early just in case.
if (document.documentElement.hasAttribute("customizing")) {
return;
}
// This function was triggered from a button while the menu was
// already open, so the panel should be in the process of hiding.
// Wait for the panel to hide first, then reopen it.
if (this.panel.state == "hiding") {
await new Promise(resolve => {
this.panel.addEventListener("popuphidden", resolve, { once: true });
});
}
if (this.panel.state != "open") {
await new Promise(resolve => {
this.panel.addEventListener("ViewShown", resolve, { once: true });
this.show();
});
}
let currentView;
let viewShownCB = event => {
viewHidingCB();
if (itemIds.length) {
let subItem = window.document.getElementById(itemIds[0]);
if (event.target.id == subItem?.closest("panelview")?.id) {
Services.tm.dispatchToMainThread(() => {
markItem(event.target);
});
} else {
itemIds = [];
}
}
};
let viewHidingCB = () => {
if (currentView) {
currentView.ignoreMouseMove = false;
}
currentView = null;
};
let popupHiddenCB = () => {
viewHidingCB();
this.panel.removeEventListener("ViewShown", viewShownCB);
};
let markItem = viewNode => {
let id = itemIds.shift();
let item = window.document.getElementById(id);
item.setAttribute("tabindex", "-1");
currentView = PanelView.forNode(viewNode);
currentView.selectedElement = item;
currentView.focusSelectedElement(true);
// Prevent the mouse from changing the highlight temporarily.
// This flag gets removed when the view is hidden or a key
// is pressed.
currentView.ignoreMouseMove = true;
if (itemIds.length) {
this.panel.addEventListener("ViewShown", viewShownCB, { once: true });
}
this.panel.addEventListener("ViewHiding", viewHidingCB, { once: true });
};
this.panel.addEventListener("popuphidden", popupHiddenCB, { once: true });
markItem(this.mainView);
},
updateNotifications(notificationsChanged) {
let notifications = this._notifications;
if (!notifications || !notifications.length) {

Просмотреть файл

@ -63,9 +63,9 @@ var gDownloadElementButtons = {
},
show: {
commandName: "downloadsCmd_show",
l10nId: "downloads-cmd-show-button",
descriptionL10nId: "downloads-cmd-show-description",
panelL10nId: "downloads-cmd-show-panel",
l10nId: "downloads-cmd-show-button-2",
descriptionL10nId: "downloads-cmd-show-description-2",
panelL10nId: "downloads-cmd-show-panel-2",
iconClass: "downloadIconShow",
},
subviewOpenOrRemoveFile: {

Просмотреть файл

@ -22,12 +22,7 @@
data-l10n-id="downloads-cmd-always-use-system-default"/>
<menuitem command="downloadsCmd_show"
class="downloadShowMenuItem"
#ifdef XP_MACOSX
data-l10n-id="downloads-cmd-show-menuitem-mac"
#else
data-l10n-id="downloads-cmd-show-menuitem"
#endif
/>
data-l10n-id="downloads-cmd-show-menuitem-2"/>
<menuseparator class="downloadCommandsSeparator"/>

Просмотреть файл

@ -85,12 +85,7 @@
data-l10n-id="downloads-cmd-always-use-system-default"/>
<menuitem command="downloadsCmd_show"
class="downloadShowMenuItem"
#ifdef XP_MACOSX
data-l10n-id="downloads-cmd-show-menuitem-mac"
#else
data-l10n-id="downloads-cmd-show-menuitem"
#endif
/>
data-l10n-id="downloads-cmd-show-menuitem-2"/>
<menuseparator class="downloadCommandsSeparator"/>

Просмотреть файл

@ -98,6 +98,8 @@ skip-if = (webrender && debug) # bug 1553577
[browser_ext_contentscript_in_parent.js]
[browser_ext_contentscript_incognito.js]
[browser_ext_contentscript_nontab_connect.js]
[browser_ext_contentscript_sender_url.js]
skip-if = debug # The nature of the reduced STR test triggers an unrelated debug assertion in DOM IPC code, see bug 1736590.
[browser_ext_contextMenus.js]
support-files = !/browser/components/places/tests/browser/head.js
[browser_ext_contextMenus_checkboxes.js]

Просмотреть файл

@ -0,0 +1,67 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
add_task(async function test_sender_url() {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
content_scripts: [
{
matches: ["http://mochi.test/*"],
run_at: "document_start",
js: ["script.js"],
},
],
},
background() {
browser.runtime.onMessage.addListener((msg, sender) => {
browser.test.log("Message received.");
browser.test.sendMessage("sender.url", sender.url);
});
},
files: {
"script.js"() {
browser.test.log("Content script loaded.");
browser.runtime.sendMessage(0);
},
},
});
const image =
"http://mochi.test:8888/browser/browser/components/extensions/test/browser/ctxmenu-image.png";
// Bug is only visible and test only works without Fission,
// or with Fission but without BFcache in parent.
await SpecialPowers.pushPrefEnv({
set: [["fission.bfcacheInParent", false]],
});
function awaitNewTab() {
return BrowserTestUtils.waitForLocationChange(gBrowser, "about:newtab");
}
await extension.startup();
await BrowserTestUtils.withNewTab({ gBrowser }, async browser => {
let newTab = awaitNewTab();
BrowserTestUtils.loadURI(browser, "about:newtab");
await newTab;
BrowserTestUtils.loadURI(browser, image);
let url = await extension.awaitMessage("sender.url");
is(url, image, `Correct sender.url: ${url}`);
let wentBack = awaitNewTab();
await browser.goBack();
await wentBack;
await browser.goForward();
url = await extension.awaitMessage("sender.url");
is(url, image, `Correct sender.url: ${url}`);
});
await extension.unload();
await SpecialPowers.popPrefEnv();
});

Просмотреть файл

@ -14,6 +14,7 @@ function openPermissionPopup() {
event => event.target == gPermissionPanel._permissionPopup
);
gPermissionPanel._identityPermissionBox.click();
info("Wait permission popup to be shown");
return promise;
}
@ -23,6 +24,7 @@ function closePermissionPopup() {
"popuphidden"
);
gPermissionPanel._permissionPopup.hidePopup();
info("Wait permission popup to be hidden");
return promise;
}
@ -67,21 +69,25 @@ async function testPermissionPopup({ expectPermissionHidden }) {
add_task(async function testPersistentStoragePermissionHidden() {
let extension = ExtensionTestUtils.loadExtension({
background() {
browser.test.sendMessage("url", browser.runtime.getURL("icon.png"));
browser.test.sendMessage("url", browser.runtime.getURL("testpage.html"));
},
manifest: {
name: "Test Extension",
permissions: ["unlimitedStorage"],
},
files: {
"icon.png": "",
"testpage.html": "<h1>Extension Test Page</h1>",
},
});
await extension.startup();
let url = await extension.awaitMessage("url");
await BrowserTestUtils.withNewTab({ gBrowser, url }, async function() {
await BrowserTestUtils.withNewTab("about:blank", async browser => {
// Wait the tab to be fully loade, then run the test on the permission prompt.
let loaded = BrowserTestUtils.browserLoaded(browser, false, url);
BrowserTestUtils.loadURI(browser, url);
await loaded;
await testPermissionPopup({ expectPermissionHidden: true });
});
@ -91,13 +97,13 @@ add_task(async function testPersistentStoragePermissionHidden() {
add_task(async function testPersistentStoragePermissionVisible() {
let extension = ExtensionTestUtils.loadExtension({
background() {
browser.test.sendMessage("url", browser.runtime.getURL("icon.png"));
browser.test.sendMessage("url", browser.runtime.getURL("testpage.html"));
},
manifest: {
name: "Test Extension",
},
files: {
"icon.png": "",
"testpage.html": "<h1>Extension Test Page</h1>",
},
});
@ -113,7 +119,11 @@ add_task(async function testPersistentStoragePermissionVisible() {
Services.perms.ALLOW_ACTION
);
await BrowserTestUtils.withNewTab({ gBrowser, url }, async function() {
await BrowserTestUtils.withNewTab("about:blank", async browser => {
// Wait the tab to be fully loade, then run the test on the permission prompt.
let loaded = BrowserTestUtils.browserLoaded(browser, false, url);
BrowserTestUtils.loadURI(browser, url);
await loaded;
await testPermissionPopup({ expectPermissionHidden: false });
});

Просмотреть файл

@ -63,6 +63,16 @@
"name": "prefval",
"condition": "pref",
"pref": "code"
},
{
"name": "experimenter-1",
"condition": "pref",
"pref": "nimbus-key-1"
},
{
"name": "experimenter-2",
"condition": "pref",
"pref": "nimbus-key-2"
}
]
}

Просмотреть файл

@ -6,10 +6,13 @@
const { AddonTestUtils } = ChromeUtils.import(
"resource://testing-common/AddonTestUtils.jsm"
);
const { SearchTestUtils } = ChromeUtils.import(
"resource://testing-common/SearchTestUtils.jsm"
);
const { NimbusFeatures } = ChromeUtils.import(
"resource://nimbus/ExperimentAPI.jsm"
);
const { sinon } = ChromeUtils.import("resource://testing-common/Sinon.jsm");
AddonTestUtils.init(this);
AddonTestUtils.overrideCertDB();
@ -50,6 +53,8 @@ const params = [
];
add_task(async function setup() {
let readyStub = sinon.stub(NimbusFeatures.search, "ready").resolves();
let updateStub = sinon.stub(NimbusFeatures.search, "onUpdate");
await promiseStartupManager();
await SearchTestUtils.useTestEngines("data", null, [
{
@ -67,6 +72,8 @@ add_task(async function setup() {
await Services.search.init();
registerCleanupFunction(async () => {
await promiseShutdownManager();
readyStub.restore();
updateStub.restore();
});
});
@ -105,6 +112,81 @@ add_task(async function test_extension_setting_moz_params() {
"search url is expected"
);
}
defaultBranch.setCharPref("param.code", "");
});
add_task(async function test_nimbus_params() {
let sandbox = sinon.createSandbox();
let stub = sandbox.stub(NimbusFeatures.search, "getVariable");
// These values should match the nimbusParams below and the data/test/manifest.json
// search engine configuration
stub.withArgs("extraParams").returns([
{
key: "nimbus-key-1",
value: "nimbus-value-1",
},
{
key: "nimbus-key-2",
value: "nimbus-value-2",
},
]);
Assert.ok(
NimbusFeatures.search.onUpdate.called,
"Called to initialize the cache"
);
// Populate the cache with the `getVariable` mock values
NimbusFeatures.search.onUpdate.firstCall.args[0]();
let engine = Services.search.getEngineByName("MozParamsTest");
// Note: these lists should be kept in sync with the lists in
// browser/components/extensions/test/xpcshell/data/test/manifest.json
// These params are conditional based on how search is initiated.
const nimbusParams = [
{ name: "experimenter-1", condition: "pref", pref: "nimbus-key-1" },
{ name: "experimenter-2", condition: "pref", pref: "nimbus-key-2" },
];
const experimentCache = {
"nimbus-key-1": "nimbus-value-1",
"nimbus-key-2": "nimbus-value-2",
};
let extraParams = [];
for (let p of params) {
if (p.value == "{searchTerms}") {
extraParams.push(`${p.name}=test`);
} else if (p.value == "{language}") {
extraParams.push(`${p.name}=${Services.locale.requestedLocale || "*"}`);
} else if (p.value == "{moz:locale}") {
extraParams.push(`${p.name}=${Services.locale.requestedLocale}`);
} else if (p.condition !== "pref") {
// Ignoring pref parameters
extraParams.push(`${p.name}=${p.value}`);
}
}
for (let p of nimbusParams) {
if (p.condition == "pref") {
extraParams.push(`${p.name}=${experimentCache[p.pref]}`);
}
}
let paramStr = extraParams.join("&");
for (let p of mozParams) {
let expectedURL = engine.getSubmission(
"test",
null,
p.condition == "purpose" ? p.purpose : null
).uri.spec;
equal(
expectedURL,
`https://example.com/?q=test&${p.name}=${p.value}&${paramStr}`,
"search url is expected"
);
}
sandbox.restore();
});
add_task(async function test_extension_setting_moz_params_fail() {

Просмотреть файл

@ -16,7 +16,7 @@ const { sinon } = ChromeUtils.import("resource://testing-common/Sinon.jsm");
add_task(async function test_engines_reloaded_nimbus() {
let reloadSpy = sinon.spy(SearchService.prototype, "_maybeReloadEngines");
let variableSpy = sinon.spy(NimbusFeatures.search, "getVariable");
let getVariableSpy = sinon.spy(NimbusFeatures.search, "getVariable");
let doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
featureId: "search",
@ -25,18 +25,21 @@ add_task(async function test_engines_reloaded_nimbus() {
Assert.equal(reloadSpy.callCount, 1, "Called by experiment enrollment");
await BrowserTestUtils.waitForCondition(
() => variableSpy.called,
() => getVariableSpy.calledWith("experiment"),
"Wait for SearchService update to run"
);
Assert.equal(
variableSpy.callCount,
1,
"Called by update function to fetch engines"
getVariableSpy.callCount,
2,
"Called by update function to fetch engines and by ParamPreferenceCache"
);
Assert.equal(
variableSpy.firstCall.args[0],
"experiment",
"Got `experiment` variable value"
Assert.ok(
getVariableSpy.calledWith("extraParams"),
"Called by ParamPreferenceCache listener"
);
Assert.ok(
getVariableSpy.calledWith("experiment"),
"Called by search service observer"
);
Assert.equal(
NimbusFeatures.search.getVariable("experiment"),
@ -49,5 +52,5 @@ add_task(async function test_engines_reloaded_nimbus() {
Assert.equal(reloadSpy.callCount, 2, "Called by experiment unenrollment");
reloadSpy.restore();
variableSpy.restore();
getVariableSpy.restore();
});

Просмотреть файл

@ -151,14 +151,6 @@ var UITour = {
},
],
["help", { query: "#appMenu-help-button2" }],
[
"history",
{
query: "#appMenu-history-button",
subItem: "restorePreviousSession",
level: "top",
},
],
["home", { query: "#home-button" }],
[
"logins",
@ -186,7 +178,6 @@ var UITour = {
},
],
["readerMode-urlBar", { query: "#reader-mode-button" }],
["restorePreviousSession", { query: "#appMenu-restoreSession" }],
[
"search",
{
@ -836,7 +827,7 @@ var UITour = {
this.hideHighlight(aWindow);
this.hideInfo(aWindow);
await this.removePanelListeners(aWindow, true);
await this.removePanelListeners(aWindow);
this.noautohideMenus.clear();
@ -849,7 +840,7 @@ var UITour = {
/**
* Remove the listeners to a panel when tearing the tour down.
*/
async removePanelListeners(aWindow, aHidePanels = false) {
async removePanelListeners(aWindow) {
let panels = [
{
name: "appMenu",
@ -858,14 +849,12 @@ var UITour = {
["popuphidden", this.onPanelHidden],
["popuphiding", this.onAppMenuHiding],
["ViewShowing", this.onAppMenuSubviewShowing],
["ViewShown", this.onAppMenuSubviewShown],
["ViewHiding", this.onAppMenuSubviewHiding],
],
},
];
for (let panel of panels) {
// Ensure the menu panel is hidden and clean up panel listeners after calling hideMenu.
if (aHidePanels && panel.node.state != "closed") {
if (panel.node.state != "closed") {
await new Promise(resolve => {
panel.node.addEventListener("popuphidden", resolve, { once: true });
this.hideMenu(aWindow, panel.name);
@ -978,8 +967,6 @@ var UITour = {
targetName: aTargetName,
widgetName: targetObject.widgetName,
allowAdd: targetObject.allowAdd,
level: targetObject.level,
subItem: targetObject.subItem,
});
})
.catch(log.error);
@ -1137,16 +1124,6 @@ var UITour = {
highlighter.parentElement.setAttribute("targetName", aTarget.targetName);
highlighter.parentElement.hidden = false;
if (aTarget.subItem) {
// This is a subitem in the app menu, so mark it as one not to hide.
this.noautohideMenus.add("appMenu");
highlighter.parentElement.setAttribute("subitem", aTarget.subItem);
}
if (aTarget.level) {
highlighter.parentElement.setAttribute("level", aTarget.level);
}
let highlightAnchor = aAnchorEl;
let targetRect = highlightAnchor.getBoundingClientRect();
let highlightHeight = targetRect.height;
@ -1442,8 +1419,6 @@ var UITour = {
menu.node = aWindow.PanelUI.panel;
menu.onPopupHiding = this.onAppMenuHiding;
menu.onViewShowing = this.onAppMenuSubviewShowing;
menu.onViewShown = this.onAppMenuSubviewShown;
menu.onViewHiding = this.onAppMenuSubviewHiding;
menu.show = () => aWindow.PanelUI.show();
if (!aOptions.autohide) {
@ -1459,8 +1434,6 @@ var UITour = {
menu.node.addEventListener("popuphidden", menu.onPanelHidden);
menu.node.addEventListener("popuphiding", menu.onPopupHiding);
menu.node.addEventListener("ViewShowing", menu.onViewShowing);
menu.node.addEventListener("ViewShown", menu.onViewShown);
menu.node.addEventListener("ViewHiding", menu.onViewHiding);
menu.show();
} else if (aMenuName == "bookmarks") {
let menuBtn = aWindow.document.getElementById("bookmarks-menu-button");
@ -1589,80 +1562,12 @@ var UITour = {
UITour._hideAnnotationsForPanel(aEvent, false, UITour.targetIsInAppMenu);
},
onAppMenuSubviewShown(aEvent) {
let win = aEvent.target.ownerGlobal;
let subItemName = UITour.getSubItem(win);
if (
subItemName &&
UITour.isSubItemToHighlight(win, subItemName, aEvent.target.id)
) {
let highlighter = UITour.getHighlightAndMaybeCreate(win.document);
UITour.recreatePopup(highlighter.parentElement);
UITour.getTarget(win, subItemName).then(subItem => {
if (!subItem.node.hidden) {
UITour.showHighlight(win, subItem, "focus-outline", {
autohide: true,
});
}
});
} else if (subItemName && aEvent.target.id != "appMenu-protonMainView") {
UITour.stopSubViewHandling(win);
}
},
onAppMenuSubviewHiding(aEvent) {
let win = aEvent.target.ownerGlobal;
let subItem = UITour.getSubItem(win);
if (subItem) {
if (UITour.isSubItemToHighlight(win, subItem, aEvent.target.id)) {
UITour.hideHighlight(win);
UITour.stopSubViewHandling(win);
}
}
},
onPanelHidden(aEvent) {
if (UITour.getSubItem(aEvent.target.ownerGlobal)) {
UITour.stopSubViewHandling(aEvent.target.ownerGlobal);
}
aEvent.target.removeAttribute("noautohide");
UITour.recreatePopup(aEvent.target);
UITour.clearAvailableTargetsCache();
},
getSubItem(aWindow) {
// Get the subitem that should be highlighted in the app menu's subview.
let highlighter = UITour.getHighlightContainerAndMaybeCreate(
aWindow.document
);
return highlighter.getAttribute("subitem");
},
isSubItemToHighlight(aWindow, aSubItem, aExpectedId) {
let targetObject = UITour.targets.get(aSubItem);
if (targetObject) {
let node = UITour.getNodeFromDocument(
aWindow.document,
targetObject.query
);
return aExpectedId == node?.closest("panelview")?.id;
}
return false;
},
stopSubViewHandling(aWindow) {
UITour.removePanelListeners(aWindow);
UITour.noautohideMenus.delete("appMenu");
let highlighter = UITour.getHighlightAndMaybeCreate(aWindow.document);
highlighter.parentElement.removeAttribute("level");
highlighter.parentElement.removeAttribute("subitem");
},
recreatePopup(aPanel) {
// After changing popup attributes that relate to how the native widget is created
// (e.g. @noautohide) we need to re-create the frame/widget for it to take effect.

Просмотреть файл

@ -15,14 +15,12 @@ function getExpectedTargets() {
"appMenu",
"backForward",
"help",
"history",
"logins",
"pageAction-bookmark",
...(hasPocket ? ["pocket"] : []),
"privateWindow",
...(hasQuit ? ["quit"] : []),
"readerMode-urlBar",
"restorePreviousSession",
"urlbar",
];
}

Просмотреть файл

@ -29,14 +29,11 @@ downloads-cmd-cancel =
downloads-cmd-cancel-panel =
.aria-label = Cancel
# This message is only displayed on Windows and Linux devices
downloads-cmd-show-menuitem =
.label = Open Containing Folder
.accesskey = F
# This message is only displayed on macOS devices
downloads-cmd-show-menuitem-mac =
.label = Show In Finder
downloads-cmd-show-menuitem-2 =
.label = { PLATFORM() ->
[macos] Show in Finder
*[other] Show in Folder
}
.accesskey = F
downloads-cmd-use-system-default =
@ -47,21 +44,21 @@ downloads-cmd-always-use-system-default =
.label = Always Open In System Viewer
.accesskey = w
downloads-cmd-show-button =
downloads-cmd-show-button-2 =
.tooltiptext = { PLATFORM() ->
[macos] Show In Finder
*[other] Open Containing Folder
[macos] Show in Finder
*[other] Show in Folder
}
downloads-cmd-show-panel =
downloads-cmd-show-panel-2 =
.aria-label = { PLATFORM() ->
[macos] Show In Finder
*[other] Open Containing Folder
[macos] Show in Finder
*[other] Show in Folder
}
downloads-cmd-show-description =
downloads-cmd-show-description-2 =
.value = { PLATFORM() ->
[macos] Show In Finder
*[other] Open Containing Folder
[macos] Show in Finder
*[other] Show in Folder
}
downloads-cmd-show-downloads =

Просмотреть файл

@ -82,17 +82,3 @@ statusSeparatorBeforeNumber=%1$S \u2014 %2$S
# semi-colon list of plural forms.
# See: http://developer.mozilla.org/en/Localization_and_Plurals
otherDownloads3=%1$S file downloading;%1$S files downloading
# LOCALIZATION NOTE (showLabel, showMacLabel):
# This is displayed when you hover a download item in the Library widget view.
# showMacLabel is only shown on Mac OSX.
showLabel=Open Containing Folder
showMacLabel=Open In Finder
# LOCALIZATION NOTE (openFileLabel):
# Displayed when hovering a complete download, indicates that it's possible to
# open the file using an app available in the system.
openFileLabel=Open File
# LOCALIZATION NOTE (retryLabel):
# Displayed when hovering a download which is able to be retried by users,
# indicates that it's possible to download this file again.
retryLabel=Retry Download

Просмотреть файл

@ -20,8 +20,9 @@ add_task(async function() {
const tabDescriptors = await mainRoot.listTabs();
await testGetTargetWithConcurrentCalls(tabDescriptors, tabTarget => {
// Tab Target is attached when it has a console front.
return !!tabTarget.getCachedFront("console");
// We only call BrowsingContextTargetFront.attach and not TargetMixin.attachAndInitThread.
// So very few things are done.
return !!tabTarget.traits;
});
await client.close();
@ -40,8 +41,9 @@ add_task(async function() {
// happens between the instantiation of ContentProcessTarget and its call to attach() from getTarget
// function.
await testGetTargetWithConcurrentCalls(processes, processTarget => {
// Content Process Target is attached when it has a console front.
return !!processTarget.getCachedFront("console");
// We only call ContentProcessTargetFront.attach and not TargetMixin.attachAndInitThread.
// So nothing is done for content process targets.
return true;
});
await client.close();

Просмотреть файл

@ -691,7 +691,8 @@ Toolbox.prototype = {
// Attach to a new top-level target.
// For now, register these event listeners only on the top level target
targetFront.on("frame-update", this._updateFrames);
targetFront.on("inspect-object", this._onInspectObject);
const consoleFront = await targetFront.getFront("console");
consoleFront.on("inspectObject", this._onInspectObject);
}
// Walker listeners allow to monitor DOM Mutation breakpoint updates.
@ -718,8 +719,9 @@ Toolbox.prototype = {
_onTargetDestroyed({ targetFront }) {
if (targetFront.isTopLevel) {
this.target.off("inspect-object", this._onInspectObject);
this.target.off("frame-update", this._updateFrames);
const consoleFront = targetFront.getCachedFront("console");
consoleFront.off("inspectObject", this._onInspectObject);
targetFront.off("frame-update", this._updateFrames);
} else if (this.selection) {
this.selection.onTargetDestroyed(targetFront);
}
@ -3611,10 +3613,6 @@ Toolbox.prototype = {
}
},
_onInspectObject: function(packet) {
this.inspectObjectActor(packet.objectActor, packet.inspectFromAnnotation);
},
_onToolSelected: function() {
this._refreshHostTitle();
@ -3626,6 +3624,13 @@ Toolbox.prototype = {
this.component.setToolboxButtons(this.toolbarButtons);
},
/**
* Listener for "inspectObject" event on console top level target actor.
*/
_onInspectObject(packet) {
this.inspectObjectActor(packet.objectActor, packet.inspectFromAnnotation);
},
inspectObjectActor: async function(objectActor, inspectFromAnnotation) {
const objectGrip = objectActor?.getGrip
? objectActor.getGrip()

Просмотреть файл

@ -95,8 +95,7 @@ class WorkerDescriptorFront extends DescriptorMixin(
const workerTargetForm = await super.getTarget();
// Set the console actor ID on the form to expose it to Target.attachConsole
// Set the ThreadActor on the target form so it is accessible by getFront
// Set the console and thread actor IDs on the form so it is accessible by TargetMixin.getFront
this.targetForm.consoleActor = workerTargetForm.consoleActor;
this.targetForm.threadActor = workerTargetForm.threadActor;
@ -104,7 +103,6 @@ class WorkerDescriptorFront extends DescriptorMixin(
return this;
}
await this.attachConsole();
return this;
})();
return this._attach;

Просмотреть файл

@ -44,11 +44,6 @@ class ContentProcessTargetFront extends TargetMixin(
}
attach() {
// All target actors have a console actor to attach.
// All but xpcshell test actors... which is using a ContentProcessTargetActor
if (this.targetForm.consoleActor) {
return this.attachConsole();
}
return Promise.resolve();
}

Просмотреть файл

@ -468,25 +468,6 @@ function TargetMixin(parentClass) {
}
}
// Attach the console actor
async attachConsole() {
const consoleFront = await this.getFront("console");
if (this.isDestroyedOrBeingDestroyed()) {
return;
}
// Calling startListeners will populate the traits as it's the first request we
// make to the front.
await consoleFront.startListeners([]);
this._onInspectObject = packet => this.emit("inspect-object", packet);
this.removeOnInspectObjectListener = consoleFront.on(
"inspectObject",
this._onInspectObject
);
}
/**
* This method attaches the target and then attaches its related thread, sending it
* the options it needs (e.g. breakpoints, pause on exception setting, ).
@ -649,12 +630,6 @@ function TargetMixin(parentClass) {
}
this.fronts.clear();
// Remove listeners set in attachConsole
if (this.removeOnInspectObjectListener) {
this.removeOnInspectObjectListener();
this.removeOnInspectObjectListener = null;
}
this.threadFront = null;
this._offResourceEvent = null;

Просмотреть файл

@ -125,12 +125,6 @@ class WindowGlobalTargetFront extends TargetMixin(
// @backward-compat { version 93 } Remove this. All the traits are on form and can be accessed
// using getTraits.
this.traits = response.traits || {};
// xpcshell tests from devtools/server/tests/xpcshell/ are implementing
// fake WindowGlobalTargetActor which do not expose any console actor.
if (this.targetForm.consoleActor) {
await this.attachConsole();
}
})();
return this._attach;
}

Просмотреть файл

@ -24,7 +24,6 @@ class WebConsoleFront extends FrontClassWithSpec(webconsoleSpec) {
constructor(client, targetFront, parentFront) {
super(client, targetFront, parentFront);
this._client = client;
this.traits = {};
this.events = [];
// Attribute name from which to retrieve the actorID out of the target actor's form
@ -306,7 +305,6 @@ class WebConsoleFront extends FrontClassWithSpec(webconsoleSpec) {
async startListeners(listeners) {
const response = await super.startListeners(listeners);
this.hasNativeConsoleAPI = response.nativeConsoleAPI;
this.traits = response.traits;
return response;
}

Просмотреть файл

@ -432,9 +432,6 @@ class Connector {
if (this.hasResourceCommandSupport && this.networkFront) {
return this.networkFront.getBlockedUrls();
}
if (!this.webConsoleFront.traits.blockedUrls) {
return [];
}
return this.webConsoleFront.getBlockedUrls();
}

Просмотреть файл

@ -13,98 +13,68 @@ var { DevToolsClient } = require("devtools/client/devtools-client");
const TAB1_URL = EXAMPLE_URL + "doc_empty-tab-01.html";
const TAB2_URL = EXAMPLE_URL + "doc_empty-tab-02.html";
var gTab1, gTab1Front, gTab2, gTab2Front, gClient;
function test() {
add_task(async function test() {
DevToolsServer.init();
DevToolsServer.registerAllActors();
const transport = DevToolsServer.connectPipe();
gClient = new DevToolsClient(transport);
gClient.connect().then(([aType, aTraits]) => {
is(aType, "browser", "Root actor should identify itself as a browser.");
const client = new DevToolsClient(transport);
const [aType] = await client.connect();
is(aType, "browser", "Root actor should identify itself as a browser.");
Promise.resolve(null)
.then(testFirstTab)
.then(testSecondTab)
.then(testRemoveTab)
.then(testAttachRemovedTab)
.then(() => gClient.close())
.then(finish)
.catch(error => {
ok(false, "Got an error: " + error.message + "\n" + error.stack);
});
});
}
function testFirstTab() {
return addTab(TAB1_URL).then(tab => {
gTab1 = tab;
return getTargetActorForUrl(gClient, TAB1_URL).then(front => {
ok(front, "Should find a target actor for the first tab.");
gTab1Front = front;
});
});
}
function testSecondTab() {
return addTab(TAB2_URL).then(tab => {
gTab2 = tab;
return getTargetActorForUrl(gClient, TAB1_URL).then(firstFront => {
return getTargetActorForUrl(gClient, TAB2_URL).then(secondFront => {
is(firstFront, gTab1Front, "First tab's actor shouldn't have changed.");
ok(secondFront, "Should find a target actor for the second tab.");
gTab2Front = secondFront;
});
});
});
}
function testRemoveTab() {
return removeTab(gTab1).then(() => {
return getTargetActorForUrl(gClient, TAB1_URL).then(front => {
ok(!front, "Shouldn't find a target actor for the first tab anymore.");
});
});
}
function testAttachRemovedTab() {
return removeTab(gTab2).then(() => {
return new Promise((resolve, reject) => {
gClient.on("paused", () => {
ok(
false,
"Attaching to an exited target actor shouldn't generate a pause."
);
reject();
});
const { actorID } = gTab2Front;
gTab2Front.reconfigure({}).then(null, error => {
ok(
error.message.includes(
`Connection closed, pending request to ${actorID}, type reconfigure failed`
),
"Actor is gone since the tab was removed."
);
resolve();
});
});
});
}
registerCleanupFunction(function() {
gTab1 = null;
gTab1Front = null;
gTab2 = null;
gTab2Front = null;
gClient = null;
const firstTab = await testFirstTab(client);
const secondTab = await testSecondTab(client, firstTab.front);
await testRemoveTab(client, firstTab.tab);
await testAttachRemovedTab(secondTab.tab, secondTab.front);
await client.close();
});
async function getTargetActorForUrl(client, url) {
async function testFirstTab(client) {
const tab = await addTab(TAB1_URL);
const front = await getDescriptorActorForUrl(client, TAB1_URL);
ok(front, "Should find a target actor for the first tab.");
return { tab, front };
}
async function testSecondTab(client, firstTabFront) {
const tab = await addTab(TAB2_URL);
const firstFront = await getDescriptorActorForUrl(client, TAB1_URL);
const secondFront = await getDescriptorActorForUrl(client, TAB2_URL);
is(firstFront, firstTabFront, "First tab's actor shouldn't have changed.");
ok(secondFront, "Should find a target actor for the second tab.");
return { tab, front: secondFront };
}
async function testRemoveTab(client, firstTab) {
await removeTab(firstTab);
const front = await getDescriptorActorForUrl(client, TAB1_URL);
ok(!front, "Shouldn't find a target actor for the first tab anymore.");
}
async function testAttachRemovedTab(secondTab, secondTabFront) {
await removeTab(secondTab);
const { actorID } = secondTabFront;
try {
await secondTabFront.getFavicon({});
ok(
false,
"any request made to the descriptor for a closed tab should have failed"
);
} catch (error) {
ok(
error.message.includes(
`Connection closed, pending request to ${actorID}, type getFavicon failed`
),
"Actor is gone since the tab was removed."
);
}
}
async function getDescriptorActorForUrl(client, url) {
const tabDescriptors = await client.mainRoot.listTabs();
const tabDescriptor = tabDescriptors.find(front => front.url == url);
return tabDescriptor?.getTarget();
return tabDescriptor;
}

Просмотреть файл

@ -198,11 +198,6 @@ const WebConsoleActor = ActorClassWithSpec(webconsoleSpec, {
"last-pb-context-exited"
);
}
this.traits = {
// Supports retrieving blocked urls
blockedUrls: true,
};
},
/**
* Debugger instance.
@ -239,12 +234,6 @@ const WebConsoleActor = ActorClassWithSpec(webconsoleSpec, {
*/
conn: null,
/**
* List of supported features by the console actor.
* @type object
*/
traits: null,
/**
* The global we work with (this can be a Window, a Worker global or even a Sandbox
* for processes and addons).
@ -794,7 +783,6 @@ const WebConsoleActor = ActorClassWithSpec(webconsoleSpec, {
return {
startedListeners: startedListeners,
nativeConsoleAPI: this.hasNativeConsoleAPI(this.global),
traits: this.traits,
};
},

Просмотреть файл

@ -12,14 +12,9 @@ const {
Arg,
} = require("devtools/shared/protocol");
types.addDictType("console.traits", {
evaluateJSAsync: "boolean",
});
types.addDictType("console.startlisteners", {
startedListeners: "array:string",
nativeConsoleAPI: "nullable:boolean",
traits: "console.traits",
});
types.addDictType("console.stoplisteners", {

Просмотреть файл

@ -121,7 +121,7 @@ interface WindowGlobalParent : WindowContext {
*/
[Throws]
JSWindowActorParent getActor(UTF8String name);
JSWindowActorParent getExistingActor(UTF8String name);
JSWindowActorParent? getExistingActor(UTF8String name);
/**
* Renders a region of the frame into an image bitmap.
@ -191,5 +191,5 @@ interface WindowGlobalChild {
*/
[Throws]
JSWindowActorChild getActor(UTF8String name);
JSWindowActorChild getExistingActor(UTF8String name);
JSWindowActorChild? getExistingActor(UTF8String name);
};

Просмотреть файл

@ -1,6 +1,5 @@
<!DOCTYPE html>
<meta charset="utf-8">
<h3>Set <code>privacy.file_unique_origin</code> to false when testing this.</h3>
<script>
fetch("./url.url")
</script>

Просмотреть файл

@ -1,2 +1,2 @@
load 1577196.html
pref(privacy.file_unique_origin,false) load 1664514.html
load 1664514.html

Просмотреть файл

@ -129,28 +129,6 @@ interface nsIBrowser : nsISupports
in uint64_t aRequestContextID,
in AString aContentType);
/**
* Determine what process switching behavior this browser element should have.
*/
cenum ProcessBehavior : 8 {
// Gecko won't automatically change which process this frame, or it's
// subframes, are loaded in.
PROCESS_BEHAVIOR_DISABLED,
// If `useRemoteTabs` is enabled, Gecko will change which process this frame
// is loaded in automatically, without calling `performProcessSwitch`.
// When `useRemoteSubframes` is enabled, subframes will change processes.
PROCESS_BEHAVIOR_STANDARD,
// Gecko won't automatically change which process this frame is loaded, but
// when `useRemoteSubframes` is enabled, subframes will change processes.
//
// NOTE: This configuration is included only for backwards compatibility,
// and will be removed, as it can easily lead to invalid behavior.
PROCESS_BEHAVIOR_SUBFRAME_ONLY,
};
readonly attribute nsIBrowser_ProcessBehavior processSwitchBehavior;
/**
* Called to perform any async tasks which must be completed before changing
* remoteness. Gecko will wait for the returned promise to resolve before

Просмотреть файл

@ -1680,12 +1680,14 @@ static void DisconnectWindowServer(bool aIsSandboxEnabled) {
// is called.
CGSShutdownServerConnections();
// Actual security benefits are only acheived when we additionally deny
// future connections, however this currently breaks WebGL so it's not done
// by default.
// Actual security benefits are only achieved when we additionally deny
// future connections using the sandbox policy. WebGL must be remoted if
// the windowserver connections are blocked. WebGL remoting is disabled
// for some tests.
if (aIsSandboxEnabled &&
Preferences::GetBool(
"security.sandbox.content.mac.disconnect-windowserver")) {
"security.sandbox.content.mac.disconnect-windowserver") &&
Preferences::GetBool("webgl.out-of-process")) {
CGError result = CGSSetDenyWindowServerConnections(true);
MOZ_DIAGNOSTIC_ASSERT(result == kCGErrorSuccess);
# if !MOZ_DIAGNOSTIC_ASSERT_ENABLED

Просмотреть файл

@ -2409,9 +2409,12 @@ static void CacheSandboxParams(std::vector<std::string>& aCachedParams) {
info.hasAudio = true;
}
// Windowserver access
// Window server access. If the disconnect-windowserver pref is not
// "true" or out-of-process WebGL is not enabled, allow window server
// access in the sandbox policy.
if (!Preferences::GetBool(
"security.sandbox.content.mac.disconnect-windowserver")) {
"security.sandbox.content.mac.disconnect-windowserver") ||
!Preferences::GetBool("webgl.out-of-process")) {
info.hasWindowServer = true;
}

Просмотреть файл

@ -3,108 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const WORKER_BODY = "postMessage(42);\n";
// file:// tests.
add_task(async function() {
await SpecialPowers.pushPrefEnv({
set: [["privacy.file_unique_origin", false]],
});
info("Creating the tmp directory.");
let parent = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIDirectoryService)
.QueryInterface(Ci.nsIProperties)
.get("TmpD", Ci.nsIFile);
parent.append("worker-dir-test");
parent.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0o700);
let dir_a = parent.clone();
dir_a.append("a");
dir_a.create(Ci.nsIFile.DIRECTORY_TYPE, 0o700);
let page_a = dir_a.clone();
page_a.append("empty.html");
page_a.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
let url_a = Services.io.newFileURI(page_a);
let worker = dir_a.clone();
worker.append("worker.js");
let stream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(
Ci.nsIFileOutputStream
);
stream.init(
worker,
0x02 | 0x08 | 0x20, // write, create, truncate
0o666,
0
);
stream.write(WORKER_BODY, WORKER_BODY.length);
stream.close();
let url_worker = Services.io.newFileURI(worker);
let dir_b = parent.clone();
dir_b.append("b");
dir_b.create(Ci.nsIFile.DIRECTORY_TYPE, 0o700);
let page_b = dir_b.clone();
page_b.append("empty.html");
page_b.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
let url_b = Services.io.newFileURI(page_b);
let tab = BrowserTestUtils.addTab(gBrowser, url_a.spec);
gBrowser.selectedTab = tab;
let browser = gBrowser.getBrowserForTab(tab);
await BrowserTestUtils.browserLoaded(browser);
await SpecialPowers.spawn(browser, [url_worker.spec], function(spec) {
return new content.Promise((resolve, reject) => {
let w = new content.window.Worker(spec);
w.onerror = _ => {
reject();
};
w.onmessage = _ => {
resolve();
};
});
});
ok(true, "The worker is loaded when the script is on the same directory.");
BrowserTestUtils.removeTab(tab);
tab = BrowserTestUtils.addTab(gBrowser, url_b.spec);
gBrowser.selectedTab = tab;
browser = gBrowser.getBrowserForTab(tab);
await BrowserTestUtils.browserLoaded(browser);
await SpecialPowers.spawn(browser, [url_worker.spec], function(spec) {
return new content.Promise((resolve, reject) => {
let w = new content.window.Worker(spec);
w.onerror = _ => {
resolve();
};
w.onmessage = _ => {
reject();
};
});
});
ok(
true,
"The worker is not loaded when the script is on a different directory."
);
BrowserTestUtils.removeTab(tab);
info("Removing the tmp directory.");
parent.remove(true);
});
const EMPTY_URL = "/browser/dom/workers/test/empty.html";
const WORKER_URL = "/browser/dom/workers/test/empty_worker.js";

Просмотреть файл

@ -97,11 +97,11 @@ already_AddRefed<MacIOSurface> MacIOSurface::CreateIOSurface(int aWidth,
size_t CreatePlaneDictionary(CFTypeRefPtr<CFMutableDictionaryRef>& aDict,
const gfx::IntSize& aSize, size_t aOffset,
size_t aBytesPerPixel) {
size_t bytesPerRow = IOSurfaceAlignProperty(kIOSurfaceBytesPerRow,
size_t bytesPerRow = IOSurfaceAlignProperty(kIOSurfacePlaneBytesPerRow,
aSize.width * aBytesPerPixel);
// Add a SIMD register worth of extra bytes to the end of the allocation for
// SWGL.
size_t totalBytes = IOSurfaceAlignProperty(kIOSurfaceAllocSize,
size_t totalBytes = IOSurfaceAlignProperty(kIOSurfacePlaneSize,
aSize.height * bytesPerRow + 16);
aDict = CFTypeRefPtr<CFMutableDictionaryRef>::WrapUnderCreateRule(
@ -114,7 +114,7 @@ size_t CreatePlaneDictionary(CFTypeRefPtr<CFMutableDictionaryRef>& aDict,
AddDictionaryInt(aDict, kIOSurfacePlaneBytesPerRow, bytesPerRow);
AddDictionaryInt(aDict, kIOSurfacePlaneOffset, aOffset);
AddDictionaryInt(aDict, kIOSurfacePlaneSize, totalBytes);
AddDictionaryInt(aDict, kIOSurfaceBytesPerElement, aBytesPerPixel);
AddDictionaryInt(aDict, kIOSurfacePlaneBytesPerElement, aBytesPerPixel);
return totalBytes;
}
@ -150,11 +150,15 @@ already_AddRefed<MacIOSurface> MacIOSurface::CreateNV12Surface(
}
CFTypeRefPtr<CFMutableDictionaryRef> planeProps[2];
size_t planeTotalBytes = CreatePlaneDictionary(planeProps[0], aYSize, 0, 1);
planeTotalBytes +=
CreatePlaneDictionary(planeProps[1], aCbCrSize, planeTotalBytes, 2);
size_t yPlaneBytes = CreatePlaneDictionary(planeProps[0], aYSize, 0, 1);
size_t cbCrOffset =
IOSurfaceAlignProperty(kIOSurfacePlaneOffset, yPlaneBytes);
size_t cbCrPlaneBytes =
CreatePlaneDictionary(planeProps[1], aCbCrSize, cbCrOffset, 2);
size_t totalBytes =
IOSurfaceAlignProperty(kIOSurfaceAllocSize, cbCrOffset + cbCrPlaneBytes);
AddDictionaryInt(props, kIOSurfaceAllocSize, planeTotalBytes);
AddDictionaryInt(props, kIOSurfaceAllocSize, totalBytes);
auto array = CFTypeRefPtr<CFArrayRef>::WrapUnderCreateRule(
CFArrayCreate(kCFAllocatorDefault, (const void**)planeProps, 2,

Просмотреть файл

@ -62,6 +62,8 @@ class gfxVarReceiver;
_(GREDirectory, nsString, nsString()) \
_(ProfDirectory, nsString, nsString()) \
_(AllowD3D11KeyedMutex, bool, false) \
_(SwapIntervalGLX, bool, false) \
_(SwapIntervalEGL, bool, false) \
_(SystemTextQuality, int32_t, 5 /* CLEARTYPE_QUALITY */) \
_(SystemTextClearTypeLevel, float, 1.0f) \
_(SystemTextEnhancedContrast, float, 1.0f) \

Просмотреть файл

@ -310,12 +310,14 @@ already_AddRefed<GLContext> GLContextEGLFactory::CreateImpl(
#ifdef MOZ_GTK_WAYLAND
if (surface && GdkIsWaylandDisplay()) {
// Make eglSwapBuffers() non-blocking on wayland
egl->fSwapInterval(0);
const int interval = gfxVars::SwapIntervalEGL() ? 1 : 0;
egl->fSwapInterval(interval);
}
#endif
if (aHardwareWebRender && egl->mLib->IsANGLE()) {
MOZ_ASSERT(doubleBuffered);
egl->fSwapInterval(0);
const int interval = gfxVars::SwapIntervalEGL() ? 1 : 0;
egl->fSwapInterval(interval);
}
return gl.forget();
}
@ -500,8 +502,10 @@ bool GLContextEGL::RenewSurface(CompositorWidget* aWidget) {
MOZ_ASSERT(ok);
#ifdef MOZ_GTK_WAYLAND
if (mSurface && GdkIsWaylandDisplay()) {
// Make eglSwapBuffers() non-blocking on wayland
mEgl->fSwapInterval(0);
// The swap interval pref is false by default so that eglSwapBuffers()
// is non-blocking on wayland.
const int interval = gfxVars::SwapIntervalEGL() ? 1 : 0;
mEgl->fSwapInterval(interval);
}
#endif
return ok;

Просмотреть файл

@ -482,8 +482,10 @@ bool GLContextGLX::MakeCurrentImpl() const {
// Many GLX implementations default to blocking until the next
// VBlank when calling glXSwapBuffers. We want to run unthrottled
// in ASAP mode. See bug 1280744.
const bool swapInterval = gfxVars::SwapIntervalGLX();
const bool isASAP = (StaticPrefs::layout_frame_rate() == 0);
mGLX->fSwapInterval(*mDisplay, mDrawable, isASAP ? 0 : 1);
const int interval = (swapInterval && !isASAP) ? 1 : 0;
mGLX->fSwapInterval(*mDisplay, mDrawable, interval);
}
return succeeded;
}

Просмотреть файл

@ -775,14 +775,12 @@ async function injectScript(aScript, aWindow = window) {
// each time this function is called.
// The computed information is an object with three fields:
// utils: the nsIDOMWindowUtils instance for this window
// isWebRender: true if WebRender is enabled
// isWindow: true if the platform is Windows
// activateAllScrollFrames: true if prefs indicate all scroll frames are
// activated with at least a minimal display port
function getHitTestConfig() {
if (!("hitTestConfig" in window)) {
var utils = SpecialPowers.getDOMWindowUtils(window);
var isWebRender = utils.layerManagerType.startsWith("WebRender");
var isWindows = getPlatform() == "windows";
let activateAllScrollFrames =
SpecialPowers.getBoolPref("apz.wr.activate_all_scroll_frames") ||
@ -793,7 +791,6 @@ function getHitTestConfig() {
window.hitTestConfig = {
utils,
isWebRender,
isWindows,
activateAllScrollFrames,
};
@ -941,27 +938,15 @@ function hitTestScrollbar(params) {
// behaviour on different platforms which makes testing harder.
var expectedHitInfo = APZHitResultFlags.VISIBLE | APZHitResultFlags.SCROLLBAR;
if (params.expectThumb) {
// The thumb has listeners which are APZ-aware. With WebRender we are able
// to losslessly propagate this flag to APZ, but with non-WebRender the area
// ends up in the mDispatchToContentRegion which we then convert back to
// a IRREGULAR_AREA flag. This still works correctly since IRREGULAR_AREA
// will fall back to the main thread for everything.
if (config.isWebRender) {
expectedHitInfo |= APZHitResultFlags.APZ_AWARE_LISTENERS;
if (
!config.activateAllScrollFrames &&
params.layerState == LayerState.INACTIVE
) {
expectedHitInfo |= APZHitResultFlags.INACTIVE_SCROLLFRAME;
}
} else {
expectedHitInfo |= APZHitResultFlags.IRREGULAR_AREA;
// The thumb has listeners which are APZ-aware.
expectedHitInfo |= APZHitResultFlags.APZ_AWARE_LISTENERS;
var expectActive =
config.activateAllScrollFrames || params.layerState == LayerState.ACTIVE;
if (!expectActive) {
expectedHitInfo |= APZHitResultFlags.INACTIVE_SCROLLFRAME;
}
// We do not generate the layers for thumbs on inactive scrollframes.
if (
params.layerState == LayerState.ACTIVE ||
config.activateAllScrollFrames
) {
if (expectActive) {
expectedHitInfo |= APZHitResultFlags.SCROLLBAR_THUMB;
}
}

Просмотреть файл

@ -22,9 +22,6 @@ add_task(async function test_main() {
);
}
var utils = SpecialPowers.getDOMWindowUtils(window);
var isWebRender = utils.layerManagerType.startsWith("WebRender");
// Each of these subtests is a dictionary that contains:
// file (required): filename of the subtest that will get opened in a new tab
// in the top-level fission-enabled browser window.
@ -64,26 +61,12 @@ add_task(async function test_main() {
{ file: "helper_fission_initial_displayport.html" },
{ file: "helper_fission_checkerboard_severity.html" },
{ file: "helper_fission_setResolution.html" },
{ file: "helper_fission_inactivescroller_positionedcontent.html" },
{ file: "helper_fission_irregular_areas.html" },
// Bug 1576514: On WebRender this test casues an assertion.
// { file: "helper_fission_animation_styling_in_transformed_oopif.html", },
// add additional tests here
];
// These tests are to ensure hit-testing works perfectly on the WR
// codepath. The layers codepath may need a main-thread fallback to get
// these working, but we can't use our synchronous hitTest(...) helpers
// for those anyway.
if (isWebRender) {
subtests = subtests.concat([
{ file: "helper_fission_inactivescroller_positionedcontent.html" },
{ file: "helper_fission_irregular_areas.html" },
// add WebRender-specific tests here
]);
} else {
subtests = subtests.concat([
// Bug 1576514: On WebRender this test casues an assertion.
{
file: "helper_fission_animation_styling_in_transformed_oopif.html",
},
]);
}
// ccov builds run slower and need longer, so let's scale up the timeout
// by the number of tests we're running.

Просмотреть файл

@ -100,13 +100,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1689492
// but it gives a good idea that the good and bad values are far apart so
// this test should be robust, and provides good context in the future if
// this test starts failing.
await testOne( 50, 5.2, "(height 50)"); // good wr 256 non-wr 256, bad wr 256 non-wr 384
await testOne(128, 2.1, "(height128)"); // good wr 256 non-wr 256, bad wr 512 non-wr 640
await testOne(200, 2.0, "(height200)"); // good wr 384 non-wr 384, bad wr 768 non-wr 896
await testOne(256, 1.6, "(height256)"); // good wr 384 non-wr 384, bad wr 768 non-wr 1024
await testOne(329, 1.6, "(height329)"); // good wr 512 non-wr 512, bad wr 896 non-wr 1280
await testOne(500, 1.3, "(height500)"); // good wr 640 non-wr 640, bad wr 1280 non-wr 1920
await testOne(640, getHitTestConfig().isWebRender ? 1.7 : 1.3, "(height640)"); // good wr 1024 non-wr 768, bad wr 1536 non-wr 2432
await testOne( 50, 5.2, "(height 50)"); // good 256, bad 256
await testOne(128, 2.1, "(height128)"); // good 256, bad 512
await testOne(200, 2.0, "(height200)"); // good 384, bad 768
await testOne(256, 1.6, "(height256)"); // good 384, bad 768
await testOne(329, 1.6, "(height329)"); // good 512, bad 896
await testOne(500, 1.3, "(height500)"); // good 640, bad 280
await testOne(640, 1.7, "(height640)"); // good 1024, bad 1536
}

Просмотреть файл

@ -25,12 +25,8 @@ async function test() {
var apzaware = document.getElementById("apzaware");
let expectedHitInfo = APZHitResultFlags.VISIBLE;
if (config.isWebRender) {
if (!config.activateAllScrollFrames) {
expectedHitInfo |= APZHitResultFlags.INACTIVE_SCROLLFRAME;
}
} else {
expectedHitInfo |= APZHitResultFlags.IRREGULAR_AREA;
if (!config.activateAllScrollFrames) {
expectedHitInfo |= APZHitResultFlags.INACTIVE_SCROLLFRAME;
}
checkHitResult(hitTest(centerOf(scroller)),
expectedHitInfo,
@ -66,13 +62,11 @@ async function test() {
await promiseApzFlushedRepaints();
var scrollY = scroller.scrollTopMax;
utils.setAsyncScrollOffset(scroller, 0, scrollY);
if (config.isWebRender) {
// Tick the refresh driver once to make sure the compositor has applied the
// async scroll offset (for APZ hit-testing this doesn't matter, but for
// WebRender hit-testing we need to make sure WR has the latest info).
utils.advanceTimeAndRefresh(16);
utils.restoreNormalRefresh();
}
// Tick the refresh driver once to make sure the compositor has applied the
// async scroll offset (for WebRender hit-testing we need to make sure WR has
// the latest info).
utils.advanceTimeAndRefresh(16);
utils.restoreNormalRefresh();
var scrollerViewId = utils.getViewId(scroller);
@ -88,8 +82,7 @@ async function test() {
apzawarePosition.y -= scrollY; // APZ position
checkHitResult(hitTest(apzawarePosition),
APZHitResultFlags.VISIBLE |
(config.isWebRender ? APZHitResultFlags.APZ_AWARE_LISTENERS
: APZHitResultFlags.IRREGULAR_AREA),
APZHitResultFlags.APZ_AWARE_LISTENERS,
scrollerViewId,
utils.getLayersId(),
"active scrollframe - apzaware block");

Просмотреть файл

@ -31,13 +31,11 @@ async function test() {
await promiseApzFlushedRepaints();
var scrollY = scroller.scrollTopMax;
utils.setAsyncScrollOffset(scroller, 0, scrollY);
if (config.isWebRender) {
// Tick the refresh driver once to make sure the compositor has applied the
// async scroll offset (for APZ hit-testing this doesn't matter, but for
// WebRender hit-testing we need to make sure WR has the latest info).
utils.advanceTimeAndRefresh(16);
utils.restoreNormalRefresh();
}
// Tick the refresh driver once to make sure the compositor has applied the
// async scroll offset (for WebRender hit-testing we need to make sure WR has
// the latest info).
utils.advanceTimeAndRefresh(16);
utils.restoreNormalRefresh();
var scrollerViewId = utils.getViewId(scroller);

Просмотреть файл

@ -35,8 +35,6 @@ async function test() {
var config = getHitTestConfig();
var utils = config.utils;
const wrTag = config.isWebRender ? "WebRender" : "Layers";
// layerize the iframe
var subwindow = document.getElementById("sub").contentWindow;
var subscroller = subwindow.document.scrollingElement;
@ -53,29 +51,27 @@ async function test() {
APZHitResultFlags.VISIBLE,
iframeViewId,
layersId,
`${wrTag} (simple) uninteresting point inside the iframe`);
`(simple) uninteresting point inside the iframe`);
checkHitResult(hitTest({ x: 500, y: 10 }),
APZHitResultFlags.VISIBLE,
rootViewId,
layersId,
`${wrTag} (simple) uninteresting point in the root scroller`);
`(simple) uninteresting point in the root scroller`);
checkHitResult(hitTest({ x: 110, y: 110 }),
APZHitResultFlags.VISIBLE,
iframeViewId,
layersId,
`${wrTag} (simple) point in the iframe behind overlaying div, but outside the bounding box of the clip path`);
`(simple) point in the iframe behind overlaying div, but outside the bounding box of the clip path`);
checkHitResult(hitTest({ x: 160, y: 160 }),
config.isWebRender ? APZHitResultFlags.VISIBLE
: APZHitResultFlags.VISIBLE | APZHitResultFlags.IRREGULAR_AREA,
config.isWebRender ? iframeViewId : rootViewId,
APZHitResultFlags.VISIBLE,
iframeViewId,
layersId,
`${wrTag} (simple) point in the iframe behind overlaying div, inside the bounding box of the clip path, but outside the actual clip shape`);
`(simple) point in the iframe behind overlaying div, inside the bounding box of the clip path, but outside the actual clip shape`);
checkHitResult(hitTest({ x: 300, y: 200 }),
config.isWebRender ? APZHitResultFlags.VISIBLE
: APZHitResultFlags.VISIBLE | APZHitResultFlags.IRREGULAR_AREA,
APZHitResultFlags.VISIBLE,
rootViewId,
layersId,
`${wrTag} (simple) point inside the clip shape of the overlaying div`);
`(simple) point inside the clip shape of the overlaying div`);
// Now we turn the "simple" clip-path that WR can handle into a more complex
// one that needs a mask. Then run the checks again; the expected results for
@ -87,29 +83,27 @@ async function test() {
APZHitResultFlags.VISIBLE,
iframeViewId,
layersId,
`${wrTag} (complex) uninteresting point inside the iframe`);
`(complex) uninteresting point inside the iframe`);
checkHitResult(hitTest({ x: 500, y: 10 }),
APZHitResultFlags.VISIBLE,
rootViewId,
layersId,
`${wrTag} (complex) uninteresting point in the root scroller`);
`(complex) uninteresting point in the root scroller`);
checkHitResult(hitTest({ x: 110, y: 110 }),
APZHitResultFlags.VISIBLE,
iframeViewId,
layersId,
`${wrTag} (complex) point in the iframe behind overlaying div, but outside the bounding box of the clip path`);
`(complex) point in the iframe behind overlaying div, but outside the bounding box of the clip path`);
checkHitResult(hitTest({ x: 160, y: 160 }),
config.isWebRender ? APZHitResultFlags.VISIBLE
: APZHitResultFlags.VISIBLE | APZHitResultFlags.IRREGULAR_AREA,
config.isWebRender ? iframeViewId : rootViewId,
APZHitResultFlags.VISIBLE,
iframeViewId,
layersId,
`${wrTag} (complex) point in the iframe behind overlaying div, inside the bounding box of the clip path, but outside the actual clip shape`);
`(complex) point in the iframe behind overlaying div, inside the bounding box of the clip path, but outside the actual clip shape`);
checkHitResult(hitTest({ x: 300, y: 200 }),
config.isWebRender ? APZHitResultFlags.VISIBLE
: APZHitResultFlags.VISIBLE | APZHitResultFlags.IRREGULAR_AREA,
config.isWebRender ? iframeViewId : rootViewId,
APZHitResultFlags.VISIBLE,
iframeViewId,
layersId,
`${wrTag} (complex) point inside the clip shape of the overlaying div`);
`(complex) point inside the clip shape of the overlaying div`);
}
waitUntilApzStable()

Просмотреть файл

@ -64,11 +64,8 @@ async function test() {
utils.setDisplayPortForElement(0, 0, 300, 500, scroller, 1);
await promiseApzFlushedRepaints();
// Inactive scrollframe flags will round-trip through the dispatch-to-content
// region and end up as IRREGULAR_AREA when WebRender is disabled.
var expectedHitFlags = config.isWebRender
? APZHitResultFlags.VISIBLE | APZHitResultFlags.INACTIVE_SCROLLFRAME
: APZHitResultFlags.VISIBLE | APZHitResultFlags.IRREGULAR_AREA;
var expectedHitFlags =
APZHitResultFlags.VISIBLE | APZHitResultFlags.INACTIVE_SCROLLFRAME;
checkHitResult(hitTest(centerOf(scroller)),
expectedHitFlags,
utils.getViewId(scroller),

Просмотреть файл

@ -41,9 +41,9 @@ async function test() {
var config = getHitTestConfig();
var utils = config.utils;
// Subframe hit testing of overscrolled APZCs does not yet work with WebRender,
// so bail out early.
if (config.isWebRender) {
// Subframe hit testing of overscrolled APZCs does not yet work with WebRender
// (bug 1701831), so bail out early.
if (true) {
SimpleTest.todo(false, "This test does not currently pass with WebRender");
return;
}

Просмотреть файл

@ -120,12 +120,6 @@ async function test() {
var scrollId = config.utils.getViewId(document.scrollingElement);
var layersId = config.utils.getLayersId();
// Elements with APZ aware listeners round-trip through the dispatch-to-content
// region and end up as IRREGULAR_AREA when WebRender is disabled.
var touchListenerFlag = config.isWebRender
? APZHitResultFlags.APZ_AWARE_LISTENERS
: APZHitResultFlags.IRREGULAR_AREA;
checkHitResult(
hitTest(centerOf("taNone")),
APZHitResultFlags.VISIBLE |
@ -263,7 +257,7 @@ async function test() {
checkHitResult(
hitTest(centerOf("taInnerManipListener")),
APZHitResultFlags.VISIBLE |
touchListenerFlag |
APZHitResultFlags.APZ_AWARE_LISTENERS |
APZHitResultFlags.DOUBLE_TAP_ZOOM_DISABLED,
scrollId,
layersId,
@ -272,14 +266,14 @@ async function test() {
checkHitResult(
hitTest(centerOf("taListener")),
APZHitResultFlags.VISIBLE |
touchListenerFlag,
APZHitResultFlags.APZ_AWARE_LISTENERS,
scrollId,
layersId,
"div with touch listener");
checkHitResult(
hitTest(centerOf("taInnerListenerPanX")),
APZHitResultFlags.VISIBLE |
touchListenerFlag |
APZHitResultFlags.APZ_AWARE_LISTENERS |
APZHitResultFlags.PAN_Y_DISABLED |
APZHitResultFlags.PINCH_ZOOM_DISABLED |
APZHitResultFlags.DOUBLE_TAP_ZOOM_DISABLED,
@ -351,14 +345,9 @@ async function test() {
"overflow:hidden div doesn't reset pan-x/pan-y from enclosing scroller");
}
if (!config.isWebRender) {
ok(true, "This test is WebRender-only because we get a bunch of dispatch-to-content regions without it and the test isn't very interesting.");
subtestDone();
} else {
waitUntilApzStable()
.then(test)
.then(subtestDone, subtestFailed);
}
waitUntilApzStable()
.then(test)
.then(subtestDone, subtestFailed);
</script>
</html>

Просмотреть файл

@ -55,13 +55,11 @@ async function test() {
await promiseAllPaintsDone();
var scrollY = 300;
utils.setAsyncScrollOffset(subframe, 0, scrollY);
if (config.isWebRender) {
// Tick the refresh driver once to make sure the compositor has applied the
// async scroll offset (for APZ hit-testing this doesn't matter, but for
// WebRender hit-testing we need to make sure WR has the latest info).
utils.advanceTimeAndRefresh(16);
utils.restoreNormalRefresh();
}
// Tick the refresh driver once to make sure the compositor has applied the
// async scroll offset (for WebRender hit-testing we need to make sure WR has
// the latest info).
utils.advanceTimeAndRefresh(16);
utils.restoreNormalRefresh();
// Scroll over the subframe, and make sure that the page does not scroll,
// i.e. overscroll-behavior is respected.

Просмотреть файл

@ -51,12 +51,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1151663
let config = getHitTestConfig();
let heightMultiplier = SpecialPowers.getCharPref("apz.y_stationary_size_multiplier");
if (config.isWebRender) {
// With WebRender, the effective height multiplier can be reduced
// for alignment reasons. The reduction should be no more than a
// factor of two.
heightMultiplier /= 2;
}
// With WebRender, the effective height multiplier can be reduced
// for alignment reasons. The reduction should be no more than a
// factor of two.
heightMultiplier /= 2;
info("effective displayport height multipler is " + heightMultiplier);
let rootDisplayPort = getLastContentDisplayportFor('root-element');

Просмотреть файл

@ -33,6 +33,7 @@ var overscroll_prefs = [...prefs,
];
var subtests = [
{"file": "helper_hittest_deep_scene_stack.html", "prefs": prefs},
{"file": "helper_hittest_pointerevents_svg.html", "prefs": prefs},
{"file": "helper_hittest_clippath.html", "prefs": prefs},
{"file": "helper_hittest_hoisted_scrollinfo.html", "prefs": prefs},
@ -47,26 +48,10 @@ var subtests = [
{"file": "helper_hittest_spam.html", "prefs": prefs},
];
function addConditionalTests(tests) {
// Add some more tests only useful with WebRender. Note that we do this in
// function run after loading, because trying to read layerManagerType can
// throw an NS_ERROR_FAILURE if called too early.
var utils = SpecialPowers.getDOMWindowUtils(window);
var isWebRender = utils.layerManagerType.startsWith("WebRender");
if (isWebRender) {
// Add new tests at the beginning, to ensure the final test remains in
// the final position.
tests = [
{"file": "helper_hittest_deep_scene_stack.html", "prefs": prefs},
].concat(tests);
}
return tests;
}
if (isApzEnabled()) {
SimpleTest.waitForExplicitFinish();
window.onload = function() {
runSubtestsSeriallyInFreshWindows(addConditionalTests(subtests))
runSubtestsSeriallyInFreshWindows(subtests)
.then(SimpleTest.finish, SimpleTest.finishWithFailure);
};
}

Просмотреть файл

@ -64,12 +64,10 @@ let config = getHitTestConfig();
let activateAllScrollFrames = config.activateAllScrollFrames;
let heightMultiplier = SpecialPowers.getCharPref("apz.y_stationary_size_multiplier");
if (config.isWebRender) {
// With WebRender, the effective height multiplier can be reduced
// for alignment reasons. The reduction should be no more than a
// factor of two.
heightMultiplier /= 2;
}
// With WebRender, the effective height multiplier can be reduced
// for alignment reasons. The reduction should be no more than a
// factor of two.
heightMultiplier /= 2;
info("effective displayport height multipler is " + heightMultiplier);
function hasNonZeroMarginDisplayPort(elementId, containingDoc = null) {

Просмотреть файл

@ -404,9 +404,7 @@ struct DIGroup {
InvalidateRect(aData->mRect);
aData->mInvalid = true;
invalidated = true;
} else if (aData->mInvalid ||
/* XXX: handle image load invalidation */ (
aItem->IsInvalid(invalid) && invalid.IsEmpty())) {
} else if (aItem->IsInvalid(invalid) && invalid.IsEmpty()) {
UniquePtr<nsDisplayItemGeometry> geometry(
aItem->AllocateGeometry(aBuilder));
nsRect clippedBounds = clip.ApplyNonRoundedIntersection(

Просмотреть файл

@ -481,6 +481,13 @@ void gfxPlatform::InitChild(const ContentDeviceData& aData) {
#define WR_DEBUG_PREF "gfx.webrender.debug"
static void SwapIntervalPrefChangeCallback(const char* aPrefName, void*) {
bool egl = Preferences::GetBool("gfx.swap-interval.egl", false);
bool glx = Preferences::GetBool("gfx.swap-interval.glx", false);
gfxVars::SetSwapIntervalEGL(egl);
gfxVars::SetSwapIntervalGLX(glx);
}
static void WebRendeProfilerUIPrefChangeCallback(const char* aPrefName, void*) {
nsCString uiString;
if (NS_SUCCEEDED(Preferences::GetCString("gfx.webrender.debug.profiler-ui",
@ -2571,6 +2578,9 @@ void gfxPlatform::InitWebRenderConfig() {
gfxVars::SetUseSoftwareWebRender(!hasHardware && hasSoftware);
Preferences::RegisterPrefixCallbackAndCall(SwapIntervalPrefChangeCallback,
"gfx.swap-interval");
// gfxFeature is not usable in the GPU process, so we use gfxVars to transmit
// this feature
if (hasWebRender) {

Просмотреть файл

@ -191,8 +191,9 @@ bool RenderCompositorEGL::Resume() {
const auto& gle = gl::GLContextEGL::Cast(gl());
const auto& egl = gle->mEgl;
MakeCurrent();
// Make eglSwapBuffers() non-blocking on wayland.
egl->fSwapInterval(0);
const int interval = gfx::gfxVars::SwapIntervalEGL() ? 1 : 0;
egl->fSwapInterval(interval);
} else {
RenderThread::Get()->HandleWebRenderError(WebRenderError::NEW_SURFACE);
return false;

Просмотреть файл

@ -370,11 +370,12 @@ static inline bool IS_HYPHEN(char16_t u) {
return (u == U_HYPHEN || u == 0x2010 || // HYPHEN
u == 0x2012 || // FIGURE DASH
u == 0x2013 || // EN DASH
#if ANDROID
/* Bug 1647377: On Android, we don't have a "platform" backend
* that supports Tibetan (nsRuleBreaker.cpp only knows about
* Thai), so instead we just treat the TSHEG like a hyphen to
* provide basic line-breaking possibilities.
#if ANDROID || XP_WIN
/* Bug 1647377: On Android and Windows, we don't have a "platform"
* backend that supports Tibetan (nsRuleBreaker.cpp only knows about
* Thai, and ScriptBreak doesn't handle Tibetan well either), so
* instead we just treat the TSHEG like a hyphen to provide basic
* line-breaking possibilities.
*/
u == 0x0F0B || // TIBETAN MARK INTERSYLLABIC TSHEG
#endif

Просмотреть файл

@ -76,8 +76,8 @@ static inline bool NS_IsSpace(char16_t u) {
static inline bool NS_NeedsPlatformNativeHandling(char16_t aChar) {
return
#if ANDROID // Bug 1647377: no "platform native" support for Tibetan;
// better to just use our class-based breaker.
#if ANDROID || XP_WIN // Bug 1647377/1736393: no "platform native" support for
// Tibetan; better to just use our class-based breaker.
(0x0e01 <= aChar && aChar <= 0x0eff) || // Thai, Lao
#else
(0x0e01 <= aChar && aChar <= 0x0fff) || // Thai, Lao, Tibetan

Просмотреть файл

@ -79,12 +79,7 @@ class GCHashMap : public js::HashMap<Key, Value, HashPolicy, AllocPolicy> {
}
void sweep() {
typename Base::Enum e(*this);
sweepEntries(e);
}
void sweepEntries(typename Base::Enum& e) {
for (; !e.empty(); e.popFront()) {
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) {
if (MapSweepPolicy::needsSweep(&e.front().mutableKey(),
&e.front().value())) {
e.removeFront();
@ -92,7 +87,13 @@ class GCHashMap : public js::HashMap<Key, Value, HashPolicy, AllocPolicy> {
}
}
void traceWeak(JSTracer* trc) {
bool traceWeak(JSTracer* trc) {
typename Base::Enum e(*this);
traceWeakEntries(trc, e);
return !this->empty();
}
void traceWeakEntries(JSTracer* trc, typename Base::Enum& e) {
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) {
if (!MapSweepPolicy::traceWeak(trc, &e.front().mutableKey(),
&e.front().value())) {
@ -149,7 +150,7 @@ class GCRekeyableHashMap : public JS::GCHashMap<Key, Value, HashPolicy,
}
}
void traceWeak(JSTracer* trc) {
bool traceWeak(JSTracer* trc) {
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) {
Key key(e.front().key());
if (!MapSweepPolicy::traceWeak(trc, &key, &e.front().value())) {
@ -158,6 +159,7 @@ class GCRekeyableHashMap : public JS::GCHashMap<Key, Value, HashPolicy,
e.rekeyFront(key);
}
}
return !this->empty();
}
// GCRekeyableHashMap is movable
@ -275,21 +277,14 @@ class GCHashSet : public js::HashSet<T, HashPolicy, AllocPolicy> {
}
}
void sweep() {
bool traceWeak(JSTracer* trc) {
typename Base::Enum e(*this);
sweepEntries(e);
traceWeakEntries(trc, e);
return !this->empty();
}
void sweepEntries(typename Base::Enum& e) {
void traceWeakEntries(JSTracer* trc, typename Base::Enum& e) {
for (; !e.empty(); e.popFront()) {
if (GCPolicy<T>::needsSweep(&e.mutableFront())) {
e.removeFront();
}
}
}
void traceWeak(JSTracer* trc) {
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) {
if (!GCPolicy<T>::traceWeak(trc, &e.mutableFront())) {
e.removeFront();
}
@ -404,35 +399,31 @@ namespace JS {
template <typename Key, typename Value, typename HashPolicy,
typename AllocPolicy, typename MapSweepPolicy>
class WeakCache<GCHashMap<Key, Value, HashPolicy, AllocPolicy, MapSweepPolicy>>
: protected detail::WeakCacheBase {
final : protected detail::WeakCacheBase {
using Map = GCHashMap<Key, Value, HashPolicy, AllocPolicy, MapSweepPolicy>;
using Self = WeakCache<Map>;
Map map;
bool needsBarrier;
JSTracer* barrierTracer = nullptr;
public:
template <typename... Args>
explicit WeakCache(Zone* zone, Args&&... args)
: WeakCacheBase(zone),
map(std::forward<Args>(args)...),
needsBarrier(false) {}
: WeakCacheBase(zone), map(std::forward<Args>(args)...) {}
template <typename... Args>
explicit WeakCache(JSRuntime* rt, Args&&... args)
: WeakCacheBase(rt),
map(std::forward<Args>(args)...),
needsBarrier(false) {}
~WeakCache() { MOZ_ASSERT(!needsBarrier); }
: WeakCacheBase(rt), map(std::forward<Args>(args)...) {}
~WeakCache() { MOZ_ASSERT(!barrierTracer); }
bool empty() override { return map.empty(); }
size_t sweep(js::gc::StoreBuffer* sbToLock) override {
size_t traceWeak(JSTracer* trc, js::gc::StoreBuffer* sbToLock) override {
size_t steps = map.count();
// Create an Enum and sweep the table entries.
mozilla::Maybe<typename Map::Enum> e;
e.emplace(map);
map.sweepEntries(e.ref());
map.traceWeakEntries(trc, e.ref());
// Potentially take a lock while the Enum's destructor is called as this can
// rehash/resize the table and access the store buffer.
@ -445,24 +436,26 @@ class WeakCache<GCHashMap<Key, Value, HashPolicy, AllocPolicy, MapSweepPolicy>>
return steps;
}
bool setNeedsIncrementalBarrier(bool needs) override {
MOZ_ASSERT(needsBarrier != needs);
needsBarrier = needs;
bool setIncrementalBarrierTracer(JSTracer* trc) override {
MOZ_ASSERT(bool(barrierTracer) != bool(trc));
barrierTracer = trc;
return true;
}
bool needsIncrementalBarrier() const override { return needsBarrier; }
bool needsIncrementalBarrier() const override { return barrierTracer; }
private:
using Entry = typename Map::Entry;
static bool entryNeedsSweep(const Entry& prior) {
static bool entryNeedsSweep(JSTracer* barrierTracer, const Entry& prior) {
Key key(prior.key());
Value value(prior.value());
bool result = MapSweepPolicy::needsSweep(&key, &value);
MOZ_ASSERT(prior.key() == key); // We shouldn't update here.
MOZ_ASSERT(prior.value() == value); // We shouldn't update here.
return result;
bool needsSweep = !MapSweepPolicy::traceWeak(barrierTracer, &key, &value);
MOZ_ASSERT_IF(!needsSweep,
prior.key() == key); // We shouldn't update here.
MOZ_ASSERT_IF(!needsSweep,
prior.value() == value); // We shouldn't update here.
return needsSweep;
}
public:
@ -470,8 +463,11 @@ class WeakCache<GCHashMap<Key, Value, HashPolicy, AllocPolicy, MapSweepPolicy>>
using Ptr = typename Map::Ptr;
using AddPtr = typename Map::AddPtr;
// Iterator over the whole collection.
struct Range {
explicit Range(const typename Map::Range& r) : range(r) { settle(); }
explicit Range(Self& self) : cache(self), range(self.map.all()) {
settle();
}
Range() = default;
bool empty() const { return range.empty(); }
@ -483,11 +479,14 @@ class WeakCache<GCHashMap<Key, Value, HashPolicy, AllocPolicy, MapSweepPolicy>>
}
private:
Self& cache;
typename Map::Range range;
void settle() {
while (!empty() && entryNeedsSweep(front())) {
popFront();
if (JSTracer* trc = cache.barrierTracer) {
while (!empty() && entryNeedsSweep(trc, front())) {
popFront();
}
}
}
};
@ -496,13 +495,13 @@ class WeakCache<GCHashMap<Key, Value, HashPolicy, AllocPolicy, MapSweepPolicy>>
explicit Enum(Self& cache) : Map::Enum(cache.map) {
// This operation is not allowed while barriers are in place as we
// may also need to enumerate the set for sweeping.
MOZ_ASSERT(!cache.needsBarrier);
MOZ_ASSERT(!cache.barrierTracer);
}
};
Ptr lookup(const Lookup& l) const {
Ptr ptr = map.lookup(l);
if (needsBarrier && ptr && entryNeedsSweep(*ptr)) {
if (barrierTracer && ptr && entryNeedsSweep(barrierTracer, *ptr)) {
const_cast<Map&>(map).remove(ptr);
return Ptr();
}
@ -511,20 +510,20 @@ class WeakCache<GCHashMap<Key, Value, HashPolicy, AllocPolicy, MapSweepPolicy>>
AddPtr lookupForAdd(const Lookup& l) {
AddPtr ptr = map.lookupForAdd(l);
if (needsBarrier && ptr && entryNeedsSweep(*ptr)) {
if (barrierTracer && ptr && entryNeedsSweep(barrierTracer, *ptr)) {
const_cast<Map&>(map).remove(ptr);
return map.lookupForAdd(l);
}
return ptr;
}
Range all() const { return Range(map.all()); }
Range all() const { return Range(*const_cast<Self*>(this)); }
bool empty() const {
// This operation is not currently allowed while barriers are in place
// as it would require iterating the map and the caller expects a
// constant time operation.
MOZ_ASSERT(!needsBarrier);
MOZ_ASSERT(!barrierTracer);
return map.empty();
}
@ -532,7 +531,7 @@ class WeakCache<GCHashMap<Key, Value, HashPolicy, AllocPolicy, MapSweepPolicy>>
// This operation is not currently allowed while barriers are in place
// as it would require iterating the set and the caller expects a
// constant time operation.
MOZ_ASSERT(!needsBarrier);
MOZ_ASSERT(!barrierTracer);
return map.count();
}
@ -550,14 +549,14 @@ class WeakCache<GCHashMap<Key, Value, HashPolicy, AllocPolicy, MapSweepPolicy>>
void clear() {
// This operation is not currently allowed while barriers are in place
// since it doesn't make sense to clear a cache while it is being swept.
MOZ_ASSERT(!needsBarrier);
MOZ_ASSERT(!barrierTracer);
map.clear();
}
void clearAndCompact() {
// This operation is not currently allowed while barriers are in place
// since it doesn't make sense to clear a cache while it is being swept.
MOZ_ASSERT(!needsBarrier);
MOZ_ASSERT(!barrierTracer);
map.clearAndCompact();
}
@ -600,36 +599,32 @@ class WeakCache<GCHashMap<Key, Value, HashPolicy, AllocPolicy, MapSweepPolicy>>
// Specialize WeakCache for GCHashSet to provide a barriered set that does not
// need to be swept immediately.
template <typename T, typename HashPolicy, typename AllocPolicy>
class WeakCache<GCHashSet<T, HashPolicy, AllocPolicy>>
class WeakCache<GCHashSet<T, HashPolicy, AllocPolicy>> final
: protected detail::WeakCacheBase {
using Set = GCHashSet<T, HashPolicy, AllocPolicy>;
using Self = WeakCache<Set>;
Set set;
bool needsBarrier;
JSTracer* barrierTracer = nullptr;
public:
using Entry = typename Set::Entry;
template <typename... Args>
explicit WeakCache(Zone* zone, Args&&... args)
: WeakCacheBase(zone),
set(std::forward<Args>(args)...),
needsBarrier(false) {}
: WeakCacheBase(zone), set(std::forward<Args>(args)...) {}
template <typename... Args>
explicit WeakCache(JSRuntime* rt, Args&&... args)
: WeakCacheBase(rt),
set(std::forward<Args>(args)...),
needsBarrier(false) {}
: WeakCacheBase(rt), set(std::forward<Args>(args)...) {}
size_t sweep(js::gc::StoreBuffer* sbToLock) override {
size_t traceWeak(JSTracer* trc, js::gc::StoreBuffer* sbToLock) override {
size_t steps = set.count();
// Create an Enum and sweep the table entries. It's not necessary to take
// the store buffer lock yet.
mozilla::Maybe<typename Set::Enum> e;
e.emplace(set);
set.sweepEntries(e.ref());
set.traceWeakEntries(trc, e.ref());
// Destroy the Enum, potentially rehashing or resizing the table. Since this
// can access the store buffer, we need to take a lock for this if we're
@ -645,20 +640,20 @@ class WeakCache<GCHashSet<T, HashPolicy, AllocPolicy>>
bool empty() override { return set.empty(); }
bool setNeedsIncrementalBarrier(bool needs) override {
MOZ_ASSERT(needsBarrier != needs);
needsBarrier = needs;
bool setIncrementalBarrierTracer(JSTracer* trc) override {
MOZ_ASSERT(bool(barrierTracer) != bool(trc));
barrierTracer = trc;
return true;
}
bool needsIncrementalBarrier() const override { return needsBarrier; }
bool needsIncrementalBarrier() const override { return barrierTracer; }
private:
static bool entryNeedsSweep(const Entry& prior) {
static bool entryNeedsSweep(JSTracer* barrierTracer, const Entry& prior) {
Entry entry(prior);
bool result = GCPolicy<T>::needsSweep(&entry);
MOZ_ASSERT(prior == entry); // We shouldn't update here.
return result;
bool needsSweep = !GCPolicy<T>::traceWeak(barrierTracer, &entry);
MOZ_ASSERT_IF(!needsSweep, prior == entry); // We shouldn't update here.
return needsSweep;
}
public:
@ -666,8 +661,11 @@ class WeakCache<GCHashSet<T, HashPolicy, AllocPolicy>>
using Ptr = typename Set::Ptr;
using AddPtr = typename Set::AddPtr;
// Iterator over the whole collection.
struct Range {
explicit Range(const typename Set::Range& r) : range(r) { settle(); }
explicit Range(Self& self) : cache(self), range(self.set.all()) {
settle();
}
Range() = default;
bool empty() const { return range.empty(); }
@ -679,11 +677,14 @@ class WeakCache<GCHashSet<T, HashPolicy, AllocPolicy>>
}
private:
Self& cache;
typename Set::Range range;
void settle() {
while (!empty() && entryNeedsSweep(front())) {
popFront();
if (JSTracer* trc = cache.barrierTracer) {
while (!empty() && entryNeedsSweep(trc, front())) {
popFront();
}
}
}
};
@ -692,13 +693,13 @@ class WeakCache<GCHashSet<T, HashPolicy, AllocPolicy>>
explicit Enum(Self& cache) : Set::Enum(cache.set) {
// This operation is not allowed while barriers are in place as we
// may also need to enumerate the set for sweeping.
MOZ_ASSERT(!cache.needsBarrier);
MOZ_ASSERT(!cache.barrierTracer);
}
};
Ptr lookup(const Lookup& l) const {
Ptr ptr = set.lookup(l);
if (needsBarrier && ptr && entryNeedsSweep(*ptr)) {
if (barrierTracer && ptr && entryNeedsSweep(barrierTracer, *ptr)) {
const_cast<Set&>(set).remove(ptr);
return Ptr();
}
@ -707,20 +708,20 @@ class WeakCache<GCHashSet<T, HashPolicy, AllocPolicy>>
AddPtr lookupForAdd(const Lookup& l) {
AddPtr ptr = set.lookupForAdd(l);
if (needsBarrier && ptr && entryNeedsSweep(*ptr)) {
if (barrierTracer && ptr && entryNeedsSweep(barrierTracer, *ptr)) {
const_cast<Set&>(set).remove(ptr);
return set.lookupForAdd(l);
}
return ptr;
}
Range all() const { return Range(set.all()); }
Range all() const { return Range(*const_cast<Self*>(this)); }
bool empty() const {
// This operation is not currently allowed while barriers are in place
// as it would require iterating the set and the caller expects a
// constant time operation.
MOZ_ASSERT(!needsBarrier);
MOZ_ASSERT(!barrierTracer);
return set.empty();
}
@ -728,7 +729,7 @@ class WeakCache<GCHashSet<T, HashPolicy, AllocPolicy>>
// This operation is not currently allowed while barriers are in place
// as it would require iterating the set and the caller expects a
// constant time operation.
MOZ_ASSERT(!needsBarrier);
MOZ_ASSERT(!barrierTracer);
return set.count();
}
@ -746,14 +747,14 @@ class WeakCache<GCHashSet<T, HashPolicy, AllocPolicy>>
void clear() {
// This operation is not currently allowed while barriers are in place
// since it doesn't make sense to clear a cache while it is being swept.
MOZ_ASSERT(!needsBarrier);
MOZ_ASSERT(!barrierTracer);
set.clear();
}
void clearAndCompact() {
// This operation is not currently allowed while barriers are in place
// since it doesn't make sense to clear a cache while it is being swept.
MOZ_ASSERT(!needsBarrier);
MOZ_ASSERT(!barrierTracer);
set.clearAndCompact();
}

Просмотреть файл

@ -60,12 +60,14 @@ class WeakCacheBase : public mozilla::LinkedListElement<WeakCacheBase> {
WeakCacheBase(WeakCacheBase&& other) = default;
virtual ~WeakCacheBase() = default;
virtual size_t sweep(js::gc::StoreBuffer* sbToLock) = 0;
virtual size_t traceWeak(JSTracer* trc, js::gc::StoreBuffer* sbToLock) = 0;
// Sweeping will be skipped if the cache is empty already.
virtual bool empty() = 0;
virtual bool setNeedsIncrementalBarrier(bool needs) {
// Enable/disable read barrier during incremental sweeping and set the tracer
// to use.
virtual bool setIncrementalBarrierTracer(JSTracer* trc) {
// Derived classes do not support incremental barriers by default.
return false;
}
@ -98,7 +100,7 @@ class WeakCache : protected detail::WeakCacheBase,
const T& get() const { return cache; }
T& get() { return cache; }
size_t sweep(js::gc::StoreBuffer* sbToLock) override {
size_t traceWeak(JSTracer* trc, js::gc::StoreBuffer* sbToLock) override {
// Take the store buffer lock in case sweeping triggers any generational
// post barriers. This is not always required and WeakCache specializations
// may delay or skip taking the lock as appropriate.
@ -107,7 +109,7 @@ class WeakCache : protected detail::WeakCacheBase,
lock.emplace(sbToLock);
}
GCPolicy<T>::sweep(&cache);
GCPolicy<T>::traceWeak(trc, &cache);
return 0;
}

Просмотреть файл

@ -459,11 +459,10 @@ void GCRuntime::sweepZoneAfterCompacting(MovingTracer* trc, Zone* zone) {
traceWeakFinalizationRegistryEdges(trc, zone);
zone->weakRefMap().sweep(&storeBuffer());
{
zone->sweepWeakMaps();
for (auto* cache : zone->weakCaches()) {
cache->sweep(nullptr);
}
zone->traceWeakMaps(trc);
for (auto* cache : zone->weakCaches()) {
cache->traceWeak(trc, nullptr);
}
if (jit::JitZone* jitZone = zone->jitZone()) {
@ -656,7 +655,7 @@ void GCRuntime::updateRttValueObjects(MovingTracer* trc, Zone* zone) {
// need to be updated. Do not update any non-reserved slots, since they might
// point back to unprocessed descriptor objects.
zone->rttValueObjects().sweep(nullptr);
zone->rttValueObjects().traceWeak(trc, nullptr);
for (auto r = zone->rttValueObjects().all(); !r.empty(); r.popFront()) {
RttValue* obj = &MaybeForwardedObjectAs<RttValue>(r.front());
@ -797,13 +796,6 @@ void GCRuntime::updateZonePointersToRelocatedCells(Zone* zone) {
// as much as possible.
updateAllCellPointers(&trc, zone);
// Mark roots to update them.
{
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::MARK_ROOTS);
WeakMapBase::traceZone(zone, &trc);
}
// Sweep everything to fix up weak pointers.
sweepZoneAfterCompacting(&trc, zone);
@ -845,7 +837,7 @@ void GCRuntime::updateRuntimePointersToRelocatedCells(AutoGCSession& session) {
// Sweep everything to fix up weak pointers.
jit::JitRuntime::TraceWeakJitcodeGlobalTable(rt, &trc);
for (JS::detail::WeakCacheBase* cache : rt->weakCaches()) {
cache->sweep(nullptr);
cache->traceWeak(&trc, nullptr);
}
// Type inference may put more blocks here to free.

Просмотреть файл

@ -370,6 +370,7 @@ GCRuntime::GCRuntime(JSRuntime* rt)
stats_(this),
marker(rt),
barrierTracer(rt),
sweepingTracer(rt),
heapSize(nullptr),
helperThreadRatio(TuningDefaults::HelperThreadRatio),
maxHelperThreads(TuningDefaults::MaxHelperThreads),

Просмотреть файл

@ -279,15 +279,6 @@ struct MovingTracer final : public GenericTracerImpl<MovingTracer> {
friend class GenericTracerImpl<MovingTracer>;
};
struct SweepingTracer final : public GenericTracerImpl<SweepingTracer> {
explicit SweepingTracer(JSRuntime* rt);
private:
template <typename T>
T* onEdge(T* thingp);
friend class GenericTracerImpl<SweepingTracer>;
};
struct MinorSweepingTracer final
: public GenericTracerImpl<MinorSweepingTracer> {
explicit MinorSweepingTracer(JSRuntime* rt);

Просмотреть файл

@ -271,6 +271,15 @@ class BarrierTracer final : public GenericTracerImpl<BarrierTracer> {
GCMarker& marker;
};
struct SweepingTracer final : public GenericTracerImpl<SweepingTracer> {
explicit SweepingTracer(JSRuntime* rt);
private:
template <typename T>
T* onEdge(T* thingp);
friend class GenericTracerImpl<SweepingTracer>;
};
class GCRuntime {
friend GCMarker::MarkQueueProgress GCMarker::processMarkQueue();
@ -912,6 +921,7 @@ class GCRuntime {
GCMarker marker;
BarrierTracer barrierTracer;
SweepingTracer sweepingTracer;
Vector<JS::GCCellPtr, 0, SystemAllocPolicy> unmarkGrayStack;

Просмотреть файл

@ -1177,7 +1177,8 @@ class ImmediateSweepWeakCacheTask : public GCParallelTask {
void run(AutoLockHelperThreadState& lock) override {
AutoUnlockHelperThreadState unlock(lock);
AutoSetThreadIsSweeping threadIsSweeping(zone);
cache.sweep(&gc->storeBuffer());
SweepingTracer trc(gc->rt);
cache.traceWeak(&trc, &gc->storeBuffer());
}
};
@ -1237,6 +1238,7 @@ void GCRuntime::sweepCompressionTasks() {
}
void GCRuntime::sweepWeakMaps() {
SweepingTracer trc(rt);
AutoSetThreadIsSweeping threadIsSweeping; // This may touch any zone.
for (SweepGroupZonesIter zone(this); !zone.done(); zone.next()) {
/* No need to look up any more weakmap keys from this sweep group. */
@ -1248,7 +1250,7 @@ void GCRuntime::sweepWeakMaps() {
// Lock the storebuffer since this may access it when rehashing or resizing
// the tables.
AutoLockStoreBuffer lock(&storeBuffer());
zone->sweepWeakMaps();
zone->sweepWeakMaps(&trc);
}
}
@ -1406,6 +1408,7 @@ static bool PrepareWeakCacheTasks(JSRuntime* rt,
MOZ_ASSERT(immediateTasks->empty());
GCRuntime* gc = &rt->gc;
bool ok =
IterateWeakCaches(rt, [&](JS::detail::WeakCacheBase* cache, Zone* zone) {
if (cache->empty()) {
@ -1413,11 +1416,11 @@ static bool PrepareWeakCacheTasks(JSRuntime* rt,
}
// Caches that support incremental sweeping will be swept later.
if (zone && cache->setNeedsIncrementalBarrier(true)) {
if (zone && cache->setIncrementalBarrierTracer(&gc->sweepingTracer)) {
return true;
}
return immediateTasks->emplaceBack(&rt->gc, zone, *cache);
return immediateTasks->emplaceBack(gc, zone, *cache);
});
if (!ok) {
@ -1430,11 +1433,12 @@ static bool PrepareWeakCacheTasks(JSRuntime* rt,
static void SweepAllWeakCachesOnMainThread(JSRuntime* rt) {
// If we ran out of memory, do all the work on the main thread.
gcstats::AutoPhase ap(rt->gc.stats(), gcstats::PhaseKind::SWEEP_WEAK_CACHES);
SweepingTracer trc(rt);
IterateWeakCaches(rt, [&](JS::detail::WeakCacheBase* cache, Zone* zone) {
if (cache->needsIncrementalBarrier()) {
cache->setNeedsIncrementalBarrier(false);
cache->setIncrementalBarrierTracer(nullptr);
}
cache->sweep(&rt->gc.storeBuffer());
cache->traceWeak(&trc, &rt->gc.storeBuffer());
return true;
});
}
@ -1843,8 +1847,10 @@ static size_t IncrementalSweepWeakCache(GCRuntime* gc,
JS::detail::WeakCacheBase* cache = item.cache;
MOZ_ASSERT(cache->needsIncrementalBarrier());
size_t steps = cache->sweep(&gc->storeBuffer());
cache->setNeedsIncrementalBarrier(false);
SweepingTracer trc(gc->rt);
size_t steps = cache->traceWeak(&trc, &gc->storeBuffer());
cache->setIncrementalBarrierTracer(nullptr);
return steps;
}

Просмотреть файл

@ -336,10 +336,10 @@ bool WeakMap<K, V>::markEntries(GCMarker* marker) {
}
template <class K, class V>
void WeakMap<K, V>::sweep() {
/* Remove all entries whose keys remain unmarked. */
void WeakMap<K, V>::traceWeakEdges(JSTracer* trc) {
// Remove all entries whose keys remain unmarked.
for (Enum e(*this); !e.empty(); e.popFront()) {
if (gc::IsAboutToBeFinalized(&e.front().mutableKey())) {
if (!TraceWeakEdge(trc, &e.front().mutableKey(), "WeakMap key")) {
e.removeFront();
}
}

Просмотреть файл

@ -41,11 +41,11 @@ void WeakMapBase::unmarkZone(JS::Zone* zone) {
}
}
void WeakMapBase::traceZone(JS::Zone* zone, JSTracer* tracer) {
MOZ_ASSERT(tracer->weakMapAction() != JS::WeakMapTraceAction::Skip);
for (WeakMapBase* m : zone->gcWeakMapList()) {
m->trace(tracer);
TraceNullableEdge(tracer, &m->memberOf, "memberOf");
void Zone::traceWeakMaps(JSTracer* trc) {
MOZ_ASSERT(trc->weakMapAction() != JS::WeakMapTraceAction::Skip);
for (WeakMapBase* m : gcWeakMapList()) {
m->trace(trc);
TraceNullableEdge(trc, &m->memberOf, "memberOf");
}
}
@ -84,20 +84,20 @@ bool WeakMapBase::findSweepGroupEdgesForZone(JS::Zone* zone) {
return true;
}
void WeakMapBase::sweepZone(JS::Zone* zone) {
for (WeakMapBase* m = zone->gcWeakMapList().getFirst(); m;) {
void Zone::sweepWeakMaps(JSTracer* trc) {
for (WeakMapBase* m = gcWeakMapList().getFirst(); m;) {
WeakMapBase* next = m->getNext();
if (m->mapColor) {
m->sweep();
m->traceWeakEdges(trc);
} else {
m->clearAndCompact();
m->removeFrom(zone->gcWeakMapList());
m->removeFrom(gcWeakMapList());
}
m = next;
}
#ifdef DEBUG
for (WeakMapBase* m : zone->gcWeakMapList()) {
for (WeakMapBase* m : gcWeakMapList()) {
MOZ_ASSERT(m->isInList() && m->mapColor);
}
#endif

Просмотреть файл

@ -107,9 +107,6 @@ class WeakMapBase : public mozilla::LinkedListElement<WeakMapBase> {
// Unmark all weak maps in a zone.
static void unmarkZone(JS::Zone* zone);
// Trace all the weakmaps in a zone.
static void traceZone(JS::Zone* zone, JSTracer* tracer);
// Check all weak maps in a zone that have been marked as live in this garbage
// collection, and mark the values of all entries that have become strong
// references to them. Return true if we marked any new values, indicating
@ -120,10 +117,6 @@ class WeakMapBase : public mozilla::LinkedListElement<WeakMapBase> {
// Add zone edges for weakmaps with key delegates in a different zone.
[[nodiscard]] static bool findSweepGroupEdgesForZone(JS::Zone* zone);
// Sweep the weak maps in a zone, removing dead weak maps and removing
// entries of live weak maps whose keys are dead.
static void sweepZone(JS::Zone* zone);
// Sweep the marked weak maps in a zone, updating moved keys.
static void sweepZoneAfterMinorGC(JS::Zone* zone);
@ -146,7 +139,7 @@ class WeakMapBase : public mozilla::LinkedListElement<WeakMapBase> {
// override these with definitions appropriate for their Key and Value types.
virtual void trace(JSTracer* tracer) = 0;
virtual bool findSweepGroupEdges() = 0;
virtual void sweep() = 0;
virtual void traceWeakEdges(JSTracer* trc) = 0;
virtual void traceMappings(WeakMapTracer* tracer) = 0;
virtual void clearAndCompact() = 0;
@ -316,7 +309,7 @@ class WeakMap
JS::ExposeObjectToActiveJS(obj);
}
void sweep() override;
void traceWeakEdges(JSTracer* trc) override;
void clearAndCompact() override {
Base::clear();

Просмотреть файл

@ -392,11 +392,6 @@ void Zone::checkStringWrappersAfterMovingGC() {
}
#endif
void Zone::sweepWeakMaps() {
/* Finalize unreachable (key,value) pairs in all weak maps. */
WeakMapBase::sweepZone(this);
}
void Zone::discardJitCode(JSFreeOp* fop, const DiscardOptions& options) {
if (!jitZone()) {
return;

Просмотреть файл

@ -480,9 +480,15 @@ class Zone : public js::ZoneAllocator, public js::gc::GraphNodeBase<JS::Zone> {
void sweepAfterMinorGC(JSTracer* trc);
void sweepUniqueIds();
void sweepWeakMaps();
void sweepCompartments(JSFreeOp* fop, bool keepAtleastOne, bool lastGC);
// Remove dead weak maps from gcWeakMapList_ and remove entries from the
// remaining weak maps whose keys are dead.
void sweepWeakMaps(JSTracer* trc);
// Trace all weak maps in this zone. Used to update edges after a moving GC.
void traceWeakMaps(JSTracer* trc);
js::gc::UniqueIdMap& uniqueIds() { return uniqueIds_.ref(); }
void notifyObservingDebuggers();

Просмотреть файл

@ -136,8 +136,9 @@ struct ObjectEntry {
HeapPtr<JSObject*> obj;
explicit ObjectEntry(JSObject* o) : obj(o) {}
bool operator==(const ObjectEntry& other) const { return obj == other.obj; }
bool needsSweep() {
return JS::GCPolicy<HeapPtr<JSObject*>>::needsSweep(&obj);
bool needsSweep() { return IsAboutToBeFinalized(&obj); }
bool traceWeak(JSTracer* trc) {
return TraceWeakEdge(trc, &obj, "ObjectEntry::obj");
}
};
@ -173,8 +174,9 @@ struct NumberAndObjectEntry {
bool operator==(const NumberAndObjectEntry& other) const {
return number == other.number && obj == other.obj;
}
bool needsSweep() {
return JS::GCPolicy<HeapPtr<JSObject*>>::needsSweep(&obj);
bool needsSweep() { return IsAboutToBeFinalized(&obj); }
bool traceWeak(JSTracer* trc) {
return TraceWeakEdge(trc, &obj, "NumberAndObjectEntry::obj");
}
};

Просмотреть файл

@ -175,12 +175,11 @@ enum class ScriptKind { Script, ScriptStencil, DecodeScript, Module };
class NonshrinkingGCObjectVector
: public GCVector<HeapPtrObject, 0, SystemAllocPolicy> {
public:
void sweep() {
bool traceWeak(JSTracer* trc) {
for (HeapPtrObject& obj : *this) {
if (JS::GCPolicy<HeapPtrObject>::needsSweep(&obj)) {
obj = nullptr;
}
TraceWeakEdge(trc, &obj, "NonshrinkingGCObjectVector element");
}
return true;
}
};

Просмотреть файл

@ -1731,27 +1731,27 @@ void InnerViewTable::removeViews(ArrayBufferObject* buffer) {
map.remove(p);
}
void InnerViewTable::sweep() { map.sweep(); }
bool InnerViewTable::traceWeak(JSTracer* trc) { return map.traceWeak(trc); }
void InnerViewTable::sweepAfterMinorGC() {
void InnerViewTable::sweepAfterMinorGC(JSTracer* trc) {
MOZ_ASSERT(needsSweepAfterMinorGC());
if (nurseryKeysValid) {
for (size_t i = 0; i < nurseryKeys.length(); i++) {
JSObject* buffer = MaybeForwarded(nurseryKeys[i]);
Map::Ptr p = map.lookup(buffer);
if (p && Map::SweepPolicy::needsSweep(&p->mutableKey(), &p->value())) {
if (p &&
!Map::SweepPolicy::traceWeak(trc, &p->mutableKey(), &p->value())) {
map.remove(p);
}
}
nurseryKeys.clear();
} else {
// Do the required sweeping by looking at every map entry.
nurseryKeys.clear();
sweep();
nurseryKeysValid = true;
map.traceWeak(trc);
}
nurseryKeys.clear();
nurseryKeysValid = true;
}
size_t InnerViewTable::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) {

Просмотреть файл

@ -564,8 +564,8 @@ class InnerViewTable {
// Remove references to dead objects in the table and update table entries
// to reflect moved objects.
void sweep();
void sweepAfterMinorGC();
bool traceWeak(JSTracer* trc);
void sweepAfterMinorGC(JSTracer* trc);
bool empty() const { return map.empty(); }

Просмотреть файл

@ -504,7 +504,7 @@ void Compartment::sweepAfterMinorGC(JSTracer* trc) {
crossCompartmentObjectWrappers.sweepAfterMinorGC(trc);
for (RealmsInCompartmentIter r(this); !r.done(); r.next()) {
r->sweepAfterMinorGC();
r->sweepAfterMinorGC(trc);
}
}

Просмотреть файл

@ -326,17 +326,17 @@ void Realm::finishRoots() {
objects_.finishRoots();
}
void ObjectRealm::sweepAfterMinorGC() {
void ObjectRealm::sweepAfterMinorGC(JSTracer* trc) {
InnerViewTable& table = innerViews.get();
if (table.needsSweepAfterMinorGC()) {
table.sweepAfterMinorGC();
table.sweepAfterMinorGC(trc);
}
}
void Realm::sweepAfterMinorGC() {
void Realm::sweepAfterMinorGC(JSTracer* trc) {
globalWriteBarriered = 0;
dtoaCache.purge();
objects_.sweepAfterMinorGC();
objects_.sweepAfterMinorGC(trc);
}
void Realm::traceWeakSavedStacks(JSTracer* trc) { savedStacks_.traceWeak(trc); }

Просмотреть файл

@ -265,7 +265,7 @@ class ObjectRealm {
void finishRoots();
void trace(JSTracer* trc);
void sweepAfterMinorGC();
void sweepAfterMinorGC(JSTracer* trc);
void traceWeakNativeIterators(JSTracer* trc);
void addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf,
@ -518,7 +518,7 @@ class JS::Realm : public JS::shadow::Realm {
*/
void finishRoots();
void sweepAfterMinorGC();
void sweepAfterMinorGC(JSTracer* trc);
void traceWeakDebugEnvironmentEdges(JSTracer* trc);
void traceWeakObjectRealm(JSTracer* trc);
void traceWeakRegExps(JSTracer* trc);

Просмотреть файл

@ -82,7 +82,7 @@ The 'column-rule-image-source' and 'row-rule-image-source' Properties {#column-r
Animation type: discrete
</pre>
These properties specifies an <<image>> to use in place of the rendering specified
These properties specify an <<image>> to use in place of the rendering specified
by the ''column-rule-style''/''row-rule-style'' properties.
As for borders, a rule image is not rendered when the corresponding ''column-rule-style''/''row-rule-style'' is ''column-rule-style/none''.
@ -101,7 +101,7 @@ The 'column-rule-image-slice' and 'row-rule-image-slice' Properties {#column-rul
Animation type: discrete
</pre>
These properties specifies inward offsets from the top and bottom edges of the image,
These properties specify inward offsets from the top and bottom edges of the image,
dividing it into three regions: two edge areas and one middle area.
When two values are specified, they set the offsets on the top and bottom sides in
@ -141,7 +141,7 @@ The 'column-rule-image-repeat' and 'row-rule-image-repeat' Properties {#column-r
Animation type: discrete
</pre>
These properties specifies how the middle part of a sliced rule image is scaled and tiled.
These properties specify how the middle part of a sliced rule image is scaled and tiled.
Values have the following meanings:
<dl dfn-for=column-rule-image-repeat dfn-type=value>
@ -530,14 +530,14 @@ The 'column-rule-align' and 'row-rule-align' Properties {#column-rule-align}
These properties specify the start/end attachment point of the [=rule containing rectangle=]
in the [=longitudinal axis=]. The start value is specified first, the end value second.
If only one value is specified it is used for both start and end.
These properties are only used for interior the edges. The '*-rule-edge-align' properties
described below specifies the alignment on the outer edges. The initial value, ''column-rule-align/gap'',
These properties are only used for interior edges. The '*-rule-edge-align' properties
described below specify the alignment on the outer edges. The initial value, ''column-rule-align/gap'',
means that, by default, a rule will stretch its longitudinal size to fill the space
from the end of the gap "above" to the start of the gap "below" ("above" meaning the gap
in the orthogonal axis on the rule's start side).
<aside class=example>
This <a href="examples/grid-align-001.html">example</a> illutrates a few alignment options.
This <a href="examples/grid-align-001.html">example</a> illustrates a few alignment options.
Note that the row rules all have a 1px longitudinal inset
to separate the individual rule segments. (''column-rule-align/rule-center'',
for example, would otherwise look like one long rule)
@ -583,7 +583,7 @@ The 'column-rule-edge-align' and 'row-rule-edge-align' Properties {#column-rule-
''column-rule-align'') since there are no rules in the edge gutters.
Thge figure below illustrates the alignment values.
The figure below illustrates the alignment values.
The red values are used for the top column rule's start edge and the yellow
values are used for its end edge. The yellow values are also used for the bottom
column rule's start edge. However, in this

Просмотреть файл

@ -10,7 +10,6 @@
<link href="../csslogo.ico" rel="shortcut icon" type="image/x-icon">
<link href="https://www.w3.org/StyleSheets/TR/2016/W3C-ED" rel="stylesheet" type="text/css">
<meta content="Bikeshed version d7036035b, updated Fri Oct 8 17:07:11 2021 -0700" name="generator">
<meta content="8e27fe76645b992566c8fe35bed8d6a37b0ecdb8" name="document-revision">
<style>/* style-autolinks */
.css.css, .property.property, .descriptor.descriptor {
@ -491,7 +490,7 @@ dd:not(:last-child) > .wpt-tests-block:not([open]):last-child {
display: grid;
margin: 0;
padding: 0;
grid-template-columns: 1fr auto auto;
grid-template-columns: 1fr max-content auto auto;
grid-column-gap: .5em;
}
.wpt-tests-block hr:last-child {
@ -505,8 +504,21 @@ dd:not(:last-child) > .wpt-tests-block:not([open]):last-child {
border: none;
}
.wpt-test > .wpt-name { grid-column: 1; }
.wpt-test > .wpt-live { grid-column: 2; }
.wpt-test > .wpt-source { grid-column: 3; }
.wpt-test > .wpt-results { grid-column: 2; }
.wpt-test > .wpt-live { grid-column: 3; }
.wpt-test > .wpt-source { grid-column: 4; }
.wpt-test > .wpt-results {
display: flex;
gap: .1em;
}
.wpt-test .wpt-result {
display: inline-block;
height: 1em;
width: 1em;
border-radius: 50%;
position: relative;
}
</style>
<style>/* style-darkmode */
@ -702,7 +714,7 @@ dd:not(:last-child) > .wpt-tests-block:not([open]):last-child {
<div class="head">
<p data-fill-with="logo"><a class="logo" href="https://www.w3.org/"> <img alt="W3C" height="48" src="https://www.w3.org/StyleSheets/TR/2016/logos/W3C" width="72"> </a> </p>
<h1 class="p-name no-ref" id="title">CSS Gap Decorations</h1>
<h2 class="no-num no-toc no-ref heading settled" id="profile-and-date"><span class="content">Editors Draft, <time class="dt-updated" datetime="2021-10-14">14 October 2021</time></span></h2>
<h2 class="no-num no-toc no-ref heading settled" id="profile-and-date"><span class="content">Editors Draft, <time class="dt-updated" datetime="2021-10-19">19 October 2021</time></span></h2>
<details>
<summary>Specification Metadata</summary>
<div data-fill-with="spec-metadata">
@ -893,7 +905,7 @@ on screen, on paper, etc.
<th><a href="https://www.w3.org/TR/web-animations/#animation-type">Animation type:</a>
<td>discrete
</table>
<p>These properties specifies an <a class="production css" data-link-type="type" href="https://drafts.csswg.org/css-images-3/#typedef-image" id="ref-for-typedef-image②">&lt;image></a> to use in place of the rendering specified
<p>These properties specify an <a class="production css" data-link-type="type" href="https://drafts.csswg.org/css-images-3/#typedef-image" id="ref-for-typedef-image②">&lt;image></a> to use in place of the rendering specified
by the <span class="css">column-rule-style</span>/<span class="css">row-rule-style</span> properties.</p>
<p>As for borders, a rule image is not rendered when the corresponding <span class="css">column-rule-style</span>/<span class="css">row-rule-style</span> is <span class="css">none</span>.</p>
<h3 class="heading settled" data-level="2.2" id="column-rule-image-slice"><span class="secno">2.2. </span><span class="content">The <a class="property" data-link-type="propdesc" href="#propdef-column-rule-image-slice" id="ref-for-propdef-column-rule-image-slice">column-rule-image-slice</a> and <a class="property" data-link-type="propdesc" href="#propdef-row-rule-image-slice" id="ref-for-propdef-row-rule-image-slice">row-rule-image-slice</a> Properties</span><a class="self-link" href="#column-rule-image-slice"></a></h3>
@ -927,7 +939,7 @@ on screen, on paper, etc.
<th><a href="https://www.w3.org/TR/web-animations/#animation-type">Animation type:</a>
<td>discrete
</table>
<p>These properties specifies inward offsets from the top and bottom edges of the image,
<p>These properties specify inward offsets from the top and bottom edges of the image,
dividing it into three regions: two edge areas and one middle area.</p>
<p>When two values are specified, they set the offsets on the top and bottom sides in
that order. If the bottom is missing, it is the same as the top.</p>
@ -975,7 +987,7 @@ on screen, on paper, etc.
<th><a href="https://www.w3.org/TR/web-animations/#animation-type">Animation type:</a>
<td>discrete
</table>
<p>These properties specifies how the middle part of a sliced rule image is scaled and tiled.
<p>These properties specify how the middle part of a sliced rule image is scaled and tiled.
Values have the following meanings:</p>
<dl>
<dt><dfn class="css" data-dfn-for="column-rule-image-repeat" data-dfn-type="value" data-export id="valdef-column-rule-image-repeat-stretch">stretch<a class="self-link" href="#valdef-column-rule-image-repeat-stretch"></a></dfn>
@ -1028,7 +1040,7 @@ on screen, on paper, etc.
<a class="self-link" href="#example-c9ee9e2e"></a> This <a href="examples/grid-image-001.html">example</a> demonstrates the new
rule image properties presented above in a grid layout with spanning elements.
<figure>
<img height="488" src="media/grid-image-001.png" width="608">
<img src="media/grid-image-001.png">
<figcaption> Example of image rules. </figcaption>
</figure>
</aside>
@ -1043,7 +1055,7 @@ on screen, on paper, etc.
<aside class="example" id="example-746571da">
<a class="self-link" href="#example-746571da"></a> This is a similar <a href="examples/grid-gradient-001.html">example</a> using gradients.
<figure>
<img height="489" src="media/grid-gradient-001.png" width="608">
<img src="media/grid-gradient-001.png">
<figcaption> Example of gradient rules. </figcaption>
</figure>
</aside>
@ -1052,7 +1064,7 @@ on screen, on paper, etc.
support for a use case mentioned in <a href="https://github.com/w3c/csswg-drafts/issues/2748#issuecomment-621983931">issue #2748</a>.
Its a coupon with a perforation rendered by a semi-transparent rule image between two flex items.
<figure>
<img height="108" src="media/flexbox-coupon-rule.png" width="253">
<img src="media/flexbox-coupon-rule.png">
<figcaption> An example of a semi-transparent column rule image. </figcaption>
</figure>
</aside>
@ -1218,7 +1230,7 @@ on screen, on paper, etc.
insets are greater than the <a data-link-type="dfn" href="#rule-containing-rectangle①" id="ref-for-rule-containing-rectangle①⑦">rule containing rectangles</a> size. Theres still
a zero-sized column rule there, which the row rule (purple) aligns to.
<figure>
<img height="651" src="media/grid-lateral-001.png" width="997">
<img src="media/grid-lateral-001.png">
<figcaption> Examples of lateral rule sizing with various inset values. </figcaption>
</figure>
</aside>
@ -1325,7 +1337,7 @@ on screen, on paper, etc.
<a class="self-link" href="#example-0ce2b88c"></a> Heres a few simple <a href="examples/grid-longitudinal-001.html">examples</a> of
the rule sizing and inset properties.
<figure>
<img height="648" src="media/grid-longitudinal-001.png" width="591">
<img src="media/grid-longitudinal-001.png">
<figcaption> Examples of rule sizing and inset values. </figcaption>
</figure>
</aside>
@ -1634,13 +1646,13 @@ on screen, on paper, etc.
</table>
<p>These properties specify the start/end attachment point of the <a data-link-type="dfn" href="#rule-containing-rectangle①" id="ref-for-rule-containing-rectangle①①②">rule containing rectangle</a> in the <a data-link-type="dfn" href="#longitudinal-axis" id="ref-for-longitudinal-axis④">longitudinal axis</a>. The start value is specified first, the end value second.
If only one value is specified it is used for both start and end.
These properties are only used for interior the edges. The <a class="property" data-link-type="propdesc">*-rule-edge-align</a> properties
described below specifies the alignment on the outer edges. The initial value, <span class="css">gap</span>,
These properties are only used for interior edges. The <a class="property" data-link-type="propdesc">*-rule-edge-align</a> properties
described below specify the alignment on the outer edges. The initial value, <span class="css">gap</span>,
means that, by default, a rule will stretch its longitudinal size to fill the space
from the end of the gap "above" to the start of the gap "below" ("above" meaning the gap
in the orthogonal axis on the rules start side).</p>
<aside class="example" id="example-07730548">
<a class="self-link" href="#example-07730548"></a> This <a href="examples/grid-align-001.html">example</a> illutrates a few alignment options.
<aside class="example" id="example-d52ec54e">
<a class="self-link" href="#example-d52ec54e"></a> This <a href="examples/grid-align-001.html">example</a> illustrates a few alignment options.
Note that the row rules all have a 1px longitudinal inset
to separate the individual rule segments. (<span class="css">rule-center</span>,
for example, would otherwise look like one long rule)
@ -1648,7 +1660,7 @@ on screen, on paper, etc.
the gap (to separate the <span class="css">rule-center</span> position
from the <span class="css">gap-center</span> position)</p>
<figure>
<img height="596" src="media/grid-align-001.png" width="692">
<img src="media/grid-align-001.png">
<figcaption> Example of <a class="property" data-link-type="propdesc" href="#propdef-row-rule-align" id="ref-for-propdef-row-rule-align①">row-rule-align</a> in a grid container. </figcaption>
</figure>
<p>You might be wondering if theres a bug in the bottom-right example.
@ -1692,7 +1704,7 @@ on screen, on paper, etc.
is used for both start and end. (Attachment points for the interior rule edges are
specified with the <a href="#column-rule-align"><a class="property" data-link-type="propdesc">*-rule-align</a></a> properties above.)</p>
<p class="note" role="note"><span>Note:</span> The <span class="css">rule</span>/<span class="css">rule-center</span>/<span class="css">rule-over</span> keywords are omitted here (compared with <span class="css">column-rule-align</span>) since there are no rules in the edge gutters.</p>
<p>Thge figure below illustrates the alignment values.
<p>The figure below illustrates the alignment values.
The red values are used for the top column rules start edge and the yellow
values are used for its end edge. The yellow values are also used for the bottom
column rules start edge. However, in this
@ -1705,7 +1717,7 @@ on screen, on paper, etc.
attachment points should be used. <span class="css">column-rule-edge-align</span> the yellow colored
ones (and all other interior edges if there were more rows).</p>
<figure>
<img height="585" src="media/rule-alignment-values.png" width="621">
<img src="media/rule-alignment-values.png">
<figcaption> Illustration of rule alignment values. </figcaption>
</figure>
<p>Heres the rule styling used for the above example:</p>
@ -1775,7 +1787,7 @@ on screen, on paper, etc.
<aside class="example" id="example-9ccc5773">
<a class="self-link" href="#example-9ccc5773"></a>
<figure>
<img height="228" src="media/grid-segment-001.png" width="312">
<img src="media/grid-segment-001.png">
<figcaption> Example of column and row rules with <span class="css">segment</span> extent in a grid container. </figcaption>
</figure>
</aside>
@ -1787,7 +1799,7 @@ on screen, on paper, etc.
<aside class="example" id="example-9818bbbb">
<a class="self-link" href="#example-9818bbbb"></a>
<figure>
<img height="228" src="media/grid-segment-002.png" width="608">
<img src="media/grid-segment-002.png">
<figcaption> Example of column and row rules with in a grid container with <a data-link-type="dfn" href="https://drafts.csswg.org/css-grid-2/#collapsed-track" id="ref-for-collapsed-track①">collapsed tracks</a>. </figcaption>
</figure>
</aside>
@ -1852,7 +1864,7 @@ on screen, on paper, etc.
They are both forced to span into the cell in row 2, column 4 to illustrate what happens
when items span like this.
<figure>
<img height="811" src="media/grid-extent-001.png" width="805">
<img src="media/grid-extent-001.png">
<figcaption> Examples of <span class="css">row-rule-extent</span> in a grid container. </figcaption>
</figure>
</aside>
@ -1879,7 +1891,7 @@ on screen, on paper, etc.
the <a class="css" data-link-type="propdesc" href="#propdef-row-rule-align" id="ref-for-propdef-row-rule-align②">row-rule-align: rule</a> in the subgrid. The subgrid is in fact completely
unaware of any parent rules.</p>
<figure>
<img height="256" src="media/grid-subgrid-001.png" width="826">
<img src="media/grid-subgrid-001.png">
<figcaption> Example of gap rules in a subgrid. </figcaption>
</figure>
</aside>
@ -1896,7 +1908,7 @@ on screen, on paper, etc.
variations of rules in a masonry grid layout. All the grids have <a class="css" data-link-type="propdesc" href="#propdef-column-rule-edge-align" id="ref-for-propdef-column-rule-edge-align①">column-rule-edge-align: gap-over</a> to extend the edge rules out to
the content-box edge.
<figure>
<img height="785" src="media/grid-masonry-001.png" width="691">
<img src="media/grid-masonry-001.png">
<figcaption> Example of gap rules in a masonry grid. </figcaption>
</figure>
</aside>
@ -1904,12 +1916,12 @@ on screen, on paper, etc.
<a class="self-link" href="#example-a0ffc13c"></a> This <a href="examples/grid-masonry-002.html">example</a> illustrates
some of the <a class="css" data-link-type="propdesc" href="#propdef-column-rule-extent" id="ref-for-propdef-column-rule-extent①">column-rule-extent: all-*</a> values.
<figure>
<img height="772" src="media/grid-masonry-002.png" width="730">
<img src="media/grid-masonry-002.png">
<figcaption> Example of gap rules in a masonry grid. </figcaption>
</figure>
</aside>
<p class="issue" id="issue-b6f1d65c"><a class="self-link" href="#issue-b6f1d65c"></a> TODO: add definition list and algorithm here...</p>
<p class="issue" id="issue-3e9abc31"><a class="self-link" href="#issue-3e9abc31"></a> is it useful to be able to create a rule extent for the <i>intersection</i> or <i>union</i> between two tracks, like so: <img height="435" src="media/masonry-all-shorter.png" style="display:block" width="701">Its pretty easy to implement, fwiw... (I accidently implemented <span class="css">short</span>/<span class="css">long</span> like that before I realized it was inconsistent with how they work elsewhere). I think its a case that is unique to a masonry axis though, at least <i>currently</i>...</p>
<p class="issue" id="issue-3e9abc31"><a class="self-link" href="#issue-3e9abc31"></a> is it useful to be able to create a rule extent for the <i>intersection</i> or <i>union</i> between two tracks, like so: <img src="media/masonry-all-shorter.png" style="display:block">Its pretty easy to implement, fwiw... (I accidently implemented <span class="css">short</span>/<span class="css">long</span> like that before I realized it was inconsistent with how they work elsewhere). I think its a case that is unique to a masonry axis though, at least <i>currently</i>...</p>
<h4 class="heading settled" data-level="6.1.2" id="rule-extent-flexbox"><span class="secno">6.1.2. </span><span class="content">Flexbox Containers</span><a class="self-link" href="#rule-extent-flexbox"></a></h4>
<p>In a <a href="https://drafts.csswg.org/css-flexbox/#valdef-flex-direction-row">row-oriented flexbox container</a>,
the <span class="css">row-rule-*</span> properties creates rules between flex lines,
@ -1981,23 +1993,23 @@ on screen, on paper, etc.
<aside class="example" id="example-374fda56">
<a class="self-link" href="#example-374fda56"></a> Here are a few examples to illustrate the <span class="css">row-rule-extent</span> values.
<figure>
<img height="194" src="media/flexbox-extent-start-001.png" width="314">
<img src="media/flexbox-extent-start-001.png">
<figcaption> A <a class="css" data-link-type="propdesc" href="#propdef-row-rule-extent" id="ref-for-propdef-row-rule-extent①">row-rule-extent: start</a> <a href="examples/flexbox-extent-start-001.html">example</a>. </figcaption>
</figure>
<figure>
<img height="194" src="media/flexbox-extent-end-001.png" width="314">
<img src="media/flexbox-extent-end-001.png">
<figcaption> A <a class="css" data-link-type="propdesc" href="#propdef-row-rule-extent" id="ref-for-propdef-row-rule-extent②">row-rule-extent: end</a> <a href="examples/flexbox-extent-end-001.html">example</a>. </figcaption>
</figure>
<figure>
<img height="194" src="media/flexbox-extent-long-001.png" width="314">
<img src="media/flexbox-extent-long-001.png">
<figcaption> A <a class="css" data-link-type="propdesc" href="#propdef-row-rule-extent" id="ref-for-propdef-row-rule-extent③">row-rule-extent: long</a> <a href="examples/flexbox-extent-long-001.html">example</a>. </figcaption>
</figure>
<figure>
<img height="194" src="media/flexbox-extent-all-short-001.png" width="314">
<img src="media/flexbox-extent-all-short-001.png">
<figcaption> A <a class="css" data-link-type="propdesc" href="#propdef-row-rule-extent" id="ref-for-propdef-row-rule-extent④">row-rule-extent: all-short</a> <a href="examples/flexbox-extent-all-short-001.html">example</a>. </figcaption>
</figure>
<figure>
<img height="194" src="media/flexbox-extent-all-long-001.png" width="314">
<img src="media/flexbox-extent-all-long-001.png">
<figcaption> A <a class="css" data-link-type="propdesc" href="#propdef-row-rule-extent" id="ref-for-propdef-row-rule-extent⑤">row-rule-extent: all-long</a> <a href="examples/flexbox-extent-all-long-001.html">example</a>. </figcaption>
</figure>
</aside>
@ -2007,7 +2019,7 @@ on screen, on paper, etc.
used and the gaps arent aligned. (The flex items are semi-transparent
to show the column rules underneath).
<figure>
<img height="194" src="media/flexbox-extent-all-long-allow-overlap-001.png" width="314">
<img src="media/flexbox-extent-all-long-allow-overlap-001.png">
<figcaption> A <a class="css" data-link-type="propdesc" href="#propdef-column-rule-extent" id="ref-for-propdef-column-rule-extent③">column-rule-extent: all-long allow-overlap</a> example. </figcaption>
</figure>
</aside>
@ -2022,7 +2034,7 @@ on screen, on paper, etc.
<aside class="example" id="example-5015561d">
<a class="self-link" href="#example-5015561d"></a> Note, column 2 is collapsed in this example.
<figure>
<img height="346" src="media/table-rules-001.png" width="818">
<img src="media/table-rules-001.png">
<figcaption> An <a href="examples/table-rules-001.html">example</a> of table rules. </figcaption>
</figure>
</aside>
@ -2040,7 +2052,7 @@ on screen, on paper, etc.
table rows and cells. And also what happens when the table rules from
the last example is also applied.
<figure>
<img height="784" src="media/table-row-group-rules-001.png" width="879">
<img src="media/table-row-group-rules-001.png">
<figcaption> Example of table row and cell rules. </figcaption>
</figure>
</aside>
@ -2058,7 +2070,7 @@ on screen, on paper, etc.
<a class="self-link" href="#example-b0c3427d"></a> This <a href="examples/multicol-row-rule-001.html">example</a> illustrates rules in
a multi-column container.
<figure>
<img height="854" src="media/multicol-row-rule-001.png" width="827">
<img src="media/multicol-row-rule-001.png">
<figcaption> Example of column and row rules in a multi-column. </figcaption>
</figure>
</aside>
@ -2067,7 +2079,7 @@ on screen, on paper, etc.
'column-span: <a class="production css" data-link-type="type" href="https://drafts.csswg.org/css-values-4/#integer-value" id="ref-for-integer-value">&lt;integer></a>' some time in the future,
this is how row rules will work:
<figure>
<img height="195" src="media/multicol-colspan-2.png" width="808">
<img src="media/multicol-colspan-2.png">
<figcaption> Example of <a class="css" data-link-type="propdesc" href="https://drafts.csswg.org/css-multicol-2/#propdef-column-span" id="ref-for-propdef-column-span">column-span: 2</a> in a multi-column with column and row rules. </figcaption>
</figure>
</aside>
@ -2089,7 +2101,7 @@ on screen, on paper, etc.
<c- k>row-rule-lateral-inset-start</c-><c- p>:</c-> <c- m>20</c-><c- k>px</c-><c- p>;</c->
</pre>
<figure>
<img height="584" src="media/rule-containing-rectangle.png" width="620">
<img src="media/rule-containing-rectangle.png">
<figcaption> The Rule Containing Rectangle </figcaption>
</figure>
<p>Note that the <a data-link-type="dfn" href="#rule-containing-rectangle①" id="ref-for-rule-containing-rectangle①①⑦">rule containing rectangle</a> extends to the start of the black horizontal rule, which has a <span class="css">20px</span> lateral inset (making it non-centered). We align to its start with <a class="css" data-link-type="propdesc" href="#propdef-column-rule-align" id="ref-for-propdef-column-rule-align②">column-rule-align: rule</a>. From there,
@ -2787,7 +2799,7 @@ on screen, on paper, etc.
<dt id="biblio-css-box-4">[CSS-BOX-4]
<dd>Elika Etemad. <a href="https://www.w3.org/TR/css-box-4/"><cite>CSS Box Model Module Level 4</cite></a>. 21 April 2020. WD. URL: <a href="https://www.w3.org/TR/css-box-4/">https://www.w3.org/TR/css-box-4/</a>
<dt id="biblio-css-cascade-5">[CSS-CASCADE-5]
<dd>Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. <a href="https://www.w3.org/TR/css-cascade-5/"><cite>CSS Cascading and Inheritance Level 5</cite></a>. 29 August 2021. WD. URL: <a href="https://www.w3.org/TR/css-cascade-5/">https://www.w3.org/TR/css-cascade-5/</a>
<dd>Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. <a href="https://www.w3.org/TR/css-cascade-5/"><cite>CSS Cascading and Inheritance Level 5</cite></a>. 15 October 2021. WD. URL: <a href="https://www.w3.org/TR/css-cascade-5/">https://www.w3.org/TR/css-cascade-5/</a>
<dt id="biblio-css-color-4">[CSS-COLOR-4]
<dd>Tab Atkins Jr.; Chris Lilley. <a href="https://www.w3.org/TR/css-color-4/"><cite>CSS Color Module Level 4</cite></a>. 1 June 2021. WD. URL: <a href="https://www.w3.org/TR/css-color-4/">https://www.w3.org/TR/css-color-4/</a>
<dt id="biblio-css-display-3">[CSS-DISPLAY-3]
@ -2811,7 +2823,7 @@ on screen, on paper, etc.
<dt id="biblio-css-tables-3">[CSS-TABLES-3]
<dd>François Remy; Greg Whitworth; David Baron. <a href="https://www.w3.org/TR/css-tables-3/"><cite>CSS Table Module Level 3</cite></a>. 27 July 2019. WD. URL: <a href="https://www.w3.org/TR/css-tables-3/">https://www.w3.org/TR/css-tables-3/</a>
<dt id="biblio-css-values-4">[CSS-VALUES-4]
<dd>Tab Atkins Jr.; Elika Etemad. <a href="https://www.w3.org/TR/css-values-4/"><cite>CSS Values and Units Module Level 4</cite></a>. 30 September 2021. WD. URL: <a href="https://www.w3.org/TR/css-values-4/">https://www.w3.org/TR/css-values-4/</a>
<dd>Tab Atkins Jr.; Elika Etemad. <a href="https://www.w3.org/TR/css-values-4/"><cite>CSS Values and Units Module Level 4</cite></a>. 16 October 2021. WD. URL: <a href="https://www.w3.org/TR/css-values-4/">https://www.w3.org/TR/css-values-4/</a>
<dt id="biblio-css-writing-modes-4">[CSS-WRITING-MODES-4]
<dd>Elika Etemad; Koji Ishii. <a href="https://www.w3.org/TR/css-writing-modes-4/"><cite>CSS Writing Modes Level 4</cite></a>. 30 July 2019. CR. URL: <a href="https://www.w3.org/TR/css-writing-modes-4/">https://www.w3.org/TR/css-writing-modes-4/</a>
<dt id="biblio-rfc2119">[RFC2119]
@ -3231,7 +3243,7 @@ on screen, on paper, etc.
e.g. 'padding | padding-center | padding-over | border...' <a class="issue-return" href="#issue-13842b6f" title="Jump to section"></a></div>
<div class="issue"> perhaps make <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/css-box-4/#valdef-margin-trim-all">all</a> a separate keyword? like so: <span class="css">[segment | [[start | end | short | long] all?] ] allow-overlap?</span> <a class="issue-return" href="#issue-70dc1ba4" title="Jump to section"></a></div>
<div class="issue"> TODO: add definition list and algorithm here... <a class="issue-return" href="#issue-b6f1d65c" title="Jump to section"></a></div>
<div class="issue"> is it useful to be able to create a rule extent for the <i>intersection</i> or <i>union</i> between two tracks, like so: <img height="435" src="media/masonry-all-shorter.png" style="display:block" width="701">Its pretty easy to implement, fwiw... (I accidently implemented <span class="css">short</span>/<span class="css">long</span> like that before I realized it was inconsistent with how they work elsewhere). I think its a case that is unique to a masonry axis though, at least <i>currently</i>... <a class="issue-return" href="#issue-3e9abc31" title="Jump to section"></a></div>
<div class="issue"> is it useful to be able to create a rule extent for the <i>intersection</i> or <i>union</i> between two tracks, like so: <img src="media/masonry-all-shorter.png" style="display:block">Its pretty easy to implement, fwiw... (I accidently implemented <span class="css">short</span>/<span class="css">long</span> like that before I realized it was inconsistent with how they work elsewhere). I think its a case that is unique to a masonry axis though, at least <i>currently</i>... <a class="issue-return" href="#issue-3e9abc31" title="Jump to section"></a></div>
<div class="issue"> sort out if non-collapsed column-groups that only contains collapsed columns should generate rules, ditto row-groups/rows <a class="issue-return" href="#issue-96acb267" title="Jump to section"></a></div>
<div class="issue"> this proposal makes the assumption that the parallel proposal that <span class="css">row-gap</span> should apply to multi-column containers is also adopted (issue #XXX). <a class="issue-return" href="#issue-b4c69802" title="Jump to section"></a></div>
</div>
@ -3611,4 +3623,6 @@ document.body.addEventListener("click", function(e) {
}
});
</script>
<script>/* script-wpt */
</script>

Просмотреть файл

@ -274,6 +274,14 @@ void nsMenuPopupFrame::EnsureWidget(bool aRecreate) {
}
}
static Maybe<ColorScheme> GetWidgetColorScheme(const nsMenuPopupFrame* aFrame) {
const auto& scheme = aFrame->StyleUI()->mColorScheme.bits;
if (!scheme) {
return Nothing();
}
return Some(LookAndFeel::ColorSchemeForFrame(aFrame));
}
nsresult nsMenuPopupFrame::CreateWidgetForView(nsView* aView) {
// Create a widget for ourselves.
nsWidgetInitData widgetData;
@ -357,7 +365,7 @@ nsresult nsMenuPopupFrame::CreateWidgetForView(nsView* aView) {
widget->SetWindowShadowStyle(GetShadowStyle());
widget->SetWindowOpacity(StyleUIReset()->mWindowOpacity);
widget->SetWindowTransform(ComputeWidgetTransform());
widget->SetColorScheme(LookAndFeel::ColorSchemeForFrame(this));
widget->SetColorScheme(GetWidgetColorScheme(this));
// most popups don't have a title so avoid setting the title if there isn't
// one
@ -507,7 +515,7 @@ void nsMenuPopupFrame::DidSetComputedStyle(ComputedStyle* aOldStyle) {
if (StyleUI()->mColorScheme != aOldStyle->StyleUI()->mColorScheme) {
if (nsIWidget* widget = GetWidget()) {
widget->SetColorScheme(LookAndFeel::ColorSchemeForFrame(this));
widget->SetColorScheme(GetWidgetColorScheme(this));
}
}

Просмотреть файл

@ -5068,6 +5068,22 @@
value: 0
mirror: always
# SwapInterval
- name: gfx.swap-interval.glx
type: RelaxedAtomicBool
value: true
mirror: always
- name: gfx.swap-interval.egl
type: RelaxedAtomicBool
mirror: always
#ifdef MOZ_WIDGET_ANDROID
value: true
#else
value: false
#endif
# Log severe performance warnings to the error console and profiles.
# This should be use to quickly find which slow paths are used by test cases.
- name: gfx.perf-warnings.enabled
@ -6528,7 +6544,7 @@
- name: layers.iosurfaceimage.use-nv12
type: bool
value: false
value: true
mirror: once
#---------------------------------------------------------------------------
@ -10258,11 +10274,6 @@
# Prefs starting with "privacy."
#---------------------------------------------------------------------------
- name: privacy.file_unique_origin
type: bool
value: true
mirror: always
- name: privacy.fuzzyfox.clockgrainus
type: RelaxedAtomicUint32
value: 100

Просмотреть файл

@ -121,8 +121,7 @@ nsresult BackgroundFileSaver::Init() {
NS_IMETHODIMP
BackgroundFileSaver::GetObserver(nsIBackgroundFileSaverObserver** aObserver) {
NS_ENSURE_ARG_POINTER(aObserver);
*aObserver = mObserver;
NS_IF_ADDREF(*aObserver);
*aObserver = do_AddRef(mObserver).take();
return NS_OK;
}

Просмотреть файл

@ -815,7 +815,7 @@ already_AddRefed<nsILoadInfo> LoadInfo::CloneForNewRequest() const {
NS_IMETHODIMP
LoadInfo::GetLoadingPrincipal(nsIPrincipal** aLoadingPrincipal) {
NS_IF_ADDREF(*aLoadingPrincipal = mLoadingPrincipal);
*aLoadingPrincipal = do_AddRef(mLoadingPrincipal).take();
return NS_OK;
}
@ -833,7 +833,7 @@ nsIPrincipal* LoadInfo::TriggeringPrincipal() { return mTriggeringPrincipal; }
NS_IMETHODIMP
LoadInfo::GetPrincipalToInherit(nsIPrincipal** aPrincipalToInherit) {
NS_IF_ADDREF(*aPrincipalToInherit = mPrincipalToInherit);
*aPrincipalToInherit = do_AddRef(mPrincipalToInherit).take();
return NS_OK;
}
@ -1752,7 +1752,7 @@ LoadInfo::GetIsFromObjectOrEmbed(bool* aIsFromObjectOrEmbed) {
NS_IMETHODIMP
LoadInfo::GetResultPrincipalURI(nsIURI** aURI) {
NS_IF_ADDREF(*aURI = mResultPrincipalURI);
*aURI = do_AddRef(mResultPrincipalURI).take();
return NS_OK;
}
@ -1893,7 +1893,7 @@ PerformanceStorage* LoadInfo::GetPerformanceStorage() {
NS_IMETHODIMP
LoadInfo::GetCspEventListener(nsICSPEventListener** aCSPEventListener) {
NS_IF_ADDREF(*aCSPEventListener = mCSPEventListener);
*aCSPEventListener = do_AddRef(mCSPEventListener).take();
return NS_OK;
}

Просмотреть файл

@ -134,8 +134,7 @@ TLSServerSocket::GetServerCert(nsIX509Cert** aCert) {
if (NS_WARN_IF(!aCert)) {
return NS_ERROR_INVALID_POINTER;
}
*aCert = mServerCert;
NS_IF_ADDREF(*aCert);
*aCert = do_AddRef(mServerCert).take();
return NS_OK;
}
@ -305,8 +304,7 @@ TLSServerConnectionInfo::GetServerSocket(nsITLSServerSocket** aSocket) {
if (NS_WARN_IF(!aSocket)) {
return NS_ERROR_INVALID_POINTER;
}
*aSocket = mServerSocket;
NS_IF_ADDREF(*aSocket);
*aSocket = do_AddRef(mServerSocket).take();
return NS_OK;
}
@ -315,8 +313,7 @@ TLSServerConnectionInfo::GetStatus(nsITLSClientStatus** aStatus) {
if (NS_WARN_IF(!aStatus)) {
return NS_ERROR_INVALID_POINTER;
}
*aStatus = this;
NS_IF_ADDREF(*aStatus);
*aStatus = do_AddRef(this).take();
return NS_OK;
}
@ -325,8 +322,7 @@ TLSServerConnectionInfo::GetPeerCert(nsIX509Cert** aCert) {
if (NS_WARN_IF(!aCert)) {
return NS_ERROR_INVALID_POINTER;
}
*aCert = mPeerCert;
NS_IF_ADDREF(*aCert);
*aCert = do_AddRef(mPeerCert).take();
return NS_OK;
}

Просмотреть файл

@ -16,19 +16,17 @@
#include "mozilla/Atomics.h"
#include "mozilla/Preferences.h"
static nsIDNSService* sDNSService = nullptr;
static mozilla::StaticRefPtr<nsIDNSService> sDNSService;
nsresult nsDNSPrefetch::Initialize(nsIDNSService* aDNSService) {
MOZ_ASSERT(NS_IsMainThread());
NS_IF_RELEASE(sDNSService);
sDNSService = aDNSService;
NS_IF_ADDREF(sDNSService);
return NS_OK;
}
nsresult nsDNSPrefetch::Shutdown() {
NS_IF_RELEASE(sDNSService);
sDNSService = nullptr;
return NS_OK;
}

Просмотреть файл

@ -41,7 +41,7 @@ nsIncrementalStreamLoader::GetNumBytesRead(uint32_t* aNumBytes) {
/* readonly attribute nsIRequest request; */
NS_IMETHODIMP
nsIncrementalStreamLoader::GetRequest(nsIRequest** aRequest) {
NS_IF_ADDREF(*aRequest = mRequest);
*aRequest = do_AddRef(mRequest).take();
return NS_OK;
}

Просмотреть файл

@ -55,7 +55,7 @@ nsInputStreamChannel::SetURI(nsIURI* uri) {
NS_IMETHODIMP
nsInputStreamChannel::GetContentStream(nsIInputStream** stream) {
NS_IF_ADDREF(*stream = mContentStream);
*stream = do_AddRef(mContentStream).take();
return NS_OK;
}
@ -87,8 +87,7 @@ nsInputStreamChannel::GetIsSrcdocChannel(bool* aIsSrcdocChannel) {
NS_IMETHODIMP
nsInputStreamChannel::GetBaseURI(nsIURI** aBaseURI) {
*aBaseURI = mBaseURI;
NS_IF_ADDREF(*aBaseURI);
*aBaseURI = do_AddRef(mBaseURI).take();
return NS_OK;
}

Просмотреть файл

@ -256,7 +256,7 @@ NS_IMETHODIMP
nsInputStreamPump::GetLoadGroup(nsILoadGroup** aLoadGroup) {
RecursiveMutexAutoLock lock(mMutex);
NS_IF_ADDREF(*aLoadGroup = mLoadGroup);
*aLoadGroup = do_AddRef(mLoadGroup).take();
return NS_OK;
}

Просмотреть файл

@ -166,8 +166,7 @@ nsMIMEInputStream::SetData(nsIInputStream* aStream) {
NS_IMETHODIMP
nsMIMEInputStream::GetData(nsIInputStream** aStream) {
NS_ENSURE_ARG_POINTER(aStream);
*aStream = mStream;
NS_IF_ADDREF(*aStream);
*aStream = do_AddRef(mStream).take();
return NS_OK;
}

Просмотреть файл

@ -2530,37 +2530,6 @@ bool NS_RelaxStrictFileOriginPolicy(nsIURI* aTargetURI, nsIURI* aSourceURI,
return false;
}
if (!StaticPrefs::privacy_file_unique_origin()) {
//
// If the file to be loaded is in a subdirectory of the source
// (or same-dir if source is not a directory) then it will
// inherit its source principal and be scriptable by that source.
//
bool sourceIsDir;
bool allowed = false;
nsresult rv = sourceFile->IsDirectory(&sourceIsDir);
if (NS_SUCCEEDED(rv) && sourceIsDir) {
rv = sourceFile->Contains(targetFile, &allowed);
} else {
nsCOMPtr<nsIFile> sourceParent;
rv = sourceFile->GetParent(getter_AddRefs(sourceParent));
if (NS_SUCCEEDED(rv) && sourceParent) {
rv = sourceParent->Equals(targetFile, &allowed);
if (NS_FAILED(rv) || !allowed) {
rv = sourceParent->Contains(targetFile, &allowed);
} else {
MOZ_ASSERT(aAllowDirectoryTarget,
"sourceFile->Parent == targetFile, but targetFile "
"should've been disallowed if it is a directory");
}
}
}
if (NS_SUCCEEDED(rv) && allowed) {
return true;
}
}
return false;
}

Просмотреть файл

@ -29,13 +29,13 @@ nsRedirectHistoryEntry::GetRemoteAddress(nsACString& result) {
NS_IMETHODIMP
nsRedirectHistoryEntry::GetReferrerURI(nsIURI** referrer) {
NS_IF_ADDREF(*referrer = mReferrer);
*referrer = do_AddRef(mReferrer).take();
return NS_OK;
}
NS_IMETHODIMP
nsRedirectHistoryEntry::GetPrincipal(nsIPrincipal** principal) {
NS_IF_ADDREF(*principal = mPrincipal);
*principal = do_AddRef(mPrincipal).take();
return NS_OK;
}

Просмотреть файл

@ -2371,14 +2371,14 @@ nsSocketTransport::Close(nsresult reason) {
NS_IMETHODIMP
nsSocketTransport::GetSecurityInfo(nsISupports** secinfo) {
MutexAutoLock lock(mLock);
NS_IF_ADDREF(*secinfo = mSecInfo);
*secinfo = do_AddRef(mSecInfo).take();
return NS_OK;
}
NS_IMETHODIMP
nsSocketTransport::GetSecurityCallbacks(nsIInterfaceRequestor** callbacks) {
MutexAutoLock lock(mLock);
NS_IF_ADDREF(*callbacks = mCallbacks);
*callbacks = do_AddRef(mCallbacks).take();
return NS_OK;
}

Просмотреть файл

@ -205,7 +205,7 @@ nsUDPMessage::GetData(nsACString& aData) {
NS_IMETHODIMP
nsUDPMessage::GetOutputStream(nsIOutputStream** aOutputStream) {
NS_ENSURE_ARG_POINTER(aOutputStream);
NS_IF_ADDREF(*aOutputStream = mOutputStream);
*aOutputStream = do_AddRef(mOutputStream).take();
return NS_OK;
}
@ -369,7 +369,7 @@ UDPMessageProxy::GetRawData(JSContext* cx, JS::MutableHandleValue aRawData) {
NS_IMETHODIMP
UDPMessageProxy::GetOutputStream(nsIOutputStream** aOutputStream) {
NS_ENSURE_ARG_POINTER(aOutputStream);
NS_IF_ADDREF(*aOutputStream = mOutputStream);
*aOutputStream = do_AddRef(mOutputStream).take();
return NS_OK;
}

Просмотреть файл

@ -35,9 +35,9 @@ using namespace mozilla;
//----------------------------------------------------------------------------
static bool gInitialized = false;
static nsIURLParser* gNoAuthURLParser = nullptr;
static nsIURLParser* gAuthURLParser = nullptr;
static nsIURLParser* gStdURLParser = nullptr;
static StaticRefPtr<nsIURLParser> gNoAuthURLParser;
static StaticRefPtr<nsIURLParser> gAuthURLParser;
static StaticRefPtr<nsIURLParser> gStdURLParser;
static void InitGlobals() {
nsCOMPtr<nsIURLParser> parser;
@ -45,22 +45,19 @@ static void InitGlobals() {
parser = do_GetService(NS_NOAUTHURLPARSER_CONTRACTID);
NS_ASSERTION(parser, "failed getting 'noauth' url parser");
if (parser) {
gNoAuthURLParser = parser.get();
NS_ADDREF(gNoAuthURLParser);
gNoAuthURLParser = parser;
}
parser = do_GetService(NS_AUTHURLPARSER_CONTRACTID);
NS_ASSERTION(parser, "failed getting 'auth' url parser");
if (parser) {
gAuthURLParser = parser.get();
NS_ADDREF(gAuthURLParser);
gAuthURLParser = parser;
}
parser = do_GetService(NS_STDURLPARSER_CONTRACTID);
NS_ASSERTION(parser, "failed getting 'std' url parser");
if (parser) {
gStdURLParser = parser.get();
NS_ADDREF(gStdURLParser);
gStdURLParser = parser;
}
gInitialized = true;
@ -68,11 +65,11 @@ static void InitGlobals() {
void net_ShutdownURLHelper() {
if (gInitialized) {
NS_IF_RELEASE(gNoAuthURLParser);
NS_IF_RELEASE(gAuthURLParser);
NS_IF_RELEASE(gStdURLParser);
gInitialized = false;
}
gNoAuthURLParser = nullptr;
gAuthURLParser = nullptr;
gStdURLParser = nullptr;
}
//----------------------------------------------------------------------------

Просмотреть файл

@ -1325,7 +1325,7 @@ nsresult CacheEntry::GetSecurityInfo(nsISupports** aSecurityInfo) {
{
mozilla::MutexAutoLock lock(mLock);
if (mSecurityInfoLoaded) {
NS_IF_ADDREF(*aSecurityInfo = mSecurityInfo);
*aSecurityInfo = do_AddRef(mSecurityInfo).take();
return NS_OK;
}
}
@ -1350,7 +1350,7 @@ nsresult CacheEntry::GetSecurityInfo(nsISupports** aSecurityInfo) {
mSecurityInfo.swap(secInfo);
mSecurityInfoLoaded = true;
NS_IF_ADDREF(*aSecurityInfo = mSecurityInfo);
*aSecurityInfo = do_AddRef(mSecurityInfo).take();
}
return NS_OK;

Просмотреть файл

@ -842,7 +842,13 @@ gov.cu
inf.cu
// cv : https://en.wikipedia.org/wiki/.cv
// cv : http://www.dns.cv/tldcv_portal/do?com=DS;5446457100;111;+PAGE(4000018)+K-CAT-CODIGO(RDOM)+RCNT(100); <- registration rules
cv
com.cv
edu.cv
int.cv
nome.cv
org.cv
// cw : http://www.una.cw/cw_registry/
// Confirmed by registry <registry@una.net> 2013-03-26
@ -1179,6 +1185,7 @@ org.gu
web.gu
// gw : https://en.wikipedia.org/wiki/.gw
// gw : https://nic.gw/regras/
gw
// gy : https://en.wikipedia.org/wiki/.gy
@ -5853,7 +5860,7 @@ com.ps
org.ps
net.ps
// pt : http://online.dns.pt/dns/start_dns
// pt : https://www.dns.pt/en/domain/pt-terms-and-conditions-registration-rules/
pt
net.pt
gov.pt
@ -10791,6 +10798,10 @@ tele.amune.org
// Submitted by Apigee Security Team <security@apigee.com>
apigee.io
// Apphud : https://apphud.com
// Submitted by Alexander Selivanov <alex@apphud.com>
siiites.com
// Appspace : https://www.appspace.com
// Submitted by Appspace Security Team <security@appspace.com>
appspacehosted.com
@ -11665,10 +11676,6 @@ tuleap-partners.com
onred.one
staging.onred.one
// One.com: https://www.one.com/
// Submitted by Jacob Bunk Nielsen <jbn@one.com>
service.one
// EU.org https://eu.org/
// Submitted by Pierre Beyssac <hostmaster@eu.org>
eu.org
@ -12912,6 +12919,10 @@ cloudycluster.net
// Submitted by Vicary Archangel <vicary@omniwe.com>
omniwe.site
// One.com: https://www.one.com/
// Submitted by Jacob Bunk Nielsen <jbn@one.com>
service.one
// One Fold Media : http://www.onefoldmedia.com/
// Submitted by Eddie Jones <eddie@onefoldmedia.com>
nid.io
@ -13466,6 +13477,11 @@ tabitorder.co.il
// Submitted by Bjoern Henke <dev-server@taifun-software.de>
taifun-dns.de
// Tailscale Inc. : https://www.tailscale.com
// Submitted by David Anderson <danderson@tailscale.com>
beta.tailscale.net
ts.net
// TASK geographical domains (www.task.gda.pl/uslugi/dns)
gda.pl
gdansk.pl

Просмотреть файл

@ -1467,6 +1467,21 @@ void DocumentLoadListener::SerializeRedirectData(
}
}
DocumentLoadListener::ProcessBehavior GetProcessSwitchBehavior(
Element* aBrowserElement) {
if (aBrowserElement->HasAttribute(u"maychangeremoteness"_ns)) {
return DocumentLoadListener::ProcessBehavior::PROCESS_BEHAVIOR_STANDARD;
}
nsCOMPtr<nsIBrowser> browser = aBrowserElement->AsBrowser();
bool isRemoteBrowser = false;
browser->GetIsRemoteBrowser(&isRemoteBrowser);
if (isRemoteBrowser) {
return DocumentLoadListener::ProcessBehavior::
PROCESS_BEHAVIOR_SUBFRAME_ONLY;
}
return DocumentLoadListener::ProcessBehavior::PROCESS_BEHAVIOR_DISABLED;
}
static bool ContextCanProcessSwitch(CanonicalBrowsingContext* aBrowsingContext,
WindowGlobalParent* aParentWindow) {
if (NS_WARN_IF(!aBrowsingContext)) {
@ -1507,26 +1522,20 @@ static bool ContextCanProcessSwitch(CanonicalBrowsingContext* aBrowsingContext,
return false;
}
nsIBrowser::ProcessBehavior processBehavior =
nsIBrowser::PROCESS_BEHAVIOR_DISABLED;
nsresult rv = browser->GetProcessSwitchBehavior(&processBehavior);
if (NS_FAILED(rv)) {
MOZ_ASSERT_UNREACHABLE(
"nsIBrowser::GetProcessSwitchBehavior shouldn't fail");
MOZ_LOG(gProcessIsolationLog, LogLevel::Warning,
("Process Switch Abort: failed to get process switch behavior"));
return false;
}
DocumentLoadListener::ProcessBehavior processBehavior =
GetProcessSwitchBehavior(browserElement);
// Check if the process switch we're considering is disabled by the
// <browser>'s process behavior.
if (processBehavior == nsIBrowser::PROCESS_BEHAVIOR_DISABLED) {
if (processBehavior ==
DocumentLoadListener::ProcessBehavior::PROCESS_BEHAVIOR_DISABLED) {
MOZ_LOG(gProcessIsolationLog, LogLevel::Warning,
("Process Switch Abort: switch disabled by <browser>"));
return false;
}
if (!aParentWindow &&
processBehavior == nsIBrowser::PROCESS_BEHAVIOR_SUBFRAME_ONLY) {
if (!aParentWindow && processBehavior ==
DocumentLoadListener::ProcessBehavior::
PROCESS_BEHAVIOR_SUBFRAME_ONLY) {
MOZ_LOG(gProcessIsolationLog, LogLevel::Warning,
("Process Switch Abort: toplevel switch disabled by <browser>"));
return false;

Просмотреть файл

@ -289,6 +289,25 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
bool IsDocumentLoad() const { return mIsDocumentLoad; }
// Determine what process switching behavior a browser element should have.
enum ProcessBehavior : uint8_t {
// Gecko won't automatically change which process this frame, or it's
// subframes, are loaded in.
PROCESS_BEHAVIOR_DISABLED,
// If `useRemoteTabs` is enabled, Gecko will change which process this frame
// is loaded in automatically, without calling `performProcessSwitch`.
// When `useRemoteSubframes` is enabled, subframes will change processes.
PROCESS_BEHAVIOR_STANDARD,
// Gecko won't automatically change which process this frame is loaded, but
// when `useRemoteSubframes` is enabled, subframes will change processes.
//
// NOTE: This configuration is included only for backwards compatibility,
// and will be removed, as it can easily lead to invalid behavior.
PROCESS_BEHAVIOR_SUBFRAME_ONLY,
};
protected:
virtual ~DocumentLoadListener();

Просмотреть файл

@ -513,6 +513,6 @@ nsFileChannel::SetUploadStream(nsIInputStream* stream,
NS_IMETHODIMP
nsFileChannel::GetUploadStream(nsIInputStream** result) {
NS_IF_ADDREF(*result = mUploadStream);
*result = do_AddRef(mUploadStream).take();
return NS_OK;
}

Просмотреть файл

@ -164,18 +164,7 @@ class nsGIOInputStream final : public nsIInputStream {
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINPUTSTREAM
explicit nsGIOInputStream(const nsCString& uriSpec)
: mSpec(uriSpec),
mChannel(nullptr),
mHandle(nullptr),
mStream(nullptr),
mBytesRemaining(UINT64_MAX),
mStatus(NS_OK),
mDirList(nullptr),
mDirListPtr(nullptr),
mDirBufCursor(0),
mDirOpen(false),
mMonitorMountInProgress("GIOInputStream::MountFinished") {}
explicit nsGIOInputStream(const nsCString& uriSpec) : mSpec(uriSpec) {}
void SetChannel(nsIChannel* channel) {
// We need to hold an owning reference to our channel. This is done
@ -191,7 +180,7 @@ class nsGIOInputStream final : public nsIInputStream {
// cycle since the channel likely owns this stream. This reference
// cycle is broken in our Close method.
NS_ADDREF(mChannel = channel);
mChannel = do_AddRef(channel).take();
}
void SetMountResult(MountOperationResult result, gint error_code);
@ -204,19 +193,19 @@ class nsGIOInputStream final : public nsIInputStream {
nsresult DoOpenDirectory();
nsresult DoOpenFile(GFileInfo* info);
nsCString mSpec;
nsIChannel* mChannel; // manually refcounted
GFile* mHandle;
GFileInputStream* mStream;
uint64_t mBytesRemaining;
nsresult mStatus;
GList* mDirList;
GList* mDirListPtr;
nsIChannel* mChannel{nullptr}; // manually refcounted
GFile* mHandle{nullptr};
GFileInputStream* mStream{nullptr};
uint64_t mBytesRemaining{UINT64_MAX};
nsresult mStatus{NS_OK};
GList* mDirList{nullptr};
GList* mDirListPtr{nullptr};
nsCString mDirBuf;
uint32_t mDirBufCursor;
bool mDirOpen;
uint32_t mDirBufCursor{0};
bool mDirOpen{false};
MountOperationResult mMountRes =
MountOperationResult::MOUNT_OPERATION_SUCCESS;
mozilla::Monitor mMonitorMountInProgress;
mozilla::Monitor mMonitorMountInProgress{"GIOInputStream::MountFinished"};
gint mMountErrorCode{};
};

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше