зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland. a=merge on a CLOSED TREE
This commit is contained in:
Коммит
a4361b904b
|
@ -50,7 +50,7 @@ var gIdentityHandler = {
|
|||
* RegExp used to decide if an about url should be shown as being part of
|
||||
* the browser UI.
|
||||
*/
|
||||
_secureInternalUIWhitelist: /^(?:accounts|addons|cache|config|crashes|customizing|downloads|healthreport|license|permissions|preferences|rights|searchreset|sessionrestore|support|welcomeback)(?:[?#]|$)/i,
|
||||
_secureInternalUIWhitelist: /^(?:accounts|addons|cache|config|crashes|customizing|downloads|healthreport|license|permissions|preferences|rights|sessionrestore|support|welcomeback)(?:[?#]|$)/i,
|
||||
|
||||
get _isBroken() {
|
||||
return this._state & Ci.nsIWebProgressListener.STATE_IS_BROKEN;
|
||||
|
|
|
@ -67,8 +67,6 @@ static const RedirEntry kRedirMap[] = {
|
|||
{"robots", "chrome://browser/content/aboutRobots.xhtml",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::ALLOW_SCRIPT},
|
||||
{"searchreset", "chrome://browser/content/search/searchReset.xhtml",
|
||||
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT},
|
||||
{"sessionrestore", "chrome://browser/content/aboutSessionRestore.xhtml",
|
||||
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT},
|
||||
{"welcomeback", "chrome://browser/content/aboutWelcomeBack.xhtml",
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const TELEMETRY_RESULT_ENUM = {
|
||||
RESTORED_DEFAULT: 0,
|
||||
KEPT_CURRENT: 1,
|
||||
CHANGED_ENGINE: 2,
|
||||
CLOSED_PAGE: 3,
|
||||
OPENED_SETTINGS: 4,
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
let defaultEngineParagraph = document.getElementById("defaultEngineParagraph");
|
||||
let originalDefault = Services.search.originalDefaultEngine;
|
||||
document.l10n.setAttributes(defaultEngineParagraph, "page-info-new-search-engine",
|
||||
{ searchEngine: originalDefault.name });
|
||||
let defaultEngine = document.getElementById("defaultEngine");
|
||||
defaultEngine.style.backgroundImage =
|
||||
'url("' + originalDefault.iconURI.spec + '")';
|
||||
|
||||
document.getElementById("searchResetChangeEngine").focus();
|
||||
window.addEventListener("unload", recordPageClosed);
|
||||
document.getElementById("linkSettingsPage")
|
||||
.addEventListener("click", openingSettings);
|
||||
};
|
||||
|
||||
function doSearch() {
|
||||
let queryString = "";
|
||||
let purpose = "";
|
||||
let params = window.location.href.match(/^about:searchreset\?([^#]*)/);
|
||||
if (params) {
|
||||
params = params[1].split("&");
|
||||
for (let param of params) {
|
||||
if (param.startsWith("data="))
|
||||
queryString = decodeURIComponent(param.slice(5));
|
||||
else if (param.startsWith("purpose="))
|
||||
purpose = param.slice(8);
|
||||
}
|
||||
}
|
||||
|
||||
let engine = Services.search.defaultEngine;
|
||||
let submission = engine.getSubmission(queryString, null, purpose);
|
||||
|
||||
window.removeEventListener("unload", recordPageClosed);
|
||||
|
||||
let win = window.docShell.rootTreeItem.domWindow;
|
||||
win.openTrustedLinkIn(submission.uri.spec, "current", {
|
||||
allowThirdPartyFixup: false,
|
||||
postData: submission.postData,
|
||||
});
|
||||
}
|
||||
|
||||
function openingSettings() {
|
||||
record(TELEMETRY_RESULT_ENUM.OPENED_SETTINGS);
|
||||
savePref("customized");
|
||||
window.removeEventListener("unload", recordPageClosed);
|
||||
}
|
||||
|
||||
function savePref(value) {
|
||||
const statusPref = "browser.search.reset.status";
|
||||
if (Services.prefs.getCharPref(statusPref, "") == "pending")
|
||||
Services.prefs.setCharPref(statusPref, value);
|
||||
}
|
||||
|
||||
function record(result) {
|
||||
Services.telemetry.getHistogramById("SEARCH_RESET_RESULT").add(result);
|
||||
}
|
||||
|
||||
function keepCurrentEngine() {
|
||||
// Calling the defaultEngine setter will force a correct loadPathHash to be
|
||||
// written for this engine, so that we don't prompt the user again.
|
||||
// eslint-disable-next-line no-self-assign
|
||||
Services.search.defaultEngine = Services.search.defaultEngine;
|
||||
record(TELEMETRY_RESULT_ENUM.KEPT_CURRENT);
|
||||
savePref("declined");
|
||||
doSearch();
|
||||
}
|
||||
|
||||
function changeSearchEngine() {
|
||||
let engine = Services.search.originalDefaultEngine;
|
||||
if (engine.hidden)
|
||||
engine.hidden = false;
|
||||
Services.search.defaultEngine = engine;
|
||||
|
||||
record(TELEMETRY_RESULT_ENUM.RESTORED_DEFAULT);
|
||||
savePref("accepted");
|
||||
|
||||
doSearch();
|
||||
}
|
||||
|
||||
function recordPageClosed() {
|
||||
record(TELEMETRY_RESULT_ENUM.CLOSED_PAGE);
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<head>
|
||||
<title data-l10n-id="tab-title"/>
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
href="chrome://global/skin/in-content/info-pages.css"/>
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
href="chrome://browser/skin/searchReset.css"/>
|
||||
<link rel="icon" type="image/png"
|
||||
href="chrome://browser/skin/favicon-search-16.svg"/>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/search/searchReset.js"/>
|
||||
<link rel="localization" href="browser/aboutSearchReset.ftl"/>
|
||||
<link rel="localization" href="branding/brand.ftl"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
<div class="title">
|
||||
<h1 class="title-text" data-l10n-id="page-title"/>
|
||||
</div>
|
||||
|
||||
<div class="description">
|
||||
<p data-l10n-id="page-info-outofdate"/>
|
||||
<p id="defaultEngineParagraph">
|
||||
<span id="defaultEngine" data-l10n-name="default-engine"/>
|
||||
</p>
|
||||
|
||||
<p data-l10n-id="page-info-how-to-change">
|
||||
<a id="linkSettingsPage" href="about:preferences#search" data-l10n-name="link"></a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="button-container">
|
||||
<xul:button id="searchResetKeepCurrent"
|
||||
data-l10n-id="no-change-button"
|
||||
oncommand="keepCurrentEngine();"/>
|
||||
<xul:button class="primary"
|
||||
id="searchResetChangeEngine"
|
||||
data-l10n-id="change-engine-button"
|
||||
oncommand="changeSearchEngine();"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -6,8 +6,6 @@ browser.jar:
|
|||
content/browser/search/search.xml (content/search.xml)
|
||||
content/browser/search/searchbar.js (content/searchbar.js)
|
||||
content/browser/search/search-one-offs.js (content/search-one-offs.js)
|
||||
content/browser/search/searchReset.xhtml (content/searchReset.xhtml)
|
||||
content/browser/search/searchReset.js (content/searchReset.js)
|
||||
|
||||
searchplugins/ (searchplugins/**)
|
||||
|
||||
|
|
|
@ -38,8 +38,6 @@ skip-if = verify
|
|||
[browser_oneOffHeader.js]
|
||||
skip-if = os == "mac" #1421238
|
||||
[browser_private_search_perwindowpb.js]
|
||||
[browser_aboutSearchReset.js]
|
||||
disabled = bug 1488946 - Telemetry probe needs extension
|
||||
[browser_searchbar_openpopup.js]
|
||||
skip-if = os == "linux" # Linux has different focus behaviours.
|
||||
[browser_searchbar_keyboard_navigation.js]
|
||||
|
|
|
@ -1,181 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
const TELEMETRY_RESULT_ENUM = {
|
||||
RESTORED_DEFAULT: 0,
|
||||
KEPT_CURRENT: 1,
|
||||
CHANGED_ENGINE: 2,
|
||||
CLOSED_PAGE: 3,
|
||||
OPENED_SETTINGS: 4,
|
||||
};
|
||||
|
||||
const kSearchStr = "a search";
|
||||
const kSearchPurpose = "searchbar";
|
||||
|
||||
const kTestEngine = "testEngine.xml";
|
||||
|
||||
const kStatusPref = "browser.search.reset.status";
|
||||
|
||||
function checkTelemetryRecords(expectedValue) {
|
||||
let histogram = Services.telemetry.getHistogramById("SEARCH_RESET_RESULT");
|
||||
let snapshot = histogram.snapshot();
|
||||
if (expectedValue != null) {
|
||||
Assert.deepEqual(snapshot.values[expectedValue], 1,
|
||||
"histogram has expected content");
|
||||
} else {
|
||||
Assert.deepEqual(!!snapshot.values[expectedValue], false,
|
||||
"histogram has expected content");
|
||||
}
|
||||
histogram.clear();
|
||||
}
|
||||
|
||||
function promiseStoppedLoad(expectedURL) {
|
||||
return new Promise(resolve => {
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
let original = browser.loadURI;
|
||||
browser.loadURI = function(URI) {
|
||||
if (URI == expectedURL) {
|
||||
browser.loadURI = original;
|
||||
ok(true, "loaded expected url: " + URI);
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
original.apply(browser, arguments);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
var gTests = [
|
||||
|
||||
{
|
||||
desc: "Test the 'Keep Current Settings' button.",
|
||||
async run() {
|
||||
let engine = await promiseNewEngine(kTestEngine, {setAsCurrent: true});
|
||||
|
||||
let expectedURL = engine.
|
||||
getSubmission(kSearchStr, null, kSearchPurpose).
|
||||
uri.spec;
|
||||
|
||||
let rawEngine = engine.wrappedJSObject;
|
||||
let initialHash = rawEngine.getAttr("loadPathHash");
|
||||
rawEngine.setAttr("loadPathHash", "broken");
|
||||
Services.prefs.setCharPref(kStatusPref, "pending");
|
||||
|
||||
let loadPromise = promiseStoppedLoad(expectedURL);
|
||||
await BrowserTestUtils.synthesizeMouseAtCenter("#searchResetKeepCurrent", {},
|
||||
gBrowser.selectedBrowser);
|
||||
await loadPromise;
|
||||
|
||||
is(engine, Services.search.defaultEngine,
|
||||
"the custom engine is still default");
|
||||
is(rawEngine.getAttr("loadPathHash"), initialHash,
|
||||
"the loadPathHash has been fixed");
|
||||
|
||||
checkTelemetryRecords(TELEMETRY_RESULT_ENUM.KEPT_CURRENT);
|
||||
is(Services.prefs.getCharPref(kStatusPref), "declined");
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Test the 'Restore Search Defaults' button.",
|
||||
async run() {
|
||||
let currentEngine = Services.search.defaultEngine;
|
||||
let originalEngine = Services.search.originalDefaultEngine;
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
let defaultEngineSpanText =
|
||||
await ContentTask.spawn(browser, null, async () => {
|
||||
return content.document.getElementById("defaultEngine").textContent;
|
||||
});
|
||||
|
||||
is(defaultEngineSpanText, originalEngine.name,
|
||||
"the name of the original default engine is displayed");
|
||||
|
||||
let expectedURL = originalEngine.
|
||||
getSubmission(kSearchStr, null, kSearchPurpose).
|
||||
uri.spec;
|
||||
let loadPromise = promiseStoppedLoad(expectedURL);
|
||||
|
||||
await ContentTask.spawn(browser, null, async () => {
|
||||
let button = content.document.getElementById("searchResetChangeEngine");
|
||||
Assert.equal(content.document.activeElement, button,
|
||||
"the 'Change Search Engine' button is focused");
|
||||
});
|
||||
|
||||
Services.prefs.setCharPref(kStatusPref, "pending");
|
||||
await BrowserTestUtils.synthesizeMouseAtCenter("#searchResetChangeEngine",
|
||||
{}, browser);
|
||||
await loadPromise;
|
||||
|
||||
is(originalEngine, Services.search.defaultEngine,
|
||||
"the default engine is back to the original one");
|
||||
|
||||
checkTelemetryRecords(TELEMETRY_RESULT_ENUM.RESTORED_DEFAULT);
|
||||
is(Services.prefs.getCharPref(kStatusPref), "accepted");
|
||||
Services.search.defaultEngine = currentEngine;
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Click the settings link.",
|
||||
async run() {
|
||||
Services.prefs.setCharPref(kStatusPref, "pending");
|
||||
let loadPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser,
|
||||
false,
|
||||
"about:preferences#search");
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
await BrowserTestUtils.synthesizeMouseAtCenter("#linkSettingsPage",
|
||||
{}, browser);
|
||||
await loadPromise;
|
||||
|
||||
checkTelemetryRecords(TELEMETRY_RESULT_ENUM.OPENED_SETTINGS);
|
||||
is(Services.prefs.getCharPref(kStatusPref), "customized");
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Load another page without clicking any of the buttons.",
|
||||
async run() {
|
||||
Services.prefs.setCharPref(kStatusPref, "pending");
|
||||
await promiseTabLoadEvent(gBrowser.selectedTab, "about:mozilla");
|
||||
|
||||
checkTelemetryRecords(TELEMETRY_RESULT_ENUM.CLOSED_PAGE);
|
||||
is(Services.prefs.getCharPref(kStatusPref), "pending");
|
||||
},
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
(async function() {
|
||||
let oldCanRecord = Services.telemetry.canRecordExtended;
|
||||
Services.telemetry.canRecordExtended = true;
|
||||
checkTelemetryRecords();
|
||||
|
||||
for (let testCase of gTests) {
|
||||
info(testCase.desc);
|
||||
|
||||
// Create a tab to run the test.
|
||||
let tab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, "about:blank");
|
||||
|
||||
// Start loading about:searchreset and wait for it to complete.
|
||||
let url = "about:searchreset?data=" + encodeURIComponent(kSearchStr) +
|
||||
"&purpose=" + kSearchPurpose;
|
||||
await promiseTabLoadEvent(tab, url);
|
||||
|
||||
info("Running test");
|
||||
await testCase.run();
|
||||
|
||||
info("Cleanup");
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
|
||||
Services.prefs.clearUserPref(kStatusPref);
|
||||
Services.telemetry.canRecordExtended = oldCanRecord;
|
||||
})().then(finish, ex => {
|
||||
ok(false, "Unexpected Exception: " + ex);
|
||||
finish();
|
||||
});
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
tab-title = Restore Search Settings
|
||||
page-title = Restore your search settings?
|
||||
page-info-outofdate = Your search settings might be out-of-date. { -brand-short-name } can help you restore the default search settings.
|
||||
# Variables:
|
||||
# $searchEngine (String) - Name of the default search engine e.g. Google
|
||||
page-info-new-search-engine = This will set your default search engine to <span data-l10n-name="default-engine">{ $searchEngine }</span>
|
||||
page-info-how-to-change = You can change these settings at any time from the <a data-l10n-name="link">Settings page</a>.
|
||||
no-change-button =
|
||||
.label = Don’t Change
|
||||
.accesskey = D
|
||||
change-engine-button =
|
||||
.label = Change Search Engine
|
||||
.accesskey = C
|
|
@ -49,18 +49,3 @@ searchWithHeader=Search with:
|
|||
# LOCALIZATION NOTE (searchSettings):
|
||||
# This is the label for the button that opens Search preferences.
|
||||
searchSettings=Change Search Settings
|
||||
|
||||
# LOCALIZATION NOTE (searchReset.intro):
|
||||
# %S is the name of the user's current search engine.
|
||||
searchReset.intro=Did you want to search using %S?
|
||||
# LOCALIZATION NOTE (searchReset.message):
|
||||
# %1$S is brandShortName. %2$S is the name of the user's current search engine.
|
||||
searchReset.message=It appears that your default search engine has changed. Should %1$S make %2$S the default search engine?
|
||||
# LOCALIZATION NOTE (searchReset.doNotResetButton):
|
||||
# This string is used as a button label in a notification popup.
|
||||
searchReset.doNotResetButton=No Thanks
|
||||
# LOCALIZATION NOTE (searchReset.resetButton):
|
||||
# %S is the name of the user's current search engine. This string is used as a
|
||||
# button label in a notification popup, where space is limited. If necessary,
|
||||
# translate simply as "Yes, Use %S" (e.g., "Yes, use Google")
|
||||
searchReset.resetButton=Yes, Use %S to Search
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<circle cx="8" cy="8" r="8" fill="#58bf43"/>
|
||||
<circle cx="8" cy="8" r="7.5" stroke="#41a833" stroke-width="1" fill="none"/>
|
||||
<path d="M12.879,12L12,12.879,9.015,9.9A4.276,4.276,0,1,1,9.9,9.015ZM6.5,3.536A2.964,2.964,0,1,0,9.464,6.5,2.964,2.964,0,0,0,6.5,3.536Z" stroke="#41a833" stroke-width="2" fill="none"/>
|
||||
<path d="M12.879,12L12,12.879,9.015,9.9A4.276,4.276,0,1,1,9.9,9.015ZM6.5,3.536A2.964,2.964,0,1,0,9.464,6.5,2.964,2.964,0,0,0,6.5,3.536Z" fill="#fff"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 809 B |
|
@ -1,12 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64">
|
||||
<ellipse cx="32" cy="34" rx="29.5" ry="30" fill="#000" fill-opacity=".1"/>
|
||||
<circle cx="32" cy="32" r="30" fill="#58bf43"/>
|
||||
<circle cx="32" cy="32" r="29.5" stroke="#41a833" stroke-width="1" fill="none"/>
|
||||
<path d="M50,47.131L47.131,50,36.776,39.647a16.038,16.038,0,1,1,2.871-2.871ZM27,15A12,12,0,1,0,39,27,12,12,0,0,0,27,15Z" stroke="#41a833" stroke-width="2" fill="none"/>
|
||||
<path d="M50,47.131L47.131,50,36.776,39.647a16.038,16.038,0,1,1,2.871-2.871ZM27,15A12,12,0,1,0,39,27,12,12,0,0,0,27,15Z" fill="#fff"/>
|
||||
<circle cx="27" cy="27" r="13" fill="#fff" fill-opacity=".2"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 925 B |
|
@ -55,7 +55,6 @@
|
|||
skin/classic/browser/identity-icon.svg (../shared/identity-block/identity-icon.svg)
|
||||
skin/classic/browser/identity-icon-notice.svg (../shared/identity-block/identity-icon-notice.svg)
|
||||
skin/classic/browser/info.svg (../shared/info.svg)
|
||||
skin/classic/browser/searchReset.css (../shared/searchReset.css)
|
||||
|
||||
skin/classic/browser/illustrations/error-session-restore.svg (../shared/illustrations/error-session-restore.svg)
|
||||
|
||||
|
@ -224,8 +223,6 @@
|
|||
skin/classic/browser/cert-error-new.svg (../shared/incontent-icons/cert-error-new.svg)
|
||||
skin/classic/browser/wifi.svg (../shared/incontent-icons/wifi.svg)
|
||||
skin/classic/browser/tab-crashed.svg (../shared/incontent-icons/tab-crashed.svg)
|
||||
skin/classic/browser/favicon-search-16.svg (../shared/favicon-search-16.svg)
|
||||
skin/classic/browser/icon-search-64.svg (../shared/incontent-icons/icon-search-64.svg)
|
||||
skin/classic/browser/welcome-back.svg (../shared/incontent-icons/welcome-back.svg)
|
||||
skin/classic/browser/readerMode.svg (../shared/reader/readerMode.svg)
|
||||
skin/classic/browser/panic-panel/header.png (../shared/panic-panel/header.png)
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
body {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
background-image: url("chrome://browser/skin/icon-search-64.svg");
|
||||
}
|
||||
|
||||
#defaultEngine {
|
||||
padding-inline-start: 26px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 5px center;
|
||||
background-size: 16px, 16px;
|
||||
}
|
||||
|
||||
#defaultEngine:dir(rtl) {
|
||||
background-position: calc(100% - 5px) center;
|
||||
}
|
|
@ -49,7 +49,10 @@ export function setPausePoints(sourceId: SourceId) {
|
|||
}
|
||||
|
||||
let pausePoints = await parser.getPausePoints(sourceId);
|
||||
pausePoints = await mapLocations(pausePoints, source, sourceMaps);
|
||||
|
||||
if (features.columnBreakpoints) {
|
||||
pausePoints = await mapLocations(pausePoints, source, sourceMaps);
|
||||
}
|
||||
|
||||
if (isGenerated(source)) {
|
||||
const compressed = compressPausePoints(pausePoints);
|
||||
|
|
|
@ -47,13 +47,14 @@ export async function mapPausePoints<T>(
|
|||
iteratee: PausePoint => T
|
||||
) {
|
||||
const results = await Promise.all(convertToList(pausePoints).map(iteratee));
|
||||
let index = 0;
|
||||
|
||||
const newPausePoints = {};
|
||||
for (const line in pausePoints) {
|
||||
const linePoints = pausePoints[line];
|
||||
const newLinePoints = (newPausePoints[line] = {});
|
||||
for (const column in linePoints) {
|
||||
newLinePoints[column] = results.shift();
|
||||
newLinePoints[column] = results[index++];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@ static int32_t gMinBackgroundTimeoutValue = 0;
|
|||
static int32_t gMinTrackingTimeoutValue = 0;
|
||||
static int32_t gMinTrackingBackgroundTimeoutValue = 0;
|
||||
static int32_t gTimeoutThrottlingDelay = 0;
|
||||
static bool gAnnotateTrackingChannels = false;
|
||||
|
||||
#define DEFAULT_BACKGROUND_BUDGET_REGENERATION_FACTOR 100 // 1ms per 100ms
|
||||
#define DEFAULT_FOREGROUND_BUDGET_REGENERATION_FACTOR 1 // 1ms per 1ms
|
||||
|
@ -398,7 +397,9 @@ TimeoutManager::TimeoutManager(nsGlobalWindowInner& aWindow)
|
|||
mBudgetThrottleTimeouts(false) {
|
||||
MOZ_LOG(gLog, LogLevel::Debug,
|
||||
("TimeoutManager %p created, tracking bucketing %s\n", this,
|
||||
gAnnotateTrackingChannels ? "enabled" : "disabled"));
|
||||
StaticPrefs::privacy_trackingprotection_annotate_channels()
|
||||
? "enabled"
|
||||
: "disabled"));
|
||||
}
|
||||
|
||||
TimeoutManager::~TimeoutManager() {
|
||||
|
@ -427,10 +428,6 @@ void TimeoutManager::Initialize() {
|
|||
"dom.timeout.throttling_delay",
|
||||
DEFAULT_TIMEOUT_THROTTLING_DELAY);
|
||||
|
||||
Preferences::AddBoolVarCache(&gAnnotateTrackingChannels,
|
||||
"privacy.trackingprotection.annotate_channels",
|
||||
false);
|
||||
|
||||
Preferences::AddUintVarCache(&gMaxConsecutiveCallbacksMilliseconds,
|
||||
"dom.timeout.max_consecutive_callbacks_ms",
|
||||
DEFAULT_MAX_CONSECUTIVE_CALLBACKS_MILLISECONDS);
|
||||
|
|
|
@ -486,6 +486,7 @@ LOCAL_INCLUDES += [
|
|||
'/layout/svg',
|
||||
'/layout/xul',
|
||||
'/netwerk/base',
|
||||
'/netwerk/url-classifier',
|
||||
'/security/manager/ssl',
|
||||
'/widget',
|
||||
'/xpcom/ds',
|
||||
|
|
|
@ -317,7 +317,6 @@ bool nsContentUtils::sAnimationsAPICoreEnabled = false;
|
|||
bool nsContentUtils::sGetBoxQuadsEnabled = false;
|
||||
bool nsContentUtils::sSkipCursorMoveForSameValueSet = false;
|
||||
bool nsContentUtils::sRequestIdleCallbackEnabled = false;
|
||||
bool nsContentUtils::sLowerNetworkPriority = false;
|
||||
bool nsContentUtils::sTailingEnabled = false;
|
||||
bool nsContentUtils::sShowInputPlaceholderOnFocus = true;
|
||||
bool nsContentUtils::sAutoFocusEnabled = true;
|
||||
|
@ -692,10 +691,6 @@ nsresult nsContentUtils::Init() {
|
|||
sBypassCSSOMOriginCheck = getenv("MOZ_BYPASS_CSSOM_ORIGIN_CHECK");
|
||||
#endif
|
||||
|
||||
Preferences::AddBoolVarCache(
|
||||
&sLowerNetworkPriority,
|
||||
"privacy.trackingprotection.lower_network_priority", false);
|
||||
|
||||
Preferences::AddBoolVarCache(&sTailingEnabled, "network.http.tailing.enabled",
|
||||
true);
|
||||
|
||||
|
|
|
@ -3223,10 +3223,6 @@ class nsContentUtils {
|
|||
*/
|
||||
static bool GetUserIsInteracting();
|
||||
|
||||
// Check pref "privacy.trackingprotection.lower_network_priority" to see
|
||||
// if we want to lower the priority of the channel.
|
||||
static bool IsLowerNetworkPriority() { return sLowerNetworkPriority; }
|
||||
|
||||
// Whether tracker tailing is turned on - "network.http.tailing.enabled".
|
||||
static bool IsTailingEnabled() { return sTailingEnabled; }
|
||||
|
||||
|
@ -3472,7 +3468,6 @@ class nsContentUtils {
|
|||
static bool sGetBoxQuadsEnabled;
|
||||
static bool sSkipCursorMoveForSameValueSet;
|
||||
static bool sRequestIdleCallbackEnabled;
|
||||
static bool sLowerNetworkPriority;
|
||||
static bool sTailingEnabled;
|
||||
static bool sShowInputPlaceholderOnFocus;
|
||||
static bool sAutoFocusEnabled;
|
||||
|
|
|
@ -684,7 +684,8 @@ nsresult FetchDriver::HttpFetch(
|
|||
nsIClassOfService::Tail);
|
||||
}
|
||||
|
||||
if (mIsTrackingFetch && nsContentUtils::IsLowerNetworkPriority()) {
|
||||
if (mIsTrackingFetch &&
|
||||
StaticPrefs::privacy_trackingprotection_lower_network_priority()) {
|
||||
nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(chan);
|
||||
if (p) {
|
||||
p->SetPriority(nsISupportsPriority::PRIORITY_LOWEST);
|
||||
|
|
|
@ -3191,7 +3191,7 @@ bool ContentChild::DeallocPURLClassifierChild(PURLClassifierChild* aActor) {
|
|||
}
|
||||
|
||||
PURLClassifierLocalChild* ContentChild::AllocPURLClassifierLocalChild(
|
||||
const URIParams& aUri, const nsCString& aTables) {
|
||||
const URIParams& aUri, const nsTArray<IPCURLClassifierFeature>& aFeatures) {
|
||||
return new URLClassifierLocalChild();
|
||||
}
|
||||
|
||||
|
|
|
@ -644,7 +644,8 @@ class ContentChild final : public PContentChild,
|
|||
|
||||
// PURLClassifierLocalChild
|
||||
virtual PURLClassifierLocalChild* AllocPURLClassifierLocalChild(
|
||||
const URIParams& aUri, const nsCString& aTables) override;
|
||||
const URIParams& aUri,
|
||||
const nsTArray<IPCURLClassifierFeature>& aFeatures) override;
|
||||
virtual bool DeallocPURLClassifierLocalChild(
|
||||
PURLClassifierLocalChild* aActor) override;
|
||||
|
||||
|
|
|
@ -5353,7 +5353,7 @@ bool ContentParent::DeallocPURLClassifierParent(PURLClassifierParent* aActor) {
|
|||
// PURLClassifierLocalParent
|
||||
|
||||
PURLClassifierLocalParent* ContentParent::AllocPURLClassifierLocalParent(
|
||||
const URIParams& aURI, const nsCString& aTables) {
|
||||
const URIParams& aURI, const nsTArray<IPCURLClassifierFeature>& aFeatures) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
RefPtr<URLClassifierLocalParent> actor = new URLClassifierLocalParent();
|
||||
|
@ -5362,10 +5362,12 @@ PURLClassifierLocalParent* ContentParent::AllocPURLClassifierLocalParent(
|
|||
|
||||
mozilla::ipc::IPCResult ContentParent::RecvPURLClassifierLocalConstructor(
|
||||
PURLClassifierLocalParent* aActor, const URIParams& aURI,
|
||||
const nsCString& aTables) {
|
||||
nsTArray<IPCURLClassifierFeature>&& aFeatures) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aActor);
|
||||
|
||||
nsTArray<IPCURLClassifierFeature> features = std::move(aFeatures);
|
||||
|
||||
nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
|
||||
if (!uri) {
|
||||
NS_WARNING("Failed to DeserializeURI");
|
||||
|
@ -5373,7 +5375,7 @@ mozilla::ipc::IPCResult ContentParent::RecvPURLClassifierLocalConstructor(
|
|||
}
|
||||
|
||||
auto* actor = static_cast<URLClassifierLocalParent*>(aActor);
|
||||
return actor->StartClassify(uri, aTables);
|
||||
return actor->StartClassify(uri, features);
|
||||
}
|
||||
|
||||
bool ContentParent::DeallocPURLClassifierLocalParent(
|
||||
|
|
|
@ -560,10 +560,12 @@ class ContentParent final : public PContentParent,
|
|||
|
||||
// PURLClassifierLocalParent.
|
||||
virtual PURLClassifierLocalParent* AllocPURLClassifierLocalParent(
|
||||
const URIParams& aURI, const nsCString& aTables) override;
|
||||
const URIParams& aURI,
|
||||
const nsTArray<IPCURLClassifierFeature>& aFeatures) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvPURLClassifierLocalConstructor(
|
||||
PURLClassifierLocalParent* aActor, const URIParams& aURI,
|
||||
const nsCString& aTables) override;
|
||||
nsTArray<IPCURLClassifierFeature>&& aFeatures) override;
|
||||
|
||||
virtual PLoginReputationParent* AllocPLoginReputationParent(
|
||||
const URIParams& aURI) override;
|
||||
|
|
|
@ -297,6 +297,13 @@ struct StringBundleDescriptor
|
|||
uint32_t mapSize;
|
||||
};
|
||||
|
||||
struct IPCURLClassifierFeature
|
||||
{
|
||||
nsCString featureName;
|
||||
nsCString[] tables;
|
||||
nsCString skipHostList;
|
||||
};
|
||||
|
||||
/**
|
||||
* The PContent protocol is a top-level protocol between the UI process
|
||||
* and a content process. There is exactly one PContentParent/PContentChild pair
|
||||
|
@ -803,10 +810,12 @@ parent:
|
|||
|
||||
sync PURLClassifier(Principal principal, bool useTrackingProtection)
|
||||
returns (bool success);
|
||||
|
||||
sync ClassifyLocal(URIParams uri, nsCString tables)
|
||||
returns (nsresult rv, nsCString[] results);
|
||||
|
||||
// The async version of ClassifyLocal.
|
||||
async PURLClassifierLocal(URIParams uri, nsCString tables);
|
||||
async PURLClassifierLocal(URIParams uri, IPCURLClassifierFeature[] features);
|
||||
|
||||
async PLoginReputation(URIParams formURI);
|
||||
|
||||
|
|
|
@ -11,12 +11,18 @@ include PURLClassifierInfo;
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
struct URLClassifierLocalResult
|
||||
{
|
||||
nsCString featureName;
|
||||
nsCString matchingList;
|
||||
};
|
||||
|
||||
protocol PURLClassifierLocal
|
||||
{
|
||||
manager PContent;
|
||||
|
||||
child:
|
||||
async __delete__(MaybeInfo info, nsresult errorCode);
|
||||
async __delete__(URLClassifierLocalResult[] results);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -9,16 +9,15 @@
|
|||
|
||||
#include "mozilla/dom/PURLClassifierChild.h"
|
||||
#include "mozilla/dom/PURLClassifierLocalChild.h"
|
||||
#include "mozilla/net/UrlClassifierFeatureResult.h"
|
||||
#include "nsIURIClassifier.h"
|
||||
#include "nsIUrlClassifierFeature.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
template <typename BaseProtocol>
|
||||
class URLClassifierChildBase : public BaseProtocol {
|
||||
class URLClassifierChild : public PURLClassifierChild {
|
||||
public:
|
||||
URLClassifierChildBase() = default;
|
||||
|
||||
void SetCallback(nsIURIClassifierCallback* aCallback) {
|
||||
mCallback = aCallback;
|
||||
}
|
||||
|
@ -35,14 +34,50 @@ class URLClassifierChildBase : public BaseProtocol {
|
|||
}
|
||||
|
||||
private:
|
||||
~URLClassifierChildBase() = default;
|
||||
|
||||
nsCOMPtr<nsIURIClassifierCallback> mCallback;
|
||||
};
|
||||
|
||||
using URLClassifierChild = URLClassifierChildBase<PURLClassifierChild>;
|
||||
using URLClassifierLocalChild =
|
||||
URLClassifierChildBase<PURLClassifierLocalChild>;
|
||||
class URLClassifierLocalChild : public PURLClassifierLocalChild {
|
||||
public:
|
||||
void SetFeaturesAndCallback(
|
||||
const nsTArray<RefPtr<nsIUrlClassifierFeature>>& aFeatures,
|
||||
nsIUrlClassifierFeatureCallback* aCallback) {
|
||||
mCallback = aCallback;
|
||||
mFeatures = aFeatures;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult Recv__delete__(
|
||||
nsTArray<URLClassifierLocalResult>&& aResults) override {
|
||||
nsTArray<RefPtr<nsIUrlClassifierFeatureResult>> finalResults;
|
||||
|
||||
nsTArray<URLClassifierLocalResult> results = std::move(aResults);
|
||||
for (URLClassifierLocalResult& result : results) {
|
||||
for (nsIUrlClassifierFeature* feature : mFeatures) {
|
||||
nsAutoCString name;
|
||||
nsresult rv = feature->GetName(name);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (result.featureName() != name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RefPtr<net::UrlClassifierFeatureResult> r =
|
||||
new net::UrlClassifierFeatureResult(feature, result.matchingList());
|
||||
finalResults.AppendElement(r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mCallback->OnClassifyComplete(finalResults);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIUrlClassifierFeatureCallback> mCallback;
|
||||
nsTArray<RefPtr<nsIUrlClassifierFeature>> mFeatures;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "URLClassifierParent.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "mozilla/net/UrlClassifierFeatureResult.h"
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
@ -41,37 +42,122 @@ mozilla::ipc::IPCResult URLClassifierParent::StartClassify(
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
void URLClassifierParent::ActorDestroy(ActorDestroyReason aWhy) {
|
||||
mIPCOpen = false;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// URLClassifierLocalParent.
|
||||
|
||||
NS_IMPL_ISUPPORTS(URLClassifierLocalParent, nsIURIClassifierCallback)
|
||||
namespace {
|
||||
|
||||
// This class implements a nsIUrlClassifierFeature on the parent side, starting
|
||||
// from an IPC data struct.
|
||||
class IPCFeature final : public nsIUrlClassifierFeature {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
explicit IPCFeature(const IPCURLClassifierFeature& aFeature)
|
||||
: mIPCFeature(aFeature) {}
|
||||
|
||||
NS_IMETHOD
|
||||
GetName(nsACString& aName) override {
|
||||
aName = mIPCFeature.featureName();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
GetTables(nsIUrlClassifierFeature::listType,
|
||||
nsTArray<nsCString>& aTables) override {
|
||||
aTables.AppendElements(mIPCFeature.tables());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
HasTable(const nsACString& aTable, nsIUrlClassifierFeature::listType,
|
||||
bool* aResult) override {
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
*aResult = mIPCFeature.tables().Contains(aTable);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
HasHostInPreferences(const nsACString& aHost,
|
||||
nsIUrlClassifierFeature::listType,
|
||||
nsACString& aTableName, bool* aResult) override {
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
*aResult = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
GetSkipHostList(nsACString& aList) override {
|
||||
aList = mIPCFeature.skipHostList();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
ProcessChannel(nsIChannel* aChannel, const nsACString& aList,
|
||||
bool* aShouldContinue) override {
|
||||
NS_ENSURE_ARG_POINTER(aShouldContinue);
|
||||
*aShouldContinue = true;
|
||||
|
||||
// Nothing to do here.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
~IPCFeature() = default;
|
||||
|
||||
IPCURLClassifierFeature mIPCFeature;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(IPCFeature, nsIUrlClassifierFeature)
|
||||
|
||||
} // namespace
|
||||
|
||||
NS_IMPL_ISUPPORTS(URLClassifierLocalParent, nsIUrlClassifierFeatureCallback)
|
||||
|
||||
mozilla::ipc::IPCResult URLClassifierLocalParent::StartClassify(
|
||||
nsIURI* aURI, const nsACString& aTables) {
|
||||
nsIURI* aURI, const nsTArray<IPCURLClassifierFeature>& aFeatures) {
|
||||
MOZ_ASSERT(aURI);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
// Note that in safe mode, the URL classifier service isn't available, so we
|
||||
// should handle the service not being present gracefully.
|
||||
nsCOMPtr<nsIURIClassifier> uriClassifier =
|
||||
do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
MOZ_ASSERT(aURI);
|
||||
rv = uriClassifier->AsyncClassifyLocalWithTables(
|
||||
aURI, aTables, nsTArray<nsCString>(), nsTArray<nsCString>(), this);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
OnClassifyComplete(nsTArray<RefPtr<nsIUrlClassifierFeatureResult>>());
|
||||
return IPC_OK();
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
// Cannot do ClassificationFailed() because the child side
|
||||
// is expecting a callback. Only the second parameter will
|
||||
// be used, which is the "matched list". We treat "unable
|
||||
// to classify" as "not on any list".
|
||||
OnClassifyComplete(NS_OK, EmptyCString(), EmptyCString(), EmptyCString());
|
||||
|
||||
nsTArray<RefPtr<nsIUrlClassifierFeature>> features;
|
||||
for (const IPCURLClassifierFeature& feature : aFeatures) {
|
||||
features.AppendElement(new IPCFeature(feature));
|
||||
}
|
||||
|
||||
// Doesn't matter if we pass blacklist, whitelist or any other list.
|
||||
// IPCFeature returns always the same values.
|
||||
rv = uriClassifier->AsyncClassifyLocalWithFeatures(
|
||||
aURI, features, nsIUrlClassifierFeature::blacklist, this);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
OnClassifyComplete(nsTArray<RefPtr<nsIUrlClassifierFeatureResult>>());
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void URLClassifierLocalParent::ActorDestroy(ActorDestroyReason aWhy) {
|
||||
mIPCOpen = false;
|
||||
NS_IMETHODIMP
|
||||
URLClassifierLocalParent::OnClassifyComplete(
|
||||
const nsTArray<RefPtr<nsIUrlClassifierFeatureResult>>& aResults) {
|
||||
nsTArray<URLClassifierLocalResult> ipcResults;
|
||||
for (nsIUrlClassifierFeatureResult* result : aResults) {
|
||||
URLClassifierLocalResult* ipcResult = ipcResults.AppendElement();
|
||||
|
||||
net::UrlClassifierFeatureResult* r =
|
||||
static_cast<net::UrlClassifierFeatureResult*>(result);
|
||||
r->Feature()->GetName(ipcResult->featureName());
|
||||
ipcResult->matchingList() = r->List();
|
||||
}
|
||||
|
||||
Unused << Send__delete__(this, ipcResults);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -10,43 +10,16 @@
|
|||
#include "mozilla/dom/PURLClassifierParent.h"
|
||||
#include "mozilla/dom/PURLClassifierLocalParent.h"
|
||||
#include "nsIURIClassifier.h"
|
||||
#include "nsIUrlClassifierFeature.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
template <typename BaseProtocol>
|
||||
class URLClassifierParentBase : public nsIURIClassifierCallback,
|
||||
public BaseProtocol {
|
||||
public:
|
||||
// nsIURIClassifierCallback.
|
||||
NS_IMETHOD OnClassifyComplete(nsresult aErrorCode, const nsACString& aList,
|
||||
const nsACString& aProvider,
|
||||
const nsACString& aFullHash) override {
|
||||
if (mIPCOpen) {
|
||||
ClassifierInfo info = ClassifierInfo(
|
||||
nsCString(aList), nsCString(aProvider), nsCString(aFullHash));
|
||||
Unused << BaseProtocol::Send__delete__(this, info, aErrorCode);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Custom.
|
||||
void ClassificationFailed() {
|
||||
if (mIPCOpen) {
|
||||
Unused << BaseProtocol::Send__delete__(this, void_t(), NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
~URLClassifierParentBase() = default;
|
||||
bool mIPCOpen = true;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// URLClassifierParent
|
||||
|
||||
class URLClassifierParent
|
||||
: public URLClassifierParentBase<PURLClassifierParent> {
|
||||
class URLClassifierParent : public nsIURIClassifierCallback,
|
||||
public PURLClassifierParent {
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
|
@ -54,30 +27,58 @@ class URLClassifierParent
|
|||
bool aUseTrackingProtection,
|
||||
bool* aSuccess);
|
||||
|
||||
// nsIURIClassifierCallback.
|
||||
NS_IMETHOD OnClassifyComplete(nsresult aErrorCode, const nsACString& aList,
|
||||
const nsACString& aProvider,
|
||||
const nsACString& aFullHash) override {
|
||||
if (mIPCOpen) {
|
||||
ClassifierInfo info = ClassifierInfo(
|
||||
nsCString(aList), nsCString(aProvider), nsCString(aFullHash));
|
||||
Unused << Send__delete__(this, info, aErrorCode);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Custom.
|
||||
void ClassificationFailed() {
|
||||
if (mIPCOpen) {
|
||||
Unused << Send__delete__(this, void_t(), NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
~URLClassifierParent() = default;
|
||||
|
||||
// Override PURLClassifierParent::ActorDestroy. We seem to unable to
|
||||
// override from the base template class.
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override { mIPCOpen = false; }
|
||||
|
||||
bool mIPCOpen = true;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// URLClassifierLocalParent
|
||||
|
||||
class URLClassifierLocalParent
|
||||
: public URLClassifierParentBase<PURLClassifierLocalParent> {
|
||||
class URLClassifierLocalParent : public nsIUrlClassifierFeatureCallback,
|
||||
public PURLClassifierLocalParent {
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
mozilla::ipc::IPCResult StartClassify(nsIURI* aURI,
|
||||
const nsACString& aTables);
|
||||
mozilla::ipc::IPCResult StartClassify(
|
||||
nsIURI* aURI, const nsTArray<IPCURLClassifierFeature>& aFeatureNames);
|
||||
|
||||
// nsIUrlClassifierFeatureCallback.
|
||||
NS_IMETHOD
|
||||
OnClassifyComplete(
|
||||
const nsTArray<RefPtr<nsIUrlClassifierFeatureResult>>& aResults) override;
|
||||
|
||||
private:
|
||||
~URLClassifierLocalParent() = default;
|
||||
|
||||
// Override PURLClassifierParent::ActorDestroy.
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
// Override PURLClassifierLocalParent::ActorDestroy.
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override { mIPCOpen = false; }
|
||||
|
||||
bool mIPCOpen = true;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -2613,7 +2613,7 @@ nsresult XMLHttpRequestMainThread::InitiateFetch(
|
|||
|
||||
// Check if this XHR is created from a tracking script.
|
||||
// If yes, lower the channel's priority.
|
||||
if (nsContentUtils::IsLowerNetworkPriority()) {
|
||||
if (StaticPrefs::privacy_trackingprotection_lower_network_priority()) {
|
||||
MaybeLowerChannelPriority();
|
||||
}
|
||||
|
||||
|
|
|
@ -854,7 +854,7 @@ static const uint32_t JSCLASS_FOREGROUND_FINALIZE =
|
|||
// application.
|
||||
static const uint32_t JSCLASS_GLOBAL_APPLICATION_SLOTS = 5;
|
||||
static const uint32_t JSCLASS_GLOBAL_SLOT_COUNT =
|
||||
JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 37;
|
||||
JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 38;
|
||||
|
||||
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
|
||||
(JSCLASS_IS_GLOBAL | \
|
||||
|
|
|
@ -62,7 +62,8 @@ extern JS_PUBLIC_API JSString* GetSymbolDescription(Handle<Symbol*> symbol);
|
|||
MACRO(toPrimitive) \
|
||||
MACRO(toStringTag) \
|
||||
MACRO(unscopables) \
|
||||
MACRO(asyncIterator)
|
||||
MACRO(asyncIterator) \
|
||||
MACRO(matchAll)
|
||||
|
||||
enum class SymbolCode : uint32_t {
|
||||
// There is one SymbolCode for each well-known symbol.
|
||||
|
|
|
@ -785,6 +785,9 @@ const JSFunctionSpec js::regexp_methods[] = {
|
|||
JS_SELF_HOSTED_FN("exec", "RegExp_prototype_Exec", 1, 0),
|
||||
JS_SELF_HOSTED_FN("test", "RegExpTest", 1, 0),
|
||||
JS_SELF_HOSTED_SYM_FN(match, "RegExpMatch", 1, 0),
|
||||
#ifdef NIGHTLY_BUILD
|
||||
JS_SELF_HOSTED_SYM_FN(matchAll, "RegExpMatchAll", 1, 0),
|
||||
#endif
|
||||
JS_SELF_HOSTED_SYM_FN(replace, "RegExpReplace", 2, 0),
|
||||
JS_SELF_HOSTED_SYM_FN(search, "RegExpSearch", 1, 0),
|
||||
JS_SELF_HOSTED_SYM_FN(split, "RegExpSplit", 2, 0),
|
||||
|
|
|
@ -1075,3 +1075,236 @@ function RegExpSpecies() {
|
|||
return this;
|
||||
}
|
||||
_SetCanonicalName(RegExpSpecies, "get [Symbol.species]");
|
||||
|
||||
function IsRegExpMatchAllOptimizable(rx, C) {
|
||||
if (!IsRegExpObject(rx))
|
||||
return false;
|
||||
|
||||
var RegExpCtor = GetBuiltinConstructor("RegExp");
|
||||
if (C !== RegExpCtor)
|
||||
return false;
|
||||
|
||||
var RegExpProto = RegExpCtor.prototype;
|
||||
return RegExpPrototypeOptimizable(RegExpProto) &&
|
||||
RegExpInstanceOptimizable(rx, RegExpProto);
|
||||
}
|
||||
|
||||
// String.prototype.matchAll proposal.
|
||||
//
|
||||
// RegExp.prototype [ @@matchAll ] ( string )
|
||||
function RegExpMatchAll(string) {
|
||||
// Step 1.
|
||||
var rx = this;
|
||||
|
||||
// Step 2.
|
||||
if (!IsObject(rx))
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, rx === null ? "null" : typeof rx);
|
||||
|
||||
// Step 3.
|
||||
var str = ToString(string);
|
||||
|
||||
// Step 4.
|
||||
var C = SpeciesConstructor(rx, GetBuiltinConstructor("RegExp"));
|
||||
|
||||
var source, flags, matcher, lastIndex;
|
||||
if (IsRegExpMatchAllOptimizable(rx, C)) {
|
||||
// Step 5, 9-12.
|
||||
source = UnsafeGetStringFromReservedSlot(rx, REGEXP_SOURCE_SLOT);
|
||||
flags = UnsafeGetInt32FromReservedSlot(rx, REGEXP_FLAGS_SLOT);
|
||||
|
||||
// Step 6.
|
||||
matcher = rx;
|
||||
|
||||
// Step 7.
|
||||
lastIndex = ToLength(rx.lastIndex);
|
||||
|
||||
// Step 8 (not applicable for the optimized path).
|
||||
} else {
|
||||
// Step 5.
|
||||
source = "";
|
||||
flags = ToString(rx.flags);
|
||||
|
||||
// Step 6.
|
||||
matcher = new C(rx, flags);
|
||||
|
||||
// Steps 7-8.
|
||||
matcher.lastIndex = ToLength(rx.lastIndex);
|
||||
|
||||
// Steps 9-12.
|
||||
flags = (callFunction(std_String_includes, flags, "g") ? REGEXP_GLOBAL_FLAG : 0) |
|
||||
(callFunction(std_String_includes, flags, "u") ? REGEXP_UNICODE_FLAG : 0);
|
||||
|
||||
// Take the non-optimized path.
|
||||
lastIndex = REGEXP_STRING_ITERATOR_LASTINDEX_SLOW;
|
||||
}
|
||||
|
||||
// Step 13.
|
||||
return CreateRegExpStringIterator(matcher, str, source, flags, lastIndex);
|
||||
}
|
||||
|
||||
// String.prototype.matchAll proposal.
|
||||
//
|
||||
// CreateRegExpStringIterator ( R, S, global, fullUnicode )
|
||||
function CreateRegExpStringIterator(regexp, string, source, flags, lastIndex) {
|
||||
// Step 1.
|
||||
assert(typeof string === "string", "|string| is a string value");
|
||||
|
||||
// Steps 2-3.
|
||||
assert(typeof flags === "number", "|flags| is a number value");
|
||||
|
||||
assert(typeof source === "string", "|source| is a string value");
|
||||
assert(typeof lastIndex === "number", "|lastIndex| is a number value");
|
||||
|
||||
// Steps 4-9.
|
||||
var iterator = NewRegExpStringIterator();
|
||||
UnsafeSetReservedSlot(iterator, REGEXP_STRING_ITERATOR_REGEXP_SLOT, regexp);
|
||||
UnsafeSetReservedSlot(iterator, REGEXP_STRING_ITERATOR_STRING_SLOT, string);
|
||||
UnsafeSetReservedSlot(iterator, REGEXP_STRING_ITERATOR_SOURCE_SLOT, source);
|
||||
UnsafeSetReservedSlot(iterator, REGEXP_STRING_ITERATOR_FLAGS_SLOT, flags | 0);
|
||||
UnsafeSetReservedSlot(iterator, REGEXP_STRING_ITERATOR_LASTINDEX_SLOT, lastIndex);
|
||||
|
||||
// Step 10.
|
||||
return iterator;
|
||||
}
|
||||
|
||||
function IsRegExpStringIteratorNextOptimizable() {
|
||||
var RegExpProto = GetBuiltinPrototype("RegExp");
|
||||
// If RegExpPrototypeOptimizable succeeds, `RegExpProto.exec` is
|
||||
// guaranteed to be a data property.
|
||||
return RegExpPrototypeOptimizable(RegExpProto) &&
|
||||
RegExpProto.exec === RegExp_prototype_Exec;
|
||||
}
|
||||
|
||||
// String.prototype.matchAll proposal.
|
||||
//
|
||||
// %RegExpStringIteratorPrototype%.next ( )
|
||||
function RegExpStringIteratorNext() {
|
||||
// Steps 1-3.
|
||||
var obj;
|
||||
if (!IsObject(this) || (obj = GuardToRegExpStringIterator(this)) === null) {
|
||||
return callFunction(CallRegExpStringIteratorMethodIfWrapped, this,
|
||||
"RegExpStringIteratorNext");
|
||||
}
|
||||
|
||||
var result = { value: undefined, done: false };
|
||||
|
||||
// Step 4.
|
||||
var lastIndex = UnsafeGetReservedSlot(obj, REGEXP_STRING_ITERATOR_LASTINDEX_SLOT);
|
||||
if (lastIndex === REGEXP_STRING_ITERATOR_LASTINDEX_DONE) {
|
||||
result.done = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Step 5.
|
||||
var regexp = UnsafeGetObjectFromReservedSlot(obj, REGEXP_STRING_ITERATOR_REGEXP_SLOT);
|
||||
|
||||
// Step 6.
|
||||
var string = UnsafeGetStringFromReservedSlot(obj, REGEXP_STRING_ITERATOR_STRING_SLOT);
|
||||
|
||||
// Steps 7-8.
|
||||
var flags = UnsafeGetInt32FromReservedSlot(obj, REGEXP_STRING_ITERATOR_FLAGS_SLOT);
|
||||
var global = !!(flags & REGEXP_GLOBAL_FLAG);
|
||||
var fullUnicode = !!(flags & REGEXP_UNICODE_FLAG);
|
||||
|
||||
if (lastIndex >= 0) {
|
||||
assert(IsRegExpObject(regexp), "|regexp| is a RegExp object");
|
||||
|
||||
var source = UnsafeGetStringFromReservedSlot(obj, REGEXP_STRING_ITERATOR_SOURCE_SLOT);
|
||||
if (IsRegExpStringIteratorNextOptimizable() &&
|
||||
UnsafeGetStringFromReservedSlot(regexp, REGEXP_SOURCE_SLOT) === source &&
|
||||
UnsafeGetInt32FromReservedSlot(regexp, REGEXP_FLAGS_SLOT) === flags)
|
||||
{
|
||||
// Step 9 (Inlined RegExpBuiltinExec).
|
||||
var globalOrSticky = !!(flags & (REGEXP_GLOBAL_FLAG | REGEXP_STICKY_FLAG));
|
||||
if (!globalOrSticky)
|
||||
lastIndex = 0;
|
||||
|
||||
var match = (lastIndex <= string.length)
|
||||
? RegExpMatcher(regexp, string, lastIndex)
|
||||
: null;
|
||||
|
||||
// Step 10.
|
||||
if (match === null) {
|
||||
// Step 10.a.
|
||||
UnsafeSetReservedSlot(obj, REGEXP_STRING_ITERATOR_LASTINDEX_SLOT,
|
||||
REGEXP_STRING_ITERATOR_LASTINDEX_DONE);
|
||||
|
||||
// Step 10.b.
|
||||
result.done = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Step 11.a.
|
||||
if (global) {
|
||||
// Step 11.a.i.
|
||||
var matchLength = match[0].length;
|
||||
lastIndex = match.index + matchLength;
|
||||
|
||||
// Step 11.a.ii.
|
||||
if (matchLength === 0) {
|
||||
// Steps 11.a.ii.1-3.
|
||||
lastIndex = fullUnicode ? AdvanceStringIndex(string, lastIndex) : lastIndex + 1;
|
||||
}
|
||||
|
||||
UnsafeSetReservedSlot(obj, REGEXP_STRING_ITERATOR_LASTINDEX_SLOT, lastIndex);
|
||||
} else {
|
||||
// Step 11.b.i.
|
||||
UnsafeSetReservedSlot(obj, REGEXP_STRING_ITERATOR_LASTINDEX_SLOT,
|
||||
REGEXP_STRING_ITERATOR_LASTINDEX_DONE);
|
||||
}
|
||||
|
||||
// Steps 11.a.iii and 11.b.ii.
|
||||
result.value = match;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Reify the RegExp object.
|
||||
regexp = regexp_construct_raw_flags(source, flags);
|
||||
regexp.lastIndex = lastIndex;
|
||||
UnsafeSetReservedSlot(obj, REGEXP_STRING_ITERATOR_REGEXP_SLOT, regexp);
|
||||
|
||||
// Mark the iterator as no longer optimizable.
|
||||
UnsafeSetReservedSlot(obj, REGEXP_STRING_ITERATOR_LASTINDEX_SLOT,
|
||||
REGEXP_STRING_ITERATOR_LASTINDEX_SLOW);
|
||||
}
|
||||
|
||||
// Step 9.
|
||||
var match = RegExpExec(regexp, string, false);
|
||||
|
||||
// Step 10.
|
||||
if (match === null) {
|
||||
// Step 10.a.
|
||||
UnsafeSetReservedSlot(obj, REGEXP_STRING_ITERATOR_LASTINDEX_SLOT,
|
||||
REGEXP_STRING_ITERATOR_LASTINDEX_DONE);
|
||||
|
||||
// Step 10.b.
|
||||
result.done = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Step 11.a.
|
||||
if (global) {
|
||||
// Step 11.a.i.
|
||||
var matchStr = ToString(match[0]);
|
||||
|
||||
// Step 11.a.ii.
|
||||
if (matchStr.length === 0) {
|
||||
// Step 11.a.ii.1.
|
||||
var thisIndex = ToLength(regexp.lastIndex);
|
||||
|
||||
// Step 11.a.ii.2.
|
||||
var nextIndex = fullUnicode ? AdvanceStringIndex(string, thisIndex) : thisIndex + 1;
|
||||
|
||||
// Step 11.a.ii.3.
|
||||
regexp.lastIndex = nextIndex;
|
||||
}
|
||||
} else {
|
||||
// Step 11.b.i.
|
||||
UnsafeSetReservedSlot(obj, REGEXP_STRING_ITERATOR_LASTINDEX_SLOT,
|
||||
REGEXP_STRING_ITERATOR_LASTINDEX_DONE);
|
||||
}
|
||||
|
||||
// Steps 11.a.iii and 11.b.ii.
|
||||
result.value = match;
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -96,6 +96,15 @@
|
|||
#define REGEXP_STICKY_FLAG 0x08
|
||||
#define REGEXP_UNICODE_FLAG 0x10
|
||||
|
||||
#define REGEXP_STRING_ITERATOR_REGEXP_SLOT 0
|
||||
#define REGEXP_STRING_ITERATOR_STRING_SLOT 1
|
||||
#define REGEXP_STRING_ITERATOR_SOURCE_SLOT 2
|
||||
#define REGEXP_STRING_ITERATOR_FLAGS_SLOT 3
|
||||
#define REGEXP_STRING_ITERATOR_LASTINDEX_SLOT 4
|
||||
|
||||
#define REGEXP_STRING_ITERATOR_LASTINDEX_DONE -1
|
||||
#define REGEXP_STRING_ITERATOR_LASTINDEX_SLOW -2
|
||||
|
||||
#define MODULE_OBJECT_ENVIRONMENT_SLOT 1
|
||||
#define MODULE_OBJECT_STATUS_SLOT 3
|
||||
#define MODULE_OBJECT_EVALUATION_ERROR_SLOT 4
|
||||
|
|
|
@ -3376,6 +3376,9 @@ static const JSFunctionSpec string_methods[] = {
|
|||
|
||||
/* Perl-ish methods (search is actually Python-esque). */
|
||||
JS_SELF_HOSTED_FN("match", "String_match", 1, 0),
|
||||
#ifdef NIGHTLY_BUILD
|
||||
JS_SELF_HOSTED_FN("matchAll", "String_matchAll", 1, 0),
|
||||
#endif
|
||||
JS_SELF_HOSTED_FN("search", "String_search", 1, 0),
|
||||
JS_SELF_HOSTED_FN("replace", "String_replace", 2, 0),
|
||||
JS_SELF_HOSTED_FN("split", "String_split", 2, 0),
|
||||
|
|
|
@ -64,6 +64,33 @@ function String_generic_match(thisValue, regexp) {
|
|||
return callFunction(String_match, thisValue, regexp);
|
||||
}
|
||||
|
||||
// String.prototype.matchAll proposal.
|
||||
//
|
||||
// String.prototype.matchAll ( regexp )
|
||||
function String_matchAll(regexp) {
|
||||
// Step 1.
|
||||
RequireObjectCoercible(this);
|
||||
|
||||
// Step 2.
|
||||
if (regexp !== undefined && regexp !== null) {
|
||||
// Step 2.a.
|
||||
var matcher = GetMethod(regexp, std_matchAll);
|
||||
|
||||
// Step 2.b.
|
||||
if (matcher !== undefined)
|
||||
return callContentFunction(matcher, regexp, this);
|
||||
}
|
||||
|
||||
// Step 3.
|
||||
var string = ToString(this);
|
||||
|
||||
// Step 4.
|
||||
var rx = RegExpCreate(regexp, "g");
|
||||
|
||||
// Step 5.
|
||||
return callContentFunction(GetMethod(rx, std_matchAll), rx, string);
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function implementing the logic for both String.prototype.padStart
|
||||
* and String.prototype.padEnd as described in ES7 Draft March 29, 2016
|
||||
|
|
|
@ -64,6 +64,11 @@ JSObject* SymbolObject::initClass(JSContext* cx, Handle<GlobalObject*> global,
|
|||
unsigned attrs = JSPROP_READONLY | JSPROP_PERMANENT;
|
||||
WellKnownSymbols* wks = cx->runtime()->wellKnownSymbols;
|
||||
for (size_t i = 0; i < JS::WellKnownSymbolLimit; i++) {
|
||||
#ifndef NIGHTLY_BUILD
|
||||
if (i == SymbolCode::matchAll) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
value.setSymbol(wks->get(i));
|
||||
if (!NativeDefineDataProperty(cx, ctor, names[i], value, attrs)) {
|
||||
return nullptr;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "mozilla/ReverseIterator.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
|
|
@ -50,9 +50,9 @@
|
|||
* 1. ... JS work, which leads to a request to do GC ...
|
||||
* 2. [first GC slice, which performs all root marking and (maybe) more marking]
|
||||
* 3. ... more JS work is allowed to run ...
|
||||
* 4. [GC mark slice, which runs entirely in GCRuntime::markUntilBudgetExhaused]
|
||||
* 4. [GC mark slice, which runs entirely in GCRuntime::markUntilBudgetExhausted]
|
||||
* 5. ... more JS work ...
|
||||
* 6. [GC mark slice, which runs entirely in GCRuntime::markUntilBudgetExhaused]
|
||||
* 6. [GC mark slice, which runs entirely in GCRuntime::markUntilBudgetExhausted]
|
||||
* 7. ... more JS work ...
|
||||
* 8. [GC marking finishes; sweeping done non-incrementally; GC is done]
|
||||
* 9. ... JS continues uninterrupted now that GC is finishes ...
|
||||
|
|
|
@ -5805,7 +5805,7 @@ bool ArenaLists::foregroundFinalize(FreeOp* fop, AllocKind thingKind,
|
|||
return true;
|
||||
}
|
||||
|
||||
IncrementalProgress GCRuntime::markUntilBudgetExhaused(
|
||||
IncrementalProgress GCRuntime::markUntilBudgetExhausted(
|
||||
SliceBudget& sliceBudget, gcstats::PhaseKind phase) {
|
||||
// Marked GC things may vary between recording and replaying, so marking
|
||||
// and sweeping should not perform any recorded events.
|
||||
|
@ -5813,12 +5813,12 @@ IncrementalProgress GCRuntime::markUntilBudgetExhaused(
|
|||
|
||||
/* Run a marking slice and return whether the stack is now empty. */
|
||||
gcstats::AutoPhase ap(stats(), phase);
|
||||
return marker.markUntilBudgetExhaused(sliceBudget) ? Finished : NotFinished;
|
||||
return marker.markUntilBudgetExhausted(sliceBudget) ? Finished : NotFinished;
|
||||
}
|
||||
|
||||
void GCRuntime::drainMarkStack() {
|
||||
auto unlimited = SliceBudget::unlimited();
|
||||
MOZ_RELEASE_ASSERT(marker.markUntilBudgetExhaused(unlimited));
|
||||
MOZ_RELEASE_ASSERT(marker.markUntilBudgetExhausted(unlimited));
|
||||
}
|
||||
|
||||
static void SweepThing(Shape* shape) {
|
||||
|
@ -6482,7 +6482,7 @@ IncrementalProgress GCRuntime::performSweepActions(SliceBudget& budget) {
|
|||
if (initialState != State::Sweep) {
|
||||
MOZ_ASSERT(marker.isDrained());
|
||||
} else {
|
||||
if (markUntilBudgetExhaused(budget, gcstats::PhaseKind::SWEEP_MARK) ==
|
||||
if (markUntilBudgetExhausted(budget, gcstats::PhaseKind::SWEEP_MARK) ==
|
||||
NotFinished) {
|
||||
return NotFinished;
|
||||
}
|
||||
|
@ -6957,7 +6957,7 @@ void GCRuntime::incrementalSlice(
|
|||
case State::Mark:
|
||||
AutoGCRooter::traceAllWrappers(rt->mainContextFromOwnThread(), &marker);
|
||||
|
||||
if (markUntilBudgetExhaused(budget, gcstats::PhaseKind::MARK) ==
|
||||
if (markUntilBudgetExhausted(budget, gcstats::PhaseKind::MARK) ==
|
||||
NotFinished) {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -286,7 +286,7 @@ class GCMarker : public JSTracer {
|
|||
|
||||
bool isDrained() { return isMarkStackEmpty() && !unmarkedArenaStackTop; }
|
||||
|
||||
MOZ_MUST_USE bool markUntilBudgetExhaused(SliceBudget& budget);
|
||||
MOZ_MUST_USE bool markUntilBudgetExhausted(SliceBudget& budget);
|
||||
|
||||
void setGCMode(JSGCMode mode) { stack.setGCMode(mode); }
|
||||
|
||||
|
|
|
@ -618,8 +618,8 @@ class GCRuntime {
|
|||
void traceRuntimeCommon(JSTracer* trc, TraceOrMarkRuntime traceOrMark);
|
||||
void maybeDoCycleCollection();
|
||||
void markCompartments();
|
||||
IncrementalProgress markUntilBudgetExhaused(SliceBudget& sliceBudget,
|
||||
gcstats::PhaseKind phase);
|
||||
IncrementalProgress markUntilBudgetExhausted(SliceBudget& sliceBudget,
|
||||
gcstats::PhaseKind phase);
|
||||
void drainMarkStack();
|
||||
template <class ZoneIterT>
|
||||
void markWeakReferences(gcstats::PhaseKind phase);
|
||||
|
|
|
@ -1571,7 +1571,7 @@ static void VisitTraceList(F f, const int32_t* traceList, uint8_t* memory,
|
|||
|
||||
/*** Mark-stack Marking *****************************************************/
|
||||
|
||||
bool GCMarker::markUntilBudgetExhaused(SliceBudget& budget) {
|
||||
bool GCMarker::markUntilBudgetExhausted(SliceBudget& budget) {
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(!strictCompartmentChecking);
|
||||
strictCompartmentChecking = true;
|
||||
|
|
|
@ -3381,6 +3381,11 @@ static bool GetTemplateObjectForNative(JSContext* cx, HandleFunction target,
|
|||
return !!res;
|
||||
}
|
||||
|
||||
if (native == js::intrinsic_NewRegExpStringIterator) {
|
||||
res.set(NewRegExpStringIteratorObject(cx, TenuredObject));
|
||||
return !!res;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -6212,6 +6212,13 @@ static const VMFunction NewStringIteratorObjectInfo =
|
|||
FunctionInfo<NewStringIteratorObjectFn>(NewStringIteratorObject,
|
||||
"NewStringIteratorObject");
|
||||
|
||||
typedef RegExpStringIteratorObject* (*NewRegExpStringIteratorObjectFn)(
|
||||
JSContext*, NewObjectKind);
|
||||
|
||||
static const VMFunction NewRegExpStringIteratorObjectInfo =
|
||||
FunctionInfo<NewRegExpStringIteratorObjectFn>(
|
||||
NewRegExpStringIteratorObject, "NewRegExpStringIteratorObject");
|
||||
|
||||
void CodeGenerator::visitNewIterator(LNewIterator* lir) {
|
||||
Register objReg = ToRegister(lir->output());
|
||||
Register tempReg = ToRegister(lir->temp());
|
||||
|
@ -6226,6 +6233,10 @@ void CodeGenerator::visitNewIterator(LNewIterator* lir) {
|
|||
ool = oolCallVM(NewStringIteratorObjectInfo, lir,
|
||||
ArgList(Imm32(GenericObject)), StoreRegisterTo(objReg));
|
||||
break;
|
||||
case MNewIterator::RegExpStringIterator:
|
||||
ool = oolCallVM(NewRegExpStringIteratorObjectInfo, lir,
|
||||
ArgList(Imm32(GenericObject)), StoreRegisterTo(objReg));
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("unexpected iterator type");
|
||||
}
|
||||
|
|
|
@ -125,6 +125,7 @@
|
|||
_(IntrinsicGuardToMapIterator) \
|
||||
_(IntrinsicGuardToSetIterator) \
|
||||
_(IntrinsicGuardToStringIterator) \
|
||||
_(IntrinsicGuardToRegExpStringIterator) \
|
||||
\
|
||||
_(IntrinsicGuardToMapObject) \
|
||||
_(IntrinsicGetNextMapEntryForIterator) \
|
||||
|
@ -134,6 +135,7 @@
|
|||
\
|
||||
_(IntrinsicNewArrayIterator) \
|
||||
_(IntrinsicNewStringIterator) \
|
||||
_(IntrinsicNewRegExpStringIterator) \
|
||||
\
|
||||
_(IntrinsicGuardToArrayBuffer) \
|
||||
_(IntrinsicArrayBufferByteLength) \
|
||||
|
|
|
@ -237,6 +237,8 @@ IonBuilder::InliningResult IonBuilder::inlineNativeCall(CallInfo& callInfo,
|
|||
return inlineRegExpInstanceOptimizable(callInfo);
|
||||
case InlinableNative::GetFirstDollarIndex:
|
||||
return inlineGetFirstDollarIndex(callInfo);
|
||||
case InlinableNative::IntrinsicNewRegExpStringIterator:
|
||||
return inlineNewIterator(callInfo, MNewIterator::RegExpStringIterator);
|
||||
|
||||
// String natives.
|
||||
case InlinableNative::String:
|
||||
|
@ -321,6 +323,8 @@ IonBuilder::InliningResult IonBuilder::inlineNativeCall(CallInfo& callInfo,
|
|||
return inlineGuardToClass(callInfo, &SetIteratorObject::class_);
|
||||
case InlinableNative::IntrinsicGuardToStringIterator:
|
||||
return inlineGuardToClass(callInfo, &StringIteratorObject::class_);
|
||||
case InlinableNative::IntrinsicGuardToRegExpStringIterator:
|
||||
return inlineGuardToClass(callInfo, &RegExpStringIteratorObject::class_);
|
||||
case InlinableNative::IntrinsicObjectHasPrototype:
|
||||
return inlineObjectHasPrototype(callInfo);
|
||||
case InlinableNative::IntrinsicFinishBoundFunctionInit:
|
||||
|
@ -1078,6 +1082,12 @@ IonBuilder::InliningResult IonBuilder::inlineNewIterator(
|
|||
pc, js::intrinsic_NewStringIterator);
|
||||
MOZ_ASSERT_IF(templateObject, templateObject->is<StringIteratorObject>());
|
||||
break;
|
||||
case MNewIterator::RegExpStringIterator:
|
||||
templateObject = inspector->getTemplateObjectForNative(
|
||||
pc, js::intrinsic_NewRegExpStringIterator);
|
||||
MOZ_ASSERT_IF(templateObject,
|
||||
templateObject->is<RegExpStringIteratorObject>());
|
||||
break;
|
||||
}
|
||||
|
||||
if (!templateObject) {
|
||||
|
|
|
@ -2230,6 +2230,7 @@ class MNewIterator : public MUnaryInstruction, public NoTypePolicy::Data {
|
|||
enum Type {
|
||||
ArrayIterator,
|
||||
StringIterator,
|
||||
RegExpStringIterator,
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -1301,6 +1301,9 @@ bool RNewIterator::recover(JSContext* cx, SnapshotIterator& iter) const {
|
|||
case MNewIterator::StringIterator:
|
||||
resultObject = NewStringIteratorObject(cx);
|
||||
break;
|
||||
case MNewIterator::RegExpStringIterator:
|
||||
resultObject = NewRegExpStringIteratorObject(cx);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!resultObject) {
|
||||
|
|
|
@ -428,6 +428,10 @@ struct TypeToDataType<StringIteratorObject*> {
|
|||
static const DataType result = Type_Object;
|
||||
};
|
||||
template <>
|
||||
struct TypeToDataType<RegExpStringIteratorObject*> {
|
||||
static const DataType result = Type_Object;
|
||||
};
|
||||
template <>
|
||||
struct TypeToDataType<JSString*> {
|
||||
static const DataType result = Type_Object;
|
||||
};
|
||||
|
|
|
@ -385,13 +385,18 @@ void CodeGenerator::visitDivI(LDivI* ins) {
|
|||
// Handle division by zero.
|
||||
if (mir->canBeDivideByZero()) {
|
||||
masm.test32(rhs, rhs);
|
||||
// TODO: x64 has an additional mir->canTruncateInfinities() handler
|
||||
// TODO: to avoid taking a bailout.
|
||||
if (mir->trapOnError()) {
|
||||
Label nonZero;
|
||||
masm.j(Assembler::NonZero, &nonZero);
|
||||
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->bytecodeOffset());
|
||||
masm.bind(&nonZero);
|
||||
} else if (mir->canTruncateInfinities()) {
|
||||
// Truncated division by zero is zero: (Infinity|0 = 0).
|
||||
Label nonZero;
|
||||
masm.j(Assembler::NonZero, &nonZero);
|
||||
masm.Mov(output32, wzr);
|
||||
masm.jump(&done);
|
||||
masm.bind(&nonZero);
|
||||
} else {
|
||||
MOZ_ASSERT(mir->fallible());
|
||||
bailoutIf(Assembler::Zero, ins->snapshot());
|
||||
|
|
|
@ -351,11 +351,19 @@ void LIRGenerator::visitWasmAtomicBinopHeap(MWasmAtomicBinopHeap* ins) {
|
|||
}
|
||||
|
||||
void LIRGeneratorARM64::lowerTruncateDToInt32(MTruncateToInt32* ins) {
|
||||
MOZ_CRASH("lowerTruncateDToInt32");
|
||||
MDefinition* opd = ins->input();
|
||||
MOZ_ASSERT(opd->type() == MIRType::Double);
|
||||
define(new (alloc())
|
||||
LTruncateDToInt32(useRegister(opd), LDefinition::BogusTemp()),
|
||||
ins);
|
||||
}
|
||||
|
||||
void LIRGeneratorARM64::lowerTruncateFToInt32(MTruncateToInt32* ins) {
|
||||
MOZ_CRASH("lowerTruncateFToInt32");
|
||||
MDefinition* opd = ins->input();
|
||||
MOZ_ASSERT(opd->type() == MIRType::Float32);
|
||||
define(new (alloc())
|
||||
LTruncateFToInt32(useRegister(opd), LDefinition::BogusTemp()),
|
||||
ins);
|
||||
}
|
||||
|
||||
void LIRGenerator::visitAtomicTypedArrayElementBinop(
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
const t = RegExp.prototype;
|
||||
|
||||
const properties = "toSource,toString,compile,exec,test," +
|
||||
"flags,global,ignoreCase,multiline,source,sticky,unicode," +
|
||||
"constructor," +
|
||||
"Symbol(Symbol.match),Symbol(Symbol.replace),Symbol(Symbol.search),Symbol(Symbol.split)";
|
||||
assertEq(Reflect.ownKeys(t).map(String).toString(), properties);
|
||||
let properties = "toSource,toString,compile,exec,test," +
|
||||
"flags,global,ignoreCase,multiline,source,sticky,unicode," +
|
||||
"constructor," +
|
||||
"Symbol(Symbol.match),Symbol(Symbol.replace),Symbol(Symbol.search),Symbol(Symbol.split)";
|
||||
if (Symbol.matchAll) {
|
||||
properties += ",Symbol(Symbol.matchAll)";
|
||||
}
|
||||
assertEqArray(Reflect.ownKeys(t).map(String).sort(), properties.split(",").sort());
|
||||
|
||||
|
||||
// Invoking getters on the prototype should not throw
|
||||
|
|
|
@ -0,0 +1,290 @@
|
|||
// |reftest| skip-if(!String.prototype.matchAll)
|
||||
|
||||
// Basic surface tests.
|
||||
|
||||
assertEq(typeof String.prototype.matchAll, "function");
|
||||
assertEq(String.prototype.matchAll.name, "matchAll");
|
||||
assertEq(String.prototype.matchAll.length, 1);
|
||||
|
||||
assertEq(typeof Symbol.matchAll, "symbol");
|
||||
|
||||
assertEq(typeof RegExp.prototype[Symbol.matchAll], "function");
|
||||
assertEq(RegExp.prototype[Symbol.matchAll].name, "[Symbol.matchAll]");
|
||||
assertEq(RegExp.prototype[Symbol.matchAll].length, 1);
|
||||
|
||||
const IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
|
||||
const RegExpStringIteratorPrototype = Object.getPrototypeOf("".matchAll(""));
|
||||
|
||||
assertEq(Object.getPrototypeOf(RegExpStringIteratorPrototype), IteratorPrototype);
|
||||
|
||||
assertEq(typeof RegExpStringIteratorPrototype.next, "function");
|
||||
assertEq(RegExpStringIteratorPrototype.next.name, "next");
|
||||
assertEq(RegExpStringIteratorPrototype.next.length, 0);
|
||||
|
||||
assertEq(RegExpStringIteratorPrototype[Symbol.toStringTag], "RegExp String Iterator");
|
||||
|
||||
|
||||
// Basic functional tests.
|
||||
|
||||
const RegExp_prototype_exec = RegExp.prototype.exec;
|
||||
const RegExp_prototype_match = RegExp.prototype[Symbol.match];
|
||||
|
||||
function assertEqIterMatchResult(actual, expected) {
|
||||
assertEq(actual.done, expected.done);
|
||||
if (actual.value === undefined || expected.value === undefined) {
|
||||
assertEq(actual.value, expected.value);
|
||||
} else {
|
||||
assertEqArray(actual.value, expected.value);
|
||||
assertEq(actual.value.input, expected.value.input);
|
||||
assertEq(actual.value.index, expected.value.index);
|
||||
}
|
||||
}
|
||||
|
||||
function assertEqMatchResults(actual, expected) {
|
||||
var actualIter = actual[Symbol.iterator]();
|
||||
var expectedIter = expected[Symbol.iterator]();
|
||||
while (true) {
|
||||
var actualResult = actualIter.next();
|
||||
var expectedResult = expectedIter.next();
|
||||
assertEqIterMatchResult(actualResult, expectedResult);
|
||||
if (actualResult.done && expectedResult.done)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function* matchResults(string, regexp, lastIndex = 0) {
|
||||
regexp.lastIndex = lastIndex;
|
||||
while (true) {
|
||||
var match = Reflect.apply(RegExp_prototype_exec, regexp, [string]);
|
||||
if (match === null)
|
||||
return;
|
||||
yield match;
|
||||
if (!regexp.global)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
assertEqMatchResults("ababcca".matchAll(/a/), matchResults("ababcca", /a/));
|
||||
assertEqMatchResults("ababcca".matchAll(/a/g), matchResults("ababcca", /a/g));
|
||||
assertEqMatchResults("ababcca".matchAll("a"), matchResults("ababcca", /a/g));
|
||||
|
||||
|
||||
// Cross-compartment tests.
|
||||
|
||||
{
|
||||
let otherGlobal = newGlobal();
|
||||
|
||||
let iterator = otherGlobal.eval(`"ababcca".matchAll(/a/)`);
|
||||
let expected = matchResults("ababcca", /a/);
|
||||
|
||||
assertEqIterMatchResult(RegExpStringIteratorPrototype.next.call(iterator),
|
||||
expected.next());
|
||||
}
|
||||
|
||||
|
||||
// Optimization tests.
|
||||
//
|
||||
// The optimized path for MatchAllIterator reuses the input RegExp to avoid
|
||||
// extra RegExp allocations. To make this optimization undetectable from
|
||||
// user code, we need to ensure that:
|
||||
// 1. Modifications to the input RegExp through RegExp.prototype.compile are
|
||||
// detected and properly handled (= ignored).
|
||||
// 2. The RegExpStringIterator doesn't modify the input RegExp, for example
|
||||
// by updating the lastIndex property.
|
||||
// 3. Guards against modifications of built-in RegExp.prototype are installed.
|
||||
|
||||
// Recompile RegExp (source) before first match.
|
||||
{
|
||||
let regexp = /a+/;
|
||||
let iterator = "aabb".matchAll(regexp);
|
||||
|
||||
regexp.compile("b+");
|
||||
assertEqMatchResults(iterator, matchResults("aabb", /a+/));
|
||||
}
|
||||
|
||||
// Recompile RegExp (flags) before first match.
|
||||
{
|
||||
let regexp = /a+/i;
|
||||
let iterator = "aAbb".matchAll(regexp);
|
||||
|
||||
regexp.compile("a+", "");
|
||||
assertEqMatchResults(iterator, matchResults("aAbb", /a+/i));
|
||||
}
|
||||
|
||||
// Recompile RegExp (source) after first match.
|
||||
{
|
||||
let regexp = /a+/g;
|
||||
let iterator = "aabbaa".matchAll(regexp);
|
||||
let expected = matchResults("aabbaa", /a+/g);
|
||||
|
||||
assertEqIterMatchResult(iterator.next(), expected.next());
|
||||
regexp.compile("b+");
|
||||
assertEqIterMatchResult(iterator.next(), expected.next());
|
||||
}
|
||||
|
||||
// Recompile RegExp (flags) after first match.
|
||||
{
|
||||
let regexp = /a+/g;
|
||||
let iterator = "aabbAA".matchAll(regexp);
|
||||
let expected = matchResults("aabbAA", /a+/g);
|
||||
|
||||
assertEqIterMatchResult(iterator.next(), expected.next());
|
||||
regexp.compile("a+", "i");
|
||||
assertEqIterMatchResult(iterator.next(), expected.next());
|
||||
}
|
||||
|
||||
// lastIndex property of input RegExp not modified when optimized path used.
|
||||
{
|
||||
let regexp = /a+/g;
|
||||
regexp.lastIndex = 1;
|
||||
let iterator = "aabbaa".matchAll(regexp);
|
||||
let expected = matchResults("aabbaa", /a+/g, 1);
|
||||
|
||||
assertEq(regexp.lastIndex, 1);
|
||||
assertEqIterMatchResult(iterator.next(), expected.next());
|
||||
assertEq(regexp.lastIndex, 1);
|
||||
assertEqIterMatchResult(iterator.next(), expected.next());
|
||||
assertEq(regexp.lastIndex, 1);
|
||||
}
|
||||
|
||||
// Modifications to lastIndex property of input RegExp ignored when optimized path used.
|
||||
{
|
||||
let regexp = /a+/g;
|
||||
let iterator = "aabbaa".matchAll(regexp);
|
||||
regexp.lastIndex = 1;
|
||||
let expected = matchResults("aabbaa", /a+/g);
|
||||
|
||||
assertEq(regexp.lastIndex, 1);
|
||||
assertEqIterMatchResult(iterator.next(), expected.next());
|
||||
assertEq(regexp.lastIndex, 1);
|
||||
assertEqIterMatchResult(iterator.next(), expected.next());
|
||||
assertEq(regexp.lastIndex, 1);
|
||||
}
|
||||
|
||||
// RegExp.prototype[Symbol.match] is modified to a getter, ensure this getter
|
||||
// is called exactly once.
|
||||
try {
|
||||
let regexp = /a+/g;
|
||||
|
||||
let callCount = 0;
|
||||
Object.defineProperty(RegExp.prototype, Symbol.match, {
|
||||
get() {
|
||||
assertEq(this, regexp);
|
||||
callCount++;
|
||||
return RegExp_prototype_match;
|
||||
}
|
||||
});
|
||||
let iterator = "aabbaa".matchAll(regexp);
|
||||
assertEq(callCount, 1);
|
||||
} finally {
|
||||
// Restore optimizable RegExp.prototype shape.
|
||||
Object.defineProperty(RegExp.prototype, Symbol.match, {
|
||||
value: RegExp_prototype_match,
|
||||
writable: true, enumerable: false, configurable: true
|
||||
});
|
||||
}
|
||||
|
||||
// RegExp.prototype.exec is changed to a getter.
|
||||
try {
|
||||
let regexp = /a+/g;
|
||||
let iterator = "aabbaa".matchAll(regexp);
|
||||
let lastIndices = [0, 2, 6][Symbol.iterator]();
|
||||
|
||||
let iteratorRegExp = null;
|
||||
let callCount = 0;
|
||||
Object.defineProperty(RegExp.prototype, "exec", {
|
||||
get() {
|
||||
callCount++;
|
||||
|
||||
if (iteratorRegExp === null)
|
||||
iteratorRegExp = this;
|
||||
|
||||
assertEq(this === regexp, false);
|
||||
assertEq(this, iteratorRegExp);
|
||||
assertEq(this.source, regexp.source);
|
||||
assertEq(this.flags, regexp.flags);
|
||||
assertEq(this.lastIndex, lastIndices.next().value);
|
||||
return RegExp_prototype_exec;
|
||||
}
|
||||
});
|
||||
|
||||
assertEqMatchResults(iterator, matchResults("aabbaa", /a+/g));
|
||||
assertEq(callCount, 3);
|
||||
} finally {
|
||||
// Restore optimizable RegExp.prototype shape.
|
||||
Object.defineProperty(RegExp.prototype, "exec", {
|
||||
value: RegExp_prototype_exec,
|
||||
writable: true, enumerable: false, configurable: true
|
||||
});
|
||||
}
|
||||
|
||||
// RegExp.prototype.exec is changed to a value property.
|
||||
try {
|
||||
let regexp = /a+/g;
|
||||
let iterator = "aabbaa".matchAll(regexp);
|
||||
let lastIndices = [0, 2, 6][Symbol.iterator]();
|
||||
|
||||
let iteratorRegExp = null;
|
||||
let callCount = 0;
|
||||
RegExp.prototype.exec = function(...args) {
|
||||
callCount++;
|
||||
|
||||
if (iteratorRegExp === null)
|
||||
iteratorRegExp = this;
|
||||
|
||||
assertEq(this === regexp, false);
|
||||
assertEq(this, iteratorRegExp);
|
||||
assertEq(this.source, regexp.source);
|
||||
assertEq(this.flags, regexp.flags);
|
||||
assertEq(this.lastIndex, lastIndices.next().value);
|
||||
return Reflect.apply(RegExp_prototype_exec, this, args);
|
||||
};
|
||||
|
||||
assertEqMatchResults(iterator, matchResults("aabbaa", /a+/g));
|
||||
assertEq(callCount, 3);
|
||||
} finally {
|
||||
// Restore optimizable RegExp.prototype shape.
|
||||
Object.defineProperty(RegExp.prototype, "exec", {
|
||||
value: RegExp_prototype_exec,
|
||||
writable: true, enumerable: false, configurable: true
|
||||
});
|
||||
}
|
||||
|
||||
// Initial 'lastIndex' is zero if the RegExp is neither global nor sticky (1).
|
||||
{
|
||||
let regexp = /a+/;
|
||||
regexp.lastIndex = 2;
|
||||
|
||||
let iterator = regexp[Symbol.matchAll]("aaaaa");
|
||||
assertEqMatchResults(iterator, matchResults("aaaaa", /a+/g, 0));
|
||||
}
|
||||
|
||||
// Initial 'lastIndex' is zero if the RegExp is neither global nor sticky (2).
|
||||
{
|
||||
let regexp = /a+/g;
|
||||
regexp.lastIndex = 2;
|
||||
|
||||
let iterator = regexp[Symbol.matchAll]("aaaaa");
|
||||
assertEqMatchResults(iterator, matchResults("aaaaa", /a+/g, 2));
|
||||
}
|
||||
|
||||
// Initial 'lastIndex' is zero if the RegExp is neither global nor sticky (3).
|
||||
{
|
||||
let regexp = /a+/y;
|
||||
regexp.lastIndex = 2;
|
||||
|
||||
let iterator = regexp[Symbol.matchAll]("aaaaa");
|
||||
assertEqMatchResults(iterator, matchResults("aaaaa", /a+/g, 2));
|
||||
}
|
||||
|
||||
//Initial 'lastIndex' is zero if the RegExp is neither global nor sticky (4).
|
||||
{
|
||||
let regexp = /a+/gy;
|
||||
regexp.lastIndex = 2;
|
||||
|
||||
let iterator = regexp[Symbol.matchAll]("aaaaa");
|
||||
assertEqMatchResults(iterator, matchResults("aaaaa", /a+/g, 2));
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
|
@ -32,8 +32,6 @@ UNSUPPORTED_FEATURES = set([
|
|||
"regexp-unicode-property-escapes",
|
||||
"numeric-separator-literal",
|
||||
"Intl.Locale",
|
||||
"String.prototype.matchAll",
|
||||
"Symbol.matchAll",
|
||||
"global",
|
||||
"export-star-as-namespace-from-module",
|
||||
"Intl.ListFormat",
|
||||
|
@ -45,6 +43,8 @@ FEATURE_CHECK_NEEDED = {
|
|||
"BigInt": "!this.hasOwnProperty('BigInt')",
|
||||
"SharedArrayBuffer": "!this.hasOwnProperty('SharedArrayBuffer')",
|
||||
"dynamic-import": "!xulRuntime.shell",
|
||||
"String.prototype.matchAll": "!String.prototype.hasOwnProperty('matchAll')",
|
||||
"Symbol.matchAll": "!Symbol.hasOwnProperty('matchAll')",
|
||||
}
|
||||
RELEASE_OR_BETA = set()
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Jordan Harband. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Jordan Harband. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Jordan Harband. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Jordan Harband. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Jordan Harband. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- Symbol.matchAll is not supported
|
||||
// |reftest| skip-if(!Symbol.hasOwnProperty('matchAll')) -- Symbol.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Peter Wong. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- String.prototype.matchAll is not supported
|
||||
// |reftest| skip-if(!String.prototype.hasOwnProperty('matchAll')) -- String.prototype.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Jordan Harband. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// |reftest| skip -- String.prototype.matchAll is not supported
|
||||
// |reftest| skip-if(!String.prototype.hasOwnProperty('matchAll')) -- String.prototype.matchAll is not enabled unconditionally
|
||||
// Copyright (C) 2018 Jordan Harband. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче