зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to fx-team. a=merge
This commit is contained in:
Коммит
740cdfc810
|
@ -85,7 +85,7 @@ tasks:
|
|||
|
||||
# Note: This task is built server side without the context or tooling that
|
||||
# exist in tree so we must hard code the version
|
||||
image: 'taskcluster/decision:0.1.5'
|
||||
image: 'taskcluster/decision:0.1.6'
|
||||
|
||||
maxRunTime: 1800
|
||||
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
"unpack": true
|
||||
},
|
||||
{
|
||||
"version": "cargo 0.13.0-nightly (664125b 2016-07-19)",
|
||||
"size": 3123796,
|
||||
"digest": "4b9d2bcb8488b6649ba6c748e19d33bfceb25c7566e882fc7e00322392e424a5a9c5878c11c61d57cdaecf67bcc110842c6eff95e49736e8f3c83d9ce1677122",
|
||||
"version": "cargo 0.13.0-nightly (e713e7f 2016-08-31)",
|
||||
"size": 3245716,
|
||||
"digest": "d5bb0d88ce7bb1b5a316d7a8ca6341672f5ee8008fa7754511bf53fabd54c0770e95397232896d6087547891f1143f6968d8b1e106e39800b43defeb0025c7c0",
|
||||
"algorithm": "sha512",
|
||||
"filename": "cargo.tar.xz",
|
||||
"unpack": true
|
||||
|
|
|
@ -691,7 +691,7 @@ function gKeywordURIFixup({ target: browser, data: fixupInfo }) {
|
|||
}
|
||||
|
||||
// Ignore number-only things entirely (no decimal IPs for you!)
|
||||
if (/^\d+$/.test(asciiHost))
|
||||
if (/^\d+$/.test(fixupInfo.originalInput.trim()))
|
||||
return;
|
||||
|
||||
let onLookupComplete = (request, record, status) => {
|
||||
|
|
|
@ -17,7 +17,7 @@ add_task(function* closing_tab_with_dependents_should_close_window() {
|
|||
|
||||
let windowClosedPromise = BrowserTestUtils.windowClosed(win);
|
||||
yield BrowserTestUtils.removeTab(tab);
|
||||
is(openedTab.linkedBrowser, null, "Opened tab should also have closed");
|
||||
is(Cu.isDeadWrapper(openedTab) || openedTab.linkedBrowser == null, true, "Opened tab should also have closed");
|
||||
info("If we timeout now, the window failed to close - that shouldn't happen!");
|
||||
yield windowClosedPromise;
|
||||
});
|
||||
|
|
|
@ -38,7 +38,7 @@ function promiseNotificationForTab(aBrowser, value, expected, tab=aBrowser.selec
|
|||
return deferred.promise;
|
||||
}
|
||||
|
||||
function* runURLBarSearchTest(valueToOpen, expectSearch, expectNotification, aWindow=window) {
|
||||
function* runURLBarSearchTest({valueToOpen, expectSearch, expectNotification, aWindow=window}) {
|
||||
aWindow.gURLBar.value = valueToOpen;
|
||||
let expectedURI;
|
||||
if (!expectSearch) {
|
||||
|
@ -62,21 +62,33 @@ function* runURLBarSearchTest(valueToOpen, expectSearch, expectNotification, aWi
|
|||
add_task(function* test_navigate_full_domain() {
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab("about:blank");
|
||||
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
|
||||
yield* runURLBarSearchTest("www.mozilla.org", false, false);
|
||||
yield* runURLBarSearchTest({
|
||||
valueToOpen: "www.mozilla.org",
|
||||
expectSearch: false,
|
||||
expectNotification: false,
|
||||
});
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
|
||||
add_task(function* test_navigate_valid_numbers() {
|
||||
add_task(function* test_navigate_decimal_ip() {
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab("about:blank");
|
||||
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
|
||||
yield* runURLBarSearchTest("1234", true, true);
|
||||
yield* runURLBarSearchTest({
|
||||
valueToOpen: "1234",
|
||||
expectSearch: true,
|
||||
expectNotification: false,
|
||||
});
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
|
||||
add_task(function* test_navigate_invalid_numbers() {
|
||||
add_task(function* test_navigate_large_number() {
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab("about:blank");
|
||||
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
|
||||
yield* runURLBarSearchTest("123456789012345", true, false);
|
||||
yield* runURLBarSearchTest({
|
||||
valueToOpen: "123456789012345",
|
||||
expectSearch: true,
|
||||
expectNotification: false
|
||||
});
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
function get_test_function_for_localhost_with_hostname(hostName, isPrivate) {
|
||||
|
@ -96,7 +108,12 @@ function get_test_function_for_localhost_with_hostname(hostName, isPrivate) {
|
|||
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
|
||||
|
||||
Services.prefs.setBoolPref(pref, false);
|
||||
yield* runURLBarSearchTest(hostName, true, true, win);
|
||||
yield* runURLBarSearchTest({
|
||||
valueToOpen: hostName,
|
||||
expectSearch: true,
|
||||
expectNotification: true,
|
||||
aWindow: win,
|
||||
});
|
||||
|
||||
let notificationBox = browser.getNotificationBox(tab.linkedBrowser);
|
||||
let notification = notificationBox.getNotificationWithValue("keyword-uri-fixup");
|
||||
|
@ -114,7 +131,12 @@ function get_test_function_for_localhost_with_hostname(hostName, isPrivate) {
|
|||
tab = browser.selectedTab = browser.addTab("about:blank");
|
||||
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
|
||||
// In a private window, the notification should appear again.
|
||||
yield* runURLBarSearchTest(hostName, isPrivate, isPrivate, win);
|
||||
yield* runURLBarSearchTest({
|
||||
valueToOpen: hostName,
|
||||
expectSearch: isPrivate,
|
||||
expectNotification: isPrivate,
|
||||
aWindow: win,
|
||||
});
|
||||
browser.removeTab(tab);
|
||||
if (isPrivate) {
|
||||
info("Waiting for private window to close");
|
||||
|
@ -134,6 +156,10 @@ add_task(get_test_function_for_localhost_with_hostname("localhost", true));
|
|||
add_task(function* test_navigate_invalid_url() {
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab("about:blank");
|
||||
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
|
||||
yield* runURLBarSearchTest("mozilla is awesome", true, false);
|
||||
yield* runURLBarSearchTest({
|
||||
valueToOpen: "mozilla is awesome",
|
||||
expectSearch: true,
|
||||
expectNotification: false,
|
||||
});
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
|
|
|
@ -848,7 +848,7 @@ BrowserGlue.prototype = {
|
|||
|
||||
if (samples >= Services.prefs.getIntPref("browser.slowStartup.maxSamples")) {
|
||||
if (averageTime > Services.prefs.getIntPref("browser.slowStartup.timeThreshold"))
|
||||
this._showSlowStartupNotification();
|
||||
this._calculateProfileAgeInDays().then(this._showSlowStartupNotification, null);
|
||||
averageTime = 0;
|
||||
samples = 0;
|
||||
}
|
||||
|
@ -857,7 +857,25 @@ BrowserGlue.prototype = {
|
|||
Services.prefs.setIntPref("browser.slowStartup.samples", samples);
|
||||
},
|
||||
|
||||
_showSlowStartupNotification: function () {
|
||||
_calculateProfileAgeInDays: Task.async(function* () {
|
||||
let ProfileAge = Cu.import("resource://gre/modules/ProfileAge.jsm", {}).ProfileAge;
|
||||
let profileAge = new ProfileAge(null, null);
|
||||
|
||||
let creationDate = yield profileAge.created;
|
||||
let resetDate = yield profileAge.reset;
|
||||
|
||||
// if the profile was reset, consider the
|
||||
// reset date for its age.
|
||||
let profileDate = resetDate || creationDate;
|
||||
|
||||
const ONE_DAY = 24 * 60 * 60 * 1000;
|
||||
return (Date.now() - profileDate) / ONE_DAY;
|
||||
}),
|
||||
|
||||
_showSlowStartupNotification: function (profileAge) {
|
||||
if (profileAge < 90) // 3 months
|
||||
return;
|
||||
|
||||
let win = RecentWindow.getMostRecentBrowserWindow();
|
||||
if (!win)
|
||||
return;
|
||||
|
|
|
@ -127,7 +127,20 @@ var gSecurityPane = {
|
|||
*/
|
||||
showPasswordExceptions: function ()
|
||||
{
|
||||
gSubDialog.open("chrome://passwordmgr/content/passwordManagerExceptions.xul");
|
||||
var bundlePrefs = document.getElementById("bundlePreferences");
|
||||
var params = {
|
||||
blockVisible: true,
|
||||
sessionVisible: false,
|
||||
allowVisible: false,
|
||||
hideStatusColumn: true,
|
||||
prefilledHost: "",
|
||||
permissionType: "login-saving",
|
||||
windowTitle: bundlePrefs.getString("savedLoginsExceptions_title"),
|
||||
introText: bundlePrefs.getString("savedLoginsExceptions_desc")
|
||||
};
|
||||
|
||||
gSubDialog.open("chrome://browser/content/preferences/permissions.xul",
|
||||
null, params);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -306,7 +306,7 @@ var gPermissionManager = {
|
|||
this._handleCapabilityChange();
|
||||
}
|
||||
else if (aData == "deleted") {
|
||||
this._removePermissionFromList(permission);
|
||||
this._removePermissionFromList(permission.principal);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
"unpack": true
|
||||
},
|
||||
{
|
||||
"version": "cargo 0.13.0-nightly (664125b 2016-07-19)",
|
||||
"size": 3123796,
|
||||
"digest": "4b9d2bcb8488b6649ba6c748e19d33bfceb25c7566e882fc7e00322392e424a5a9c5878c11c61d57cdaecf67bcc110842c6eff95e49736e8f3c83d9ce1677122",
|
||||
"version": "cargo 0.13.0-nightly (e713e7f 2016-08-31)",
|
||||
"size": 3245716,
|
||||
"digest": "d5bb0d88ce7bb1b5a316d7a8ca6341672f5ee8008fa7754511bf53fabd54c0770e95397232896d6087547891f1143f6968d8b1e106e39800b43defeb0025c7c0",
|
||||
"algorithm": "sha512",
|
||||
"filename": "cargo.tar.xz",
|
||||
"unpack": true
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
"unpack": true
|
||||
},
|
||||
{
|
||||
"version": "cargo 0.13.0-nightly (664125b 2016-07-19)",
|
||||
"size": 3123796,
|
||||
"digest": "4b9d2bcb8488b6649ba6c748e19d33bfceb25c7566e882fc7e00322392e424a5a9c5878c11c61d57cdaecf67bcc110842c6eff95e49736e8f3c83d9ce1677122",
|
||||
"version": "cargo 0.13.0-nightly (e713e7f 2016-08-31)",
|
||||
"size": 3245716,
|
||||
"digest": "d5bb0d88ce7bb1b5a316d7a8ca6341672f5ee8008fa7754511bf53fabd54c0770e95397232896d6087547891f1143f6968d8b1e106e39800b43defeb0025c7c0",
|
||||
"algorithm": "sha512",
|
||||
"filename": "cargo.tar.xz",
|
||||
"unpack": true
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
"unpack": true
|
||||
},
|
||||
{
|
||||
"version": "cargo 0.13.0-nightly (664125b 2016-07-19)",
|
||||
"size": 2571167,
|
||||
"digest": "b2616459fbf15c75b54628a6bfe8cf89c0841ea08431f5096e72be4fac4c685785dfc7a2f18a03a5f7bd377e78d3c108e5029b12616842cbbd0497ff7363fdaf",
|
||||
"version": "cargo 0.13.0-nightly (e713e7f 2016-08-31)",
|
||||
"size": 2715131,
|
||||
"digest": "f037d2bbbeccb2c95519e083d6d9eecb5cb06a510e849b5721d6933a6c2428203b93ed3d20d3f20329f4d4eee17177d762f051b1ae79fee97d93b84611f3df66",
|
||||
"algorithm": "sha512",
|
||||
"filename": "cargo.tar.bz2",
|
||||
"unpack": true
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
"unpack": true
|
||||
},
|
||||
{
|
||||
"version": "cargo 0.13.0-nightly (664125b 2016-07-19)",
|
||||
"size": 2298848,
|
||||
"digest": "d3d1f7b6d195248550f98eb8ce87aa314d36a8a667c110ff2058777fe5a97b7007a41dc1c8a4605c4230e9105972768918222352d5e0fdebbc49639671de38ca",
|
||||
"version": "cargo 0.13.0-nightly (e713e7f 2016-08-31)",
|
||||
"size": 2402000,
|
||||
"digest": "56f12f7ac437742ed717ce0ccfb0b4134160948e45d73016e48d9033567e5b01a171ac95dd7965eb007702c31da73274b5913281655f461f611ddeee37181ecc",
|
||||
"algorithm": "sha512",
|
||||
"filename": "cargo.tar.bz2",
|
||||
"unpack": true
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
"unpack": true
|
||||
},
|
||||
{
|
||||
"version": "cargo 0.13.0-nightly (664125b 2016-07-19)",
|
||||
"size": 2561498,
|
||||
"digest": "d300fd06b16efe49bdb1a238d516c8797d2de0edca7efadd55249401e1dd1d775fb84649630e273f95d9e8b956d87d1f75726c0a68294d25fafe078c3b2b9ba9",
|
||||
"version": "cargo 0.13.0-nightly (e713e7f 2016-08-31)",
|
||||
"size": 2677831,
|
||||
"digest": "eada1edd6142dcde907f14f23c08a2a0b86f108a8fb242f62be6573bbbe1d3b2a4a04c05465d561253d6a617e18cdabee3c87d8cef9a1b5bdd20fe835ef25ff1",
|
||||
"algorithm": "sha512",
|
||||
"filename": "cargo.tar.bz2",
|
||||
"unpack": true
|
||||
|
|
|
@ -17,7 +17,8 @@ const TEST_THRESHOLD = {
|
|||
};
|
||||
|
||||
const ADDON_ROLLOUT_POLICY = {
|
||||
"beta" : "2a", // Set 2 + any WebExtension
|
||||
"beta" : "49a", // 10 tested add-ons + any WebExtension
|
||||
"release" : "49a", // 10 tested add-ons + any WebExtension
|
||||
};
|
||||
|
||||
const PREF_COHORT_SAMPLE = "e10s.rollout.cohortSample";
|
||||
|
|
|
@ -141,13 +141,6 @@
|
|||
@RESPATH@/run-mozilla.sh
|
||||
#endif
|
||||
#endif
|
||||
#ifdef XP_WIN
|
||||
#ifdef _AMD64_
|
||||
@BINPATH@/@DLL_PREFIX@qipcap64@DLL_SUFFIX@
|
||||
#else
|
||||
@BINPATH@/@DLL_PREFIX@qipcap@DLL_SUFFIX@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
; [Components]
|
||||
#ifdef MOZ_ARTIFACT_BUILDS
|
||||
|
|
|
@ -31,6 +31,8 @@ notificationspermissionstext4=Control which websites are always or never allowed
|
|||
notificationspermissionstitle=Notification Permissions
|
||||
invalidURI=Please enter a valid hostname
|
||||
invalidURITitle=Invalid Hostname Entered
|
||||
savedLoginsExceptions_title=Exceptions - Saved Logins
|
||||
savedLoginsExceptions_desc=Logins for the following sites will not be saved:
|
||||
|
||||
#### Block List Manager
|
||||
|
||||
|
|
|
@ -24,4 +24,5 @@ support-files =
|
|||
[browser_taskbar_preview.js]
|
||||
skip-if = os != "win"
|
||||
[browser_UsageTelemetry.js]
|
||||
[browser_UsageTelemetry_private_and_restore.js]
|
||||
[browser_urlBar_zoom.js]
|
||||
|
|
|
@ -44,15 +44,6 @@ function browserLocationChanged(browser) {
|
|||
});
|
||||
}
|
||||
|
||||
function promiseBrowserStateRestored() {
|
||||
return new Promise(resolve => {
|
||||
Services.obs.addObserver(function observer(aSubject, aTopic) {
|
||||
Services.obs.removeObserver(observer, "sessionstore-browser-state-restored");
|
||||
resolve();
|
||||
}, "sessionstore-browser-state-restored", false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* An helper that checks the value of a scalar if it's expected to be > 0,
|
||||
* otherwise makes sure that the scalar it's not reported.
|
||||
|
@ -251,74 +242,3 @@ add_task(function* test_URIAndDomainCounts() {
|
|||
yield BrowserTestUtils.removeTab(firstTab);
|
||||
yield BrowserTestUtils.closeWindow(newWin);
|
||||
});
|
||||
|
||||
add_task(function* test_privateMode() {
|
||||
// Let's reset the counts.
|
||||
Services.telemetry.clearScalars();
|
||||
|
||||
// Open a private window and load a website in it.
|
||||
let privateWin = yield BrowserTestUtils.openNewBrowserWindow({private: true});
|
||||
yield BrowserTestUtils.loadURI(privateWin.gBrowser.selectedBrowser, "http://example.com/");
|
||||
yield BrowserTestUtils.browserLoaded(privateWin.gBrowser.selectedBrowser);
|
||||
|
||||
// Check that tab and window count is recorded.
|
||||
const scalars =
|
||||
Services.telemetry.snapshotScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN);
|
||||
|
||||
ok(!(TOTAL_URI_COUNT in scalars), "We should not track URIs in private mode.");
|
||||
ok(!(UNIQUE_DOMAINS_COUNT in scalars), "We should not track unique domains in private mode.");
|
||||
is(scalars[TAB_EVENT_COUNT], 1, "The number of open tab event count must match the expected value.");
|
||||
is(scalars[MAX_CONCURRENT_TABS], 2, "The maximum tab count must match the expected value.");
|
||||
is(scalars[WINDOW_OPEN_COUNT], 1, "The number of window open event count must match the expected value.");
|
||||
is(scalars[MAX_CONCURRENT_WINDOWS], 2, "The maximum window count must match the expected value.");
|
||||
|
||||
// Clean up.
|
||||
yield BrowserTestUtils.closeWindow(privateWin);
|
||||
});
|
||||
|
||||
add_task(function* test_sessionRestore() {
|
||||
const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
|
||||
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false);
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
|
||||
});
|
||||
|
||||
// Let's reset the counts.
|
||||
Services.telemetry.clearScalars();
|
||||
|
||||
// The first window will be put into the already open window and the second
|
||||
// window will be opened with _openWindowWithState, which is the source of the problem.
|
||||
const state = {
|
||||
windows: [
|
||||
{
|
||||
tabs: [
|
||||
{ entries: [{ url: "http://example.org" }], extData: { "uniq": 3785 } }
|
||||
],
|
||||
selected: 1
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// Save the current session.
|
||||
let SessionStore =
|
||||
Cu.import("resource:///modules/sessionstore/SessionStore.jsm", {}).SessionStore;
|
||||
let backupState = SessionStore.getBrowserState();
|
||||
|
||||
// Load the custom state and wait for SSTabRestored, as we want to make sure
|
||||
// that the URI counting code was hit.
|
||||
let tabRestored = BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "SSTabRestored");
|
||||
SessionStore.setBrowserState(JSON.stringify(state));
|
||||
yield tabRestored;
|
||||
|
||||
// Check that the URI is not recorded.
|
||||
const scalars =
|
||||
Services.telemetry.snapshotScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN);
|
||||
|
||||
ok(!(TOTAL_URI_COUNT in scalars), "We should not track URIs from restored sessions.");
|
||||
ok(!(UNIQUE_DOMAINS_COUNT in scalars), "We should not track unique domains from restored sessions.");
|
||||
|
||||
// Restore the original session and cleanup.
|
||||
let sessionRestored = promiseBrowserStateRestored();
|
||||
SessionStore.setBrowserState(JSON.stringify(state));
|
||||
yield sessionRestored;
|
||||
});
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
"use strict";
|
||||
|
||||
const MAX_CONCURRENT_TABS = "browser.engagement.max_concurrent_tab_count";
|
||||
const TAB_EVENT_COUNT = "browser.engagement.tab_open_event_count";
|
||||
const MAX_CONCURRENT_WINDOWS = "browser.engagement.max_concurrent_window_count";
|
||||
const WINDOW_OPEN_COUNT = "browser.engagement.window_open_event_count";
|
||||
const TOTAL_URI_COUNT = "browser.engagement.total_uri_count";
|
||||
const UNIQUE_DOMAINS_COUNT = "browser.engagement.unique_domains_count";
|
||||
|
||||
function promiseBrowserStateRestored() {
|
||||
return new Promise(resolve => {
|
||||
Services.obs.addObserver(function observer(aSubject, aTopic) {
|
||||
Services.obs.removeObserver(observer, "sessionstore-browser-state-restored");
|
||||
resolve();
|
||||
}, "sessionstore-browser-state-restored", false);
|
||||
});
|
||||
}
|
||||
|
||||
add_task(function* test_privateMode() {
|
||||
// Let's reset the counts.
|
||||
Services.telemetry.clearScalars();
|
||||
|
||||
// Open a private window and load a website in it.
|
||||
let privateWin = yield BrowserTestUtils.openNewBrowserWindow({private: true});
|
||||
yield BrowserTestUtils.loadURI(privateWin.gBrowser.selectedBrowser, "http://example.com/");
|
||||
yield BrowserTestUtils.browserLoaded(privateWin.gBrowser.selectedBrowser);
|
||||
|
||||
// Check that tab and window count is recorded.
|
||||
const scalars =
|
||||
Services.telemetry.snapshotScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN);
|
||||
|
||||
ok(!(TOTAL_URI_COUNT in scalars), "We should not track URIs in private mode.");
|
||||
ok(!(UNIQUE_DOMAINS_COUNT in scalars), "We should not track unique domains in private mode.");
|
||||
is(scalars[TAB_EVENT_COUNT], 1, "The number of open tab event count must match the expected value.");
|
||||
is(scalars[MAX_CONCURRENT_TABS], 2, "The maximum tab count must match the expected value.");
|
||||
is(scalars[WINDOW_OPEN_COUNT], 1, "The number of window open event count must match the expected value.");
|
||||
is(scalars[MAX_CONCURRENT_WINDOWS], 2, "The maximum window count must match the expected value.");
|
||||
|
||||
// Clean up.
|
||||
yield BrowserTestUtils.closeWindow(privateWin);
|
||||
});
|
||||
|
||||
add_task(function* test_sessionRestore() {
|
||||
const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
|
||||
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false);
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
|
||||
});
|
||||
|
||||
// Let's reset the counts.
|
||||
Services.telemetry.clearScalars();
|
||||
|
||||
// The first window will be put into the already open window and the second
|
||||
// window will be opened with _openWindowWithState, which is the source of the problem.
|
||||
const state = {
|
||||
windows: [
|
||||
{
|
||||
tabs: [
|
||||
{ entries: [{ url: "http://example.org" }], extData: { "uniq": 3785 } }
|
||||
],
|
||||
selected: 1
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// Save the current session.
|
||||
let SessionStore =
|
||||
Cu.import("resource:///modules/sessionstore/SessionStore.jsm", {}).SessionStore;
|
||||
let backupState = SessionStore.getBrowserState();
|
||||
|
||||
// Load the custom state and wait for SSTabRestored, as we want to make sure
|
||||
// that the URI counting code was hit.
|
||||
let tabRestored = BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "SSTabRestored");
|
||||
SessionStore.setBrowserState(JSON.stringify(state));
|
||||
yield tabRestored;
|
||||
|
||||
// Check that the URI is not recorded.
|
||||
const scalars =
|
||||
Services.telemetry.snapshotScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN);
|
||||
|
||||
ok(!(TOTAL_URI_COUNT in scalars), "We should not track URIs from restored sessions.");
|
||||
ok(!(UNIQUE_DOMAINS_COUNT in scalars), "We should not track unique domains from restored sessions.");
|
||||
|
||||
// Restore the original session and cleanup.
|
||||
let sessionRestored = promiseBrowserStateRestored();
|
||||
SessionStore.setBrowserState(JSON.stringify(state));
|
||||
yield sessionRestored;
|
||||
});
|
|
@ -440,12 +440,10 @@
|
|||
|
||||
.tabbrowser-tab::after,
|
||||
.tabbrowser-tab::before {
|
||||
width: 1px;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 4px;
|
||||
margin-inline-start: -1px;
|
||||
background-image: linear-gradient(transparent 5px,
|
||||
currentColor 5px,
|
||||
currentColor calc(100% - 4px),
|
||||
transparent calc(100% - 4px));
|
||||
border-left: 1px solid currentColor;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
|
|
|
@ -147,6 +147,7 @@ skip-if = os == "mac" # Full keyboard navigation on OSX only works if Full Keybo
|
|||
[browser_inspector_search-08.js]
|
||||
[browser_inspector_search-clear.js]
|
||||
[browser_inspector_search-filter_context-menu.js]
|
||||
subsuite = clipboard
|
||||
[browser_inspector_search_keyboard_trap.js]
|
||||
[browser_inspector_search-label.js]
|
||||
[browser_inspector_search-reserved.js]
|
||||
|
|
|
@ -1548,6 +1548,19 @@ OpenFile(nsIPrincipal* aPrincipal,
|
|||
return JS::AsmJSCache_SynchronousScript;
|
||||
}
|
||||
|
||||
// Check to see whether the principal reflects a private browsing session.
|
||||
// Since AsmJSCache requires disk access at the moment, caching should be
|
||||
// disabled in private browsing situations. Failing here will cause later
|
||||
// read/write requests to also fail.
|
||||
uint32_t pbId;
|
||||
if (NS_WARN_IF(NS_FAILED(aPrincipal->GetPrivateBrowsingId(&pbId)))) {
|
||||
return JS::AsmJSCache_InternalError;
|
||||
}
|
||||
|
||||
if (pbId > 0) {
|
||||
return JS::AsmJSCache_Disabled_PrivateBrowsing;
|
||||
}
|
||||
|
||||
// We need to synchronously call into the parent to open the file and
|
||||
// interact with the QuotaManager. The child can then map the file into its
|
||||
// address space to perform I/O.
|
||||
|
|
|
@ -185,7 +185,7 @@ public:
|
|||
{
|
||||
nsCOMPtr<nsIParser> parser = do_QueryReferent(mCreatorParser);
|
||||
if (parser) {
|
||||
parser->BeginEvaluatingParserInsertedScript();
|
||||
parser->PushDefinedInsertionPoint();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,7 +196,7 @@ public:
|
|||
{
|
||||
nsCOMPtr<nsIParser> parser = do_QueryReferent(mCreatorParser);
|
||||
if (parser) {
|
||||
parser->EndEvaluatingParserInsertedScript();
|
||||
parser->PopDefinedInsertionPoint();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,15 @@ nsScriptElement::ScriptAvailable(nsresult aResult,
|
|||
int32_t aLineNo)
|
||||
{
|
||||
if (!aIsInline && NS_FAILED(aResult)) {
|
||||
return FireErrorEvent();
|
||||
nsCOMPtr<nsIParser> parser = do_QueryReferent(mCreatorParser);
|
||||
if (parser) {
|
||||
parser->PushDefinedInsertionPoint();
|
||||
}
|
||||
nsresult rv = FireErrorEvent();
|
||||
if (parser) {
|
||||
parser->PopDefinedInsertionPoint();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -2524,8 +2524,16 @@ nsScriptLoader::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
|
|||
MOZ_ASSERT(!request->isInList());
|
||||
mParserBlockingRequest = nullptr;
|
||||
UnblockParser(request);
|
||||
|
||||
// Ensure that we treat request->mElement as our current parser-inserted
|
||||
// script while firing onerror on it.
|
||||
MOZ_ASSERT(request->mElement->GetParserCreated());
|
||||
nsCOMPtr<nsIScriptElement> oldParserInsertedScript =
|
||||
mCurrentParserInsertedScript;
|
||||
mCurrentParserInsertedScript = request->mElement;
|
||||
FireScriptAvailable(rv, request);
|
||||
ContinueParserAsync(request);
|
||||
mCurrentParserInsertedScript = oldParserInsertedScript;
|
||||
} else {
|
||||
mPreloads.RemoveElement(request, PreloadRequestComparator());
|
||||
}
|
||||
|
|
|
@ -1292,15 +1292,15 @@ XrayResolveAttribute(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
|||
desc.setAttributes(attrSpec.flags);
|
||||
// They all have getters, so we can just make it.
|
||||
JS::Rooted<JSObject*> funobj(cx,
|
||||
XrayCreateFunction(cx, wrapper, attrSpec.getter.native, 0, id));
|
||||
XrayCreateFunction(cx, wrapper, attrSpec.accessors.getter.native, 0, id));
|
||||
if (!funobj)
|
||||
return false;
|
||||
desc.setGetterObject(funobj);
|
||||
desc.attributesRef() |= JSPROP_GETTER;
|
||||
if (attrSpec.setter.native.op) {
|
||||
if (attrSpec.accessors.setter.native.op) {
|
||||
// We have a setter! Make it.
|
||||
funobj =
|
||||
XrayCreateFunction(cx, wrapper, attrSpec.setter.native, 1, id);
|
||||
XrayCreateFunction(cx, wrapper, attrSpec.accessors.setter.native, 1, id);
|
||||
if (!funobj)
|
||||
return false;
|
||||
desc.setSetterObject(funobj);
|
||||
|
|
|
@ -3063,15 +3063,15 @@ struct CreateGlobalOptions<nsGlobalWindow>
|
|||
nsresult
|
||||
RegisterDOMNames();
|
||||
|
||||
// The return value is whatever the ProtoHandleGetter we used
|
||||
// returned. This should be the DOM prototype for the global.
|
||||
// The return value is true if we created and successfully performed our part of
|
||||
// the setup for the global, false otherwise.
|
||||
//
|
||||
// Typically this method's caller will want to ensure that
|
||||
// xpc::InitGlobalObjectOptions is called before, and xpc::InitGlobalObject is
|
||||
// called after, this method, to ensure that this global object and its
|
||||
// compartment are consistent with other global objects.
|
||||
template <class T, ProtoHandleGetter GetProto>
|
||||
JS::Handle<JSObject*>
|
||||
bool
|
||||
CreateGlobal(JSContext* aCx, T* aNative, nsWrapperCache* aCache,
|
||||
const JSClass* aClass, JS::CompartmentOptions& aOptions,
|
||||
JSPrincipals* aPrincipal, bool aInitStandardClasses,
|
||||
|
@ -3086,7 +3086,7 @@ CreateGlobal(JSContext* aCx, T* aNative, nsWrapperCache* aCache,
|
|||
JS::DontFireOnNewGlobalHook, aOptions));
|
||||
if (!aGlobal) {
|
||||
NS_WARNING("Failed to create global");
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
JSAutoCompartment ac(aCx, aGlobal);
|
||||
|
@ -3101,31 +3101,31 @@ CreateGlobal(JSContext* aCx, T* aNative, nsWrapperCache* aCache,
|
|||
CreateGlobalOptions<T>::ProtoAndIfaceCacheKind);
|
||||
|
||||
if (!CreateGlobalOptions<T>::PostCreateGlobal(aCx, aGlobal)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (aInitStandardClasses &&
|
||||
!JS_InitStandardClasses(aCx, aGlobal)) {
|
||||
NS_WARNING("Failed to init standard classes");
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::Handle<JSObject*> proto = GetProto(aCx);
|
||||
if (!proto || !JS_SplicePrototype(aCx, aGlobal, proto)) {
|
||||
NS_WARNING("Failed to set proto");
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool succeeded;
|
||||
if (!JS_SetImmutablePrototype(aCx, aGlobal, &succeeded)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(succeeded,
|
||||
"making a fresh global object's [[Prototype]] immutable can "
|
||||
"internally fail, but it should never be unsuccessful");
|
||||
|
||||
return proto;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -586,7 +586,10 @@ class CGPrototypeJSClass(CGThing):
|
|||
def define(self):
|
||||
prototypeID, depth = PrototypeIDAndDepth(self.descriptor)
|
||||
slotCount = "DOM_INTERFACE_PROTO_SLOTS_BASE"
|
||||
if self.descriptor.hasUnforgeableMembers:
|
||||
# Globals handle unforgeables directly in Wrap() instead of
|
||||
# via a holder.
|
||||
if (self.descriptor.hasUnforgeableMembers and
|
||||
not self.descriptor.isGlobal()):
|
||||
slotCount += " + 1 /* slot for the JSObject holding the unforgeable properties */"
|
||||
(protoGetter, _) = InterfacePrototypeObjectProtoGetter(self.descriptor)
|
||||
type = "eGlobalInterfacePrototype" if self.descriptor.isGlobal() else "eInterfacePrototype"
|
||||
|
@ -2527,7 +2530,7 @@ class AttrDefiner(PropertyDefiner):
|
|||
|
||||
return self.generatePrefableArray(
|
||||
array, name,
|
||||
lambda fields: ' { "%s", %s, %s, %s}' % fields,
|
||||
lambda fields: ' { "%s", %s, { { %s, %s } } }' % fields,
|
||||
' JS_PS_END',
|
||||
'JSPropertySpec',
|
||||
PropertyDefiner.getControllingCondition, specData, doIdArrays)
|
||||
|
@ -2930,7 +2933,9 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
|||
else:
|
||||
defineAliases = None
|
||||
|
||||
if self.descriptor.hasUnforgeableMembers:
|
||||
# Globals handle unforgeables directly in Wrap() instead of
|
||||
# via a holder.
|
||||
if self.descriptor.hasUnforgeableMembers and not self.descriptor.isGlobal():
|
||||
assert needInterfacePrototypeObject
|
||||
|
||||
# We want to use the same JSClass and prototype as the object we'll
|
||||
|
@ -2939,12 +2944,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
|||
# a fast copy. In the case of proxies that's null, because the
|
||||
# expando object is a vanilla object, but in the case of other DOM
|
||||
# objects it's whatever our class is.
|
||||
#
|
||||
# Also, for a global we can't use the global's class; just use
|
||||
# nullpr and when we do the copy off the holder we'll take a slower
|
||||
# path. This also means that we don't need to worry about matching
|
||||
# the prototype.
|
||||
if self.descriptor.proxy or self.descriptor.isGlobal():
|
||||
if self.descriptor.proxy:
|
||||
holderClass = "nullptr"
|
||||
holderProto = "nullptr"
|
||||
else:
|
||||
|
@ -3334,7 +3334,8 @@ def CreateBindingJSObject(descriptor, properties):
|
|||
return objDecl + create
|
||||
|
||||
|
||||
def InitUnforgeablePropertiesOnHolder(descriptor, properties, failureCode):
|
||||
def InitUnforgeablePropertiesOnHolder(descriptor, properties, failureCode,
|
||||
holderName="unforgeableHolder"):
|
||||
"""
|
||||
Define the unforgeable properties on the unforgeable holder for
|
||||
the interface represented by descriptor.
|
||||
|
@ -3351,18 +3352,20 @@ def InitUnforgeablePropertiesOnHolder(descriptor, properties, failureCode):
|
|||
|
||||
defineUnforgeableAttrs = fill(
|
||||
"""
|
||||
if (!DefineUnforgeableAttributes(aCx, unforgeableHolder, %s)) {
|
||||
if (!DefineUnforgeableAttributes(aCx, ${holderName}, %s)) {
|
||||
$*{failureCode}
|
||||
}
|
||||
""",
|
||||
failureCode=failureCode)
|
||||
failureCode=failureCode,
|
||||
holderName=holderName)
|
||||
defineUnforgeableMethods = fill(
|
||||
"""
|
||||
if (!DefineUnforgeableMethods(aCx, unforgeableHolder, %s)) {
|
||||
if (!DefineUnforgeableMethods(aCx, ${holderName}, %s)) {
|
||||
$*{failureCode}
|
||||
}
|
||||
""",
|
||||
failureCode=failureCode)
|
||||
failureCode=failureCode,
|
||||
holderName=holderName)
|
||||
|
||||
unforgeableMembers = [
|
||||
(defineUnforgeableAttrs, properties.unforgeableAttrs),
|
||||
|
@ -3384,25 +3387,28 @@ def InitUnforgeablePropertiesOnHolder(descriptor, properties, failureCode):
|
|||
"""
|
||||
JS::RootedId toPrimitive(aCx,
|
||||
SYMBOL_TO_JSID(JS::GetWellKnownSymbol(aCx, JS::SymbolCode::toPrimitive)));
|
||||
if (!JS_DefinePropertyById(aCx, unforgeableHolder, toPrimitive,
|
||||
if (!JS_DefinePropertyById(aCx, ${holderName}, toPrimitive,
|
||||
JS::UndefinedHandleValue,
|
||||
JSPROP_READONLY | JSPROP_PERMANENT) ||
|
||||
!JS_DefineProperty(aCx, unforgeableHolder, "toJSON",
|
||||
!JS_DefineProperty(aCx, ${holderName}, "toJSON",
|
||||
JS::UndefinedHandleValue,
|
||||
JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT)) {
|
||||
$*{failureCode}
|
||||
}
|
||||
""",
|
||||
failureCode=failureCode)))
|
||||
failureCode=failureCode,
|
||||
holderName=holderName)))
|
||||
|
||||
return CGWrapper(CGList(unforgeables), pre="\n")
|
||||
|
||||
|
||||
def CopyUnforgeablePropertiesToInstance(descriptor, wrapperCache):
|
||||
def CopyUnforgeablePropertiesToInstance(descriptor, failureCode):
|
||||
"""
|
||||
Copy the unforgeable properties from the unforgeable holder for
|
||||
this interface to the instance object we have.
|
||||
"""
|
||||
assert not descriptor.isGlobal();
|
||||
|
||||
if not descriptor.hasUnforgeableMembers:
|
||||
return ""
|
||||
|
||||
|
@ -3416,15 +3422,6 @@ def CopyUnforgeablePropertiesToInstance(descriptor, wrapperCache):
|
|||
"""))
|
||||
]
|
||||
|
||||
if wrapperCache:
|
||||
cleanup = dedent(
|
||||
"""
|
||||
aCache->ReleaseWrapper(aObject);
|
||||
aCache->ClearWrapper();
|
||||
""")
|
||||
else:
|
||||
cleanup = ""
|
||||
|
||||
# For proxies, we want to define on the expando object, not directly on the
|
||||
# reflector, so we can make sure we don't get confused by named getters.
|
||||
if descriptor.proxy:
|
||||
|
@ -3433,34 +3430,24 @@ def CopyUnforgeablePropertiesToInstance(descriptor, wrapperCache):
|
|||
JS::Rooted<JSObject*> expando(aCx,
|
||||
DOMProxyHandler::EnsureExpandoObject(aCx, aReflector));
|
||||
if (!expando) {
|
||||
$*{cleanup}
|
||||
return false;
|
||||
$*{failureCode}
|
||||
}
|
||||
""",
|
||||
cleanup=cleanup)))
|
||||
failureCode=failureCode)))
|
||||
obj = "expando"
|
||||
else:
|
||||
obj = "aReflector"
|
||||
|
||||
# We can't do the fast copy for globals, because we can't allocate the
|
||||
# unforgeable holder for those with the right JSClass. Luckily, there
|
||||
# aren't too many globals being created.
|
||||
if descriptor.isGlobal():
|
||||
copyFunc = "JS_CopyPropertiesFrom"
|
||||
else:
|
||||
copyFunc = "JS_InitializePropertiesFromCompatibleNativeObject"
|
||||
copyCode.append(CGGeneric(fill(
|
||||
"""
|
||||
JS::Rooted<JSObject*> unforgeableHolder(aCx,
|
||||
&js::GetReservedSlot(canonicalProto, DOM_INTERFACE_PROTO_SLOTS_BASE).toObject());
|
||||
if (!${copyFunc}(aCx, ${obj}, unforgeableHolder)) {
|
||||
$*{cleanup}
|
||||
return false;
|
||||
if (!JS_InitializePropertiesFromCompatibleNativeObject(aCx, ${obj}, unforgeableHolder)) {
|
||||
$*{failureCode}
|
||||
}
|
||||
""",
|
||||
copyFunc=copyFunc,
|
||||
obj=obj,
|
||||
cleanup=cleanup)))
|
||||
failureCode=failureCode)))
|
||||
|
||||
return CGWrapper(CGList(copyCode), pre="\n").define()
|
||||
|
||||
|
@ -3480,7 +3467,7 @@ def AssertInheritanceChain(descriptor):
|
|||
return asserts
|
||||
|
||||
|
||||
def InitMemberSlots(descriptor, wrapperCache):
|
||||
def InitMemberSlots(descriptor, failureCode):
|
||||
"""
|
||||
Initialize member slots on our JS object if we're supposed to have some.
|
||||
|
||||
|
@ -3491,22 +3478,31 @@ def InitMemberSlots(descriptor, wrapperCache):
|
|||
"""
|
||||
if not descriptor.interface.hasMembersInSlots():
|
||||
return ""
|
||||
if wrapperCache:
|
||||
clearWrapper = dedent(
|
||||
"""
|
||||
aCache->ReleaseWrapper(aObject);
|
||||
aCache->ClearWrapper();
|
||||
""")
|
||||
else:
|
||||
clearWrapper = ""
|
||||
return fill(
|
||||
"""
|
||||
if (!UpdateMemberSlots(aCx, aReflector, aObject)) {
|
||||
$*{clearWrapper}
|
||||
return false;
|
||||
$*{failureCode}
|
||||
}
|
||||
""",
|
||||
clearWrapper=clearWrapper)
|
||||
failureCode=failureCode)
|
||||
|
||||
|
||||
def SetImmutablePrototype(descriptor, failureCode):
|
||||
if not descriptor.hasNonOrdinaryGetPrototypeOf():
|
||||
return ""
|
||||
|
||||
return fill(
|
||||
"""
|
||||
bool succeeded;
|
||||
if (!JS_SetImmutablePrototype(aCx, aReflector, &succeeded)) {
|
||||
${failureCode}
|
||||
}
|
||||
MOZ_ASSERT(succeeded,
|
||||
"Making a fresh reflector instance have an immutable "
|
||||
"prototype can internally fail, but it should never be "
|
||||
"unsuccessful");
|
||||
""",
|
||||
failureCode=failureCode)
|
||||
|
||||
|
||||
def DeclareProto():
|
||||
|
@ -3563,6 +3559,14 @@ class CGWrapWithCacheMethod(CGAbstractMethod):
|
|||
""")
|
||||
else:
|
||||
preserveWrapper = "PreserveWrapper(aObject);\n"
|
||||
|
||||
failureCode = dedent(
|
||||
"""
|
||||
aCache->ReleaseWrapper(aObject);
|
||||
aCache->ClearWrapper();
|
||||
return false;
|
||||
""")
|
||||
|
||||
return fill(
|
||||
"""
|
||||
$*{assertInheritance}
|
||||
|
@ -3598,6 +3602,7 @@ class CGWrapWithCacheMethod(CGAbstractMethod):
|
|||
aCache->SetWrapper(aReflector);
|
||||
$*{unforgeable}
|
||||
$*{slots}
|
||||
$*{setImmutablePrototype}
|
||||
creator.InitializationSucceeded();
|
||||
|
||||
MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
|
||||
|
@ -3617,8 +3622,11 @@ class CGWrapWithCacheMethod(CGAbstractMethod):
|
|||
assertInheritance=AssertInheritanceChain(self.descriptor),
|
||||
declareProto=DeclareProto(),
|
||||
createObject=CreateBindingJSObject(self.descriptor, self.properties),
|
||||
unforgeable=CopyUnforgeablePropertiesToInstance(self.descriptor, True),
|
||||
slots=InitMemberSlots(self.descriptor, True),
|
||||
unforgeable=CopyUnforgeablePropertiesToInstance(self.descriptor,
|
||||
failureCode),
|
||||
slots=InitMemberSlots(self.descriptor, failureCode),
|
||||
setImmutablePrototype=SetImmutablePrototype(self.descriptor,
|
||||
failureCode),
|
||||
preserveWrapper=preserveWrapper)
|
||||
|
||||
|
||||
|
@ -3657,6 +3665,8 @@ class CGWrapNonWrapperCacheMethod(CGAbstractMethod):
|
|||
self.properties = properties
|
||||
|
||||
def definition_body(self):
|
||||
failureCode = "return false;\n"
|
||||
|
||||
return fill(
|
||||
"""
|
||||
$*{assertions}
|
||||
|
@ -3669,14 +3679,19 @@ class CGWrapNonWrapperCacheMethod(CGAbstractMethod):
|
|||
$*{unforgeable}
|
||||
|
||||
$*{slots}
|
||||
|
||||
$*{setImmutablePrototype}
|
||||
creator.InitializationSucceeded();
|
||||
return true;
|
||||
""",
|
||||
assertions=AssertInheritanceChain(self.descriptor),
|
||||
declareProto=DeclareProto(),
|
||||
createObject=CreateBindingJSObject(self.descriptor, self.properties),
|
||||
unforgeable=CopyUnforgeablePropertiesToInstance(self.descriptor, False),
|
||||
slots=InitMemberSlots(self.descriptor, False))
|
||||
unforgeable=CopyUnforgeablePropertiesToInstance(self.descriptor,
|
||||
failureCode),
|
||||
slots=InitMemberSlots(self.descriptor, failureCode),
|
||||
setImmutablePrototype=SetImmutablePrototype(self.descriptor,
|
||||
failureCode))
|
||||
|
||||
|
||||
class CGWrapGlobalMethod(CGAbstractMethod):
|
||||
|
@ -3709,14 +3724,19 @@ class CGWrapGlobalMethod(CGAbstractMethod):
|
|||
else:
|
||||
chromeProperties = "nullptr"
|
||||
|
||||
failureCode = dedent(
|
||||
"""
|
||||
aCache->ReleaseWrapper(aObject);
|
||||
aCache->ClearWrapper();
|
||||
return false;
|
||||
""");
|
||||
|
||||
if self.descriptor.hasUnforgeableMembers:
|
||||
declareProto = "JS::Handle<JSObject*> canonicalProto =\n"
|
||||
assertProto = (
|
||||
"MOZ_ASSERT(canonicalProto &&\n"
|
||||
" IsDOMIfaceAndProtoClass(js::GetObjectClass(canonicalProto)));\n")
|
||||
unforgeable = InitUnforgeablePropertiesOnHolder(
|
||||
self.descriptor, self.properties, failureCode,
|
||||
"aReflector").define();
|
||||
else:
|
||||
declareProto = ""
|
||||
assertProto = ""
|
||||
unforgeable = ""
|
||||
|
||||
return fill(
|
||||
"""
|
||||
|
@ -3724,26 +3744,23 @@ class CGWrapGlobalMethod(CGAbstractMethod):
|
|||
MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
|
||||
"nsISupports must be on our primary inheritance chain");
|
||||
|
||||
$*{declareProto}
|
||||
CreateGlobal<${nativeType}, GetProtoObjectHandle>(aCx,
|
||||
if (!CreateGlobal<${nativeType}, GetProtoObjectHandle>(aCx,
|
||||
aObject,
|
||||
aCache,
|
||||
sClass.ToJSClass(),
|
||||
aOptions,
|
||||
aPrincipal,
|
||||
aInitStandardClasses,
|
||||
aReflector);
|
||||
if (!aReflector) {
|
||||
return false;
|
||||
aReflector)) {
|
||||
$*{failureCode}
|
||||
}
|
||||
$*{assertProto}
|
||||
|
||||
// aReflector is a new global, so has a new compartment. Enter it
|
||||
// before doing anything with it.
|
||||
JSAutoCompartment ac(aCx, aReflector);
|
||||
|
||||
if (!DefineProperties(aCx, aReflector, ${properties}, ${chromeProperties})) {
|
||||
return false;
|
||||
$*{failureCode}
|
||||
}
|
||||
$*{unforgeable}
|
||||
|
||||
|
@ -3753,12 +3770,11 @@ class CGWrapGlobalMethod(CGAbstractMethod):
|
|||
""",
|
||||
assertions=AssertInheritanceChain(self.descriptor),
|
||||
nativeType=self.descriptor.nativeType,
|
||||
declareProto=declareProto,
|
||||
assertProto=assertProto,
|
||||
properties=properties,
|
||||
chromeProperties=chromeProperties,
|
||||
unforgeable=CopyUnforgeablePropertiesToInstance(self.descriptor, True),
|
||||
slots=InitMemberSlots(self.descriptor, True))
|
||||
failureCode=failureCode,
|
||||
unforgeable=unforgeable,
|
||||
slots=InitMemberSlots(self.descriptor, failureCode))
|
||||
|
||||
|
||||
class CGUpdateMemberSlotsMethod(CGAbstractStaticMethod):
|
||||
|
|
|
@ -45,6 +45,7 @@ skip-if = (toolkit == 'gonk' && !debug)
|
|||
[test_browserElement_oop_Close.html]
|
||||
[test_browserElement_oop_CookiesNotThirdParty.html]
|
||||
[test_browserElement_oop_CopyPaste.html]
|
||||
subsuite = clipboard
|
||||
[test_browserElement_oop_DOMRequestError.html]
|
||||
disabled = Disabling some OOP tests for WebIDL scope changes
|
||||
[test_browserElement_oop_DataURI.html]
|
||||
|
|
|
@ -51,7 +51,6 @@ OffscreenCanvas::OffscreenCanvas(nsIGlobalObject* aGlobal,
|
|||
, mWidth(aWidth)
|
||||
, mHeight(aHeight)
|
||||
, mCompositorBackendType(aCompositorBackend)
|
||||
, mCanvasClient(nullptr)
|
||||
, mCanvasRenderer(aRenderer)
|
||||
{}
|
||||
|
||||
|
@ -85,8 +84,6 @@ OffscreenCanvas::ClearResources()
|
|||
{
|
||||
if (mCanvasClient) {
|
||||
mCanvasClient->Clear();
|
||||
ImageBridgeChild::DispatchReleaseCanvasClient(mCanvasClient);
|
||||
mCanvasClient = nullptr;
|
||||
|
||||
if (mCanvasRenderer) {
|
||||
nsCOMPtr<nsIThread> activeThread = mCanvasRenderer->GetActiveThread();
|
||||
|
@ -99,6 +96,8 @@ OffscreenCanvas::ClearResources()
|
|||
mCanvasRenderer->mGLContext = nullptr;
|
||||
mCanvasRenderer->ResetActiveThread();
|
||||
}
|
||||
|
||||
mCanvasClient = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,7 +150,7 @@ OffscreenCanvas::GetContext(JSContext* aCx,
|
|||
if (ImageBridgeChild::IsCreated()) {
|
||||
TextureFlags flags = TextureFlags::ORIGIN_BOTTOM_LEFT;
|
||||
mCanvasClient = ImageBridgeChild::GetSingleton()->
|
||||
CreateCanvasClient(CanvasClient::CanvasClientTypeShSurf, flags).take();
|
||||
CreateCanvasClient(CanvasClient::CanvasClientTypeShSurf, flags);
|
||||
mCanvasRenderer->SetCanvasClient(mCanvasClient);
|
||||
|
||||
gl::GLScreenBuffer* screen = gl->Screen();
|
||||
|
|
|
@ -204,7 +204,7 @@ private:
|
|||
|
||||
layers::LayersBackend mCompositorBackendType;
|
||||
|
||||
layers::CanvasClient* mCanvasClient;
|
||||
RefPtr<layers::CanvasClient> mCanvasClient;
|
||||
RefPtr<layers::AsyncCanvasRenderer> mCanvasRenderer;
|
||||
};
|
||||
|
||||
|
|
|
@ -1544,9 +1544,9 @@ EventListenerManager::GetListenerInfo(nsCOMArray<nsIEventListenerInfo>* aList)
|
|||
nsCOMPtr<EventTarget> target = do_QueryInterface(mTarget);
|
||||
NS_ENSURE_STATE(target);
|
||||
aList->Clear();
|
||||
uint32_t count = mListeners.Length();
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
const Listener& listener = mListeners.ElementAt(i);
|
||||
nsAutoTObserverArray<Listener, 2>::ForwardIterator iter(mListeners);
|
||||
while (iter.HasMore()) {
|
||||
const Listener& listener = iter.GetNext();
|
||||
// If this is a script handler and we haven't yet
|
||||
// compiled the event handler itself go ahead and compile it
|
||||
if (listener.mListenerType == Listener::eJSEventListener &&
|
||||
|
|
|
@ -85,7 +85,7 @@ class nsGeolocationRequest final
|
|||
nsGeolocationRequest(Geolocation* aLocator,
|
||||
GeoPositionCallback aCallback,
|
||||
GeoPositionErrorCallback aErrorCallback,
|
||||
PositionOptions* aOptions,
|
||||
nsAutoPtr<PositionOptions>&& aOptions,
|
||||
uint8_t aProtocolType,
|
||||
bool aWatchPositionRequest = false,
|
||||
int32_t aWatchId = 0);
|
||||
|
@ -138,7 +138,7 @@ class nsGeolocationRequest final
|
|||
uint8_t mProtocolType;
|
||||
};
|
||||
|
||||
static PositionOptions*
|
||||
static nsAutoPtr<PositionOptions>
|
||||
CreatePositionOptionsCopy(const PositionOptions& aOptions)
|
||||
{
|
||||
nsAutoPtr<PositionOptions> geoOptions(new PositionOptions());
|
||||
|
@ -147,7 +147,7 @@ CreatePositionOptionsCopy(const PositionOptions& aOptions)
|
|||
geoOptions->mMaximumAge = aOptions.mMaximumAge;
|
||||
geoOptions->mTimeout = aOptions.mTimeout;
|
||||
|
||||
return geoOptions.forget();
|
||||
return geoOptions;
|
||||
}
|
||||
|
||||
class GeolocationSettingsCallback : public nsISettingsServiceCallback
|
||||
|
@ -349,14 +349,14 @@ PositionError::NotifyCallback(const GeoPositionErrorCallback& aCallback)
|
|||
nsGeolocationRequest::nsGeolocationRequest(Geolocation* aLocator,
|
||||
GeoPositionCallback aCallback,
|
||||
GeoPositionErrorCallback aErrorCallback,
|
||||
PositionOptions* aOptions,
|
||||
nsAutoPtr<PositionOptions>&& aOptions,
|
||||
uint8_t aProtocolType,
|
||||
bool aWatchPositionRequest,
|
||||
int32_t aWatchId)
|
||||
: mIsWatchPositionRequest(aWatchPositionRequest),
|
||||
mCallback(Move(aCallback)),
|
||||
mErrorCallback(Move(aErrorCallback)),
|
||||
mOptions(aOptions),
|
||||
mOptions(Move(aOptions)),
|
||||
mLocator(aLocator),
|
||||
mWatchId(aWatchId),
|
||||
mShutdown(false),
|
||||
|
@ -1392,7 +1392,7 @@ Geolocation::GetCurrentPosition(PositionCallback& aCallback,
|
|||
{
|
||||
nsresult rv = GetCurrentPosition(GeoPositionCallback(&aCallback),
|
||||
GeoPositionErrorCallback(aErrorCallback),
|
||||
CreatePositionOptionsCopy(aOptions));
|
||||
Move(CreatePositionOptionsCopy(aOptions)));
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
|
@ -1404,30 +1404,34 @@ Geolocation::GetCurrentPosition(PositionCallback& aCallback,
|
|||
NS_IMETHODIMP
|
||||
Geolocation::GetCurrentPosition(nsIDOMGeoPositionCallback* aCallback,
|
||||
nsIDOMGeoPositionErrorCallback* aErrorCallback,
|
||||
PositionOptions* aOptions)
|
||||
nsAutoPtr<PositionOptions>&& aOptions)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCallback);
|
||||
|
||||
return GetCurrentPosition(GeoPositionCallback(aCallback),
|
||||
GeoPositionErrorCallback(aErrorCallback), aOptions);
|
||||
GeoPositionErrorCallback(aErrorCallback),
|
||||
Move(aOptions));
|
||||
}
|
||||
|
||||
nsresult
|
||||
Geolocation::GetCurrentPosition(GeoPositionCallback callback,
|
||||
GeoPositionErrorCallback errorCallback,
|
||||
PositionOptions *options)
|
||||
nsAutoPtr<PositionOptions>&& options)
|
||||
{
|
||||
if (mPendingCallbacks.Length() > MAX_GEO_REQUESTS_PER_WINDOW) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// After this we hand over ownership of options to our nsGeolocationRequest.
|
||||
|
||||
// Count the number of requests per protocol/scheme.
|
||||
Telemetry::Accumulate(Telemetry::GEOLOCATION_GETCURRENTPOSITION_SECURE_ORIGIN,
|
||||
static_cast<uint8_t>(mProtocolType));
|
||||
|
||||
RefPtr<nsGeolocationRequest> request =
|
||||
new nsGeolocationRequest(this, Move(callback), Move(errorCallback), options,
|
||||
static_cast<uint8_t>(mProtocolType), false);
|
||||
new nsGeolocationRequest(this, Move(callback), Move(errorCallback),
|
||||
Move(options), static_cast<uint8_t>(mProtocolType),
|
||||
false);
|
||||
|
||||
if (!sGeoEnabled) {
|
||||
nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(false, request);
|
||||
|
@ -1477,7 +1481,7 @@ Geolocation::WatchPosition(PositionCallback& aCallback,
|
|||
int32_t ret = 0;
|
||||
nsresult rv = WatchPosition(GeoPositionCallback(&aCallback),
|
||||
GeoPositionErrorCallback(aErrorCallback),
|
||||
CreatePositionOptionsCopy(aOptions), &ret);
|
||||
Move(CreatePositionOptionsCopy(aOptions)), &ret);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
|
@ -1489,20 +1493,20 @@ Geolocation::WatchPosition(PositionCallback& aCallback,
|
|||
NS_IMETHODIMP
|
||||
Geolocation::WatchPosition(nsIDOMGeoPositionCallback *aCallback,
|
||||
nsIDOMGeoPositionErrorCallback *aErrorCallback,
|
||||
PositionOptions *aOptions,
|
||||
nsAutoPtr<PositionOptions>&& aOptions,
|
||||
int32_t* aRv)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCallback);
|
||||
|
||||
return WatchPosition(GeoPositionCallback(aCallback),
|
||||
GeoPositionErrorCallback(aErrorCallback),
|
||||
aOptions, aRv);
|
||||
Move(aOptions), aRv);
|
||||
}
|
||||
|
||||
nsresult
|
||||
Geolocation::WatchPosition(GeoPositionCallback aCallback,
|
||||
GeoPositionErrorCallback aErrorCallback,
|
||||
PositionOptions* aOptions,
|
||||
nsAutoPtr<PositionOptions>&& aOptions,
|
||||
int32_t* aRv)
|
||||
{
|
||||
if (mWatchingCallbacks.Length() > MAX_GEO_REQUESTS_PER_WINDOW) {
|
||||
|
@ -1518,8 +1522,8 @@ Geolocation::WatchPosition(GeoPositionCallback aCallback,
|
|||
|
||||
RefPtr<nsGeolocationRequest> request =
|
||||
new nsGeolocationRequest(this, Move(aCallback), Move(aErrorCallback),
|
||||
aOptions, static_cast<uint8_t>(mProtocolType),
|
||||
true, *aRv);
|
||||
Move(aOptions),
|
||||
static_cast<uint8_t>(mProtocolType), true, *aRv);
|
||||
|
||||
if (!sGeoEnabled) {
|
||||
nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(false, request);
|
||||
|
|
|
@ -191,10 +191,10 @@ private:
|
|||
|
||||
nsresult GetCurrentPosition(GeoPositionCallback aCallback,
|
||||
GeoPositionErrorCallback aErrorCallback,
|
||||
PositionOptions* aOptions);
|
||||
nsAutoPtr<PositionOptions>&& aOptions);
|
||||
nsresult WatchPosition(GeoPositionCallback aCallback,
|
||||
GeoPositionErrorCallback aErrorCallback,
|
||||
PositionOptions* aOptions, int32_t* aRv);
|
||||
nsAutoPtr<PositionOptions>&& aOptions, int32_t* aRv);
|
||||
|
||||
bool RegisterRequestWithPrompt(nsGeolocationRequest* request);
|
||||
|
||||
|
|
|
@ -13,18 +13,20 @@ namespace dom {
|
|||
struct PositionOptions;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T> class nsAutoPtr;
|
||||
%}
|
||||
|
||||
[ptr] native NamespacedPositionOptions(mozilla::dom::PositionOptions);
|
||||
native PositionOptionsRef(nsAutoPtr<mozilla::dom::PositionOptions>&&);
|
||||
|
||||
[builtinclass, uuid(9142ab45-0ab5-418c-9bab-338a6d271d4f)]
|
||||
interface nsIDOMGeoGeolocation : nsISupports
|
||||
{
|
||||
int32_t watchPosition(in nsIDOMGeoPositionCallback callback,
|
||||
in nsIDOMGeoPositionErrorCallback errorCallback,
|
||||
in NamespacedPositionOptions options);
|
||||
in PositionOptionsRef options);
|
||||
void getCurrentPosition(in nsIDOMGeoPositionCallback callback,
|
||||
in nsIDOMGeoPositionErrorCallback errorCallback,
|
||||
in NamespacedPositionOptions options);
|
||||
in PositionOptionsRef options);
|
||||
void clearWatch(in long watchId);
|
||||
};
|
||||
|
|
|
@ -4061,12 +4061,12 @@ AddGeolocationListener(nsIDOMGeoPositionCallback* watcher,
|
|||
return -1;
|
||||
}
|
||||
|
||||
PositionOptions* options = new PositionOptions();
|
||||
nsAutoPtr<PositionOptions> options(new PositionOptions());
|
||||
options->mTimeout = 0;
|
||||
options->mMaximumAge = 0;
|
||||
options->mEnableHighAccuracy = highAccuracy;
|
||||
int32_t retval = 1;
|
||||
geo->WatchPosition(watcher, errorCallBack, options, &retval);
|
||||
geo->WatchPosition(watcher, errorCallBack, Move(options), &retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
|
@ -288,6 +288,15 @@ function testCatch1() {
|
|||
).then(nextTest);
|
||||
}
|
||||
|
||||
function testToStringTag1() {
|
||||
is(win.Promise.prototype[Symbol.toStringTag], "Promise", "@@toStringTag was incorrect");
|
||||
var p = win.Promise.resolve();
|
||||
is(String(p), "[object Promise]", "String() result was incorrect");
|
||||
is(p.toString(), "[object Promise]", "toString result was incorrect");
|
||||
is(Object.prototype.toString.call(p), "[object Promise]", "second toString result was incorrect");
|
||||
nextTest();
|
||||
}
|
||||
|
||||
var tests = [
|
||||
testLoadComplete,
|
||||
testHaveXray,
|
||||
|
@ -309,6 +318,7 @@ var tests = [
|
|||
testThen1,
|
||||
testThen2,
|
||||
testCatch1,
|
||||
testToStringTag1,
|
||||
];
|
||||
|
||||
function nextTest() {
|
||||
|
|
|
@ -108,6 +108,8 @@ interface Node : EventTarget {
|
|||
[ChromeOnly]
|
||||
sequence<MutationObserver> getBoundMutationObservers();
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
[Pref="accessibility.AOM.enabled"]
|
||||
readonly attribute AccessibleNode? accessibleNode;
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -11,6 +11,7 @@ GENERATED_WEBIDL_FILES = [
|
|||
PREPROCESSED_WEBIDL_FILES = [
|
||||
'HTMLMediaElement.webidl',
|
||||
'Navigator.webidl',
|
||||
'Node.webidl',
|
||||
'Promise.webidl',
|
||||
'PromiseDebugging.webidl',
|
||||
'Window.webidl',
|
||||
|
@ -18,7 +19,6 @@ PREPROCESSED_WEBIDL_FILES = [
|
|||
|
||||
WEBIDL_FILES = [
|
||||
'AbstractWorker.webidl',
|
||||
'AccessibleNode.webidl',
|
||||
'AddonManager.webidl',
|
||||
'AnalyserNode.webidl',
|
||||
'Animatable.webidl',
|
||||
|
@ -350,7 +350,6 @@ WEBIDL_FILES = [
|
|||
'NetDashboard.webidl',
|
||||
'NetworkInformation.webidl',
|
||||
'NetworkOptions.webidl',
|
||||
'Node.webidl',
|
||||
'NodeFilter.webidl',
|
||||
'NodeIterator.webidl',
|
||||
'NodeList.webidl',
|
||||
|
@ -925,3 +924,8 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android':
|
|||
WEBIDL_FILES += [
|
||||
'AlarmsManager.webidl',
|
||||
]
|
||||
|
||||
if CONFIG['ACCESSIBILITY']:
|
||||
WEBIDL_FILES += [
|
||||
'AccessibleNode.webidl',
|
||||
]
|
||||
|
|
|
@ -672,6 +672,7 @@ public:
|
|||
typedef void (*FontDescriptorOutput)(const uint8_t *aData, uint32_t aLength, Float aFontSize, void *aBaton);
|
||||
|
||||
virtual FontType GetType() const = 0;
|
||||
virtual AntialiasMode GetDefaultAAMode() { return AntialiasMode::DEFAULT; }
|
||||
|
||||
/** This allows getting a path that describes the outline of a set of glyphs.
|
||||
* A target is passed in so that the guarantee is made the returned path
|
||||
|
|
|
@ -1183,12 +1183,8 @@ ShouldUseCGToFillGlyphs(const GlyphRenderingOptions* aOptions, const Pattern& aP
|
|||
|
||||
#endif
|
||||
|
||||
void
|
||||
DrawTargetSkia::FillGlyphs(ScaledFont *aFont,
|
||||
const GlyphBuffer &aBuffer,
|
||||
const Pattern &aPattern,
|
||||
const DrawOptions &aOptions,
|
||||
const GlyphRenderingOptions *aRenderingOptions)
|
||||
static bool
|
||||
CanDrawFont(ScaledFont* aFont)
|
||||
{
|
||||
switch (aFont->GetType()) {
|
||||
case FontType::SKIA:
|
||||
|
@ -1197,8 +1193,20 @@ DrawTargetSkia::FillGlyphs(ScaledFont *aFont,
|
|||
case FontType::MAC:
|
||||
case FontType::GDI:
|
||||
case FontType::DWRITE:
|
||||
break;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetSkia::FillGlyphs(ScaledFont *aFont,
|
||||
const GlyphBuffer &aBuffer,
|
||||
const Pattern &aPattern,
|
||||
const DrawOptions &aOptions,
|
||||
const GlyphRenderingOptions *aRenderingOptions)
|
||||
{
|
||||
if (!CanDrawFont(aFont)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1219,11 +1227,18 @@ DrawTargetSkia::FillGlyphs(ScaledFont *aFont,
|
|||
}
|
||||
|
||||
AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
|
||||
AntialiasMode aaMode = aFont->GetDefaultAAMode();
|
||||
if (aOptions.mAntialiasMode != AntialiasMode::DEFAULT) {
|
||||
aaMode = aOptions.mAntialiasMode;
|
||||
}
|
||||
bool aaEnabled = aaMode != AntialiasMode::NONE;
|
||||
|
||||
paint.mPaint.setAntiAlias(aaEnabled);
|
||||
paint.mPaint.setTypeface(typeface);
|
||||
paint.mPaint.setTextSize(SkFloatToScalar(skiaFont->mSize));
|
||||
paint.mPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
|
||||
|
||||
bool shouldLCDRenderText = ShouldLCDRenderText(aFont->GetType(), aOptions.mAntialiasMode);
|
||||
bool shouldLCDRenderText = ShouldLCDRenderText(aFont->GetType(), aaMode);
|
||||
paint.mPaint.setLCDRenderText(shouldLCDRenderText);
|
||||
|
||||
bool useSubpixelText = true;
|
||||
|
@ -1237,7 +1252,7 @@ DrawTargetSkia::FillGlyphs(ScaledFont *aFont,
|
|||
useSubpixelText = false;
|
||||
break;
|
||||
case FontType::MAC:
|
||||
if (aOptions.mAntialiasMode == AntialiasMode::GRAY) {
|
||||
if (aaMode == AntialiasMode::GRAY) {
|
||||
// Normally, Skia enables LCD FontSmoothing which creates thicker fonts
|
||||
// and also enables subpixel AA. CoreGraphics without font smoothing
|
||||
// explicitly creates thinner fonts and grayscale AA.
|
||||
|
@ -1257,14 +1272,15 @@ DrawTargetSkia::FillGlyphs(ScaledFont *aFont,
|
|||
}
|
||||
break;
|
||||
case FontType::GDI:
|
||||
{
|
||||
if (!shouldLCDRenderText) {
|
||||
// If we have non LCD GDI text, Cairo currently always uses cleartype fonts and
|
||||
// converts them to grayscale. Force Skia to do the same, otherwise we use
|
||||
// GDI fonts with the ANTIALIASED_QUALITY which is generally bolder than
|
||||
// Cleartype fonts.
|
||||
// If we have non LCD GDI text, render the fonts as cleartype and convert them
|
||||
// to grayscale. This seems to be what Chrome and IE are doing on Windows 7.
|
||||
// This also applies if cleartype is disabled system wide.
|
||||
paint.mPaint.setFlags(paint.mPaint.getFlags() | SkPaint::kGenA8FromLCD_Flag);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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/. */
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
// Cleartype can be dynamically enabled/disabled, so we have to check it
|
||||
// everytime we want to render some text.
|
||||
static BYTE
|
||||
GetSystemTextQuality()
|
||||
{
|
||||
BOOL font_smoothing;
|
||||
UINT smoothing_type;
|
||||
|
||||
if (!SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0)) {
|
||||
return DEFAULT_QUALITY;
|
||||
}
|
||||
|
||||
if (font_smoothing) {
|
||||
if (!SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE,
|
||||
0, &smoothing_type, 0)) {
|
||||
return DEFAULT_QUALITY;
|
||||
}
|
||||
|
||||
if (smoothing_type == FE_FONTSMOOTHINGCLEARTYPE) {
|
||||
return CLEARTYPE_QUALITY;
|
||||
}
|
||||
|
||||
return ANTIALIASED_QUALITY;
|
||||
}
|
||||
|
||||
return DEFAULT_QUALITY;
|
||||
}
|
||||
|
||||
static AntialiasMode
|
||||
GetSystemDefaultAAMode()
|
||||
{
|
||||
AntialiasMode defaultMode = AntialiasMode::SUBPIXEL;
|
||||
|
||||
switch (GetSystemTextQuality()) {
|
||||
case CLEARTYPE_QUALITY:
|
||||
defaultMode = AntialiasMode::SUBPIXEL;
|
||||
break;
|
||||
case ANTIALIASED_QUALITY:
|
||||
defaultMode = AntialiasMode::GRAY;
|
||||
break;
|
||||
case DEFAULT_QUALITY:
|
||||
defaultMode = AntialiasMode::NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
return defaultMode;
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
|
@ -22,35 +22,11 @@ using namespace std;
|
|||
#include "cairo-win32.h"
|
||||
#endif
|
||||
|
||||
#include "HelpersWinFonts.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
static BYTE
|
||||
GetSystemTextQuality()
|
||||
{
|
||||
BOOL font_smoothing;
|
||||
UINT smoothing_type;
|
||||
|
||||
if (!SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0)) {
|
||||
return DEFAULT_QUALITY;
|
||||
}
|
||||
|
||||
if (font_smoothing) {
|
||||
if (!SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE,
|
||||
0, &smoothing_type, 0)) {
|
||||
return DEFAULT_QUALITY;
|
||||
}
|
||||
|
||||
if (smoothing_type == FE_FONTSMOOTHINGCLEARTYPE) {
|
||||
return CLEARTYPE_QUALITY;
|
||||
}
|
||||
|
||||
return ANTIALIASED_QUALITY;
|
||||
}
|
||||
|
||||
return DEFAULT_QUALITY;
|
||||
}
|
||||
|
||||
#define GASP_TAG 0x70736167
|
||||
#define GASP_DOGRAY 0x2
|
||||
|
||||
|
@ -315,19 +291,7 @@ ScaledFontDWrite::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton
|
|||
AntialiasMode
|
||||
ScaledFontDWrite::GetDefaultAAMode()
|
||||
{
|
||||
AntialiasMode defaultMode = AntialiasMode::SUBPIXEL;
|
||||
|
||||
switch (GetSystemTextQuality()) {
|
||||
case CLEARTYPE_QUALITY:
|
||||
defaultMode = AntialiasMode::SUBPIXEL;
|
||||
break;
|
||||
case ANTIALIASED_QUALITY:
|
||||
defaultMode = AntialiasMode::GRAY;
|
||||
break;
|
||||
case DEFAULT_QUALITY:
|
||||
defaultMode = AntialiasMode::NONE;
|
||||
break;
|
||||
}
|
||||
AntialiasMode defaultMode = GetSystemDefaultAAMode();
|
||||
|
||||
if (defaultMode == AntialiasMode::GRAY) {
|
||||
if (!DoGrayscale(mFontFace, mSize)) {
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
|
||||
virtual bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton);
|
||||
|
||||
virtual AntialiasMode GetDefaultAAMode();
|
||||
virtual AntialiasMode GetDefaultAAMode() override;
|
||||
|
||||
#ifdef USE_SKIA
|
||||
virtual SkTypeface* GetSkTypeface();
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include "cairo-win32.h"
|
||||
#endif
|
||||
|
||||
#include "HelpersWinFonts.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
|
@ -86,6 +88,12 @@ ScaledFontWin::GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton)
|
|||
return true;
|
||||
}
|
||||
|
||||
AntialiasMode
|
||||
ScaledFontWin::GetDefaultAAMode()
|
||||
{
|
||||
return GetSystemDefaultAAMode();
|
||||
}
|
||||
|
||||
#ifdef USE_SKIA
|
||||
SkTypeface* ScaledFontWin::GetSkTypeface()
|
||||
{
|
||||
|
|
|
@ -22,6 +22,7 @@ public:
|
|||
bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) override;
|
||||
|
||||
virtual bool GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) override;
|
||||
virtual AntialiasMode GetDefaultAAMode() override;
|
||||
|
||||
#ifdef USE_SKIA
|
||||
virtual SkTypeface* GetSkTypeface();
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "mozilla/ipc/ProtocolUtils.h"
|
||||
#include "mozilla/layers/CompositableForwarder.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "gfxPlatform.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
|
|
@ -188,7 +188,6 @@ ImageContainer::ImageContainer(Mode flag)
|
|||
mDroppedImageCount(0),
|
||||
mImageFactory(new ImageFactory()),
|
||||
mRecycleBin(new BufferRecycleBin()),
|
||||
mImageClient(nullptr),
|
||||
mCurrentProducerID(-1),
|
||||
mIPDLChild(nullptr)
|
||||
{
|
||||
|
@ -200,7 +199,7 @@ ImageContainer::ImageContainer(Mode flag)
|
|||
break;
|
||||
case ASYNCHRONOUS:
|
||||
mIPDLChild = new ImageContainerChild(this);
|
||||
mImageClient = ImageBridgeChild::GetSingleton()->CreateImageClient(CompositableType::IMAGE, this).take();
|
||||
mImageClient = ImageBridgeChild::GetSingleton()->CreateImageClient(CompositableType::IMAGE, this);
|
||||
MOZ_ASSERT(mImageClient);
|
||||
break;
|
||||
default:
|
||||
|
@ -219,7 +218,6 @@ ImageContainer::ImageContainer(uint64_t aAsyncContainerID)
|
|||
mDroppedImageCount(0),
|
||||
mImageFactory(nullptr),
|
||||
mRecycleBin(nullptr),
|
||||
mImageClient(nullptr),
|
||||
mAsyncContainerID(aAsyncContainerID),
|
||||
mCurrentProducerID(-1),
|
||||
mIPDLChild(nullptr)
|
||||
|
@ -231,7 +229,7 @@ ImageContainer::~ImageContainer()
|
|||
{
|
||||
if (mIPDLChild) {
|
||||
mIPDLChild->ForgetImageContainer();
|
||||
ImageBridgeChild::DispatchReleaseImageClient(mImageClient, mIPDLChild);
|
||||
ImageBridgeChild::DispatchReleaseImageContainer(mIPDLChild);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -636,7 +636,7 @@ private:
|
|||
// In this case the ImageContainer is perfectly usable, but it will forward
|
||||
// frames to the compositor through transactions in the main thread rather than
|
||||
// asynchronusly using the ImageBridge IPDL protocol.
|
||||
ImageClient* mImageClient;
|
||||
RefPtr<ImageClient> mImageClient;
|
||||
|
||||
uint64_t mAsyncContainerID;
|
||||
|
||||
|
|
|
@ -649,10 +649,10 @@ ClientLayerManager::ForwardTransaction(bool aScheduleComposite)
|
|||
|
||||
const OpContentBufferSwap& obs = reply.get_OpContentBufferSwap();
|
||||
|
||||
CompositableClient* compositable =
|
||||
RefPtr<CompositableClient> compositable =
|
||||
CompositableClient::FromIPDLActor(obs.compositableChild());
|
||||
ContentClientRemote* contentClient =
|
||||
static_cast<ContentClientRemote*>(compositable);
|
||||
static_cast<ContentClientRemote*>(compositable.get());
|
||||
MOZ_ASSERT(contentClient);
|
||||
|
||||
contentClient->SwapBuffers(obs.frontUpdatedRegion());
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#include "CompositableChild.h"
|
||||
#include "CompositableClient.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
/* static */ PCompositableChild*
|
||||
CompositableChild::CreateActor()
|
||||
{
|
||||
CompositableChild* child = new CompositableChild();
|
||||
child->AddRef();
|
||||
return child;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
CompositableChild::DestroyActor(PCompositableChild* aChild)
|
||||
{
|
||||
static_cast<CompositableChild*>(aChild)->Release();
|
||||
}
|
||||
|
||||
CompositableChild::CompositableChild()
|
||||
: mCompositableClient(nullptr),
|
||||
mAsyncID(0),
|
||||
mCanSend(true)
|
||||
{
|
||||
MOZ_COUNT_CTOR(CompositableChild);
|
||||
}
|
||||
|
||||
CompositableChild::~CompositableChild()
|
||||
{
|
||||
MOZ_COUNT_DTOR(CompositableChild);
|
||||
}
|
||||
|
||||
bool
|
||||
CompositableChild::IsConnected() const
|
||||
{
|
||||
return mCompositableClient && mCanSend;
|
||||
}
|
||||
|
||||
void
|
||||
CompositableChild::Init(CompositableClient* aCompositable, uint64_t aAsyncID)
|
||||
{
|
||||
mCompositableClient = aCompositable;
|
||||
mAsyncID = aAsyncID;
|
||||
}
|
||||
|
||||
void
|
||||
CompositableChild::RevokeCompositableClient()
|
||||
{
|
||||
mCompositableClient = nullptr;
|
||||
}
|
||||
|
||||
RefPtr<CompositableClient>
|
||||
CompositableChild::GetCompositableClient()
|
||||
{
|
||||
return mCompositableClient;
|
||||
}
|
||||
|
||||
void
|
||||
CompositableChild::ActorDestroy(ActorDestroyReason)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mCanSend = false;
|
||||
|
||||
if (mCompositableClient) {
|
||||
mCompositableClient->mCompositableChild = nullptr;
|
||||
mCompositableClient = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ PCompositableChild*
|
||||
AsyncCompositableChild::CreateActor()
|
||||
{
|
||||
AsyncCompositableChild* child = new AsyncCompositableChild();
|
||||
child->AddRef();
|
||||
return child;
|
||||
}
|
||||
|
||||
AsyncCompositableChild::AsyncCompositableChild()
|
||||
: mLock("AsyncCompositableChild.mLock")
|
||||
{
|
||||
}
|
||||
|
||||
AsyncCompositableChild::~AsyncCompositableChild()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
AsyncCompositableChild::ActorDestroy(ActorDestroyReason)
|
||||
{
|
||||
mCanSend = false;
|
||||
|
||||
// We do not revoke CompositableClient::mCompositableChild here, since that
|
||||
// could race with the main thread.
|
||||
RevokeCompositableClient();
|
||||
}
|
||||
|
||||
void
|
||||
AsyncCompositableChild::RevokeCompositableClient()
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
mCompositableClient = nullptr;
|
||||
}
|
||||
|
||||
RefPtr<CompositableClient>
|
||||
AsyncCompositableChild::GetCompositableClient()
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
return CompositableChild::GetCompositableClient();
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,91 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_gfx_layers_client_CompositableChild_h
|
||||
#define mozilla_gfx_layers_client_CompositableChild_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include "IPDLActor.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/layers/PCompositableChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class CompositableClient;
|
||||
class AsyncCompositableChild;
|
||||
|
||||
/**
|
||||
* IPDL actor used by CompositableClient to match with its corresponding
|
||||
* CompositableHost on the compositor side.
|
||||
*
|
||||
* CompositableChild is owned by a CompositableClient.
|
||||
*/
|
||||
class CompositableChild : public PCompositableChild
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositableChild)
|
||||
|
||||
static PCompositableChild* CreateActor();
|
||||
static void DestroyActor(PCompositableChild* aChild);
|
||||
|
||||
void Init(CompositableClient* aCompositable, uint64_t aAsyncID);
|
||||
virtual void RevokeCompositableClient();
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason) override;
|
||||
|
||||
virtual RefPtr<CompositableClient> GetCompositableClient();
|
||||
|
||||
virtual AsyncCompositableChild* AsAsyncCompositableChild() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint64_t GetAsyncID() const {
|
||||
return mAsyncID;
|
||||
}
|
||||
|
||||
// These should only be called on the IPDL thread.
|
||||
bool IsConnected() const;
|
||||
bool CanSend() const {
|
||||
return mCanSend;
|
||||
}
|
||||
|
||||
protected:
|
||||
CompositableChild();
|
||||
virtual ~CompositableChild();
|
||||
|
||||
protected:
|
||||
CompositableClient* mCompositableClient;
|
||||
uint64_t mAsyncID;
|
||||
bool mCanSend;
|
||||
};
|
||||
|
||||
// This CompositableChild can be used off the main thread.
|
||||
class AsyncCompositableChild final : public CompositableChild
|
||||
{
|
||||
public:
|
||||
static PCompositableChild* CreateActor();
|
||||
|
||||
void RevokeCompositableClient() override;
|
||||
RefPtr<CompositableClient> GetCompositableClient() override;
|
||||
|
||||
void ActorDestroy(ActorDestroyReason) override;
|
||||
|
||||
AsyncCompositableChild* AsAsyncCompositableChild() override {
|
||||
return this;
|
||||
}
|
||||
|
||||
protected:
|
||||
AsyncCompositableChild();
|
||||
~AsyncCompositableChild() override;
|
||||
|
||||
private:
|
||||
Mutex mLock;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_gfx_layers_client_CompositableChild_h
|
|
@ -6,6 +6,7 @@
|
|||
#include "mozilla/layers/CompositableClient.h"
|
||||
#include <stdint.h> // for uint64_t, uint32_t
|
||||
#include "gfxPlatform.h" // for gfxPlatform
|
||||
#include "mozilla/layers/CompositableChild.h"
|
||||
#include "mozilla/layers/CompositableForwarder.h"
|
||||
#include "mozilla/layers/ImageBridgeChild.h"
|
||||
#include "mozilla/layers/TextureClient.h" // for TextureClient, etc
|
||||
|
@ -26,37 +27,6 @@ namespace layers {
|
|||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
/**
|
||||
* IPDL actor used by CompositableClient to match with its corresponding
|
||||
* CompositableHost on the compositor side.
|
||||
*
|
||||
* CompositableChild is owned by a CompositableClient.
|
||||
*/
|
||||
class CompositableChild : public ChildActor<PCompositableChild>
|
||||
{
|
||||
public:
|
||||
CompositableChild()
|
||||
: mCompositableClient(nullptr), mAsyncID(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(CompositableChild);
|
||||
}
|
||||
|
||||
virtual ~CompositableChild()
|
||||
{
|
||||
MOZ_COUNT_DTOR(CompositableChild);
|
||||
}
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason) override {
|
||||
if (mCompositableClient) {
|
||||
mCompositableClient->mCompositableChild = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
CompositableClient* mCompositableClient;
|
||||
|
||||
uint64_t mAsyncID;
|
||||
};
|
||||
|
||||
void
|
||||
RemoveTextureFromCompositableTracker::ReleaseTextureClient()
|
||||
{
|
||||
|
@ -73,40 +43,34 @@ RemoveTextureFromCompositableTracker::ReleaseTextureClient()
|
|||
}
|
||||
}
|
||||
|
||||
/* static */ PCompositableChild*
|
||||
CompositableClient::CreateIPDLActor()
|
||||
{
|
||||
return new CompositableChild();
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
CompositableClient::DestroyIPDLActor(PCompositableChild* actor)
|
||||
{
|
||||
delete actor;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CompositableClient::InitIPDLActor(PCompositableChild* aActor, uint64_t aAsyncID)
|
||||
{
|
||||
MOZ_ASSERT(aActor);
|
||||
CompositableChild* child = static_cast<CompositableChild*>(aActor);
|
||||
mCompositableChild = child;
|
||||
child->mCompositableClient = this;
|
||||
child->mAsyncID = aAsyncID;
|
||||
|
||||
mForwarder->AssertInForwarderThread();
|
||||
|
||||
mCompositableChild = static_cast<CompositableChild*>(aActor);
|
||||
mCompositableChild->Init(this, aAsyncID);
|
||||
}
|
||||
|
||||
/* static */ CompositableClient*
|
||||
/* static */ RefPtr<CompositableClient>
|
||||
CompositableClient::FromIPDLActor(PCompositableChild* aActor)
|
||||
{
|
||||
MOZ_ASSERT(aActor);
|
||||
return static_cast<CompositableChild*>(aActor)->mCompositableClient;
|
||||
|
||||
RefPtr<CompositableClient> client = static_cast<CompositableChild*>(aActor)->GetCompositableClient();
|
||||
if (!client) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
client->mForwarder->AssertInForwarderThread();
|
||||
return client;
|
||||
}
|
||||
|
||||
CompositableClient::CompositableClient(CompositableForwarder* aForwarder,
|
||||
TextureFlags aTextureFlags)
|
||||
: mCompositableChild(nullptr)
|
||||
, mForwarder(aForwarder)
|
||||
: mForwarder(aForwarder)
|
||||
, mTextureFlags(aTextureFlags)
|
||||
{
|
||||
MOZ_COUNT_CTOR(CompositableClient);
|
||||
|
@ -124,12 +88,6 @@ CompositableClient::GetCompositorBackendType() const
|
|||
return mForwarder->GetCompositorBackendType();
|
||||
}
|
||||
|
||||
void
|
||||
CompositableClient::SetIPDLActor(CompositableChild* aChild)
|
||||
{
|
||||
mCompositableChild = aChild;
|
||||
}
|
||||
|
||||
PCompositableChild*
|
||||
CompositableClient::GetIPDLActor() const
|
||||
{
|
||||
|
@ -143,6 +101,8 @@ CompositableClient::Connect(ImageContainer* aImageContainer)
|
|||
if (!GetForwarder() || GetIPDLActor()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GetForwarder()->AssertInForwarderThread();
|
||||
GetForwarder()->Connect(this, aImageContainer);
|
||||
return true;
|
||||
}
|
||||
|
@ -150,35 +110,35 @@ CompositableClient::Connect(ImageContainer* aImageContainer)
|
|||
bool
|
||||
CompositableClient::IsConnected() const
|
||||
{
|
||||
return mCompositableChild && mCompositableChild->CanSend();
|
||||
// CanSend() is only reliable in the same thread as the IPDL channel.
|
||||
mForwarder->AssertInForwarderThread();
|
||||
return mCompositableChild && mCompositableChild->IsConnected();
|
||||
}
|
||||
|
||||
void
|
||||
CompositableClient::Destroy()
|
||||
{
|
||||
if (!IsConnected()) {
|
||||
if (!mCompositableChild) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mTextureClientRecycler) {
|
||||
mTextureClientRecycler->Destroy();
|
||||
}
|
||||
mCompositableChild->mCompositableClient = nullptr;
|
||||
mCompositableChild->Destroy(mForwarder);
|
||||
mCompositableChild = nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
CompositableClient::DestroyFallback(PCompositableChild* aActor)
|
||||
{
|
||||
return aActor->SendDestroySync();
|
||||
// Take away our IPDL's actor reference back to us.
|
||||
mCompositableChild->RevokeCompositableClient();
|
||||
|
||||
// Schedule the IPDL actor to be destroyed on the forwarder's thread.
|
||||
mForwarder->Destroy(mCompositableChild);
|
||||
mCompositableChild = nullptr;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
CompositableClient::GetAsyncID() const
|
||||
{
|
||||
if (mCompositableChild) {
|
||||
return mCompositableChild->mAsyncID;
|
||||
return mCompositableChild->GetAsyncID();
|
||||
}
|
||||
return 0; // zero is always an invalid async ID
|
||||
}
|
||||
|
|
|
@ -161,15 +161,10 @@ public:
|
|||
|
||||
void Destroy();
|
||||
|
||||
static bool DestroyFallback(PCompositableChild* aActor);
|
||||
|
||||
bool IsConnected() const;
|
||||
|
||||
PCompositableChild* GetIPDLActor() const;
|
||||
|
||||
// should only be called by a CompositableForwarder
|
||||
virtual void SetIPDLActor(CompositableChild* aChild);
|
||||
|
||||
CompositableForwarder* GetForwarder() const
|
||||
{
|
||||
return mForwarder;
|
||||
|
@ -216,19 +211,7 @@ public:
|
|||
*/
|
||||
virtual void RemoveTexture(TextureClient* aTexture);
|
||||
|
||||
static CompositableClient* FromIPDLActor(PCompositableChild* aActor);
|
||||
|
||||
/**
|
||||
* Allocate and deallocate a CompositableChild actor.
|
||||
*
|
||||
* CompositableChild is an implementation detail of CompositableClient that is not
|
||||
* exposed to the rest of the code base. CreateIPDLActor and DestroyIPDLActor
|
||||
* are for use with the managing IPDL protocols only (so that they can
|
||||
* implement AllocCompositableChild and DeallocPCompositableChild).
|
||||
*/
|
||||
static PCompositableChild* CreateIPDLActor();
|
||||
|
||||
static bool DestroyIPDLActor(PCompositableChild* actor);
|
||||
static RefPtr<CompositableClient> FromIPDLActor(PCompositableChild* aActor);
|
||||
|
||||
void InitIPDLActor(PCompositableChild* aActor, uint64_t aAsyncID = 0);
|
||||
|
||||
|
@ -242,7 +225,7 @@ public:
|
|||
TextureClient* aTexture,
|
||||
TextureDumpMode aCompress);
|
||||
protected:
|
||||
CompositableChild* mCompositableChild;
|
||||
RefPtr<CompositableChild> mCompositableChild;
|
||||
RefPtr<CompositableForwarder> mForwarder;
|
||||
// Some layers may want to enforce some flags to all their textures
|
||||
// (like disallowing tiling)
|
||||
|
|
|
@ -131,11 +131,6 @@ public:
|
|||
return TextureInfo(mType);
|
||||
}
|
||||
|
||||
virtual void SetIPDLActor(CompositableChild* aChild) override
|
||||
{
|
||||
MOZ_ASSERT(!aChild, "ImageClientBridge should not have IPDL actor");
|
||||
}
|
||||
|
||||
protected:
|
||||
uint64_t mAsyncContainerID;
|
||||
};
|
||||
|
|
|
@ -883,7 +883,7 @@ TextureClient::InitIPDLActor(CompositableForwarder* aForwarder)
|
|||
// It's Ok for a texture to move from a ShadowLayerForwarder to another, but
|
||||
// not form a CompositorBridgeChild to another (they use different channels).
|
||||
if (currentTexFwd && currentTexFwd != aForwarder->AsTextureForwarder()) {
|
||||
gfxCriticalError() << "Attempt to move a texture to a different channel.";
|
||||
gfxCriticalError() << "Attempt to move a texture to a different channel CF.";
|
||||
return false;
|
||||
}
|
||||
if (currentFwd && currentFwd->GetCompositorBackendType() != aForwarder->GetCompositorBackendType()) {
|
||||
|
@ -940,7 +940,7 @@ TextureClient::InitIPDLActor(TextureForwarder* aForwarder, LayersBackend aBacken
|
|||
}
|
||||
|
||||
if (currentTexFwd && currentTexFwd != aForwarder) {
|
||||
gfxCriticalError() << "Attempt to move a texture to a different channel.";
|
||||
gfxCriticalError() << "Attempt to move a texture to a different channel TF.";
|
||||
return false;
|
||||
}
|
||||
mActor->mTextureForwarder = aForwarder;
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "CompositableForwarder.h"
|
||||
#include "mozilla/layers/CompositableChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
void
|
||||
CompositableForwarder::Destroy(CompositableChild* aCompositable)
|
||||
{
|
||||
AssertInForwarderThread();
|
||||
|
||||
if (!aCompositable->CanSend()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!DestroyInTransaction(aCompositable, false)) {
|
||||
aCompositable->SendDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
|
@ -111,6 +111,8 @@ public:
|
|||
const gfx::IntRect& aPictureRect) = 0;
|
||||
#endif
|
||||
|
||||
virtual void Destroy(CompositableChild* aCompositable);
|
||||
|
||||
virtual bool DestroyInTransaction(PTextureChild* aTexture, bool synchronously) = 0;
|
||||
virtual bool DestroyInTransaction(PCompositableChild* aCompositable, bool synchronously) = 0;
|
||||
|
||||
|
@ -174,6 +176,12 @@ public:
|
|||
return mTextureFactoryIdentifier.mMaxTextureSize;
|
||||
}
|
||||
|
||||
virtual bool InForwarderThread() = 0;
|
||||
|
||||
void AssertInForwarderThread() {
|
||||
MOZ_ASSERT(InForwarderThread());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of backend that is used off the main thread.
|
||||
* We only don't allow changing the backend type at runtime so this value can
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "mozilla/layers/AsyncCanvasRenderer.h"
|
||||
#include "mozilla/media/MediaSystemResourceManager.h" // for MediaSystemResourceManager
|
||||
#include "mozilla/media/MediaSystemResourceManagerChild.h" // for MediaSystemResourceManagerChild
|
||||
#include "mozilla/layers/CompositableChild.h"
|
||||
#include "mozilla/layers/CompositableClient.h" // for CompositableChild, etc
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
#include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator
|
||||
|
@ -142,7 +143,7 @@ struct CompositableTransaction
|
|||
break;
|
||||
}
|
||||
case OpDestroy::TPCompositableChild: {
|
||||
DebugOnly<bool> ok = CompositableClient::DestroyFallback(actor.get_PCompositableChild());
|
||||
DebugOnly<bool> ok = actor.get_PCompositableChild()->SendDestroySync();
|
||||
MOZ_ASSERT(ok);
|
||||
break;
|
||||
}
|
||||
|
@ -521,6 +522,8 @@ ImageBridgeChild::Connect(CompositableClient* aCompositable,
|
|||
{
|
||||
MOZ_ASSERT(aCompositable);
|
||||
MOZ_ASSERT(!mShuttingDown);
|
||||
MOZ_ASSERT(InImageBridgeChildThread());
|
||||
|
||||
uint64_t id = 0;
|
||||
|
||||
PImageContainerChild* imageContainerChild = nullptr;
|
||||
|
@ -539,13 +542,14 @@ ImageBridgeChild::AllocPCompositableChild(const TextureInfo& aInfo,
|
|||
PImageContainerChild* aChild, uint64_t* aID)
|
||||
{
|
||||
MOZ_ASSERT(!mShuttingDown);
|
||||
return CompositableClient::CreateIPDLActor();
|
||||
return AsyncCompositableChild::CreateActor();
|
||||
}
|
||||
|
||||
bool
|
||||
ImageBridgeChild::DeallocPCompositableChild(PCompositableChild* aActor)
|
||||
{
|
||||
return CompositableClient::DestroyIPDLActor(aActor);
|
||||
AsyncCompositableChild::DestroyActor(aActor);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -564,13 +568,9 @@ bool ImageBridgeChild::IsCreated()
|
|||
return GetSingleton() != nullptr;
|
||||
}
|
||||
|
||||
static void ReleaseImageClientNow(ImageClient* aClient,
|
||||
PImageContainerChild* aChild)
|
||||
static void ReleaseImageContainerNow(PImageContainerChild* aChild)
|
||||
{
|
||||
MOZ_ASSERT(InImageBridgeChildThread());
|
||||
if (aClient) {
|
||||
aClient->Release();
|
||||
}
|
||||
|
||||
if (aChild) {
|
||||
ImageContainer::AsyncDestroyActor(aChild);
|
||||
|
@ -578,57 +578,19 @@ static void ReleaseImageClientNow(ImageClient* aClient,
|
|||
}
|
||||
|
||||
// static
|
||||
void ImageBridgeChild::DispatchReleaseImageClient(ImageClient* aClient,
|
||||
PImageContainerChild* aChild)
|
||||
void ImageBridgeChild::DispatchReleaseImageContainer(PImageContainerChild* aChild)
|
||||
{
|
||||
if (!aClient && !aChild) {
|
||||
if (!aChild) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsCreated()) {
|
||||
if (aClient) {
|
||||
// CompositableClient::Release should normally happen in the ImageBridgeChild
|
||||
// thread because it usually generate some IPDL messages.
|
||||
// However, if we take this branch it means that the ImageBridgeChild
|
||||
// has already shut down, along with the CompositableChild, which means no
|
||||
// message will be sent and it is safe to run this code from any thread.
|
||||
MOZ_ASSERT(aClient->GetIPDLActor() == nullptr);
|
||||
aClient->Release();
|
||||
}
|
||||
delete aChild;
|
||||
return;
|
||||
}
|
||||
|
||||
sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
|
||||
NewRunnableFunction(&ReleaseImageClientNow, aClient, aChild));
|
||||
}
|
||||
|
||||
static void ReleaseCanvasClientNow(CanvasClient* aClient)
|
||||
{
|
||||
MOZ_ASSERT(InImageBridgeChildThread());
|
||||
aClient->Release();
|
||||
}
|
||||
|
||||
// static
|
||||
void ImageBridgeChild::DispatchReleaseCanvasClient(CanvasClient* aClient)
|
||||
{
|
||||
if (!aClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsCreated()) {
|
||||
// CompositableClient::Release should normally happen in the ImageBridgeChild
|
||||
// thread because it usually generate some IPDL messages.
|
||||
// However, if we take this branch it means that the ImageBridgeChild
|
||||
// has already shut down, along with the CompositableChild, which means no
|
||||
// message will be sent and it is safe to run this code from any thread.
|
||||
MOZ_ASSERT(aClient->GetIPDLActor() == nullptr);
|
||||
aClient->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
|
||||
NewRunnableFunction(&ReleaseCanvasClientNow, aClient));
|
||||
NewRunnableFunction(&ReleaseImageContainerNow, aChild));
|
||||
}
|
||||
|
||||
static void ReleaseTextureClientNow(TextureClient* aClient)
|
||||
|
@ -659,7 +621,8 @@ void ImageBridgeChild::DispatchReleaseTextureClient(TextureClient* aClient)
|
|||
NewRunnableFunction(&ReleaseTextureClientNow, aClient));
|
||||
}
|
||||
|
||||
static void UpdateImageClientNow(ImageClient* aClient, RefPtr<ImageContainer>&& aContainer)
|
||||
static void
|
||||
UpdateImageClientNow(RefPtr<ImageClient> aClient, RefPtr<ImageContainer>&& aContainer)
|
||||
{
|
||||
if (!ImageBridgeChild::IsCreated() || ImageBridgeChild::IsShutDown()) {
|
||||
NS_WARNING("Something is holding on to graphics resources after the shutdown"
|
||||
|
@ -668,6 +631,13 @@ static void UpdateImageClientNow(ImageClient* aClient, RefPtr<ImageContainer>&&
|
|||
}
|
||||
MOZ_ASSERT(aClient);
|
||||
MOZ_ASSERT(aContainer);
|
||||
|
||||
// If the client has become disconnected before this event was dispatched,
|
||||
// early return now.
|
||||
if (!aClient->IsConnected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
sImageBridgeChildSingleton->BeginTransaction();
|
||||
aClient->UpdateImage(aContainer, Layer::CONTENT_OPAQUE);
|
||||
sImageBridgeChildSingleton->EndTransaction();
|
||||
|
@ -690,8 +660,10 @@ void ImageBridgeChild::DispatchImageClientUpdate(ImageClient* aClient,
|
|||
UpdateImageClientNow(aClient, aContainer);
|
||||
return;
|
||||
}
|
||||
|
||||
sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
|
||||
NewRunnableFunction(&UpdateImageClientNow, aClient, RefPtr<ImageContainer>(aContainer)));
|
||||
NewRunnableFunction(&UpdateImageClientNow,
|
||||
RefPtr<ImageClient>(aClient), RefPtr<ImageContainer>(aContainer)));
|
||||
}
|
||||
|
||||
static void UpdateAsyncCanvasRendererSync(AsyncCanvasRenderer* aWrapper,
|
||||
|
@ -1424,5 +1396,25 @@ bool ImageBridgeChild::IsSameProcess() const
|
|||
return OtherPid() == base::GetCurrentProcId();
|
||||
}
|
||||
|
||||
static void
|
||||
DestroyCompositableNow(RefPtr<ImageBridgeChild> aImageBridge,
|
||||
RefPtr<CompositableChild> aCompositable)
|
||||
{
|
||||
aImageBridge->Destroy(aCompositable);
|
||||
}
|
||||
|
||||
void
|
||||
ImageBridgeChild::Destroy(CompositableChild* aCompositable)
|
||||
{
|
||||
if (!InImageBridgeChildThread()) {
|
||||
RefPtr<ImageBridgeChild> self = this;
|
||||
RefPtr<CompositableChild> compositable = aCompositable;
|
||||
GetMessageLoop()->PostTask(
|
||||
NewRunnableFunction(&DestroyCompositableNow, self, compositable));
|
||||
return;
|
||||
}
|
||||
CompositableForwarder::Destroy(aCompositable);
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -227,9 +227,7 @@ public:
|
|||
already_AddRefed<CanvasClient> CreateCanvasClientNow(CanvasClient::CanvasClientType aType,
|
||||
TextureFlags aFlag);
|
||||
|
||||
static void DispatchReleaseImageClient(ImageClient* aClient,
|
||||
PImageContainerChild* aChild = nullptr);
|
||||
static void DispatchReleaseCanvasClient(CanvasClient* aClient);
|
||||
static void DispatchReleaseImageContainer(PImageContainerChild* aChild = nullptr);
|
||||
static void DispatchReleaseTextureClient(TextureClient* aClient);
|
||||
static void DispatchImageClientUpdate(ImageClient* aClient, ImageContainer* aContainer);
|
||||
|
||||
|
@ -262,6 +260,8 @@ public:
|
|||
const nsIntRect& aPictureRect) override;
|
||||
#endif
|
||||
|
||||
void Destroy(CompositableChild* aCompositable) override;
|
||||
|
||||
/**
|
||||
* Hold TextureClient ref until end of usage on host side if TextureFlags::RECYCLE is set.
|
||||
* Host side's usage is checked via CompositableRef.
|
||||
|
@ -341,6 +341,11 @@ public:
|
|||
virtual void UpdateFwdTransactionId() override { ++mFwdTransactionId; }
|
||||
virtual uint64_t GetFwdTransactionId() override { return mFwdTransactionId; }
|
||||
|
||||
bool InForwarderThread() override {
|
||||
return InImageBridgeChildThread();
|
||||
}
|
||||
|
||||
|
||||
void MarkShutDown();
|
||||
|
||||
void FallbackDestroyActors();
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include "LayerTransactionChild.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/layers/CompositableClient.h" // for CompositableChild
|
||||
#include "mozilla/layers/CompositableChild.h"
|
||||
#include "mozilla/layers/PCompositableChild.h" // for PCompositableChild
|
||||
#include "mozilla/layers/PLayerChild.h" // for PLayerChild
|
||||
#include "mozilla/layers/PImageContainerChild.h"
|
||||
|
@ -60,13 +60,14 @@ PCompositableChild*
|
|||
LayerTransactionChild::AllocPCompositableChild(const TextureInfo& aInfo)
|
||||
{
|
||||
MOZ_ASSERT(!mDestroyed);
|
||||
return CompositableClient::CreateIPDLActor();
|
||||
return CompositableChild::CreateActor();
|
||||
}
|
||||
|
||||
bool
|
||||
LayerTransactionChild::DeallocPCompositableChild(PCompositableChild* actor)
|
||||
{
|
||||
return CompositableClient::DestroyIPDLActor(actor);
|
||||
CompositableChild::DestroyActor(actor);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_LOG
|
||||
#include "mozilla/layers/LayerTransactionChild.h"
|
||||
#include "mozilla/layers/SharedBufferManagerChild.h"
|
||||
#include "mozilla/layers/PCompositableChild.h"
|
||||
#include "mozilla/layers/PTextureChild.h"
|
||||
#include "ShadowLayerUtils.h"
|
||||
#include "mozilla/layers/TextureClient.h" // for TextureClient
|
||||
|
@ -169,7 +170,7 @@ public:
|
|||
break;
|
||||
}
|
||||
case OpDestroy::TPCompositableChild: {
|
||||
DebugOnly<bool> ok = CompositableClient::DestroyFallback(actor.get_PCompositableChild());
|
||||
DebugOnly<bool> ok = actor.get_PCompositableChild()->SendDestroySync();
|
||||
MOZ_ASSERT(ok);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -392,6 +392,10 @@ public:
|
|||
virtual void UpdateFwdTransactionId() override;
|
||||
virtual uint64_t GetFwdTransactionId() override;
|
||||
|
||||
bool InForwarderThread() override {
|
||||
return NS_IsMainThread();
|
||||
}
|
||||
|
||||
// Returns true if aSurface wraps a Shmem.
|
||||
static bool IsShmem(SurfaceDescriptor* aSurface);
|
||||
|
||||
|
|
|
@ -43,8 +43,6 @@ SharedPlanarYCbCrImage::~SharedPlanarYCbCrImage() {
|
|||
ImageBridgeChild::DispatchReleaseTextureClient(mTextureClient);
|
||||
mTextureClient = nullptr;
|
||||
}
|
||||
|
||||
ImageBridgeChild::DispatchReleaseImageClient(mCompositable.forget().take());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -68,8 +68,6 @@ SharedRGBImage::~SharedRGBImage()
|
|||
ADDREF_MANUALLY(mTextureClient);
|
||||
ImageBridgeChild::DispatchReleaseTextureClient(mTextureClient);
|
||||
mTextureClient = nullptr;
|
||||
|
||||
ImageBridgeChild::DispatchReleaseImageClient(mCompositable.forget().take());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -128,6 +128,7 @@ EXPORTS.mozilla.layers += [
|
|||
'BSPTree.h',
|
||||
'BufferTexture.h',
|
||||
'client/CanvasClient.h',
|
||||
'client/CompositableChild.h',
|
||||
'client/CompositableClient.h',
|
||||
'client/ContentClient.h',
|
||||
'client/ImageClient.h',
|
||||
|
@ -316,6 +317,7 @@ UNIFIED_SOURCES += [
|
|||
'client/ClientLayerManager.cpp',
|
||||
'client/ClientPaintedLayer.cpp',
|
||||
'client/ClientTiledPaintedLayer.cpp',
|
||||
'client/CompositableChild.cpp',
|
||||
'client/CompositableClient.cpp',
|
||||
'client/ContentClient.cpp',
|
||||
'client/ImageClient.cpp',
|
||||
|
@ -352,6 +354,7 @@ UNIFIED_SOURCES += [
|
|||
'ipc/APZCTreeManagerChild.cpp',
|
||||
'ipc/APZCTreeManagerParent.cpp',
|
||||
'ipc/AsyncTransactionTracker.cpp',
|
||||
'ipc/CompositableForwarder.cpp',
|
||||
'ipc/CompositableTransactionParent.cpp',
|
||||
'ipc/CompositorBench.cpp',
|
||||
'ipc/CompositorBridgeChild.cpp',
|
||||
|
|
|
@ -758,6 +758,17 @@ VRDisplayOculus::SubmitFrame(TextureSourceD3D11* aSource,
|
|||
if (!mIsPresenting) {
|
||||
return;
|
||||
}
|
||||
if (mRenderTargets.IsEmpty()) {
|
||||
/**
|
||||
* XXX - We should resolve fail the promise returned by
|
||||
* VRDisplay.requestPresent() when the DX11 resources fail allocation
|
||||
* in VRDisplayOculus::StartPresentation().
|
||||
* Bailing out here prevents the crash but content should be aware
|
||||
* that frames are not being presented.
|
||||
* See Bug 1299309.
|
||||
**/
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(mDevice);
|
||||
MOZ_ASSERT(mContext);
|
||||
|
||||
|
|
|
@ -31,6 +31,8 @@ class Latin1Chars : public mozilla::Range<Latin1Char>
|
|||
typedef mozilla::Range<Latin1Char> Base;
|
||||
|
||||
public:
|
||||
using CharT = Latin1Char;
|
||||
|
||||
Latin1Chars() : Base() {}
|
||||
Latin1Chars(char* aBytes, size_t aLength) : Base(reinterpret_cast<Latin1Char*>(aBytes), aLength) {}
|
||||
Latin1Chars(const Latin1Char* aBytes, size_t aLength)
|
||||
|
@ -49,6 +51,8 @@ class Latin1CharsZ : public mozilla::RangedPtr<Latin1Char>
|
|||
typedef mozilla::RangedPtr<Latin1Char> Base;
|
||||
|
||||
public:
|
||||
using CharT = Latin1Char;
|
||||
|
||||
Latin1CharsZ() : Base(nullptr, 0) {}
|
||||
|
||||
Latin1CharsZ(char* aBytes, size_t aLength)
|
||||
|
@ -73,6 +77,8 @@ class UTF8Chars : public mozilla::Range<unsigned char>
|
|||
typedef mozilla::Range<unsigned char> Base;
|
||||
|
||||
public:
|
||||
using CharT = unsigned char;
|
||||
|
||||
UTF8Chars() : Base() {}
|
||||
UTF8Chars(char* aBytes, size_t aLength)
|
||||
: Base(reinterpret_cast<unsigned char*>(aBytes), aLength)
|
||||
|
@ -90,6 +96,8 @@ class UTF8CharsZ : public mozilla::RangedPtr<unsigned char>
|
|||
typedef mozilla::RangedPtr<unsigned char> Base;
|
||||
|
||||
public:
|
||||
using CharT = unsigned char;
|
||||
|
||||
UTF8CharsZ() : Base(nullptr, 0) {}
|
||||
|
||||
UTF8CharsZ(char* aBytes, size_t aLength)
|
||||
|
@ -120,6 +128,8 @@ class ConstUTF8CharsZ
|
|||
const char* data_;
|
||||
|
||||
public:
|
||||
using CharT = unsigned char;
|
||||
|
||||
ConstUTF8CharsZ() : data_(nullptr)
|
||||
{}
|
||||
|
||||
|
@ -157,6 +167,8 @@ class TwoByteChars : public mozilla::Range<char16_t>
|
|||
typedef mozilla::Range<char16_t> Base;
|
||||
|
||||
public:
|
||||
using CharT = char16_t;
|
||||
|
||||
TwoByteChars() : Base() {}
|
||||
TwoByteChars(char16_t* aChars, size_t aLength) : Base(aChars, aLength) {}
|
||||
TwoByteChars(const char16_t* aChars, size_t aLength) : Base(const_cast<char16_t*>(aChars), aLength) {}
|
||||
|
@ -170,6 +182,8 @@ class TwoByteCharsZ : public mozilla::RangedPtr<char16_t>
|
|||
typedef mozilla::RangedPtr<char16_t> Base;
|
||||
|
||||
public:
|
||||
using CharT = char16_t;
|
||||
|
||||
TwoByteCharsZ() : Base(nullptr, 0) {}
|
||||
|
||||
TwoByteCharsZ(char16_t* chars, size_t length)
|
||||
|
@ -191,6 +205,8 @@ class ConstTwoByteChars : public mozilla::Range<const char16_t>
|
|||
typedef mozilla::Range<const char16_t> Base;
|
||||
|
||||
public:
|
||||
using CharT = char16_t;
|
||||
|
||||
ConstTwoByteChars() : Base() {}
|
||||
ConstTwoByteChars(const char16_t* aChars, size_t aLength) : Base(aChars, aLength) {}
|
||||
};
|
||||
|
@ -272,6 +288,41 @@ JS_PUBLIC_API(void)
|
|||
DeflateStringToUTF8Buffer(JSFlatString* src, mozilla::RangedPtr<char> dst,
|
||||
size_t* dstlenp = nullptr, size_t* numcharsp = nullptr);
|
||||
|
||||
/*
|
||||
* The smallest character encoding capable of fully representing a particular
|
||||
* string.
|
||||
*/
|
||||
enum class SmallestEncoding {
|
||||
ASCII,
|
||||
Latin1,
|
||||
UTF16
|
||||
};
|
||||
|
||||
/*
|
||||
* Returns the smallest encoding possible for the given string: if all
|
||||
* codepoints are <128 then ASCII, otherwise if all codepoints are <256
|
||||
* Latin-1, else UTF16.
|
||||
*/
|
||||
JS_PUBLIC_API(SmallestEncoding)
|
||||
FindSmallestEncoding(UTF8Chars utf8);
|
||||
|
||||
/*
|
||||
* Return a null-terminated Latin-1 string copied from the input string,
|
||||
* storing its length (excluding null terminator) in |*outlen|. Fail and
|
||||
* report an error if the string contains non-Latin-1 codepoints. Returns
|
||||
* Latin1CharsZ() on failure.
|
||||
*/
|
||||
extern Latin1CharsZ
|
||||
UTF8CharsToNewLatin1CharsZ(JSContext* cx, const UTF8Chars utf8, size_t* outlen);
|
||||
|
||||
/*
|
||||
* Return a null-terminated Latin-1 string copied from the input string,
|
||||
* storing its length (excluding null terminator) in |*outlen|. Non-Latin-1
|
||||
* codepoints are replaced by '?'. Returns Latin1CharsZ() on failure.
|
||||
*/
|
||||
extern Latin1CharsZ
|
||||
LossyUTF8CharsToNewLatin1CharsZ(JSContext* cx, const UTF8Chars utf8, size_t* outlen);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
inline void JS_free(JS::Latin1CharsZ& ptr) { js_free((void*)ptr.get()); }
|
||||
|
|
|
@ -8504,6 +8504,9 @@ BuildConsoleMessage(ExclusiveContext* cx, unsigned time, JS::AsmJSCacheResult ca
|
|||
case JS::AsmJSCache_InternalError:
|
||||
cacheString = "unable to store in cache due to internal error (consider filing a bug)";
|
||||
break;
|
||||
case JS::AsmJSCache_Disabled_PrivateBrowsing:
|
||||
cacheString = "caching disabled by private browsing mode";
|
||||
break;
|
||||
case JS::AsmJSCache_LIMIT:
|
||||
MOZ_CRASH("bad AsmJSCacheResult");
|
||||
break;
|
||||
|
|
|
@ -1397,6 +1397,11 @@ static const JSFunctionSpec promise_methods[] = {
|
|||
JS_FS_END
|
||||
};
|
||||
|
||||
static const JSPropertySpec promise_properties[] = {
|
||||
JS_STRING_SYM_PS(toStringTag, "Promise", JSPROP_READONLY),
|
||||
JS_PS_END
|
||||
};
|
||||
|
||||
static const JSFunctionSpec promise_static_methods[] = {
|
||||
JS_SELF_HOSTED_FN("all", "Promise_static_all", 1, 0),
|
||||
JS_SELF_HOSTED_FN("race", "Promise_static_race", 1, 0),
|
||||
|
@ -1415,7 +1420,8 @@ static const ClassSpec PromiseObjectClassSpec = {
|
|||
CreatePromisePrototype,
|
||||
promise_static_methods,
|
||||
promise_static_properties,
|
||||
promise_methods
|
||||
promise_methods,
|
||||
promise_properties
|
||||
};
|
||||
|
||||
const Class PromiseObject::class_ = {
|
||||
|
|
|
@ -3112,15 +3112,6 @@ ByteSizeOfScript(JSContext*cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
ImmutablePrototypesEnabled(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
args.rval().setBoolean(JS_ImmutablePrototypesEnabled());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
SetImmutablePrototype(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
@ -3991,11 +3982,6 @@ gc::ZealModeHelpText),
|
|||
"byteSizeOfScript(f)",
|
||||
" Return the size in bytes occupied by the function |f|'s JSScript.\n"),
|
||||
|
||||
JS_FN_HELP("immutablePrototypesEnabled", ImmutablePrototypesEnabled, 0, 0,
|
||||
"immutablePrototypesEnabled()",
|
||||
" Returns true if immutable-prototype behavior (triggered by setImmutablePrototype)\n"
|
||||
" is enabled, such that modifying an immutable prototype will fail."),
|
||||
|
||||
JS_FN_HELP("setImmutablePrototype", SetImmutablePrototype, 1, 0,
|
||||
"setImmutablePrototype(obj)",
|
||||
" Try to make obj's [[Prototype]] immutable, such that subsequent attempts to\n"
|
||||
|
|
|
@ -1170,22 +1170,15 @@ BytecodeEmitter::EmitterScope::enterFunctionExtraBodyVar(BytecodeEmitter* bce, F
|
|||
|
||||
class DynamicBindingIter : public BindingIter
|
||||
{
|
||||
uint32_t functionEnd_;
|
||||
|
||||
public:
|
||||
explicit DynamicBindingIter(GlobalSharedContext* sc)
|
||||
: BindingIter(*sc->bindings),
|
||||
functionEnd_(sc->functionBindingEnd)
|
||||
{
|
||||
MOZ_ASSERT(functionEnd_ >= varStart_ && functionEnd_ <= letStart_);
|
||||
}
|
||||
: BindingIter(*sc->bindings)
|
||||
{ }
|
||||
|
||||
explicit DynamicBindingIter(EvalSharedContext* sc)
|
||||
: BindingIter(*sc->bindings, /* strict = */ false),
|
||||
functionEnd_(sc->functionBindingEnd)
|
||||
: BindingIter(*sc->bindings, /* strict = */ false)
|
||||
{
|
||||
MOZ_ASSERT(!sc->strict());
|
||||
MOZ_ASSERT(functionEnd_ >= varStart_ && functionEnd_ <= letStart_);
|
||||
}
|
||||
|
||||
JSOp bindingOp() const {
|
||||
|
@ -1200,10 +1193,6 @@ class DynamicBindingIter : public BindingIter
|
|||
MOZ_CRASH("Bad BindingKind");
|
||||
}
|
||||
}
|
||||
|
||||
bool isBodyLevelFunction() const {
|
||||
return index_ < functionEnd_;
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
|
@ -1243,7 +1232,7 @@ BytecodeEmitter::EmitterScope::enterGlobal(BytecodeEmitter* bce, GlobalSharedCon
|
|||
|
||||
// Define the name in the prologue. Do not emit DEFVAR for
|
||||
// functions that we'll emit DEFFUN for.
|
||||
if (bi.isBodyLevelFunction())
|
||||
if (bi.isTopLevelFunction())
|
||||
continue;
|
||||
|
||||
if (!bce->emitAtomOp(name, bi.bindingOp()))
|
||||
|
@ -1303,7 +1292,7 @@ BytecodeEmitter::EmitterScope::enterEval(BytecodeEmitter* bce, EvalSharedContext
|
|||
for (DynamicBindingIter bi(evalsc); bi; bi++) {
|
||||
MOZ_ASSERT(bi.bindingOp() == JSOP_DEFVAR);
|
||||
|
||||
if (bi.isBodyLevelFunction())
|
||||
if (bi.isTopLevelFunction())
|
||||
continue;
|
||||
|
||||
if (!bce->emitAtomOp(bi.name(), JSOP_DEFVAR))
|
||||
|
|
|
@ -275,7 +275,6 @@ EvalSharedContext::EvalSharedContext(ExclusiveContext* cx, JSObject* enclosingEn
|
|||
bool extraWarnings)
|
||||
: SharedContext(cx, Kind::Eval, directives, extraWarnings),
|
||||
enclosingScope_(cx, enclosingScope),
|
||||
functionBindingEnd(0),
|
||||
bindings(cx)
|
||||
{
|
||||
computeAllowSyntax(enclosingScope);
|
||||
|
@ -1374,8 +1373,7 @@ NewEmptyBindingData(ExclusiveContext* cx, LifoAlloc& alloc, uint32_t numBindings
|
|||
|
||||
template <>
|
||||
Maybe<GlobalScope::Data*>
|
||||
Parser<FullParseHandler>::newGlobalScopeData(ParseContext::Scope& scope,
|
||||
uint32_t* functionBindingEnd)
|
||||
Parser<FullParseHandler>::newGlobalScopeData(ParseContext::Scope& scope)
|
||||
{
|
||||
Vector<BindingName> funs(context);
|
||||
Vector<BindingName> vars(context);
|
||||
|
@ -1420,12 +1418,10 @@ Parser<FullParseHandler>::newGlobalScopeData(ParseContext::Scope& scope,
|
|||
BindingName* start = bindings->names;
|
||||
BindingName* cursor = start;
|
||||
|
||||
// Keep track of what vars are functions. This is only used in BCE to omit
|
||||
// superfluous DEFVARs.
|
||||
PodCopy(cursor, funs.begin(), funs.length());
|
||||
cursor += funs.length();
|
||||
*functionBindingEnd = cursor - start;
|
||||
|
||||
bindings->varStart = cursor - start;
|
||||
PodCopy(cursor, vars.begin(), vars.length());
|
||||
cursor += vars.length();
|
||||
|
||||
|
@ -1510,8 +1506,7 @@ Parser<FullParseHandler>::newModuleScopeData(ParseContext::Scope& scope)
|
|||
|
||||
template <>
|
||||
Maybe<EvalScope::Data*>
|
||||
Parser<FullParseHandler>::newEvalScopeData(ParseContext::Scope& scope,
|
||||
uint32_t* functionBindingEnd)
|
||||
Parser<FullParseHandler>::newEvalScopeData(ParseContext::Scope& scope)
|
||||
{
|
||||
Vector<BindingName> funs(context);
|
||||
Vector<BindingName> vars(context);
|
||||
|
@ -1545,8 +1540,8 @@ Parser<FullParseHandler>::newEvalScopeData(ParseContext::Scope& scope,
|
|||
// superfluous DEFVARs.
|
||||
PodCopy(cursor, funs.begin(), funs.length());
|
||||
cursor += funs.length();
|
||||
*functionBindingEnd = cursor - start;
|
||||
|
||||
bindings->varStart = cursor - start;
|
||||
PodCopy(cursor, vars.begin(), vars.length());
|
||||
bindings->length = numBindings;
|
||||
}
|
||||
|
@ -1830,14 +1825,10 @@ Parser<FullParseHandler>::evalBody(EvalSharedContext* evalsc)
|
|||
if (!FoldConstants(context, &body, this))
|
||||
return nullptr;
|
||||
|
||||
uint32_t functionBindingEnd = 0;
|
||||
Maybe<EvalScope::Data*> bindings =
|
||||
newEvalScopeData(pc->varScope(), &functionBindingEnd);
|
||||
Maybe<EvalScope::Data*> bindings = newEvalScopeData(pc->varScope());
|
||||
if (!bindings)
|
||||
return nullptr;
|
||||
|
||||
evalsc->bindings = *bindings;
|
||||
evalsc->functionBindingEnd = functionBindingEnd;
|
||||
|
||||
return body;
|
||||
}
|
||||
|
@ -1864,13 +1855,10 @@ Parser<FullParseHandler>::globalBody(GlobalSharedContext* globalsc)
|
|||
if (!FoldConstants(context, &body, this))
|
||||
return nullptr;
|
||||
|
||||
uint32_t functionBindingEnd = 0;
|
||||
Maybe<GlobalScope::Data*> bindings = newGlobalScopeData(pc->varScope(), &functionBindingEnd);
|
||||
Maybe<GlobalScope::Data*> bindings = newGlobalScopeData(pc->varScope());
|
||||
if (!bindings)
|
||||
return nullptr;
|
||||
|
||||
globalsc->bindings = *bindings;
|
||||
globalsc->functionBindingEnd = functionBindingEnd;
|
||||
|
||||
return body;
|
||||
}
|
||||
|
|
|
@ -1290,11 +1290,9 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
// Required on Scope exit.
|
||||
bool propagateFreeNamesAndMarkClosedOverBindings(ParseContext::Scope& scope);
|
||||
|
||||
mozilla::Maybe<GlobalScope::Data*> newGlobalScopeData(ParseContext::Scope& scope,
|
||||
uint32_t* functionBindingEnd);
|
||||
mozilla::Maybe<GlobalScope::Data*> newGlobalScopeData(ParseContext::Scope& scope);
|
||||
mozilla::Maybe<ModuleScope::Data*> newModuleScopeData(ParseContext::Scope& scope);
|
||||
mozilla::Maybe<EvalScope::Data*> newEvalScopeData(ParseContext::Scope& scope,
|
||||
uint32_t* functionBindingEnd);
|
||||
mozilla::Maybe<EvalScope::Data*> newEvalScopeData(ParseContext::Scope& scope);
|
||||
mozilla::Maybe<FunctionScope::Data*> newFunctionScopeData(ParseContext::Scope& scope,
|
||||
bool hasParameterExprs);
|
||||
mozilla::Maybe<VarScope::Data*> newVarScopeData(ParseContext::Scope& scope);
|
||||
|
|
|
@ -380,22 +380,12 @@ class MOZ_STACK_CLASS GlobalSharedContext : public SharedContext
|
|||
ScopeKind scopeKind_;
|
||||
|
||||
public:
|
||||
// We omit DEFFVAR in the prologue for global functions since we emit
|
||||
// DEFFUN for them. In order to distinguish function vars, functions are
|
||||
// ordered before vars. See Parser::newGlobalScopeData and
|
||||
// EmitterScope::enterGlobal.
|
||||
//
|
||||
// This is only used in BytecodeEmitter, and is thus not kept in
|
||||
// GlobalScope::Data.
|
||||
uint32_t functionBindingEnd;
|
||||
|
||||
Rooted<GlobalScope::Data*> bindings;
|
||||
|
||||
GlobalSharedContext(ExclusiveContext* cx, ScopeKind scopeKind, Directives directives,
|
||||
bool extraWarnings)
|
||||
: SharedContext(cx, Kind::Global, directives, extraWarnings),
|
||||
scopeKind_(scopeKind),
|
||||
functionBindingEnd(0),
|
||||
bindings(cx)
|
||||
{
|
||||
MOZ_ASSERT(scopeKind == ScopeKind::Global || scopeKind == ScopeKind::NonSyntactic);
|
||||
|
@ -423,15 +413,6 @@ class MOZ_STACK_CLASS EvalSharedContext : public SharedContext
|
|||
RootedScope enclosingScope_;
|
||||
|
||||
public:
|
||||
// We omit DEFFVAR in the prologue for body-level functions since we emit
|
||||
// DEFFUN for them. In order to distinguish function vars, functions are
|
||||
// ordered before vars. See Parser::newEvalScopeData and
|
||||
// EmitterScope::enterEval.
|
||||
//
|
||||
// This is only used in BytecodeEmitter, and is thus not kept in
|
||||
// EvalScope::Data.
|
||||
uint32_t functionBindingEnd;
|
||||
|
||||
Rooted<EvalScope::Data*> bindings;
|
||||
|
||||
EvalSharedContext(ExclusiveContext* cx, JSObject* enclosingEnv, Scope* enclosingScope,
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
function globalPrototypeChainIsMutable()
|
||||
{
|
||||
if (typeof immutablePrototypesEnabled !== "function")
|
||||
return true;
|
||||
|
||||
return !immutablePrototypesEnabled();
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
var g = newGlobal();
|
||||
g.parent = this;
|
||||
g.eval("(" + function() {
|
||||
var dbg = new Debugger(parent);
|
||||
dbg.onExceptionUnwind = function(frame) {
|
||||
frame.eval("h = 3");
|
||||
};
|
||||
} + ")()");
|
||||
g = function h() { }
|
||||
g();
|
|
@ -0,0 +1,41 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
// Flags: -e "version(170)"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
version(170)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
var du = new Debugger();
|
||||
if (typeof du.drainTraceLoggerScriptCalls == "function") {
|
||||
du.setupTraceLoggerScriptCalls();
|
||||
|
||||
du.startTraceLogger();
|
||||
test();
|
||||
du.endTraceLogger();
|
||||
|
||||
var objs = du.drainTraceLoggerScriptCalls();
|
||||
var scripts = 0;
|
||||
var stops = 0;
|
||||
for (var i = 0; i < objs.length; i++) {
|
||||
if (objs[i].logType == "Script") {
|
||||
scripts++;
|
||||
} else if (objs[i].logType == "Stop") {
|
||||
stops++;
|
||||
} else {
|
||||
throw "We shouldn't receive non-script events.";
|
||||
}
|
||||
}
|
||||
assertEq(scripts, stops + 1);
|
||||
// "+ 1" because we get a start for bug1298541.js:1, but not the stop.
|
||||
}
|
||||
|
||||
function test()
|
||||
{
|
||||
for (var i in (function(){ for (var j=0;j<4;++j) { yield ""; } })());
|
||||
}
|
|
@ -2,7 +2,7 @@ function TestDrainTraceLoggerInvariants(obj) {
|
|||
var scripts = 0;
|
||||
var stops = 0;
|
||||
for (var i = 0; i < objs.length; i++) {
|
||||
if (objs[i].logType == "Scripts") {
|
||||
if (objs[i].logType == "Script") {
|
||||
scripts++;
|
||||
assertEq("fileName" in objs[i], true);
|
||||
assertEq("lineNumber" in objs[i], true);
|
||||
|
@ -13,11 +13,13 @@ function TestDrainTraceLoggerInvariants(obj) {
|
|||
assertEq(true, false);
|
||||
}
|
||||
}
|
||||
assertEq(scripts, stops);
|
||||
assertEq(scripts, stops + 1);
|
||||
// "+ 1" because we get a start for drainTraceLogger.js:1, but not the stop.
|
||||
}
|
||||
|
||||
function GetMaxScriptDepth(obj) {
|
||||
var max_depth = 0;
|
||||
var depth = 0;
|
||||
for (var i = 0; i < objs.length; i++) {
|
||||
if (objs[i].logType == "Stop")
|
||||
depth--;
|
||||
|
@ -38,42 +40,39 @@ function foo2() {
|
|||
}
|
||||
|
||||
var du = new Debugger();
|
||||
if (typeof du.drainTraceLoggerTraces == "function") {
|
||||
print(1);
|
||||
if (typeof du.drainTraceLoggerScriptCalls == "function") {
|
||||
// Test normal setup.
|
||||
du = new Debugger();
|
||||
du.setupTraceLoggerForTraces();
|
||||
du.setupTraceLoggerScriptCalls();
|
||||
|
||||
du.startTraceLogger();
|
||||
du.endTraceLogger();
|
||||
|
||||
var objs = du.drainTraceLoggerTraces();
|
||||
var objs = du.drainTraceLoggerScriptCalls();
|
||||
TestDrainTraceLoggerInvariants(objs);
|
||||
var empty_depth = GetMaxScriptDepth(objs);
|
||||
var empty_length = objs.length;
|
||||
|
||||
// Test basic script.
|
||||
for (var i=0; i<20; i++)
|
||||
foo1();
|
||||
|
||||
du = new Debugger();
|
||||
du.setupTraceLoggerTraces();
|
||||
du.setupTraceLoggerScriptCalls();
|
||||
|
||||
du.startTraceLogger();
|
||||
foo1();
|
||||
du.endTraceLogger();
|
||||
|
||||
var objs = du.drainTraceLoggerTraces();
|
||||
var objs = du.drainTraceLoggerScriptCalls();
|
||||
TestDrainTraceLoggerInvariants(objs);
|
||||
assertEq(empty_depth + 2 == GetMaxScriptDepth(objs));
|
||||
assertEq(empty_length + 4 == GetMaxScriptDepth(objs));
|
||||
assertEq(3, GetMaxScriptDepth(objs), "drainTraceLogger.js:0 + foo1 + foo2");
|
||||
assertEq(5, objs.length, "drainTraceLogger.js:0 + foo1 + foo2 + stop + stop");
|
||||
|
||||
// Test basic script.
|
||||
for (var i=0; i<20; i++)
|
||||
foo1();
|
||||
|
||||
du = new Debugger();
|
||||
du.setupTraceLoggerForTraces();
|
||||
du.setupTraceLoggerScriptCalls();
|
||||
|
||||
du.startTraceLogger();
|
||||
for (var i=0; i<100; i++) {
|
||||
|
@ -81,8 +80,9 @@ print(1);
|
|||
}
|
||||
du.endTraceLogger();
|
||||
|
||||
var objs = du.drainTraceLoggerTraces();
|
||||
var objs = du.drainTraceLoggerScriptCalls();
|
||||
TestDrainTraceLoggerInvariants(objs);
|
||||
assertEq(empty_depth + 2 == GetMaxScriptDepth(objs));
|
||||
assertEq(empty_length + 4*100 == GetMaxScriptDepth(objs));
|
||||
assertEq(3, GetMaxScriptDepth(objs), "drainTraceLogger.js:0 + foo1 + foo2");
|
||||
assertEq(4*100 + 1, objs.length);
|
||||
assertEq(1 + 4*100, objs.length, "drainTraceLogger.js:0 + 4 * ( foo1 + foo2 + stop + stop )");
|
||||
}
|
||||
|
|
|
@ -196,20 +196,18 @@ BaselineCompiler::compile()
|
|||
|
||||
// Note: There is an extra entry in the bytecode type map for the search hint, see below.
|
||||
size_t bytecodeTypeMapEntries = script->nTypeSets() + 1;
|
||||
|
||||
UniquePtr<BaselineScript> baselineScript(
|
||||
BaselineScript::New(script, prologueOffset_.offset(),
|
||||
epilogueOffset_.offset(),
|
||||
profilerEnterFrameToggleOffset_.offset(),
|
||||
profilerExitFrameToggleOffset_.offset(),
|
||||
traceLoggerEnterToggleOffset_.offset(),
|
||||
traceLoggerExitToggleOffset_.offset(),
|
||||
postDebugPrologueOffset_.offset(),
|
||||
icEntries_.length(),
|
||||
pcMappingIndexEntries.length(),
|
||||
pcEntries.length(),
|
||||
bytecodeTypeMapEntries,
|
||||
yieldOffsets_.length()),
|
||||
yieldOffsets_.length(),
|
||||
traceLoggerToggleOffsets_.length()),
|
||||
JS::DeletePolicy<BaselineScript>(cx->runtime()));
|
||||
if (!baselineScript) {
|
||||
ReportOutOfMemory(cx);
|
||||
|
@ -263,7 +261,7 @@ BaselineCompiler::compile()
|
|||
|
||||
#ifdef JS_TRACE_LOGGING
|
||||
// Initialize the tracelogger instrumentation.
|
||||
baselineScript->initTraceLogger(cx->runtime(), script);
|
||||
baselineScript->initTraceLogger(cx->runtime(), script, traceLoggerToggleOffsets_);
|
||||
#endif
|
||||
|
||||
uint32_t* bytecodeMap = baselineScript->bytecodeTypeMap();
|
||||
|
@ -842,7 +840,8 @@ BaselineCompiler::emitTraceLoggerEnter()
|
|||
Register scriptReg = regs.takeAnyGeneral();
|
||||
|
||||
Label noTraceLogger;
|
||||
traceLoggerEnterToggleOffset_ = masm.toggledJump(&noTraceLogger);
|
||||
if (!traceLoggerToggleOffsets_.append(masm.toggledJump(&noTraceLogger)))
|
||||
return false;
|
||||
|
||||
masm.Push(loggerReg);
|
||||
masm.Push(scriptReg);
|
||||
|
@ -875,7 +874,8 @@ BaselineCompiler::emitTraceLoggerExit()
|
|||
Register loggerReg = regs.takeAnyGeneral();
|
||||
|
||||
Label noTraceLogger;
|
||||
traceLoggerExitToggleOffset_ = masm.toggledJump(&noTraceLogger);
|
||||
if (!traceLoggerToggleOffsets_.append(masm.toggledJump(&noTraceLogger)))
|
||||
return false;
|
||||
|
||||
masm.Push(loggerReg);
|
||||
masm.movePtr(ImmPtr(logger), loggerReg);
|
||||
|
@ -889,6 +889,32 @@ BaselineCompiler::emitTraceLoggerExit()
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCompiler::emitTraceLoggerResume(Register baselineScript, AllocatableGeneralRegisterSet& regs)
|
||||
{
|
||||
Register scriptId = regs.takeAny();
|
||||
Register loggerReg = regs.takeAny();
|
||||
|
||||
Label noTraceLogger;
|
||||
if (!traceLoggerToggleOffsets_.append(masm.toggledJump(&noTraceLogger)))
|
||||
return false;
|
||||
|
||||
TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
|
||||
masm.movePtr(ImmPtr(logger), loggerReg);
|
||||
|
||||
Address scriptEvent(baselineScript, BaselineScript::offsetOfTraceLoggerScriptEvent());
|
||||
masm.computeEffectiveAddress(scriptEvent, scriptId);
|
||||
masm.tracelogStartEvent(loggerReg, scriptId);
|
||||
masm.tracelogStartId(loggerReg, TraceLogger_Baseline, /* force = */ true);
|
||||
|
||||
regs.add(loggerReg);
|
||||
regs.add(scriptId);
|
||||
|
||||
masm.bind(&noTraceLogger);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
|
@ -4223,6 +4249,11 @@ BaselineCompiler::emit_JSOP_RESUME()
|
|||
masm.loadPtr(Address(scratch1, JSScript::offsetOfBaselineScript()), scratch1);
|
||||
masm.branchPtr(Assembler::BelowOrEqual, scratch1, ImmPtr(BASELINE_DISABLED_SCRIPT), &interpret);
|
||||
|
||||
#ifdef JS_TRACE_LOGGING
|
||||
if (!emitTraceLoggerResume(scratch1, regs))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
Register constructing = regs.takeAny();
|
||||
ValueOperand newTarget = regs.takeAnyValue();
|
||||
masm.loadValue(Address(genObj, GeneratorObject::offsetOfNewTargetSlot()), newTarget);
|
||||
|
|
|
@ -300,6 +300,7 @@ class BaselineCompiler : public BaselineCompilerSpecific
|
|||
MOZ_MUST_USE bool emitDebugTrap();
|
||||
MOZ_MUST_USE bool emitTraceLoggerEnter();
|
||||
MOZ_MUST_USE bool emitTraceLoggerExit();
|
||||
MOZ_MUST_USE bool emitTraceLoggerResume(Register script, AllocatableGeneralRegisterSet& regs);
|
||||
|
||||
void emitProfilerEnterFrame();
|
||||
void emitProfilerExitFrame();
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "jit/BaselineJIT.h"
|
||||
|
||||
#include "mozilla/BinarySearch.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
|
||||
#include "asmjs/WasmInstance.h"
|
||||
|
@ -28,6 +29,7 @@
|
|||
#include "vm/Stack-inl.h"
|
||||
|
||||
using mozilla::BinarySearchIf;
|
||||
using mozilla::DebugOnly;
|
||||
|
||||
using namespace js;
|
||||
using namespace js::jit;
|
||||
|
@ -54,8 +56,6 @@ ICStubSpace::freeAllAfterMinorGC(JSRuntime* rt)
|
|||
BaselineScript::BaselineScript(uint32_t prologueOffset, uint32_t epilogueOffset,
|
||||
uint32_t profilerEnterToggleOffset,
|
||||
uint32_t profilerExitToggleOffset,
|
||||
uint32_t traceLoggerEnterToggleOffset,
|
||||
uint32_t traceLoggerExitToggleOffset,
|
||||
uint32_t postDebugPrologueOffset)
|
||||
: method_(nullptr),
|
||||
templateEnv_(nullptr),
|
||||
|
@ -70,8 +70,6 @@ BaselineScript::BaselineScript(uint32_t prologueOffset, uint32_t epilogueOffset,
|
|||
traceLoggerScriptsEnabled_(false),
|
||||
traceLoggerEngineEnabled_(false),
|
||||
# endif
|
||||
traceLoggerEnterToggleOffset_(traceLoggerEnterToggleOffset),
|
||||
traceLoggerExitToggleOffset_(traceLoggerExitToggleOffset),
|
||||
traceLoggerScriptEvent_(),
|
||||
#endif
|
||||
postDebugPrologueOffset_(postDebugPrologueOffset),
|
||||
|
@ -404,13 +402,12 @@ BaselineScript::New(JSScript* jsscript,
|
|||
uint32_t prologueOffset, uint32_t epilogueOffset,
|
||||
uint32_t profilerEnterToggleOffset,
|
||||
uint32_t profilerExitToggleOffset,
|
||||
uint32_t traceLoggerEnterToggleOffset,
|
||||
uint32_t traceLoggerExitToggleOffset,
|
||||
uint32_t postDebugPrologueOffset,
|
||||
size_t icEntries,
|
||||
size_t pcMappingIndexEntries, size_t pcMappingSize,
|
||||
size_t bytecodeTypeMapEntries,
|
||||
size_t yieldEntries)
|
||||
size_t yieldEntries,
|
||||
size_t traceLoggerToggleOffsetEntries)
|
||||
{
|
||||
static const unsigned DataAlignment = sizeof(uintptr_t);
|
||||
|
||||
|
@ -418,25 +415,27 @@ BaselineScript::New(JSScript* jsscript,
|
|||
size_t pcMappingIndexEntriesSize = pcMappingIndexEntries * sizeof(PCMappingIndexEntry);
|
||||
size_t bytecodeTypeMapSize = bytecodeTypeMapEntries * sizeof(uint32_t);
|
||||
size_t yieldEntriesSize = yieldEntries * sizeof(uintptr_t);
|
||||
size_t tlEntriesSize = traceLoggerToggleOffsetEntries * sizeof(uint32_t);
|
||||
|
||||
size_t paddedICEntriesSize = AlignBytes(icEntriesSize, DataAlignment);
|
||||
size_t paddedPCMappingIndexEntriesSize = AlignBytes(pcMappingIndexEntriesSize, DataAlignment);
|
||||
size_t paddedPCMappingSize = AlignBytes(pcMappingSize, DataAlignment);
|
||||
size_t paddedBytecodeTypesMapSize = AlignBytes(bytecodeTypeMapSize, DataAlignment);
|
||||
size_t paddedYieldEntriesSize = AlignBytes(yieldEntriesSize, DataAlignment);
|
||||
size_t paddedTLEntriesSize = AlignBytes(tlEntriesSize, DataAlignment);
|
||||
|
||||
size_t allocBytes = paddedICEntriesSize +
|
||||
paddedPCMappingIndexEntriesSize +
|
||||
paddedPCMappingSize +
|
||||
paddedBytecodeTypesMapSize +
|
||||
paddedYieldEntriesSize;
|
||||
paddedYieldEntriesSize +
|
||||
paddedTLEntriesSize;
|
||||
|
||||
BaselineScript* script = jsscript->zone()->pod_malloc_with_extra<BaselineScript, uint8_t>(allocBytes);
|
||||
if (!script)
|
||||
return nullptr;
|
||||
new (script) BaselineScript(prologueOffset, epilogueOffset,
|
||||
profilerEnterToggleOffset, profilerExitToggleOffset,
|
||||
traceLoggerEnterToggleOffset, traceLoggerExitToggleOffset,
|
||||
postDebugPrologueOffset);
|
||||
|
||||
size_t offsetCursor = sizeof(BaselineScript);
|
||||
|
@ -460,6 +459,10 @@ BaselineScript::New(JSScript* jsscript,
|
|||
script->yieldEntriesOffset_ = yieldEntries ? offsetCursor : 0;
|
||||
offsetCursor += paddedYieldEntriesSize;
|
||||
|
||||
script->traceLoggerToggleOffsetsOffset_ = tlEntriesSize ? offsetCursor : 0;
|
||||
script->numTraceLoggerToggleOffsets_ = traceLoggerToggleOffsetEntries;
|
||||
offsetCursor += paddedTLEntriesSize;
|
||||
|
||||
MOZ_ASSERT(offsetCursor == sizeof(BaselineScript) + allocBytes);
|
||||
return script;
|
||||
}
|
||||
|
@ -968,7 +971,8 @@ BaselineScript::toggleDebugTraps(JSScript* script, jsbytecode* pc)
|
|||
|
||||
#ifdef JS_TRACE_LOGGING
|
||||
void
|
||||
BaselineScript::initTraceLogger(JSRuntime* runtime, JSScript* script)
|
||||
BaselineScript::initTraceLogger(JSRuntime* runtime, JSScript* script,
|
||||
const Vector<CodeOffset>& offsets)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
traceLoggerScriptsEnabled_ = TraceLogTextIdEnabled(TraceLogger_Scripts);
|
||||
|
@ -976,45 +980,42 @@ BaselineScript::initTraceLogger(JSRuntime* runtime, JSScript* script)
|
|||
#endif
|
||||
|
||||
TraceLoggerThread* logger = TraceLoggerForMainThread(runtime);
|
||||
traceLoggerScriptEvent_ = TraceLoggerEvent(logger, TraceLogger_Scripts, script);
|
||||
|
||||
MOZ_ASSERT(offsets.length() == numTraceLoggerToggleOffsets_);
|
||||
for (size_t i = 0; i < offsets.length(); i++)
|
||||
traceLoggerToggleOffsets()[i] = offsets[i].offset();
|
||||
|
||||
if (TraceLogTextIdEnabled(TraceLogger_Engine) || TraceLogTextIdEnabled(TraceLogger_Scripts)) {
|
||||
CodeLocationLabel enter(method_, CodeOffset(traceLoggerEnterToggleOffset_));
|
||||
CodeLocationLabel exit(method_, CodeOffset(traceLoggerExitToggleOffset_));
|
||||
Assembler::ToggleToCmp(enter);
|
||||
Assembler::ToggleToCmp(exit);
|
||||
traceLoggerScriptEvent_ = TraceLoggerEvent(logger, TraceLogger_Scripts, script);
|
||||
for (size_t i = 0; i < numTraceLoggerToggleOffsets_; i++) {
|
||||
CodeLocationLabel label(method_, CodeOffset(traceLoggerToggleOffsets()[i]));
|
||||
Assembler::ToggleToCmp(label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BaselineScript::toggleTraceLoggerScripts(JSRuntime* runtime, JSScript* script, bool enable)
|
||||
{
|
||||
bool engineEnabled = TraceLogTextIdEnabled(TraceLogger_Engine);
|
||||
|
||||
DebugOnly<bool> engineEnabled = TraceLogTextIdEnabled(TraceLogger_Engine);
|
||||
MOZ_ASSERT(enable == !traceLoggerScriptsEnabled_);
|
||||
MOZ_ASSERT(engineEnabled == traceLoggerEngineEnabled_);
|
||||
|
||||
// Patch the logging script textId to be correct.
|
||||
// When logging log the specific textId else the global Scripts textId.
|
||||
TraceLoggerThread* logger = TraceLoggerForMainThread(runtime);
|
||||
if (enable)
|
||||
if (enable && !traceLoggerScriptEvent_.hasPayload())
|
||||
traceLoggerScriptEvent_ = TraceLoggerEvent(logger, TraceLogger_Scripts, script);
|
||||
else
|
||||
traceLoggerScriptEvent_ = TraceLoggerEvent(logger, TraceLogger_Scripts);
|
||||
|
||||
AutoWritableJitCode awjc(method());
|
||||
|
||||
// Enable/Disable the traceLogger prologue and epilogue.
|
||||
CodeLocationLabel enter(method_, CodeOffset(traceLoggerEnterToggleOffset_));
|
||||
CodeLocationLabel exit(method_, CodeOffset(traceLoggerExitToggleOffset_));
|
||||
if (!engineEnabled) {
|
||||
if (enable) {
|
||||
Assembler::ToggleToCmp(enter);
|
||||
Assembler::ToggleToCmp(exit);
|
||||
} else {
|
||||
Assembler::ToggleToJmp(enter);
|
||||
Assembler::ToggleToJmp(exit);
|
||||
}
|
||||
// Enable/Disable the traceLogger.
|
||||
for (size_t i = 0; i < numTraceLoggerToggleOffsets_; i++) {
|
||||
CodeLocationLabel label(method_, CodeOffset(traceLoggerToggleOffsets()[i]));
|
||||
if (enable)
|
||||
Assembler::ToggleToCmp(label);
|
||||
else
|
||||
Assembler::ToggleToJmp(label);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
@ -1025,24 +1026,19 @@ BaselineScript::toggleTraceLoggerScripts(JSRuntime* runtime, JSScript* script, b
|
|||
void
|
||||
BaselineScript::toggleTraceLoggerEngine(bool enable)
|
||||
{
|
||||
bool scriptsEnabled = TraceLogTextIdEnabled(TraceLogger_Scripts);
|
||||
|
||||
DebugOnly<bool> scriptsEnabled = TraceLogTextIdEnabled(TraceLogger_Scripts);
|
||||
MOZ_ASSERT(enable == !traceLoggerEngineEnabled_);
|
||||
MOZ_ASSERT(scriptsEnabled == traceLoggerScriptsEnabled_);
|
||||
|
||||
AutoWritableJitCode awjc(method());
|
||||
|
||||
// Enable/Disable the traceLogger prologue and epilogue.
|
||||
CodeLocationLabel enter(method_, CodeOffset(traceLoggerEnterToggleOffset_));
|
||||
CodeLocationLabel exit(method_, CodeOffset(traceLoggerExitToggleOffset_));
|
||||
if (!scriptsEnabled) {
|
||||
if (enable) {
|
||||
Assembler::ToggleToCmp(enter);
|
||||
Assembler::ToggleToCmp(exit);
|
||||
} else {
|
||||
Assembler::ToggleToJmp(enter);
|
||||
Assembler::ToggleToJmp(exit);
|
||||
}
|
||||
for (size_t i = 0; i < numTraceLoggerToggleOffsets_; i++) {
|
||||
CodeLocationLabel label(method_, CodeOffset(traceLoggerToggleOffsets()[i]));
|
||||
if (enable)
|
||||
Assembler::ToggleToCmp(label);
|
||||
else
|
||||
Assembler::ToggleToJmp(label);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
|
|
@ -158,8 +158,6 @@ struct BaselineScript
|
|||
bool traceLoggerScriptsEnabled_;
|
||||
bool traceLoggerEngineEnabled_;
|
||||
# endif
|
||||
uint32_t traceLoggerEnterToggleOffset_;
|
||||
uint32_t traceLoggerExitToggleOffset_;
|
||||
TraceLoggerEvent traceLoggerScriptEvent_;
|
||||
#endif
|
||||
|
||||
|
@ -221,6 +219,11 @@ struct BaselineScript
|
|||
// instruction.
|
||||
uint32_t yieldEntriesOffset_;
|
||||
|
||||
// By default tracelogger is disabled. Therefore we disable the logging code
|
||||
// by default. We store the offsets we must patch to enable the logging.
|
||||
uint32_t traceLoggerToggleOffsetsOffset_;
|
||||
uint32_t numTraceLoggerToggleOffsets_;
|
||||
|
||||
// The total bytecode length of all scripts we inlined when we Ion-compiled
|
||||
// this script. 0 if Ion did not compile this script or if we didn't inline
|
||||
// anything.
|
||||
|
@ -241,8 +244,6 @@ struct BaselineScript
|
|||
BaselineScript(uint32_t prologueOffset, uint32_t epilogueOffset,
|
||||
uint32_t profilerEnterToggleOffset,
|
||||
uint32_t profilerExitToggleOffset,
|
||||
uint32_t traceLoggerEnterToggleOffset,
|
||||
uint32_t traceLoggerExitToggleOffset,
|
||||
uint32_t postDebugPrologueOffset);
|
||||
|
||||
~BaselineScript() {
|
||||
|
@ -255,13 +256,12 @@ struct BaselineScript
|
|||
uint32_t prologueOffset, uint32_t epilogueOffset,
|
||||
uint32_t profilerEnterToggleOffset,
|
||||
uint32_t profilerExitToggleOffset,
|
||||
uint32_t traceLoggerEnterToggleOffset,
|
||||
uint32_t traceLoggerExitToggleOffset,
|
||||
uint32_t postDebugPrologueOffset,
|
||||
size_t icEntries,
|
||||
size_t pcMappingIndexEntries, size_t pcMappingSize,
|
||||
size_t bytecodeTypeMapEntries,
|
||||
size_t yieldEntries);
|
||||
size_t yieldEntries,
|
||||
size_t traceLoggerToggleOffsetEntries);
|
||||
|
||||
static void Trace(JSTracer* trc, BaselineScript* script);
|
||||
static void Destroy(FreeOp* fop, BaselineScript* script);
|
||||
|
@ -433,13 +433,19 @@ struct BaselineScript
|
|||
}
|
||||
|
||||
#ifdef JS_TRACE_LOGGING
|
||||
void initTraceLogger(JSRuntime* runtime, JSScript* script);
|
||||
void initTraceLogger(JSRuntime* runtime, JSScript* script, const Vector<CodeOffset>& offsets);
|
||||
void toggleTraceLoggerScripts(JSRuntime* runtime, JSScript* script, bool enable);
|
||||
void toggleTraceLoggerEngine(bool enable);
|
||||
|
||||
static size_t offsetOfTraceLoggerScriptEvent() {
|
||||
return offsetof(BaselineScript, traceLoggerScriptEvent_);
|
||||
}
|
||||
|
||||
uint32_t* traceLoggerToggleOffsets() {
|
||||
MOZ_ASSERT(traceLoggerToggleOffsetsOffset_);
|
||||
return reinterpret_cast<uint32_t*>(reinterpret_cast<uint8_t*>(this) +
|
||||
traceLoggerToggleOffsetsOffset_);
|
||||
}
|
||||
#endif
|
||||
|
||||
void noteAccessedGetter(uint32_t pcOffset);
|
||||
|
|
|
@ -787,6 +787,15 @@ HandleException(ResumeFromException* rfe)
|
|||
IonScript* ionScript = nullptr;
|
||||
bool invalidated = iter.checkInvalidation(&ionScript);
|
||||
|
||||
#ifdef JS_TRACE_LOGGING
|
||||
if (logger && cx->compartment()->isDebuggee() && logger->enabled()) {
|
||||
logger->disable(/* force = */ true,
|
||||
"Forcefully disabled tracelogger, due to "
|
||||
"throwing an exception with an active Debugger "
|
||||
"in IonMonkey.");
|
||||
}
|
||||
#endif
|
||||
|
||||
for (;;) {
|
||||
HandleExceptionIon(cx, frames, rfe, &overrecursed);
|
||||
|
||||
|
|
|
@ -770,6 +770,11 @@ FinalSuspend(JSContext* cx, HandleObject obj, BaselineFrame* frame, jsbytecode*
|
|||
MOZ_ASSERT(*pc == JSOP_FINALYIELDRVAL);
|
||||
|
||||
if (!GeneratorObject::finalSuspend(cx, obj)) {
|
||||
|
||||
TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
|
||||
TraceLogStopEvent(logger, TraceLogger_Engine);
|
||||
TraceLogStopEvent(logger, TraceLogger_Scripts);
|
||||
|
||||
// Leave this frame and propagate the exception to the caller.
|
||||
return DebugEpilogue(cx, frame, pc, /* ok = */ false);
|
||||
}
|
||||
|
|
|
@ -36,8 +36,7 @@ BaselineCompilerShared::BaselineCompilerShared(JSContext* cx, TempAllocator& all
|
|||
spsPushToggleOffset_(),
|
||||
profilerEnterFrameToggleOffset_(),
|
||||
profilerExitFrameToggleOffset_(),
|
||||
traceLoggerEnterToggleOffset_(),
|
||||
traceLoggerExitToggleOffset_(),
|
||||
traceLoggerToggleOffsets_(cx),
|
||||
traceLoggerScriptTextIdOffset_()
|
||||
{ }
|
||||
|
||||
|
|
|
@ -65,8 +65,8 @@ class BaselineCompilerShared
|
|||
CodeOffset spsPushToggleOffset_;
|
||||
CodeOffset profilerEnterFrameToggleOffset_;
|
||||
CodeOffset profilerExitFrameToggleOffset_;
|
||||
CodeOffset traceLoggerEnterToggleOffset_;
|
||||
CodeOffset traceLoggerExitToggleOffset_;
|
||||
|
||||
Vector<CodeOffset> traceLoggerToggleOffsets_;
|
||||
CodeOffset traceLoggerScriptTextIdOffset_;
|
||||
|
||||
BaselineCompilerShared(JSContext* cx, TempAllocator& alloc, JSScript* script);
|
||||
|
|
|
@ -118,6 +118,7 @@ MSG_DEF(JSMSG_TOO_MANY_CON_SPREADARGS, 0, JSEXN_RANGEERR, "too many constructor
|
|||
MSG_DEF(JSMSG_TOO_MANY_FUN_SPREADARGS, 0, JSEXN_RANGEERR, "too many function arguments")
|
||||
MSG_DEF(JSMSG_UNINITIALIZED_LEXICAL, 1, JSEXN_REFERENCEERR, "can't access lexical declaration `{0}' before initialization")
|
||||
MSG_DEF(JSMSG_BAD_CONST_ASSIGN, 1, JSEXN_TYPEERR, "invalid assignment to const `{0}'")
|
||||
MSG_DEF(JSMSG_CANT_DECLARE_GLOBAL_BINDING, 2, JSEXN_TYPEERR, "cannot declare global binding `{0}': {1}")
|
||||
|
||||
// Date
|
||||
MSG_DEF(JSMSG_INVALID_DATE, 0, JSEXN_RANGEERR, "invalid date")
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
#include "vm/SelfHosting.h"
|
||||
#include "vm/Shape.h"
|
||||
#include "vm/StopIterationObject.h"
|
||||
#include "vm/String.h"
|
||||
#include "vm/StringBuffer.h"
|
||||
#include "vm/Symbol.h"
|
||||
#include "vm/TypedArrayCommon.h"
|
||||
|
@ -3138,17 +3139,31 @@ JS_DefineProperties(JSContext* cx, HandleObject obj, const JSPropertySpec* ps)
|
|||
if (!PropertySpecNameToId(cx, ps->name, &id))
|
||||
return false;
|
||||
|
||||
if (ps->isAccessor()) {
|
||||
if (ps->isSelfHosted()) {
|
||||
if (!DefineSelfHostedProperty(cx, obj, id,
|
||||
ps->getter.selfHosted.funname,
|
||||
ps->setter.selfHosted.funname,
|
||||
ps->accessors.getter.selfHosted.funname,
|
||||
ps->accessors.setter.selfHosted.funname,
|
||||
ps->flags, 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!DefinePropertyById(cx, obj, id, JS::UndefinedHandleValue,
|
||||
ps->getter.native, ps->setter.native, ps->flags, 0))
|
||||
ps->accessors.getter.native, ps->accessors.setter.native,
|
||||
ps->flags, 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
RootedAtom atom(cx, Atomize(cx, ps->string.value, strlen(ps->string.value)));
|
||||
if (!atom)
|
||||
return false;
|
||||
|
||||
RootedValue v(cx, StringValue(atom));
|
||||
if (!DefinePropertyById(cx, obj, id, v, NativeOpWrapper(nullptr),
|
||||
NativeOpWrapper(nullptr), ps->flags & ~JSPROP_INTERNAL_USE_BIT, 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -4938,6 +4953,22 @@ JS_NewStringCopyZ(JSContext* cx, const char* s)
|
|||
return NewStringCopyZ<CanGC>(cx, s);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSString*)
|
||||
JS_NewStringCopyUTF8Z(JSContext* cx, const JS::ConstUTF8CharsZ s)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
return NewStringCopyUTF8Z<CanGC>(cx, s);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSString*)
|
||||
JS_NewStringCopyUTF8N(JSContext* cx, const JS::UTF8Chars s)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
return NewStringCopyUTF8N<CanGC>(cx, s);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_StringHasBeenPinned(JSContext* cx, JSString* str)
|
||||
{
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "jspubtd.h"
|
||||
|
||||
#include "js/CallArgs.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "js/Class.h"
|
||||
#include "js/GCVector.h"
|
||||
#include "js/HashTable.h"
|
||||
|
@ -843,7 +844,6 @@ class MOZ_STACK_CLASS SourceBufferHolder final
|
|||
object that delegates to a prototype
|
||||
containing this property */
|
||||
#define JSPROP_INTERNAL_USE_BIT 0x80 /* internal JS engine use only */
|
||||
// 0x100 /* Unused */
|
||||
#define JSFUN_STUB_GSOPS 0x200 /* use JS_PropertyStub getter/setter
|
||||
instead of defaulting to class gsops
|
||||
for property holding function */
|
||||
|
@ -1874,8 +1874,15 @@ struct JSPropertySpec {
|
|||
const char* funname;
|
||||
};
|
||||
|
||||
struct StringValueWrapper {
|
||||
void* unused;
|
||||
const char* value;
|
||||
};
|
||||
|
||||
const char* name;
|
||||
uint8_t flags;
|
||||
union {
|
||||
struct {
|
||||
union {
|
||||
JSNativeWrapper native;
|
||||
SelfHostedWrapper selfHosted;
|
||||
|
@ -1884,8 +1891,17 @@ struct JSPropertySpec {
|
|||
JSNativeWrapper native;
|
||||
SelfHostedWrapper selfHosted;
|
||||
} setter;
|
||||
} accessors;
|
||||
StringValueWrapper string;
|
||||
};
|
||||
|
||||
bool isAccessor() const {
|
||||
return !(flags & JSPROP_INTERNAL_USE_BIT);
|
||||
}
|
||||
|
||||
bool isSelfHosted() const {
|
||||
MOZ_ASSERT(isAccessor());
|
||||
|
||||
#ifdef DEBUG
|
||||
// Verify that our accessors match our JSPROP_GETTER flag.
|
||||
if (flags & JSPROP_GETTER)
|
||||
|
@ -1904,17 +1920,17 @@ struct JSPropertySpec {
|
|||
"JSNativeWrapper::info");
|
||||
private:
|
||||
void checkAccessorsAreNative() const {
|
||||
MOZ_ASSERT(getter.native.op);
|
||||
MOZ_ASSERT(accessors.getter.native.op);
|
||||
// We may not have a setter at all. So all we can assert here, for the
|
||||
// native case is that if we have a jitinfo for the setter then we have
|
||||
// a setter op too. This is good enough to make sure we don't have a
|
||||
// SelfHostedWrapper for the setter.
|
||||
MOZ_ASSERT_IF(setter.native.info, setter.native.op);
|
||||
MOZ_ASSERT_IF(accessors.setter.native.info, accessors.setter.native.op);
|
||||
}
|
||||
|
||||
void checkAccessorsAreSelfHosted() const {
|
||||
MOZ_ASSERT(!getter.selfHosted.unused);
|
||||
MOZ_ASSERT(!setter.selfHosted.unused);
|
||||
MOZ_ASSERT(!accessors.getter.selfHosted.unused);
|
||||
MOZ_ASSERT(!accessors.setter.selfHosted.unused);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1963,37 +1979,46 @@ inline int CheckIsSetterOp(JSSetterOp op);
|
|||
|
||||
#define JS_STUBSETTER JS_PROPERTYOP_SETTER(JS_StrictPropertyStub)
|
||||
|
||||
#define JS_PS_ACCESSOR_SPEC(name, getter, setter, flags, extraFlags) \
|
||||
{ name, uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | extraFlags), \
|
||||
{ { getter, setter } } }
|
||||
#define JS_PS_STRINGVALUE_SPEC(name, value, flags) \
|
||||
{ name, uint8_t(flags | JSPROP_INTERNAL_USE_BIT), \
|
||||
{ { STRINGVALUE_WRAPPER(value), JSNATIVE_WRAPPER(nullptr) } } }
|
||||
|
||||
#define SELFHOSTED_WRAPPER(name) \
|
||||
{ { nullptr, JS_CAST_STRING_TO(name, const JSJitInfo*) } }
|
||||
#define STRINGVALUE_WRAPPER(value) \
|
||||
{ { nullptr, JS_CAST_STRING_TO(value, const JSJitInfo*) } }
|
||||
|
||||
/*
|
||||
* JSPropertySpec uses JSNativeWrapper. These macros encapsulate the definition
|
||||
* of JSNative-backed JSPropertySpecs, by defining the JSNativeWrappers for
|
||||
* them.
|
||||
*/
|
||||
#define JS_PSG(name, getter, flags) \
|
||||
{name, \
|
||||
uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED), \
|
||||
JSNATIVE_WRAPPER(getter), \
|
||||
JSNATIVE_WRAPPER(nullptr)}
|
||||
JS_PS_ACCESSOR_SPEC(name, JSNATIVE_WRAPPER(getter), JSNATIVE_WRAPPER(nullptr), flags, \
|
||||
JSPROP_SHARED)
|
||||
#define JS_PSGS(name, getter, setter, flags) \
|
||||
{name, \
|
||||
uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED), \
|
||||
JSNATIVE_WRAPPER(getter), \
|
||||
JSNATIVE_WRAPPER(setter)}
|
||||
JS_PS_ACCESSOR_SPEC(name, JSNATIVE_WRAPPER(getter), JSNATIVE_WRAPPER(setter), flags, \
|
||||
JSPROP_SHARED)
|
||||
#define JS_SELF_HOSTED_GET(name, getterName, flags) \
|
||||
{name, \
|
||||
uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER), \
|
||||
{ { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo*) } }, \
|
||||
JSNATIVE_WRAPPER(nullptr) }
|
||||
JS_PS_ACCESSOR_SPEC(name, SELFHOSTED_WRAPPER(getterName), JSNATIVE_WRAPPER(nullptr), flags, \
|
||||
JSPROP_SHARED | JSPROP_GETTER)
|
||||
#define JS_SELF_HOSTED_GETSET(name, getterName, setterName, flags) \
|
||||
{name, \
|
||||
uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER | JSPROP_SETTER), \
|
||||
{ nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo*) }, \
|
||||
{ nullptr, JS_CAST_STRING_TO(setterName, const JSJitInfo*) } }
|
||||
#define JS_PS_END { nullptr, 0, JSNATIVE_WRAPPER(nullptr), JSNATIVE_WRAPPER(nullptr) }
|
||||
JS_PS_ACCESSOR_SPEC(name, SELFHOSTED_WRAPPER(getterName), SELFHOSTED_WRAPPER(setterName), \
|
||||
flags, JSPROP_SHARED | JSPROP_GETTER | JSPROP_SETTER)
|
||||
#define JS_SELF_HOSTED_SYM_GET(symbol, getterName, flags) \
|
||||
{reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \
|
||||
uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER), \
|
||||
{ { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo*) } }, \
|
||||
JSNATIVE_WRAPPER(nullptr) }
|
||||
JS_PS_ACCESSOR_SPEC(reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \
|
||||
SELFHOSTED_WRAPPER(getterName), JSNATIVE_WRAPPER(nullptr), flags, \
|
||||
JSPROP_SHARED | JSPROP_GETTER)
|
||||
#define JS_STRING_PS(name, string, flags) \
|
||||
JS_PS_STRINGVALUE_SPEC(name, string, flags)
|
||||
#define JS_STRING_SYM_PS(symbol, string, flags) \
|
||||
JS_PS_STRINGVALUE_SPEC(reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \
|
||||
string, flags)
|
||||
#define JS_PS_END \
|
||||
JS_PS_ACCESSOR_SPEC(nullptr, JSNATIVE_WRAPPER(nullptr), JSNATIVE_WRAPPER(nullptr), 0, 0)
|
||||
|
||||
/**
|
||||
* To define a native function, set call to a JSNativeWrapper. To define a
|
||||
|
@ -4615,6 +4640,12 @@ JS_NewStringCopyN(JSContext* cx, const char* s, size_t n);
|
|||
extern JS_PUBLIC_API(JSString*)
|
||||
JS_NewStringCopyZ(JSContext* cx, const char* s);
|
||||
|
||||
extern JS_PUBLIC_API(JSString*)
|
||||
JS_NewStringCopyUTF8Z(JSContext* cx, const JS::ConstUTF8CharsZ s);
|
||||
|
||||
extern JS_PUBLIC_API(JSString*)
|
||||
JS_NewStringCopyUTF8N(JSContext* cx, const JS::UTF8Chars s);
|
||||
|
||||
extern JS_PUBLIC_API(JSString*)
|
||||
JS_AtomizeAndPinJSString(JSContext* cx, JS::HandleString str);
|
||||
|
||||
|
@ -5803,6 +5834,7 @@ enum AsmJSCacheResult
|
|||
AsmJSCache_Disabled_ShellFlags,
|
||||
AsmJSCache_Disabled_JitInspector,
|
||||
AsmJSCache_InternalError,
|
||||
AsmJSCache_Disabled_PrivateBrowsing,
|
||||
AsmJSCache_LIMIT
|
||||
};
|
||||
|
||||
|
|
|
@ -74,9 +74,6 @@ JS_ObjectCountDynamicSlots(JS::HandleObject obj);
|
|||
extern JS_FRIEND_API(size_t)
|
||||
JS_SetProtoCalled(JSContext* cx);
|
||||
|
||||
extern JS_FRIEND_API(bool)
|
||||
JS_ImmutablePrototypesEnabled();
|
||||
|
||||
extern JS_FRIEND_API(size_t)
|
||||
JS_GetCustomIteratorCount(JSContext* cx);
|
||||
|
||||
|
|
|
@ -2493,20 +2493,6 @@ js::GetPrototypeIfOrdinary(JSContext* cx, HandleObject obj, bool* isOrdinary,
|
|||
return true;
|
||||
}
|
||||
|
||||
// Our immutable-prototype behavior is non-standard, and it's unclear whether
|
||||
// it's shippable. (Or at least it's unclear whether it's shippable with any
|
||||
// provided-by-default uses exposed to script.) If this bool is true,
|
||||
// immutable-prototype behavior is enforced; if it's false, behavior is not
|
||||
// enforced, and immutable-prototype bits stored on objects are completely
|
||||
// ignored.
|
||||
static const bool ImmutablePrototypesEnabled = true;
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
JS_ImmutablePrototypesEnabled()
|
||||
{
|
||||
return ImmutablePrototypesEnabled;
|
||||
}
|
||||
|
||||
/*** ES6 standard internal methods ***************************************************************/
|
||||
|
||||
bool
|
||||
|
@ -2527,7 +2513,7 @@ js::SetPrototype(JSContext* cx, HandleObject obj, HandleObject proto, JS::Object
|
|||
return result.succeed();
|
||||
|
||||
/* Disallow mutation of immutable [[Prototype]]s. */
|
||||
if (obj->staticPrototypeIsImmutable() && ImmutablePrototypesEnabled)
|
||||
if (obj->staticPrototypeIsImmutable())
|
||||
return result.fail(JSMSG_CANT_SET_PROTO);
|
||||
|
||||
/*
|
||||
|
@ -2550,16 +2536,6 @@ js::SetPrototype(JSContext* cx, HandleObject obj, HandleObject proto, JS::Object
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Explicitly disallow mutating the [[Prototype]] of Location objects
|
||||
* for flash-related security reasons.
|
||||
*/
|
||||
if (!strcmp(obj->getClass()->name, "Location")) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_SET_PROTO_OF,
|
||||
"incompatible Location object");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ES6 9.1.2 step 5 forbids changing [[Prototype]] if not [[Extensible]]. */
|
||||
bool extensible;
|
||||
if (!IsExtensible(cx, obj, &extensible))
|
||||
|
|
|
@ -1179,6 +1179,8 @@ ExpressionDecompiler::decompilePC(jsbytecode* pc)
|
|||
case JSOP_GETARG: {
|
||||
unsigned slot = GET_ARGNO(pc);
|
||||
JSAtom* atom = getArg(slot);
|
||||
if (!atom)
|
||||
return false;
|
||||
return write(atom);
|
||||
}
|
||||
case JSOP_GETLOCAL: {
|
||||
|
|
|
@ -6360,8 +6360,10 @@ static const JSJitInfo doFoo_methodinfo = {
|
|||
static const JSPropertySpec dom_props[] = {
|
||||
{"x",
|
||||
JSPROP_SHARED | JSPROP_ENUMERATE,
|
||||
{ {
|
||||
{ { dom_genericGetter, &dom_x_getterinfo } },
|
||||
{ { dom_genericSetter, &dom_x_setterinfo } }
|
||||
} },
|
||||
},
|
||||
JS_PS_END
|
||||
};
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
try {
|
||||
eval("var shouldNotBeDefined1; function NaN(){}; var shouldNotBeDefined2;");
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
assertEq(Object.getOwnPropertyDescriptor(this, 'shouldNotBeDefined2'), undefined);
|
||||
assertEq(Object.getOwnPropertyDescriptor(this, 'shouldNotBeDefined1'), undefined);
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
|
@ -147,7 +147,6 @@ testDefault(function* () {}.constructor.prototype, "GeneratorFunction");
|
|||
testDefault(function* () {}().__proto__.__proto__, "Generator");
|
||||
|
||||
// ES6 25.4.5.4 Promise.prototype [ @@toStringTag ]
|
||||
// testDefault(Promise.prototype, "Promise");
|
||||
// Promise is not yet implemented.
|
||||
testDefault(Promise.prototype, "Promise");
|
||||
|
||||
reportCompare(true, true);
|
||||
|
|
|
@ -36,13 +36,6 @@ if (typeof setImmutablePrototype !== "function")
|
|||
}
|
||||
}
|
||||
|
||||
if (typeof immutablePrototypesEnabled !== "function" &&
|
||||
typeof SpecialPowers !== "undefined")
|
||||
{
|
||||
immutablePrototypesEnabled =
|
||||
SpecialPowers.Cu.getJSTestingFunctions().immutablePrototypesEnabled;
|
||||
}
|
||||
|
||||
if (typeof wrap !== "function")
|
||||
{
|
||||
// good enough
|
||||
|
@ -93,9 +86,7 @@ function checkPrototypeMutationFailure(obj, desc)
|
|||
|
||||
function runNormalTests(global)
|
||||
{
|
||||
if (typeof setImmutablePrototype !== "function" ||
|
||||
typeof immutablePrototypesEnabled !== "function" ||
|
||||
!immutablePrototypesEnabled())
|
||||
if (typeof setImmutablePrototype !== "function")
|
||||
{
|
||||
print("no testable setImmutablePrototype function available, skipping tests");
|
||||
return;
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
|
||||
#include "mozilla/Range.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
|
||||
#include "jscntxt.h"
|
||||
#include "jsprf.h"
|
||||
|
||||
|
@ -250,22 +253,30 @@ enum InflateUTF8Action {
|
|||
CountAndReportInvalids,
|
||||
CountAndIgnoreInvalids,
|
||||
AssertNoInvalids,
|
||||
Copy
|
||||
Copy,
|
||||
FindEncoding
|
||||
};
|
||||
|
||||
static const uint32_t REPLACE_UTF8 = 0xFFFD;
|
||||
static const char16_t REPLACE_UTF8 = 0xFFFD;
|
||||
static const Latin1Char REPLACE_UTF8_LATIN1 = '?';
|
||||
|
||||
// If making changes to this algorithm, make sure to also update
|
||||
// LossyConvertUTF8toUTF16() in dom/wifi/WifiUtils.cpp
|
||||
template <InflateUTF8Action Action>
|
||||
template <InflateUTF8Action Action, typename CharT>
|
||||
static bool
|
||||
InflateUTF8StringToBuffer(JSContext* cx, const UTF8Chars src, char16_t* dst, size_t* dstlenp,
|
||||
bool* isAsciip)
|
||||
InflateUTF8StringToBuffer(JSContext* cx, const UTF8Chars src, CharT* dst, size_t* dstlenp,
|
||||
JS::SmallestEncoding *smallestEncoding)
|
||||
{
|
||||
if (Action != AssertNoInvalids)
|
||||
*isAsciip = true;
|
||||
*smallestEncoding = JS::SmallestEncoding::ASCII;
|
||||
auto RequireLatin1 = [&smallestEncoding]{
|
||||
*smallestEncoding = std::max(JS::SmallestEncoding::Latin1, *smallestEncoding);
|
||||
};
|
||||
auto RequireUTF16 = [&smallestEncoding]{
|
||||
*smallestEncoding = JS::SmallestEncoding::UTF16;
|
||||
};
|
||||
|
||||
// Count how many char16_t characters need to be in the inflated string.
|
||||
// Count how many code units need to be in the inflated string.
|
||||
// |i| is the index into |src|, and |j| is the the index into |dst|.
|
||||
size_t srclen = src.length();
|
||||
uint32_t j = 0;
|
||||
|
@ -274,12 +285,10 @@ InflateUTF8StringToBuffer(JSContext* cx, const UTF8Chars src, char16_t* dst, siz
|
|||
if (!(v & 0x80)) {
|
||||
// ASCII code unit. Simple copy.
|
||||
if (Action == Copy)
|
||||
dst[j] = char16_t(v);
|
||||
dst[j] = CharT(v);
|
||||
|
||||
} else {
|
||||
// Non-ASCII code unit. Determine its length in bytes (n).
|
||||
if (Action != AssertNoInvalids)
|
||||
*isAsciip = false;
|
||||
uint32_t n = 1;
|
||||
while (v & (0x80 >> n))
|
||||
n++;
|
||||
|
@ -292,10 +301,15 @@ InflateUTF8StringToBuffer(JSContext* cx, const UTF8Chars src, char16_t* dst, siz
|
|||
} else if (Action == AssertNoInvalids) { \
|
||||
MOZ_CRASH("invalid UTF-8 string: " # report); \
|
||||
} else { \
|
||||
if (Action == Copy) \
|
||||
dst[j] = char16_t(REPLACE_UTF8); \
|
||||
if (Action == Copy) { \
|
||||
if (std::is_same<decltype(dst[0]), Latin1Char>::value) \
|
||||
dst[j] = CharT(REPLACE_UTF8_LATIN1); \
|
||||
else \
|
||||
MOZ_ASSERT(Action == CountAndIgnoreInvalids); \
|
||||
dst[j] = CharT(REPLACE_UTF8); \
|
||||
} else { \
|
||||
MOZ_ASSERT(Action == CountAndIgnoreInvalids || \
|
||||
Action == FindEncoding); \
|
||||
} \
|
||||
n = n2; \
|
||||
goto invalidMultiByteCodeUnit; \
|
||||
} \
|
||||
|
@ -320,29 +334,40 @@ InflateUTF8StringToBuffer(JSContext* cx, const UTF8Chars src, char16_t* dst, siz
|
|||
}
|
||||
|
||||
// Check the continuation bytes.
|
||||
for (uint32_t m = 1; m < n; m++)
|
||||
for (uint32_t m = 1; m < n; m++) {
|
||||
if ((src[i + m] & 0xC0) != 0x80)
|
||||
INVALID(ReportInvalidCharacter, i, m);
|
||||
}
|
||||
|
||||
// Determine the code unit's length in char16_t and act accordingly.
|
||||
// Determine the code unit's length in CharT and act accordingly.
|
||||
v = JS::Utf8ToOneUcs4Char((uint8_t*)&src[i], n);
|
||||
if (Action != AssertNoInvalids) {
|
||||
if (v > 0xff) {
|
||||
RequireUTF16();
|
||||
if (Action == FindEncoding) {
|
||||
MOZ_ASSERT(dst == nullptr);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
RequireLatin1();
|
||||
}
|
||||
}
|
||||
if (v < 0x10000) {
|
||||
// The n-byte UTF8 code unit will fit in a single char16_t.
|
||||
// The n-byte UTF8 code unit will fit in a single CharT.
|
||||
if (Action == Copy)
|
||||
dst[j] = char16_t(v);
|
||||
|
||||
dst[j] = CharT(v);
|
||||
} else {
|
||||
v -= 0x10000;
|
||||
if (v <= 0xFFFFF) {
|
||||
// The n-byte UTF8 code unit will fit in two char16_t units.
|
||||
// The n-byte UTF8 code unit will fit in two CharT units.
|
||||
if (Action == Copy)
|
||||
dst[j] = char16_t((v >> 10) + 0xD800);
|
||||
dst[j] = CharT((v >> 10) + 0xD800);
|
||||
j++;
|
||||
if (Action == Copy)
|
||||
dst[j] = char16_t((v & 0x3FF) + 0xDC00);
|
||||
dst[j] = CharT((v & 0x3FF) + 0xDC00);
|
||||
|
||||
} else {
|
||||
// The n-byte UTF8 code unit won't fit in two char16_t units.
|
||||
// The n-byte UTF8 code unit won't fit in two CharT units.
|
||||
INVALID(ReportTooBigCharacter, v, 1);
|
||||
}
|
||||
}
|
||||
|
@ -352,70 +377,97 @@ InflateUTF8StringToBuffer(JSContext* cx, const UTF8Chars src, char16_t* dst, siz
|
|||
// header will do the final i++ to move to the start of the next
|
||||
// code unit.
|
||||
i += n - 1;
|
||||
if (Action != AssertNoInvalids)
|
||||
RequireUTF16();
|
||||
}
|
||||
}
|
||||
|
||||
if (Action != AssertNoInvalids)
|
||||
if (Action != AssertNoInvalids || Action != FindEncoding)
|
||||
*dstlenp = j;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <InflateUTF8Action Action>
|
||||
static TwoByteCharsZ
|
||||
template <InflateUTF8Action Action, typename CharsT>
|
||||
static CharsT
|
||||
InflateUTF8StringHelper(JSContext* cx, const UTF8Chars src, size_t* outlen)
|
||||
{
|
||||
using CharT = typename CharsT::CharT;
|
||||
*outlen = 0;
|
||||
|
||||
bool isAscii;
|
||||
if (!InflateUTF8StringToBuffer<Action>(cx, src, /* dst = */ nullptr, outlen, &isAscii))
|
||||
return TwoByteCharsZ();
|
||||
JS::SmallestEncoding encoding;
|
||||
if (!InflateUTF8StringToBuffer<Action, CharT>(cx, src, /* dst = */ nullptr, outlen, &encoding))
|
||||
return CharsT();
|
||||
|
||||
char16_t* dst = cx->pod_malloc<char16_t>(*outlen + 1); // +1 for NUL
|
||||
CharT* dst = cx->pod_malloc<CharT>(*outlen + 1); // +1 for NUL
|
||||
if (!dst) {
|
||||
ReportOutOfMemory(cx);
|
||||
return TwoByteCharsZ();
|
||||
return CharsT();
|
||||
}
|
||||
|
||||
if (isAscii) {
|
||||
if (encoding == JS::SmallestEncoding::ASCII) {
|
||||
size_t srclen = src.length();
|
||||
MOZ_ASSERT(*outlen == srclen);
|
||||
for (uint32_t i = 0; i < srclen; i++)
|
||||
dst[i] = char16_t(src[i]);
|
||||
|
||||
dst[i] = CharT(src[i]);
|
||||
} else {
|
||||
JS_ALWAYS_TRUE(InflateUTF8StringToBuffer<Copy>(cx, src, dst, outlen, &isAscii));
|
||||
MOZ_ALWAYS_TRUE((InflateUTF8StringToBuffer<Copy, CharT>(cx, src, dst, outlen, &encoding)));
|
||||
}
|
||||
|
||||
dst[*outlen] = 0; // NUL char
|
||||
|
||||
return TwoByteCharsZ(dst, *outlen);
|
||||
return CharsT(dst, *outlen);
|
||||
}
|
||||
|
||||
TwoByteCharsZ
|
||||
JS::UTF8CharsToNewTwoByteCharsZ(JSContext* cx, const UTF8Chars utf8, size_t* outlen)
|
||||
{
|
||||
return InflateUTF8StringHelper<CountAndReportInvalids>(cx, utf8, outlen);
|
||||
return InflateUTF8StringHelper<CountAndReportInvalids, TwoByteCharsZ>(cx, utf8, outlen);
|
||||
}
|
||||
|
||||
TwoByteCharsZ
|
||||
JS::UTF8CharsToNewTwoByteCharsZ(JSContext* cx, const ConstUTF8CharsZ& utf8, size_t* outlen)
|
||||
{
|
||||
UTF8Chars chars(utf8.c_str(), strlen(utf8.c_str()));
|
||||
return InflateUTF8StringHelper<CountAndReportInvalids>(cx, chars, outlen);
|
||||
return InflateUTF8StringHelper<CountAndReportInvalids, TwoByteCharsZ>(cx, chars, outlen);
|
||||
}
|
||||
|
||||
TwoByteCharsZ
|
||||
JS::LossyUTF8CharsToNewTwoByteCharsZ(JSContext* cx, const UTF8Chars utf8, size_t* outlen)
|
||||
{
|
||||
return InflateUTF8StringHelper<CountAndIgnoreInvalids>(cx, utf8, outlen);
|
||||
return InflateUTF8StringHelper<CountAndIgnoreInvalids, TwoByteCharsZ>(cx, utf8, outlen);
|
||||
}
|
||||
|
||||
TwoByteCharsZ
|
||||
JS::LossyUTF8CharsToNewTwoByteCharsZ(JSContext* cx, const ConstUTF8CharsZ& utf8, size_t* outlen)
|
||||
{
|
||||
UTF8Chars chars(utf8.c_str(), strlen(utf8.c_str()));
|
||||
return InflateUTF8StringHelper<CountAndIgnoreInvalids>(cx, chars, outlen);
|
||||
return InflateUTF8StringHelper<CountAndIgnoreInvalids, TwoByteCharsZ>(cx, chars, outlen);
|
||||
}
|
||||
|
||||
JS::SmallestEncoding
|
||||
JS::FindSmallestEncoding(UTF8Chars utf8)
|
||||
{
|
||||
JS::SmallestEncoding encoding;
|
||||
MOZ_ALWAYS_TRUE((InflateUTF8StringToBuffer<FindEncoding, char16_t>(
|
||||
/* cx = */ nullptr,
|
||||
utf8,
|
||||
/* dst = */ nullptr,
|
||||
/* dstlen = */ nullptr,
|
||||
&encoding)));
|
||||
return encoding;
|
||||
}
|
||||
|
||||
Latin1CharsZ
|
||||
JS::UTF8CharsToNewLatin1CharsZ(JSContext* cx, const UTF8Chars utf8, size_t* outlen)
|
||||
{
|
||||
return InflateUTF8StringHelper<CountAndReportInvalids, Latin1CharsZ>(cx, utf8, outlen);
|
||||
}
|
||||
|
||||
Latin1CharsZ
|
||||
JS::LossyUTF8CharsToNewLatin1CharsZ(JSContext* cx, const UTF8Chars utf8, size_t* outlen)
|
||||
{
|
||||
return InflateUTF8StringHelper<CountAndIgnoreInvalids, Latin1CharsZ>(cx, utf8, outlen);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -424,6 +476,7 @@ JS::ConstUTF8CharsZ::validate(size_t aLength)
|
|||
{
|
||||
MOZ_ASSERT(data_);
|
||||
UTF8Chars chars(data_, aLength);
|
||||
InflateUTF8StringToBuffer<AssertNoInvalids>(nullptr, chars, nullptr, nullptr, nullptr);
|
||||
InflateUTF8StringToBuffer<AssertNoInvalids, char16_t>(nullptr, chars, nullptr, nullptr,
|
||||
nullptr);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -650,6 +650,17 @@ Debugger::Debugger(JSContext* cx, NativeObject* dbg)
|
|||
|
||||
JS_INIT_CLIST(&breakpoints);
|
||||
JS_INIT_CLIST(&onNewGlobalObjectWatchersLink);
|
||||
|
||||
#ifdef JS_TRACE_LOGGING
|
||||
TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
|
||||
if (logger) {
|
||||
#ifdef NIGHTLY_BUILD
|
||||
logger->getIterationAndSize(&traceLoggerLastDrainedIteration, &traceLoggerLastDrainedSize);
|
||||
#endif
|
||||
logger->getIterationAndSize(&traceLoggerScriptedCallsLastDrainedIteration,
|
||||
&traceLoggerScriptedCallsLastDrainedSize);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Debugger::~Debugger()
|
||||
|
@ -5056,7 +5067,14 @@ Debugger::drainTraceLoggerScriptCalls(JSContext* cx, unsigned argc, Value* vp)
|
|||
if (!item)
|
||||
return false;
|
||||
|
||||
// Filter out internal time.
|
||||
uint32_t textId = eventItem->textId;
|
||||
if (textId == TraceLogger_Internal) {
|
||||
eventItem++;
|
||||
MOZ_ASSERT(eventItem->textId == TraceLogger_Stop);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (textId != TraceLogger_Stop && !logger->textIdIsScriptEvent(textId))
|
||||
continue;
|
||||
|
||||
|
|
|
@ -1375,28 +1375,27 @@ class DebugEnvironmentProxyHandler : public BaseProxyHandler
|
|||
};
|
||||
|
||||
/*
|
||||
* This function handles access to unaliased locals/formals. Since they are
|
||||
* unaliased, the values of these variables are not stored in the slots of
|
||||
* the normal Call/ClonedBlockObject scope objects and thus must be
|
||||
* recovered from somewhere else:
|
||||
* + if the invocation for which the scope was created is still executing,
|
||||
* This function handles access to unaliased locals/formals. Since they
|
||||
* are unaliased, the values of these variables are not stored in the
|
||||
* slots of the normal CallObject and LexicalEnvironmentObject
|
||||
* environments and thus must be recovered from somewhere else:
|
||||
* + if the invocation for which the env was created is still executing,
|
||||
* there is a JS frame live on the stack holding the values;
|
||||
* + if the invocation for which the scope was created finished executing:
|
||||
* - and there was a DebugEnvironmentProxy associated with scope, then the
|
||||
* DebugEnvironments::onPop(Call|Block) handler copied out the unaliased
|
||||
* variables:
|
||||
* . for block scopes, the unaliased values were copied directly
|
||||
* into the block object, since there is a slot allocated for every
|
||||
* block binding, regardless of whether it is aliased;
|
||||
* . for function scopes, a dense array is created in onPopCall to hold
|
||||
* the unaliased values and attached to the DebugEnvironmentProxy;
|
||||
* + if the invocation for which the env was created finished executing:
|
||||
* - and there was a DebugEnvironmentProxy associated with env, then
|
||||
* the DebugEnvironments::onPop(Call|Lexical) handler copied out the
|
||||
* unaliased variables. In both cases, a dense array is created in
|
||||
* onPop(Call|Lexical) to hold the unaliased values and attached to
|
||||
* the DebugEnvironmentProxy;
|
||||
* - and there was not a DebugEnvironmentProxy yet associated with the
|
||||
* scope, then the unaliased values are lost and not recoverable.
|
||||
*
|
||||
* Callers should check accessResult for non-failure results:
|
||||
* - ACCESS_UNALIASED if the access was unaliased and completed
|
||||
* - ACCESS_GENERIC if the access was aliased or the property not found
|
||||
* - ACCESS_LOST if the value has been lost to the debugger
|
||||
* - ACCESS_LOST if the value has been lost to the debugger and the
|
||||
* action is GET; if the action is SET, we assign to the
|
||||
* name of the variable on the environment object
|
||||
*/
|
||||
bool handleUnaliasedAccess(JSContext* cx, Handle<DebugEnvironmentProxy*> debugEnv,
|
||||
Handle<EnvironmentObject*> env, HandleId id, Action action,
|
||||
|
@ -1532,6 +1531,7 @@ class DebugEnvironmentProxyHandler : public BaseProxyHandler
|
|||
|
||||
// Named lambdas that are not closed over are lost.
|
||||
if (loc.kind() == BindingLocation::Kind::NamedLambdaCallee) {
|
||||
if (action == GET)
|
||||
*accessResult = ACCESS_LOST;
|
||||
return true;
|
||||
}
|
||||
|
@ -2031,8 +2031,7 @@ class DebugEnvironmentProxyHandler : public BaseProxyHandler
|
|||
switch (access) {
|
||||
case ACCESS_UNALIASED:
|
||||
return result.succeed();
|
||||
case ACCESS_GENERIC:
|
||||
{
|
||||
case ACCESS_GENERIC: {
|
||||
RootedValue envVal(cx, ObjectValue(*env));
|
||||
return SetProperty(cx, env, id, v, envVal, result);
|
||||
}
|
||||
|
@ -3182,6 +3181,59 @@ js::CheckVarNameConflict(JSContext* cx, Handle<LexicalEnvironmentObject*> lexica
|
|||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
ReportCannotDeclareGlobalBinding(JSContext* cx, HandlePropertyName name, const char* reason)
|
||||
{
|
||||
JSAutoByteString printable;
|
||||
if (AtomToPrintableString(cx, name, &printable)) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_CANT_DECLARE_GLOBAL_BINDING,
|
||||
printable.ptr(), reason);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
js::CheckCanDeclareGlobalBinding(JSContext* cx, Handle<GlobalObject*> global,
|
||||
HandlePropertyName name, bool isFunction)
|
||||
{
|
||||
RootedId id(cx, NameToId(name));
|
||||
Rooted<PropertyDescriptor> desc(cx);
|
||||
if (!GetOwnPropertyDescriptor(cx, global, id, &desc))
|
||||
return false;
|
||||
|
||||
// ES 8.1.14.15 CanDeclareGlobalVar
|
||||
// ES 8.1.14.16 CanDeclareGlobalFunction
|
||||
|
||||
// Step 4.
|
||||
if (!desc.object()) {
|
||||
// 8.1.14.15 step 6.
|
||||
// 8.1.14.16 step 5.
|
||||
if (global->nonProxyIsExtensible())
|
||||
return true;
|
||||
|
||||
ReportCannotDeclareGlobalBinding(cx, name, "global is non-extensible");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Global functions have additional restrictions.
|
||||
if (isFunction) {
|
||||
// 8.1.14.16 step 6.
|
||||
if (desc.configurable())
|
||||
return true;
|
||||
|
||||
// 8.1.14.16 step 7.
|
||||
if (desc.isDataDescriptor() && desc.writable() && desc.enumerable())
|
||||
return true;
|
||||
|
||||
ReportCannotDeclareGlobalBinding(cx, name,
|
||||
"property must be configurable or "
|
||||
"both writable and enumerable");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::CheckGlobalDeclarationConflicts(JSContext* cx, HandleScript script,
|
||||
Handle<LexicalEnvironmentObject*> lexicalEnv,
|
||||
|
@ -3196,14 +3248,32 @@ js::CheckGlobalDeclarationConflicts(JSContext* cx, HandleScript script,
|
|||
RootedPropertyName name(cx);
|
||||
Rooted<BindingIter> bi(cx, BindingIter(script));
|
||||
|
||||
// ES 15.1.11 GlobalDeclarationInstantiation
|
||||
|
||||
// Step 6.
|
||||
//
|
||||
// Check 'var' declarations do not conflict with existing bindings in the
|
||||
// global lexical environment.
|
||||
for (; bi; bi++) {
|
||||
if (bi.kind() != BindingKind::Var)
|
||||
break;
|
||||
name = bi.name()->asPropertyName();
|
||||
if (!CheckVarNameConflict(cx, lexicalEnv, name))
|
||||
return false;
|
||||
|
||||
// Step 10 and 12.
|
||||
//
|
||||
// Check that global functions and vars may be declared.
|
||||
if (varObj->is<GlobalObject>()) {
|
||||
Handle<GlobalObject*> global = varObj.as<GlobalObject>();
|
||||
if (!CheckCanDeclareGlobalBinding(cx, global, name, bi.isTopLevelFunction()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5.
|
||||
//
|
||||
// Check that lexical bindings do not conflict.
|
||||
for (; bi; bi++) {
|
||||
name = bi.name()->asPropertyName();
|
||||
if (!CheckLexicalNameConflict(cx, lexicalEnv, varObj, name))
|
||||
|
@ -3256,7 +3326,9 @@ js::CheckEvalDeclarationConflicts(JSContext* cx, HandleScript script,
|
|||
|
||||
RootedObject obj(cx, scopeChain);
|
||||
|
||||
// ES6 18.2.1.2 step d
|
||||
// ES 18.2.1.3.
|
||||
|
||||
// Step 5.
|
||||
//
|
||||
// Check that a direct eval will not hoist 'var' bindings over lexical
|
||||
// bindings with the same name.
|
||||
|
@ -3266,6 +3338,19 @@ js::CheckEvalDeclarationConflicts(JSContext* cx, HandleScript script,
|
|||
obj = obj->enclosingEnvironment();
|
||||
}
|
||||
|
||||
// Step 8.
|
||||
//
|
||||
// Check that global functions may be declared.
|
||||
if (varObj->is<GlobalObject>()) {
|
||||
Handle<GlobalObject*> global = varObj.as<GlobalObject>();
|
||||
RootedPropertyName name(cx);
|
||||
for (Rooted<BindingIter> bi(cx, BindingIter(script)); bi; bi++) {
|
||||
name = bi.name()->asPropertyName();
|
||||
if (!CheckCanDeclareGlobalBinding(cx, global, name, bi.isTopLevelFunction()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче