Merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Razvan Maries 2018-12-14 18:22:09 +02:00
Родитель a965a67574 dcf701b66b
Коммит 87aca70b7f
198 изменённых файлов: 13848 добавлений и 3094 удалений

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

@ -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 = Dont 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(

13
js/src/tests/non262/RegExp/prototype.js поставляемый
Просмотреть файл

@ -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.
/*---

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