author | Brindusan Cristian <cbrindusan@mozilla.com> |
Tue, 02 Apr 2019 11:32:59 +0300 | |
changeset 467515 | ea09774456976ada64ed753a00724ef6bc6be62f |
parent 467514 | 3ebf6f2a81387d7087ef235c3ce60452baf550f3 (current diff) |
parent 467512 | 661bafa045c4206511058bc760343318df4a751b (diff) |
child 467516 | bd1a81666a6bb95b89eb72dce23a340335483ac2 |
child 467566 | 41e4fc459ec96f96d1e49a203717a7d233f075ce |
push id | 112626 |
push user | cbrindusan@mozilla.com |
push date | Tue, 02 Apr 2019 08:40:51 +0000 |
treeherder | mozilla-inbound@ea0977445697 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 68.0a1 |
first release with | nightly linux32
ea0977445697
/
68.0a1
/
20190402083512
/
files
nightly linux64
ea0977445697
/
68.0a1
/
20190402083512
/
files
nightly mac
ea0977445697
/
68.0a1
/
20190402083512
/
files
nightly win32
ea0977445697
/
68.0a1
/
20190402083512
/
files
nightly win64
ea0977445697
/
68.0a1
/
20190402083512
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
68.0a1
/
20190402083512
/
pushlog to previous
nightly linux64
68.0a1
/
20190402083512
/
pushlog to previous
nightly mac
68.0a1
/
20190402083512
/
pushlog to previous
nightly win32
68.0a1
/
20190402083512
/
pushlog to previous
nightly win64
68.0a1
/
20190402083512
/
pushlog to previous
|
--- a/accessible/base/MarkupMap.h +++ b/accessible/base/MarkupMap.h @@ -181,21 +181,27 @@ MARKUPMAP(h6, New_HyperText, roles::HEAD MARKUPMAP(hr, [](Element* aElement, Accessible* aContext) -> Accessible* { return new HTMLHRAccessible(aElement, aContext->Document()); }, 0) MARKUPMAP(input, [](Element* aElement, Accessible* aContext) -> Accessible* { + // TODO(emilio): This would be faster if it used + // HTMLInputElement's already-parsed representation. if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type, nsGkAtoms::checkbox, eIgnoreCase)) { return new CheckboxAccessible(aElement, aContext->Document()); } if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type, + nsGkAtoms::image, eIgnoreCase)) { + return new HTMLButtonAccessible(aElement, aContext->Document()); + } + if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type, nsGkAtoms::radio, eIgnoreCase)) { return new HTMLRadioButtonAccessible(aElement, aContext->Document()); } if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type, nsGkAtoms::time, eIgnoreCase)) { return new EnumRoleAccessible<roles::GROUPING>( aElement, aContext->Document());
--- a/accessible/tests/mochitest/elm/test_HTMLSpec.html +++ b/accessible/tests/mochitest/elm/test_HTMLSpec.html @@ -711,16 +711,17 @@ // HTML:input@type="image" obj = { role: ROLE_PUSHBUTTON, absentStates: STATE_DEFAULT, actions: "press", }; testElm("input_image", obj); + testElm("input_image_display", obj); testElm("input_submit", obj); obj = { role: ROLE_PUSHBUTTON, actions: "press", states: STATE_DEFAULT, }; testElm("input_image_default", obj); @@ -1646,16 +1647,17 @@ <p id="i_container">normal<i>italic</i></p> <img id="img" src="../moz.png"> <input id="input_button" type="button" value="Button"> <input id="input_checkbox" type="checkbox"> <input id="input_checkbox_true" type="checkbox" checked> <input id="input_file" type="file"> <input id="input_image" type="image"> + <input id="input_image_display" type="image" style="display: block"> <form> <input id="input_image_default" type="image"> </form> <input id="input_submit" type="submit"> <form> <input id="input_submit_default" type="submit"> </form> <input id="input_number" type="number" value="44">
--- a/browser/actors/NetErrorChild.jsm +++ b/browser/actors/NetErrorChild.jsm @@ -11,18 +11,16 @@ const {ActorChild} = ChromeUtils.import( ChromeUtils.defineModuleGetter(this, "BrowserUtils", "resource://gre/modules/BrowserUtils.jsm"); ChromeUtils.defineModuleGetter(this, "WebNavigationFrames", "resource://gre/modules/WebNavigationFrames.jsm"); XPCOMUtils.defineLazyGlobalGetters(this, ["URL"]); -XPCOMUtils.defineLazyGlobalGetters(this, ["URL"]); - XPCOMUtils.defineLazyGetter(this, "gPipNSSBundle", function() { return Services.strings.createBundle("chrome://pipnss/locale/pipnss.properties"); }); XPCOMUtils.defineLazyGetter(this, "gBrandBundle", function() { return Services.strings.createBundle("chrome://branding/locale/brand.properties"); }); XPCOMUtils.defineLazyPreferenceGetter(this, "mitmErrorPageEnabled", "browser.security.newcerterrorpage.mitm.enabled");
--- a/browser/base/content/browser-contentblocking.js +++ b/browser/base/content/browser-contentblocking.js @@ -1118,17 +1118,17 @@ var ContentBlocking = { this.iconBox.removeAttribute("animate"); // Only play the animation when the shield is not already shown on the page (the visibility // of the shield based on this onSecurityChange be determined afterwards). } else if (anyBlocking && !this.iconBox.hasAttribute("active")) { this.iconBox.setAttribute("animate", "true"); if (!isBrowserPrivate) { let introCount = Services.prefs.getIntPref(this.prefIntroCount); - if (introCount < this.MAX_INTROS) { + if (introCount < this.MAX_INTROS && !this.anyOtherWindowHasTour()) { Services.prefs.setIntPref(this.prefIntroCount, ++introCount); Services.prefs.savePrefFile(null); this.showIntroPanel(); } } } // We consider the shield state "active" when some kind of blocking activity @@ -1184,16 +1184,26 @@ var ContentBlocking = { if (cryptominingBlocking) { this.cryptominersHistogramAdd("blocked"); } else if (cryptominingAllowing) { this.cryptominersHistogramAdd("allowed"); } }, + // Check if any existing window has a UItour initiated, both showing and hidden. + anyOtherWindowHasTour() { + for (let win of BrowserWindowTracker.orderedWindows) { + if (win != window && UITour.tourBrowsersByWindow.has(win)) { + return true; + } + } + return false; + }, + disableForCurrentPage() { let baseURI = this._baseURIForChannelClassifier; // Add the current host in the 'trackingprotection' consumer of // the permission manager using a normalized URI. This effectively // places this host on the tracking protection allowlist. if (PrivateBrowsingUtils.isBrowserPrivate(gBrowser.selectedBrowser)) { PrivateBrowsingUtils.addToTrackingAllowlist(baseURI);
--- a/browser/base/content/test/general/browser.ini +++ b/browser/base/content/test/general/browser.ini @@ -352,16 +352,17 @@ reason = depends on UpdateUtils .Locale support-files = test_remoteTroubleshoot.html # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD. [browser_remoteWebNavigation_postdata.js] # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD. [browser_removeTabsToTheEnd.js] # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD. [browser_restore_isAppTab.js] +skip-if = !crashreporter # test requires crashreporter due to 1536221 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD. [browser_save_link-perwindowpb.js] skip-if = (e10s && debug && os == "win") || verify # Bug 1280505 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD. [browser_save_private_link_perwindowpb.js] # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD. [browser_save_link_when_window_navigates.js] # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
--- a/browser/base/content/test/plugins/browser.ini +++ b/browser/base/content/test/plugins/browser.ini @@ -87,13 +87,13 @@ tags = blocklist skip-if = !e10s tags = blocklist [browser_enable_DRM_prompt.js] skip-if = (os == 'win' && processor == 'aarch64') # bug 1533164 [browser_private_browsing_eme_persistent_state.js] [browser_globalplugin_crashinfobar.js] skip-if = !crashreporter [browser_pluginCrashCommentAndURL.js] -skip-if = !crashreporter +skip-if = !crashreporter || (processor == 'aarch64' && os == 'win') # aarch64 due to 1538785 [browser_pluginCrashReportNonDeterminism.js] -skip-if = !crashreporter +skip-if = !crashreporter || (processor == 'aarch64' && os == 'win') # aarch64 due to 1538785 [browser_private_clicktoplay.js] [browser_subframe_access_hidden_plugins.js]
--- a/browser/components/enterprisepolicies/tests/browser/browser.ini +++ b/browser/components/enterprisepolicies/tests/browser/browser.ini @@ -34,16 +34,17 @@ skip-if = os != 'mac' [browser_policy_block_about_support.js] [browser_policy_block_set_desktop_background.js] [browser_policy_bookmarks.js] [browser_policy_clear_blocked_cookies.js] [browser_policy_cookie_settings.js] [browser_policy_default_browser_check.js] [browser_policy_disable_feedback_commands.js] [browser_policy_disable_flash_plugin.js] +skip-if = (processor == 'aarch64' && os == 'win') # aarch64 due to 1538785 [browser_policy_disable_fxaccounts.js] skip-if = (verify && debug && (os == 'mac')) [browser_policy_disable_masterpassword.js] [browser_policy_disable_pocket.js] [browser_policy_disable_popup_blocker.js] [browser_policy_disable_privatebrowsing.js] [browser_policy_disable_profile_reset.js] [browser_policy_disable_profile_import.js]
--- a/browser/components/extensions/test/browser/browser-common.ini +++ b/browser/components/extensions/test/browser/browser-common.ini @@ -152,17 +152,17 @@ skip-if = (verify && debug && (os == 'ma [browser_ext_popup_api_injection.js] [browser_ext_popup_background.js] [browser_ext_popup_corners.js] [browser_ext_popup_focus.js] disabled = bug 1438663 [browser_ext_popup_sendMessage.js] [browser_ext_popup_shutdown.js] [browser_ext_port_disconnect_on_crash.js] -skip-if = !e10s || !crashreporter # the tab's process is killed during the test. Without e10s the parent process would die too. +skip-if = !e10s || !crashreporter || (processor == 'aarch64' && os == 'win') # the tab's process is killed during the test. Without e10s the parent process would die too, aarch64 due to 1538785 [browser_ext_port_disconnect_on_window_close.js] [browser_ext_runtime_openOptionsPage.js] [browser_ext_runtime_openOptionsPage_uninstall.js] [browser_ext_search.js] [browser_ext_runtime_setUninstallURL.js] [browser_ext_sessions_forgetClosedTab.js] [browser_ext_sessions_forgetClosedWindow.js] [browser_ext_sessions_incognito.js]
--- a/browser/components/preferences/connection.js +++ b/browser/components/preferences/connection.js @@ -40,17 +40,24 @@ Preferences.addAll([ { id: "network.trr.custom_uri", "type": "string" }, ]); window.addEventListener("DOMContentLoaded", () => { Preferences.get("network.proxy.type").on("change", gConnectionsDialog.proxyTypeChanged.bind(gConnectionsDialog)); Preferences.get("network.proxy.socks_version").on("change", gConnectionsDialog.updateDNSPref.bind(gConnectionsDialog)); - gConnectionsDialog.initDnsOverHttpsUI(); + + // wait until the network.trr prefs are added before init'ing the UI for them + gConnectionsDialog.uiReady = new Promise(resolve => { + gConnectionsDialog._initialPrefsAdded = resolve; + }).then(() => { + delete gConnectionsDialog._initialPrefsAdded; + gConnectionsDialog.initDnsOverHttpsUI(); + }); document .getElementById("disableProxyExtension") .addEventListener( "command", makeDisableControllingExtension( PREF_SETTING_TYPE, PROXY_KEY).bind(gConnectionsDialog)); gConnectionsDialog.updateProxySettingsUI(); initializeProxyUI(gConnectionsDialog); @@ -297,19 +304,23 @@ var gConnectionsDialog = { // values outside 1:4 are considered falsey/disabled in this context let trrPref = Preferences.get("network.trr.mode"); let enabled = trrPref.value > 0 && trrPref.value < 5; return enabled; }, readDnsOverHttpsMode() { // called to update checked element property to reflect current pref value + // this is the first signal we get when the prefs are added, so lazy-init let enabled = this.isDnsOverHttpsEnabled(); let uriPref = Preferences.get("network.trr.uri"); uriPref.disabled = !enabled || this.isDnsOverHttpsLocked(); + if (this._initialPrefsAdded) { + this._initialPrefsAdded(); + } return enabled; }, writeDnsOverHttpsMode() { // called to update pref with user change let trrModeCheckbox = document.getElementById("networkDnsOverHttps"); // we treat checked/enabled as mode 2 return trrModeCheckbox.checked ? 2 : 0;
--- a/browser/components/preferences/fonts.js +++ b/browser/components/preferences/fonts.js @@ -10,17 +10,17 @@ const kDefaultFontType = "font.default.%LANG%"; const kFontNameFmtSerif = "font.name.serif.%LANG%"; const kFontNameFmtSansSerif = "font.name.sans-serif.%LANG%"; const kFontNameFmtMonospace = "font.name.monospace.%LANG%"; const kFontNameListFmtSerif = "font.name-list.serif.%LANG%"; const kFontNameListFmtSansSerif = "font.name-list.sans-serif.%LANG%"; const kFontNameListFmtMonospace = "font.name-list.monospace.%LANG%"; const kFontSizeFmtVariable = "font.size.variable.%LANG%"; -const kFontSizeFmtFixed = "font.size.fixed.%LANG%"; +const kFontSizeFmtFixed = "font.size.monospace.%LANG%"; const kFontMinSizeFmt = "font.minimum-size.%LANG%"; document.documentElement.addEventListener("dialoghelp", window.top.openPrefsHelp); Preferences.addAll([ { id: "font.language.group", type: "wstring" }, { id: "browser.display.use_document_fonts", type: "int" }, { id: "intl.charset.fallback.override", type: "string" },
--- a/browser/components/preferences/in-content/tests/browser.ini +++ b/browser/components/preferences/in-content/tests/browser.ini @@ -30,16 +30,17 @@ skip-if = (os == 'win' && (processor == [browser_search_subdialogs_within_preferences_8.js] [browser_search_subdialogs_within_preferences_site_data.js] [browser_bug795764_cachedisabled.js] [browser_bug1018066_resetScrollPosition.js] [browser_bug1020245_openPreferences_to_paneContent.js] [browser_bug1184989_prevent_scrolling_when_preferences_flipped.js] support-files = browser_bug1184989_prevent_scrolling_when_preferences_flipped.xul +[browser_cookie_exceptions_addRemove.js] [browser_cert_export.js] [browser_engines.js] [browser_change_app_handler.js] skip-if = os != "win" # Windows-specific handler application selection dialog [browser_checkspelling.js] [browser_cloud_storage.js] [browser_connection.js] [browser_connection_bug388287.js]
--- a/browser/components/preferences/in-content/tests/browser_connection_dnsoverhttps.js +++ b/browser/components/preferences/in-content/tests/browser_connection_dnsoverhttps.js @@ -59,16 +59,17 @@ async function testWithProperties(props, if (props.hasOwnProperty(TRR_CUSTOM_URI_PREF)) { Services.prefs.setStringPref(TRR_CUSTOM_URI_PREF, props[TRR_CUSTOM_URI_PREF]); } if (props.hasOwnProperty(TRR_URI_PREF)) { Services.prefs.setStringPref(TRR_URI_PREF, props[TRR_URI_PREF]); } let dialog = await openConnectionsSubDialog(); + await dialog.uiReady; info((Date.now() - startTime) + ": testWithProperties: connections dialog now open"); let doc = dialog.document; let win = doc.ownerGlobal; let dialogClosingPromise = BrowserTestUtils.waitForEvent(doc.documentElement, "dialogclosing"); let modeCheckbox = doc.querySelector(modeCheckboxSelector); let uriTextbox = doc.querySelector(uriTextboxSelector); let uriPrefChangedPromise;
new file mode 100644 --- /dev/null +++ b/browser/components/preferences/in-content/tests/browser_cookie_exceptions_addRemove.js @@ -0,0 +1,241 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const PERMISSIONS_URL = "chrome://browser/content/preferences/permissions.xul"; + +async function openCookiesDialog(doc) { + let cookieExceptionsButton = doc.getElementById("cookieExceptions"); + ok(cookieExceptionsButton, "cookieExceptionsButton found"); + let dialogPromise = promiseLoadSubDialog(PERMISSIONS_URL); + cookieExceptionsButton.click(); + let dialog = await dialogPromise; + return dialog; +} + +function checkCookiesDialog(dialog) { + ok(dialog, "dialog loaded"); + let buttonIds = ["removePermission", "removeAllPermissions", "btnApplyChanges"]; + + for (let buttonId of buttonIds) { + let button = dialog.document.getElementById(buttonId); + ok(button, `${buttonId} found`); + } + + let cancelButton = + dialog.document.getElementsByClassName("actionButtons")[1].children[0]; + + is(cancelButton.getAttribute("label"), "Cancel", "cancelButton found"); +} + +function addNewPermission(websiteAddress, dialog) { + let url = dialog.document.getElementById("url"); + let buttonDialog = dialog.document.getElementById("btnBlock"); + let permissionsBox = dialog.document.getElementById("permissionsBox"); + let currentPermissions = permissionsBox.itemCount; + + url.value = websiteAddress; + url.dispatchEvent(new Event("input", {bubbles: true})); + is(buttonDialog.hasAttribute("disabled"), false, + "When the user add an url the button should be clickable"); + buttonDialog.click(); + + is(permissionsBox.itemCount, currentPermissions + 1, + "Website added in url should be in the list"); +} + +async function cleanList(dialog) { + let removeAllButton = dialog.document.getElementById("removeAllPermissions"); + if (!removeAllButton.hasAttribute("disabled")) removeAllButton.click(); +} + +function addData(websites, dialog) { + for (let website of websites) { + addNewPermission(website, dialog); + } +} + +function deletePermission(permission, dialog) { + let permissionsBox = dialog.document.getElementById("permissionsBox"); + let elements = permissionsBox.getElementsByAttribute("origin", permission); + is(elements.length, 1, "It should find only one entry"); + permissionsBox.selectItem(elements[0]); + let removePermissionButton = dialog.document.getElementById("removePermission"); + is(removePermissionButton.hasAttribute("disabled"), false, + "The button should be clickable to remove selected item"); + removePermissionButton.click(); +} + +function save(dialog) { + let saveButton = dialog.document.getElementById("btnApplyChanges"); + saveButton.click(); +} + +function cancel(dialog) { + let cancelButton = + dialog.document.getElementsByClassName("actionButtons")[1].children[0]; + is(cancelButton.getAttribute("label"), "Cancel", "cancelButton found"); + cancelButton.click(); +} + +async function checkExpected(expected, doc) { + let dialog = await openCookiesDialog(doc); + let permissionsBox = dialog.document.getElementById("permissionsBox"); + + is(permissionsBox.itemCount, expected.length, + `There should be ${expected.length} elements in the list`); + + for (let website of expected) { + let elements = permissionsBox.getElementsByAttribute("origin", website); + is(elements.length, 1, "It should find only one entry"); + } + return dialog; +} + +async function runTest(test, websites, doc) { + let dialog = await openCookiesDialog(doc); + checkCookiesDialog(dialog); + + if (test.needPreviousData) { + addData(websites, dialog); + save(dialog); + dialog = await openCookiesDialog(doc); + } + + for (let step of test.steps) { + switch (step) { + case "addNewPermission": + addNewPermission(test.newData, dialog); + break; + case "deletePermission": + deletePermission(test.newData, dialog); + break; + case "deleteAllPermission": + await cleanList(dialog); + break; + case "save": + save(dialog); + break; + case "cancel": + cancel(dialog); + break; + case "openPane": + dialog = await openCookiesDialog(doc); + break; + default: + // code block + } + } + dialog = await checkExpected(test.expected, doc); + await cleanList(dialog); + save(dialog); +} + +add_task(async function checkPermissions() { + await openPreferencesViaOpenPreferencesAPI("panePrivacy", {leaveOpen: true}); + let win = gBrowser.selectedBrowser.contentWindow; + let doc = win.document; + let websites = ["http://test1.com", "http://test2.com"]; + + let tests = [{ + "needPreviousData": false, + "newData": "https://mytest.com", + "steps": ["addNewPermission", "save"], + "expected": ["https://mytest.com"], // when open the pane again it should find this in the list + }, + { + "needPreviousData": false, + "newData": "https://mytest.com", + "steps": ["addNewPermission", "cancel"], + "expected": [], + }, + { + "needPreviousData": false, + "newData": "https://mytest.com", + "steps": ["addNewPermission", "deletePermission", "save"], + "expected": [], + }, + { + "needPreviousData": false, + "newData": "https://mytest.com", + "steps": ["addNewPermission", "deletePermission", "cancel"], + "expected": [], + }, + { + "needPreviousData": false, + "newData": "https://mytest.com", + "steps": ["addNewPermission", "save", "openPane", "deletePermission", "save"], + "expected": [], + }, + { + "needPreviousData": false, + "newData": "https://mytest.com", + "steps": ["addNewPermission", "save", "openPane", "deletePermission", "cancel"], + "expected": ["https://mytest.com"], + }, + { + "needPreviousData": false, + "newData": "https://mytest.com", + "steps": ["addNewPermission", "deleteAllPermission", "save"], + "expected": [], + }, + { + "needPreviousData": false, + "newData": "https://mytest.com", + "steps": ["addNewPermission", "deleteAllPermission", "cancel"], + "expected": [], + }, + { + "needPreviousData": false, + "newData": "https://mytest.com", + "steps": ["addNewPermission", "save", "openPane", "deleteAllPermission", "save"], + "expected": [], + }, + { + "needPreviousData": false, + "newData": "https://mytest.com", + "steps": ["addNewPermission", "save", "openPane", "deleteAllPermission", "cancel"], + "expected": ["https://mytest.com"], + }, + { + "needPreviousData": true, + "newData": "https://mytest.com", + "steps": ["deleteAllPermission", "save"], + "expected": [], + }, + { + "needPreviousData": true, + "newData": "https://mytest.com", + "steps": ["deleteAllPermission", "cancel"], + "expected": websites, + }, + { + "needPreviousData": true, + "newData": "https://mytest.com", + "steps": ["addNewPermission", "save"], + "expected": (function() { + let result = websites.slice(); + result.push("https://mytest.com"); + return result; + }()), + }, + { + "needPreviousData": true, + "newData": "https://mytest.com", + "steps": ["addNewPermission", "cancel"], + "expected": websites, + }, + { + "needPreviousData": false, + "newData": "https://mytest.com", + "steps": ["addNewPermission", "save", "openPane", "deleteAllPermission", "addNewPermission", "save"], + "expected": ["https://mytest.com"], + }]; + + for (let test of tests) { + await runTest(test, websites, doc); + } + + gBrowser.removeCurrentTab(); +});
--- a/browser/components/preferences/permissions.js +++ b/browser/components/preferences/permissions.js @@ -370,24 +370,24 @@ var gPermissionManager = { }, onApplyChanges() { // Stop observing permission changes since we are about // to write out the pending adds/deletes and don't need // to update the UI this.uninit(); + for (let p of this._permissionsToDelete.values()) { + Services.perms.removeFromPrincipal(p.principal, p.type); + } + for (let p of this._permissionsToAdd.values()) { Services.perms.addFromPrincipal(p.principal, p.type, p.capability); } - for (let p of this._permissionsToDelete.values()) { - Services.perms.removeFromPrincipal(p.principal, p.type); - } - window.close(); }, buildPermissionsList(sortCol) { // Clear old entries. let oldItems = this._list.querySelectorAll("richlistitem"); for (let item of oldItems) { item.remove();
--- a/browser/config/mozconfigs/linux64/code-coverage +++ b/browser/config/mozconfigs/linux64/code-coverage @@ -7,11 +7,11 @@ TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir} ac_add_options --disable-install-strip ac_add_options --disable-elf-hack ac_add_options --disable-sandbox ac_add_options --disable-dmd ac_add_options --disable-profiling ac_add_options --disable-warnings-as-errors ac_add_options --enable-coverage -export LDFLAGS="--coverage -L$topsrcdir/clang/lib/clang/7.0.1/lib/linux/" +export LDFLAGS="--coverage -L$topsrcdir/clang/lib/clang/8.0.0/lib/linux/" export LIBS="-lclang_rt.profile-x86_64" -export RUSTFLAGS="-Ccodegen-units=1 -Zprofile -Zno-landing-pads" +export RUSTFLAGS="-Ccodegen-units=1 -Zprofile -Zno-landing-pads -Clink-dead-code -Coverflow-checks=off"
--- a/browser/config/mozconfigs/macosx64/code-coverage +++ b/browser/config/mozconfigs/macosx64/code-coverage @@ -3,11 +3,11 @@ ac_add_options --disable-lto TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir} ac_add_options --disable-sandbox ac_add_options --disable-warnings-as-errors ac_add_options --enable-coverage -export LDFLAGS="-coverage -L$topsrcdir/clang/lib/clang/7.0.1/lib/darwin/" +export LDFLAGS="-coverage -L$topsrcdir/clang/lib/clang/8.0.0/lib/darwin/" export LIBS="-lclang_rt.profile_osx" -export RUSTFLAGS="-Ccodegen-units=1 -Zprofile -Zno-landing-pads" +export RUSTFLAGS="-Ccodegen-units=1 -Zprofile -Zno-landing-pads -Clink-dead-code -Coverflow-checks=off"
--- a/browser/config/mozconfigs/win64/code-coverage +++ b/browser/config/mozconfigs/win64/code-coverage @@ -23,12 +23,12 @@ export MOZ_PACKAGE_JSSHELL=1 if [ -d "$topsrcdir/clang" ]; then CLANG_LIB_DIR="$(cd $topsrcdir/clang/lib/clang/* && cd lib/windows && pwd)" export LIB=$LIB:$CLANG_LIB_DIR export LDFLAGS="clang_rt.profile-x86_64.lib" fi -export RUSTFLAGS="-Ccodegen-units=1 -Zprofile -Zno-landing-pads" +export RUSTFLAGS="-Ccodegen-units=1 -Zprofile -Zno-landing-pads -Clink-dead-code -Coverflow-checks=off" . "$topsrcdir/build/mozconfig.common.override" . "$topsrcdir/build/mozconfig.clang-cl"
--- a/build/.lldbinit.in +++ b/build/.lldbinit.in @@ -1,2 +1,17 @@ #filter substitution script topsrcdir = "@topsrcdir@"; lldb.debugger.HandleCommand("command source -s true '%s'" % os.path.join(topsrcdir, ".lldbinit")) + +#ifdef MOZ_WIDGET_ANDROID +settings set symbols.enable-external-lookup true + +# This is where libxul.so and libmozglue.so are produced in full builds. +settings append target.exec-search-paths @topobjdir@/toolkit/library +settings append target.exec-search-paths @topobjdir@/mozglue/build + +# This is where artifact builds unpacks "crashreporter-symbols-full.zip" uncompressed ELF debug symbols. +settings append target.debug-file-search-paths @topobjdir@/dist/crashreporter-symbols + +# These are specific paths encoded into Mozilla's automation outputs. +settings append target.source-map /builds/worker/workspace/build/src/obj-firefox @topobjdir@ +settings append target.source-map /builds/worker/workspace/build/src @topsrcdir@ +#endif
rename from build/build-clang/clang-7-android.json rename to build/build-clang/clang-8-android.json --- a/build/build-clang/clang-7-android.json +++ b/build/build-clang/clang-8-android.json @@ -1,20 +1,20 @@ { - "llvm_revision": "349247", + "llvm_revision": "356365", "stages": "2", "build_libcxx": true, "build_type": "Release", "assertions": false, - "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_701/final", - "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_701/final", - "lld_repo": "https://llvm.org/svn/llvm-project/lld/tags/RELEASE_701/final", - "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_701/final", - "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_701/final", - "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_701/final", + "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_800/final", + "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_800/final", + "lld_repo": "https://llvm.org/svn/llvm-project/lld/tags/RELEASE_800/final", + "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_800/final", + "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_800/final", + "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_800/final", "python_path": "/usr/bin/python2.7", "gcc_dir": "/builds/worker/workspace/build/src/gcc", "cc": "/builds/worker/workspace/build/src/gcc/bin/gcc", "cxx": "/builds/worker/workspace/build/src/gcc/bin/g++", "as": "/builds/worker/workspace/build/src/gcc/bin/gcc", "android_targets": { "armv7-linux-android": { "ndk_toolchain": "/builds/worker/workspace/build/src/android-ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64", @@ -42,12 +42,11 @@ "/builds/worker/workspace/build/src/android-ndk/sysroot/usr/include" ], "api_level": 21 } }, "patches": [ "static-llvm-symbolizer.patch", "find_symbolizer_linux.patch", - "rename_gcov_flush_.patch", - "r350774.patch" + "rename_gcov_flush_.patch" ] }
rename from build/build-clang/clang-7-linux64.json rename to build/build-clang/clang-8-linux64.json --- a/build/build-clang/clang-7-linux64.json +++ b/build/build-clang/clang-8-linux64.json @@ -1,25 +1,24 @@ { - "llvm_revision": "349247", + "llvm_revision": "356365", "stages": "3", "build_libcxx": true, "build_type": "Release", "assertions": false, - "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_701/final", - "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_701/final", - "lld_repo": "https://llvm.org/svn/llvm-project/lld/tags/RELEASE_701/final", - "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_701/final", - "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_701/final", - "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_701/final", + "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_800/final", + "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_800/final", + "lld_repo": "https://llvm.org/svn/llvm-project/lld/tags/RELEASE_800/final", + "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_800/final", + "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_800/final", + "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_800/final", "python_path": "/usr/bin/python2.7", "gcc_dir": "/builds/worker/workspace/build/src/gcc", "cc": "/builds/worker/workspace/build/src/gcc/bin/gcc", "cxx": "/builds/worker/workspace/build/src/gcc/bin/g++", "as": "/builds/worker/workspace/build/src/gcc/bin/gcc", "patches": [ "static-llvm-symbolizer.patch", "find_symbolizer_linux.patch", "rename_gcov_flush_.patch", - "r350774.patch", "android-mangling-error.patch" ] }
rename from build/build-clang/clang-7-macosx64.json rename to build/build-clang/clang-8-macosx64.json --- a/build/build-clang/clang-7-macosx64.json +++ b/build/build-clang/clang-8-macosx64.json @@ -1,29 +1,28 @@ { - "llvm_revision": "349247", + "llvm_revision": "356365", "stages": "1", "build_libcxx": true, "build_type": "Release", "assertions": false, "osx_cross_compile": true, - "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_701/final", - "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_701/final", - "lld_repo": "https://llvm.org/svn/llvm-project/lld/tags/RELEASE_701/final", - "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_701/final", - "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_701/final", - "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_701/final", + "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_800/final", + "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_800/final", + "lld_repo": "https://llvm.org/svn/llvm-project/lld/tags/RELEASE_800/final", + "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_800/final", + "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_800/final", + "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_800/final", "python_path": "/usr/bin/python2.7", "gcc_dir": "/builds/worker/workspace/build/src/gcc", "cc": "/builds/worker/workspace/build/src/clang/bin/clang", "cxx": "/builds/worker/workspace/build/src/clang/bin/clang++", "as": "/builds/worker/workspace/build/src/clang/bin/clang", "ar": "/builds/worker/workspace/build/src/cctools/bin/x86_64-darwin11-ar", "ranlib": "/builds/worker/workspace/build/src/cctools/bin/x86_64-darwin11-ranlib", "libtool": "/builds/worker/workspace/build/src/cctools/bin/x86_64-darwin11-libtool", "ld": "/builds/worker/workspace/build/src/clang/bin/clang", "patches": [ "static-llvm-symbolizer.patch", "compiler-rt-cross-compile.patch", - "compiler-rt-no-codesign.patch", - "r350774.patch" + "compiler-rt-no-codesign.patch" ] }
rename from build/build-clang/clang-trunk-mingw.json rename to build/build-clang/clang-8-mingw.json --- a/build/build-clang/clang-trunk-mingw.json +++ b/build/build-clang/clang-8-mingw.json @@ -11,11 +11,10 @@ "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/trunk", "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/trunk", "python_path": "/usr/bin/python2.7", "gcc_dir": "/builds/worker/workspace/build/src/gcc", "cc": "/builds/worker/workspace/build/src/gcc/bin/gcc", "cxx": "/builds/worker/workspace/build/src/gcc/bin/g++", "as": "/builds/worker/workspace/build/src/gcc/bin/gcc", "patches": [ - "r350774.patch" ] }
new file mode 100644 --- /dev/null +++ b/build/build-clang/clang-tidy-8.patch @@ -0,0 +1,10 @@ +--- a/extra/clang-tidy/tool/run-clang-tidy.py 2019-03-27 15:12:48.000000000 +0200 ++++ b/extra/clang-tidy/tool/run-clang-tidy.py 2019-03-27 15:12:39.000000000 +0200 +@@ -169,6 +169,7 @@ + with lock: + sys.stdout.write(' '.join(invocation) + '\n' + output.decode('utf-8') + '\n') + if len(err) > 0: ++ sys.stdout.flush() + sys.stderr.write(err.decode('utf-8') + '\n') + queue.task_done() +
--- a/build/build-clang/clang-tidy-linux64.json +++ b/build/build-clang/clang-tidy-linux64.json @@ -1,20 +1,21 @@ { - "llvm_revision": "349247", + "llvm_revision": "356365", "stages": "1", "build_libcxx": true, "build_type": "Release", "assertions": false, "build_clang_tidy": true, - "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_701/final/", - "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_701/final/", - "extra_repo": "https://llvm.org/svn/llvm-project/clang-tools-extra/tags/RELEASE_701/final/", - "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_701/final/", - "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_701/final/", + "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_800/final/", + "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_800/final/", + "extra_repo": "https://llvm.org/svn/llvm-project/clang-tools-extra/tags/RELEASE_800/final/", + "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_800/final/", + "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_800/final/", "python_path": "/usr/bin/python2.7", "gcc_dir": "/builds/worker/workspace/build/src/gcc", "cc": "/builds/worker/workspace/build/src/gcc/bin/gcc", "cxx": "/builds/worker/workspace/build/src/gcc/bin/g++", "as": "/builds/worker/workspace/build/src/gcc/bin/gcc", "patches": [ + "clang-tidy-8.patch" ] }
--- a/build/build-clang/clang-tidy-macosx64.json +++ b/build/build-clang/clang-tidy-macosx64.json @@ -1,25 +1,26 @@ { - "llvm_revision": "349247", + "llvm_revision": "356365", "stages": "1", "build_libcxx": true, "build_type": "Release", "assertions": false, "build_clang_tidy": true, "osx_cross_compile": true, - "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_701/final", - "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_701/final", - "extra_repo": "https://llvm.org/svn/llvm-project/clang-tools-extra/tags/RELEASE_701/final", - "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_701/final", - "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_701/final", + "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_800/final", + "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_800/final", + "extra_repo": "https://llvm.org/svn/llvm-project/clang-tools-extra/tags/RELEASE_800/final", + "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_800/final", + "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_800/final", "python_path": "/usr/bin/python2.7", "gcc_dir": "/builds/worker/workspace/build/src/gcc", "cc": "/builds/worker/workspace/build/src/clang/bin/clang", "cxx": "/builds/worker/workspace/build/src/clang/bin/clang++", "as": "/builds/worker/workspace/build/src/clang/bin/clang", "ar": "/builds/worker/workspace/build/src/cctools/bin/x86_64-darwin11-ar", "ranlib": "/builds/worker/workspace/build/src/cctools/bin/x86_64-darwin11-ranlib", "libtool": "/builds/worker/workspace/build/src/cctools/bin/x86_64-darwin11-libtool", "ld": "/builds/worker/workspace/build/src/clang/bin/clang", "patches": [ + "clang-tidy-8.patch" ] }
--- a/build/build-clang/clang-tidy-win64.json +++ b/build/build-clang/clang-tidy-win64.json @@ -1,19 +1,20 @@ { - "llvm_revision": "349247", + "llvm_revision": "356365", "stages": "1", "build_libcxx": false, "build_type": "Release", "assertions": false, "build_clang_tidy": true, - "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_701/final", - "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_701/final", - "extra_repo": "https://llvm.org/svn/llvm-project/clang-tools-extra/tags/RELEASE_701/final", - "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_701/final", - "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_701/final", + "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_800/final", + "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_800/final", + "extra_repo": "https://llvm.org/svn/llvm-project/clang-tools-extra/tags/RELEASE_800/final", + "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_800/final", + "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_800/final", "python_path": "c:/mozilla-build/python/python.exe", "cc": "cl.exe", "cxx": "cl.exe", "ml": "ml64.exe", "patches": [ + "clang-tidy-8.patch" ] }
deleted file mode 100644 --- a/build/build-clang/r350774.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff --git a/llvm/lib/Object/Binary.cpp b/llvm/lib/Object/Binary.cpp -index d7c25921ec3..fe41987f5c2 100644 ---- a/llvm/lib/Object/Binary.cpp -+++ b/llvm/lib/Object/Binary.cpp -@@ -88,7 +88,8 @@ Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer, - - Expected<OwningBinary<Binary>> object::createBinary(StringRef Path) { - ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = -- MemoryBuffer::getFileOrSTDIN(Path); -+ MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1, -+ /*RequiresNullTerminator=*/false); - if (std::error_code EC = FileOrErr.getError()) - return errorCodeToError(EC); - std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
--- a/build/build-clang/rename_gcov_flush_.patch +++ b/build/build-clang/rename_gcov_flush_.patch @@ -7,8 +7,21 @@ diff --git a/compiler-rt/lib/profile/GCD fn_list_insert(&flush_fn_list, fn); } -void __gcov_flush() { +void __custom_llvm_gcov_flush() { struct fn_node* curr = flush_fn_list.head; while (curr) { +diff --git a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp +index 9af64ed332c..bcebe303ff4 100644 +--- a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp ++++ b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp +@@ -648,7 +648,7 @@ void GCOVProfiler::AddFlushBeforeForkAndExec() { + for (auto I : ForkAndExecs) { + IRBuilder<> Builder(I); + FunctionType *FTy = FunctionType::get(Builder.getVoidTy(), {}, false); +- Constant *GCOVFlush = M->getOrInsertFunction("__gcov_flush", FTy); ++ Constant *GCOVFlush = M->getOrInsertFunction("__custom_llvm_gcov_flush", FTy); + Builder.CreateCall(GCOVFlush); + I->getParent()->splitBasicBlock(I); + }
--- a/build/clang-plugin/import_mozilla_checks.py +++ b/build/clang-plugin/import_mozilla_checks.py @@ -49,16 +49,17 @@ add_clang_library(clangTidyMozillaModule LINK_LIBS clangAST clangASTMatchers clangBasic clangLex clangTidy clangTidyReadabilityModule clangTidyUtils + clangTidyMPIModule )""" % {'names': "\n".join(names)}) def add_item_to_cmake_section(cmake_path, section, library): with open(cmake_path, 'r') as f: lines = f.readlines() f.close()
--- a/build/clang-plugin/moz.build +++ b/build/clang-plugin/moz.build @@ -65,16 +65,21 @@ third_party_paths.inputs = [ HOST_COMPILE_FLAGS['STL'] = [] HOST_COMPILE_FLAGS['VISIBILITY'] = [] # libc++ is required to build plugins against clang on OS X. if CONFIG['HOST_OS_ARCH'] == 'Darwin': HOST_CXXFLAGS += ['-stdlib=libc++'] +# As of clang 8, llvm-config doesn't output the flags used to build clang +# itself, so we don't end up with -fPIC as a side effect. llvm.org/PR8220 +if CONFIG['HOST_OS_ARCH'] != 'Windows': + HOST_CXXFLAGS += ['-fPIC'] + DIRS += [ 'tests', ] # In the current moz.build world, we need to override essentially every # variable to limit ourselves to what we need to build the clang plugin. if CONFIG['HOST_OS_ARCH'] == 'WINNT':
--- a/build/moz.build +++ b/build/moz.build @@ -109,16 +109,17 @@ if CONFIG['ENABLE_TESTS']: # NOTE: Keep .gdbinit in the topsrcdir for people who run gdb from the topsrcdir. OBJDIR_FILES += ['/.gdbinit'] # Put a .lldbinit in the bin directory and the objdir, to be picked up # automatically by LLDB when we debug executables using either of those two # directories as the current working directory. The .lldbinit file will # load $(topsrcdir)/.lldbinit, which is where the actual debugging commands are. DEFINES['topsrcdir'] = TOPSRCDIR +DEFINES['topobjdir'] = TOPOBJDIR FINAL_TARGET_PP_FILES += ['.lldbinit.in'] OBJDIR_FILES += ['!/dist/bin/.lldbinit'] # Put the .ycm_extra_conf.py file at the root of the objdir. It is used by # the vim plugin YouCompleteMe. OBJDIR_FILES += ['/.ycm_extra_conf.py'] if CONFIG['MOZ_VALGRIND']:
--- a/caps/nsScriptSecurityManager.cpp +++ b/caps/nsScriptSecurityManager.cpp @@ -1143,17 +1143,18 @@ nsresult nsScriptSecurityManager::Report nsCOMPtr<nsIConsoleService> console( do_GetService(NS_CONSOLESERVICE_CONTRACTID)); NS_ENSURE_TRUE(console, NS_ERROR_FAILURE); nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID)); NS_ENSURE_TRUE(error, NS_ERROR_FAILURE); // using category of "SOP" so we can link to MDN rv = error->Init(message, EmptyString(), EmptyString(), 0, 0, - nsIScriptError::errorFlag, "SOP", aFromPrivateWindow); + nsIScriptError::errorFlag, "SOP", aFromPrivateWindow, + true /* From chrome context */); NS_ENSURE_SUCCESS(rv, rv); console->LogMessage(error); return NS_OK; } NS_IMETHODIMP nsScriptSecurityManager::CheckLoadURIStrWithPrincipal( nsIPrincipal* aPrincipal, const nsACString& aTargetURIStr,
--- a/chrome/nsChromeRegistry.cpp +++ b/chrome/nsChromeRegistry.cpp @@ -75,20 +75,20 @@ void nsChromeRegistry::LogMessageWithCon va_start(args, aMsg); mozilla::SmprintfPointer formatted = mozilla::Vsmprintf(aMsg, args); va_end(args); if (!formatted) return; nsCString spec; if (aURL) aURL->GetSpec(spec); - rv = error->Init(NS_ConvertUTF8toUTF16(formatted.get()), - NS_ConvertUTF8toUTF16(spec), EmptyString(), aLineNumber, 0, - flags, "chrome registration", - false /* from private window */); + rv = error->Init( + NS_ConvertUTF8toUTF16(formatted.get()), NS_ConvertUTF8toUTF16(spec), + EmptyString(), aLineNumber, 0, flags, "chrome registration", + false /* from private window */, true /* from chrome context */); if (NS_FAILED(rv)) return; console->LogMessage(error); } nsChromeRegistry::~nsChromeRegistry() { gChromeRegistry = nullptr; }
--- a/devtools/client/webconsole/test/fixtures/stubs/consoleApi.js +++ b/devtools/client/webconsole/test/fixtures/stubs/consoleApi.js @@ -2099,16 +2099,17 @@ stubPreparedMessages.set(`console.countR stubPackets.set(`console.log('foobar', 'test')`, { "message": { "addonId": "", "arguments": [ "foobar", "test" ], + "chromeContext": false, "columnNumber": 35, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "log", "lineNumber": 1, "prefix": "", @@ -2128,16 +2129,17 @@ stubPackets.set(`console.log('foobar', ' stubPackets.set(`console.log(undefined)`, { "message": { "addonId": "", "arguments": [ { "type": "undefined" } ], + "chromeContext": false, "columnNumber": 35, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "log", "lineNumber": 1, "prefix": "", @@ -2155,16 +2157,17 @@ stubPackets.set(`console.log(undefined)` }); stubPackets.set(`console.warn('danger, will robinson!')`, { "message": { "addonId": "", "arguments": [ "danger, will robinson!" ], + "chromeContext": false, "columnNumber": 35, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "warn", "lineNumber": 1, "prefix": "", @@ -2184,16 +2187,17 @@ stubPackets.set(`console.warn('danger, w stubPackets.set(`console.log(NaN)`, { "message": { "addonId": "", "arguments": [ { "type": "NaN" } ], + "chromeContext": false, "columnNumber": 35, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "log", "lineNumber": 1, "prefix": "", @@ -2213,16 +2217,17 @@ stubPackets.set(`console.log(NaN)`, { stubPackets.set(`console.log(null)`, { "message": { "addonId": "", "arguments": [ { "type": "null" } ], + "chromeContext": false, "columnNumber": 35, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "log", "lineNumber": 1, "prefix": "", @@ -2240,16 +2245,17 @@ stubPackets.set(`console.log(null)`, { }); stubPackets.set(`console.log('鼬')`, { "message": { "addonId": "", "arguments": [ "鼬" ], + "chromeContext": false, "columnNumber": 35, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "log", "lineNumber": 1, "prefix": "", @@ -2265,16 +2271,17 @@ stubPackets.set(`console.log('鼬')`, { "type": "consoleAPICall", "from": "server1.conn0.child1/consoleActor2" }); stubPackets.set(`console.clear()`, { "message": { "addonId": "", "arguments": [], + "chromeContext": false, "columnNumber": 35, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "clear", "lineNumber": 1, "prefix": "", @@ -2292,16 +2299,17 @@ stubPackets.set(`console.clear()`, { }); stubPackets.set(`console.count('bar')`, { "message": { "addonId": "", "arguments": [ "bar" ], + "chromeContext": false, "columnNumber": 35, "counter": { "count": 1, "label": "bar" }, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", @@ -2345,16 +2353,17 @@ stubPackets.set(`console.assert(false, { }, "ownSymbols": [], "ownPropertiesLength": 1, "ownSymbolsLength": 0, "safeGetterValues": {} } } ], + "chromeContext": false, "columnNumber": 35, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "assert", "lineNumber": 1, "prefix": "", @@ -2381,16 +2390,17 @@ stubPackets.set(`console.assert(false, { }); stubPackets.set(`console.log('hello \nfrom \rthe \"string world!')`, { "message": { "addonId": "", "arguments": [ "hello \nfrom \rthe \"string world!" ], + "chromeContext": false, "columnNumber": 35, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "log", "lineNumber": 1, "prefix": "", @@ -2408,16 +2418,17 @@ stubPackets.set(`console.log('hello \nfr }); stubPackets.set(`console.log('úṇĩçödê țĕșť')`, { "message": { "addonId": "", "arguments": [ "úṇĩçödê țĕșť" ], + "chromeContext": false, "columnNumber": 35, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "log", "lineNumber": 1, "prefix": "", @@ -2447,16 +2458,17 @@ stubPackets.set(`console.dirxml(window)` "sealed": false, "ownPropertyLength": 830, "preview": { "kind": "ObjectWithURL", "url": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html" } } ], + "chromeContext": false, "columnNumber": 35, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "dirxml", "lineNumber": 1, "prefix": "", @@ -2492,16 +2504,17 @@ stubPackets.set(`console.log('myarray', "items": [ "red", "green", "blue" ] } } ], + "chromeContext": false, "columnNumber": 35, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "log", "lineNumber": 1, "prefix": "", @@ -2529,16 +2542,17 @@ stubPackets.set(`console.log('myregex', "class": "RegExp", "extensible": true, "frozen": false, "sealed": false, "ownPropertyLength": 1, "displayString": "/a.b.c/" } ], + "chromeContext": false, "columnNumber": 35, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "log", "lineNumber": 1, "prefix": "", @@ -2573,16 +2587,17 @@ stubPackets.set(`console.table(['red', ' "items": [ "red", "green", "blue" ] } } ], + "chromeContext": false, "columnNumber": 35, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "table", "lineNumber": 1, "prefix": "", @@ -2636,16 +2651,17 @@ stubPackets.set(`console.log('myobject', }, "ownSymbols": [], "ownPropertiesLength": 3, "ownSymbolsLength": 0, "safeGetterValues": {} } } ], + "chromeContext": false, "columnNumber": 35, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "log", "lineNumber": 1, "prefix": "", @@ -2663,16 +2679,17 @@ stubPackets.set(`console.log('myobject', }); stubPackets.set(`console.debug('debug message');`, { "message": { "addonId": "", "arguments": [ "debug message" ], + "chromeContext": false, "columnNumber": 35, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "debug", "lineNumber": 1, "prefix": "", @@ -2690,16 +2707,17 @@ stubPackets.set(`console.debug('debug me }); stubPackets.set(`console.info('info message');`, { "message": { "addonId": "", "arguments": [ "info message" ], + "chromeContext": false, "columnNumber": 35, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "info", "lineNumber": 1, "prefix": "", @@ -2717,16 +2735,17 @@ stubPackets.set(`console.info('info mess }); stubPackets.set(`console.error('error message');`, { "message": { "addonId": "", "arguments": [ "error message" ], + "chromeContext": false, "columnNumber": 35, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "error", "lineNumber": 1, "prefix": "", @@ -2776,16 +2795,17 @@ stubPackets.set(`console.log('mymap')`, [ "key2", "value2" ] ] } } ], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "log", "lineNumber": 5, "prefix": "", @@ -2820,16 +2840,17 @@ stubPackets.set(`console.log('myset')`, "length": 2, "items": [ "a", "b" ] } } ], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "log", "lineNumber": 2, "prefix": "", @@ -2845,16 +2866,17 @@ stubPackets.set(`console.log('myset')`, "type": "consoleAPICall", "from": "server1.conn0.child1/consoleActor2" }); stubPackets.set(`console.trace()`, { "message": { "addonId": "", "arguments": [], + "chromeContext": false, "columnNumber": 11, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "testStacktraceFiltering", "groupName": "", "level": "trace", "lineNumber": 3, "prefix": "", @@ -2937,16 +2959,17 @@ stubPackets.set(`console.trace('bar', {' "items": [ 1, 2, 3 ] } } ], + "chromeContext": false, "columnNumber": 11, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "testStacktraceWithLog", "groupName": "", "level": "trace", "lineNumber": 3, "prefix": "", @@ -2987,16 +3010,17 @@ stubPackets.set(`console.trace('bar', {' }); stubPackets.set(`console.time('bar')`, { "message": { "addonId": "", "arguments": [ "bar" ], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "time", "lineNumber": 2, "prefix": "", @@ -3016,16 +3040,17 @@ stubPackets.set(`console.time('bar')`, { }); stubPackets.set(`timerAlreadyExists`, { "message": { "addonId": "", "arguments": [ "bar" ], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "time", "lineNumber": 3, "prefix": "", @@ -3046,16 +3071,17 @@ stubPackets.set(`timerAlreadyExists`, { }); stubPackets.set(`console.timeLog('bar') - 1`, { "message": { "addonId": "", "arguments": [ "bar" ], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "timeLog", "lineNumber": 4, "prefix": "", @@ -3101,16 +3127,17 @@ stubPackets.set(`console.timeLog('bar') }, "ownSymbols": [], "ownPropertiesLength": 1, "ownSymbolsLength": 0, "safeGetterValues": {} } } ], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "timeLog", "lineNumber": 5, "prefix": "", @@ -3131,16 +3158,17 @@ stubPackets.set(`console.timeLog('bar') }); stubPackets.set(`console.timeEnd('bar')`, { "message": { "addonId": "", "arguments": [ "bar" ], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "timeEnd", "lineNumber": 6, "prefix": "", @@ -3161,16 +3189,17 @@ stubPackets.set(`console.timeEnd('bar')` }); stubPackets.set(`timeEnd.timerDoesntExist`, { "message": { "addonId": "", "arguments": [ "bar" ], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "timeEnd", "lineNumber": 7, "prefix": "", @@ -3191,16 +3220,17 @@ stubPackets.set(`timeEnd.timerDoesntExis }); stubPackets.set(`timeLog.timerDoesntExist`, { "message": { "addonId": "", "arguments": [ "bar" ], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "timeLog", "lineNumber": 8, "prefix": "", @@ -3221,16 +3251,17 @@ stubPackets.set(`timeLog.timerDoesntExis }); stubPackets.set(`console.table('bar')`, { "message": { "addonId": "", "arguments": [ "bar" ], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "table", "lineNumber": 2, "prefix": "", @@ -3265,16 +3296,17 @@ stubPackets.set(`console.table(['a', 'b' "items": [ "a", "b", "c" ] } } ], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "table", "lineNumber": 2, "prefix": "", @@ -3292,16 +3324,17 @@ stubPackets.set(`console.table(['a', 'b' }); stubPackets.set(`console.group('bar')`, { "message": { "addonId": "", "arguments": [ "bar" ], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "bar", "level": "group", "lineNumber": 2, "prefix": "", @@ -3317,16 +3350,17 @@ stubPackets.set(`console.group('bar')`, "type": "consoleAPICall", "from": "server1.conn0.child1/consoleActor2" }); stubPackets.set(`console.groupEnd('bar')`, { "message": { "addonId": "", "arguments": [], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "bar", "level": "groupEnd", "lineNumber": 3, "prefix": "", @@ -3344,16 +3378,17 @@ stubPackets.set(`console.groupEnd('bar') }); stubPackets.set(`console.groupCollapsed('foo')`, { "message": { "addonId": "", "arguments": [ "foo" ], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "foo", "level": "groupCollapsed", "lineNumber": 2, "prefix": "", @@ -3369,16 +3404,17 @@ stubPackets.set(`console.groupCollapsed( "type": "consoleAPICall", "from": "server1.conn0.child1/consoleActor2" }); stubPackets.set(`console.groupEnd('foo')`, { "message": { "addonId": "", "arguments": [], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "foo", "level": "groupEnd", "lineNumber": 3, "prefix": "", @@ -3394,16 +3430,17 @@ stubPackets.set(`console.groupEnd('foo') "type": "consoleAPICall", "from": "server1.conn0.child1/consoleActor2" }); stubPackets.set(`console.group()`, { "message": { "addonId": "", "arguments": [], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "group", "lineNumber": 2, "prefix": "", @@ -3419,16 +3456,17 @@ stubPackets.set(`console.group()`, { "type": "consoleAPICall", "from": "server1.conn0.child1/consoleActor2" }); stubPackets.set(`console.groupEnd()`, { "message": { "addonId": "", "arguments": [], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "groupEnd", "lineNumber": 3, "prefix": "", @@ -3447,16 +3485,17 @@ stubPackets.set(`console.groupEnd()`, { stubPackets.set(`console.log(%cfoobar)`, { "message": { "addonId": "", "arguments": [ "foo", "bar" ], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "log", "lineNumber": 2, "prefix": "", @@ -3479,16 +3518,17 @@ stubPackets.set(`console.log(%cfoobar)`, stubPackets.set(`console.log("%cHello%c|%cWorld")`, { "message": { "addonId": "", "arguments": [ "Hello", "|", "World" ], + "chromeContext": false, "columnNumber": 11, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "log", "lineNumber": 2, "prefix": "", @@ -3511,16 +3551,17 @@ stubPackets.set(`console.log("%cHello%c| stubPackets.set(`console.group(%cfoo%cbar)`, { "message": { "addonId": "", "arguments": [ "foo", "bar" ], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "foo bar", "level": "group", "lineNumber": 2, "prefix": "", @@ -3539,16 +3580,17 @@ stubPackets.set(`console.group(%cfoo%cba "type": "consoleAPICall", "from": "server1.conn0.child1/consoleActor2" }); stubPackets.set(`console.groupEnd(%cfoo%cbar)`, { "message": { "addonId": "", "arguments": [], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "foo bar", "level": "groupEnd", "lineNumber": 6, "prefix": "", @@ -3567,16 +3609,17 @@ stubPackets.set(`console.groupEnd(%cfoo% stubPackets.set(`console.groupCollapsed(%cfoo%cbaz)`, { "message": { "addonId": "", "arguments": [ "foo", "baz" ], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "foo baz", "level": "groupCollapsed", "lineNumber": 2, "prefix": "", @@ -3595,16 +3638,17 @@ stubPackets.set(`console.groupCollapsed( "type": "consoleAPICall", "from": "server1.conn0.child1/consoleActor2" }); stubPackets.set(`console.groupEnd(%cfoo%cbaz)`, { "message": { "addonId": "", "arguments": [], + "chromeContext": false, "columnNumber": 9, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "foo baz", "level": "groupEnd", "lineNumber": 6, "prefix": "", @@ -3663,16 +3707,17 @@ stubPackets.set(`console.dir({C, M, Y, K }, "ownSymbols": [], "ownPropertiesLength": 4, "ownSymbolsLength": 0, "safeGetterValues": {} } } ], + "chromeContext": false, "columnNumber": 35, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "dir", "lineNumber": 1, "prefix": "", @@ -3690,16 +3735,17 @@ stubPackets.set(`console.dir({C, M, Y, K }); stubPackets.set(`console.count | default: 1`, { "message": { "addonId": "", "arguments": [ "default" ], + "chromeContext": false, "columnNumber": 13, "counter": { "count": 1, "label": "default" }, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", @@ -3720,16 +3766,17 @@ stubPackets.set(`console.count | default }); stubPackets.set(`console.count | default: 2`, { "message": { "addonId": "", "arguments": [ "default" ], + "chromeContext": false, "columnNumber": 13, "counter": { "count": 2, "label": "default" }, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", @@ -3750,16 +3797,17 @@ stubPackets.set(`console.count | default }); stubPackets.set(`console.count | test counter: 1`, { "message": { "addonId": "", "arguments": [ "test counter" ], + "chromeContext": false, "columnNumber": 13, "counter": { "count": 1, "label": "test counter" }, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", @@ -3780,16 +3828,17 @@ stubPackets.set(`console.count | test co }); stubPackets.set(`console.count | test counter: 2`, { "message": { "addonId": "", "arguments": [ "test counter" ], + "chromeContext": false, "columnNumber": 13, "counter": { "count": 2, "label": "test counter" }, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", @@ -3810,16 +3859,17 @@ stubPackets.set(`console.count | test co }); stubPackets.set(`console.count | default: 3`, { "message": { "addonId": "", "arguments": [ "default" ], + "chromeContext": false, "columnNumber": 13, "counter": { "count": 3, "label": "default" }, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", @@ -3838,16 +3888,17 @@ stubPackets.set(`console.count | default "type": "consoleAPICall", "from": "server1.conn0.child1/consoleActor2" }); stubPackets.set(`console.count | clear`, { "message": { "addonId": "", "arguments": [], + "chromeContext": false, "columnNumber": 13, "counter": null, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", "level": "clear", "lineNumber": 7, "prefix": "", @@ -3865,16 +3916,17 @@ stubPackets.set(`console.count | clear`, }); stubPackets.set(`console.count | default: 4`, { "message": { "addonId": "", "arguments": [ "default" ], + "chromeContext": false, "columnNumber": 13, "counter": { "count": 4, "label": "default" }, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", @@ -3895,16 +3947,17 @@ stubPackets.set(`console.count | default }); stubPackets.set(`console.count | test counter: 3`, { "message": { "addonId": "", "arguments": [ "test counter" ], + "chromeContext": false, "columnNumber": 13, "counter": { "count": 3, "label": "test counter" }, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", @@ -3925,16 +3978,17 @@ stubPackets.set(`console.count | test co }); stubPackets.set(`console.countReset | test counter: 0`, { "message": { "addonId": "", "arguments": [ "test counter" ], + "chromeContext": false, "columnNumber": 13, "counter": { "count": 0, "label": "test counter" }, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "", @@ -3955,16 +4009,17 @@ stubPackets.set(`console.countReset | te }); stubPackets.set(`console.countReset | counterDoesntExist`, { "message": { "addonId": "", "arguments": [ "test counter" ], + "chromeContext": false, "columnNumber": 13, "counter": { "error": "counterDoesntExist", "label": "test counter" }, "filename": "http://example.com/browser/devtools/client/webconsole/test/fixtures/stub-generators/test-console-api.html", "functionName": "triggerPacket", "groupName": "",
--- a/dom/base/PostMessageEvent.cpp +++ b/dom/base/PostMessageEvent.cpp @@ -14,17 +14,16 @@ #include "mozilla/dom/FileListBinding.h" #include "mozilla/dom/MessageEventBinding.h" #include "mozilla/dom/MessagePort.h" #include "mozilla/dom/MessagePortBinding.h" #include "mozilla/dom/PMessagePort.h" #include "mozilla/dom/StructuredCloneTags.h" #include "mozilla/dom/UnionConversions.h" #include "mozilla/EventDispatcher.h" -#include "nsContentUtils.h" #include "nsDocShell.h" #include "nsGlobalWindow.h" #include "nsIConsoleService.h" #include "nsIPresShell.h" #include "nsIPrincipal.h" #include "nsIScriptError.h" #include "nsNetUtil.h" #include "nsPresContext.h" @@ -132,19 +131,20 @@ PostMessageEvent::Run() { rv = errorObject->InitWithSourceURI( errorText, callerDocumentURI, EmptyString(), 0, 0, nsIScriptError::errorFlag, "DOM Window", mCallerWindowID.value()); } else { nsString uriSpec; rv = NS_GetSanitizedURIStringFromURI(callerDocumentURI, uriSpec); NS_ENSURE_SUCCESS(rv, rv); - rv = errorObject->Init(errorText, uriSpec, EmptyString(), 0, 0, - nsIScriptError::errorFlag, "DOM Window", - mIsFromPrivateWindow); + rv = errorObject->Init( + errorText, uriSpec, EmptyString(), 0, 0, nsIScriptError::errorFlag, + "DOM Window", mIsFromPrivateWindow, + nsContentUtils::IsSystemPrincipal(mProvidedPrincipal)); } NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); return consoleService->LogMessage(errorObject);
--- a/dom/base/PostMessageEvent.h +++ b/dom/base/PostMessageEvent.h @@ -8,16 +8,17 @@ #define mozilla_dom_PostMessageEvent_h #include "mozilla/dom/Event.h" #include "mozilla/dom/ipc/StructuredCloneData.h" #include "mozilla/dom/StructuredCloneHolder.h" #include "nsCOMPtr.h" #include "mozilla/MaybeOneOf.h" #include "mozilla/RefPtr.h" +#include "nsContentUtils.h" #include "nsTArray.h" #include "nsThreadUtils.h" class nsGlobalWindowOuter; class nsGlobalWindowInner; class nsIPrincipal; namespace mozilla {
--- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -3729,26 +3729,27 @@ nsresult nsContentUtils::FormatLocalized } return FormatLocalizedString(aFile, aKey, params.get(), paramsLength, aResult); } /* static */ void nsContentUtils::LogSimpleConsoleError(const nsAString& aErrorText, const char* classification, - bool aFromPrivateWindow) { + bool aFromPrivateWindow, + bool aFromChromeContext) { nsCOMPtr<nsIScriptError> scriptError = do_CreateInstance(NS_SCRIPTERROR_CONTRACTID); if (scriptError) { nsCOMPtr<nsIConsoleService> console = do_GetService(NS_CONSOLESERVICE_CONTRACTID); - if (console && - NS_SUCCEEDED(scriptError->Init(aErrorText, EmptyString(), EmptyString(), - 0, 0, nsIScriptError::errorFlag, - classification, aFromPrivateWindow))) { + if (console && NS_SUCCEEDED(scriptError->Init( + aErrorText, EmptyString(), EmptyString(), 0, 0, + nsIScriptError::errorFlag, classification, + aFromPrivateWindow, aFromChromeContext))) { console->LogMessage(scriptError); } } } /* static */ nsresult nsContentUtils::ReportToConsole( uint32_t aErrorFlags, const nsACString& aCategory, @@ -5294,30 +5295,32 @@ nsContentUtils::GetMostRecentNonPBWindow return pwindow.forget(); } /* static */ void nsContentUtils::WarnScriptWasIgnored(Document* aDocument) { nsAutoString msg; bool privateBrowsing = false; + bool chromeContext = false; if (aDocument) { nsCOMPtr<nsIURI> uri = aDocument->GetDocumentURI(); if (uri) { msg.Append(NS_ConvertUTF8toUTF16(uri->GetSpecOrDefault())); msg.AppendLiteral(" : "); } privateBrowsing = !!aDocument->NodePrincipal()->OriginAttributesRef().mPrivateBrowsingId; + chromeContext = IsSystemPrincipal(aDocument->NodePrincipal()); } msg.AppendLiteral( "Unable to run script because scripts are blocked internally."); - LogSimpleConsoleError(msg, "DOM", privateBrowsing); + LogSimpleConsoleError(msg, "DOM", privateBrowsing, chromeContext); } /* static */ void nsContentUtils::AddScriptRunner(already_AddRefed<nsIRunnable> aRunnable) { nsCOMPtr<nsIRunnable> runnable = aRunnable; if (!runnable) { return; } @@ -6508,17 +6511,17 @@ bool nsContentUtils::IsPatternMatching(n // The pattern has to match the entire value. aPattern.InsertLiteral(u"^(?:", 0); aPattern.AppendLiteral(")$"); JS::Rooted<JSObject*> re( cx, JS::NewUCRegExpObject(cx, static_cast<char16_t*>(aPattern.BeginWriting()), - aPattern.Length(), JS::RegExpFlags::Unicode)); + aPattern.Length(), JS::RegExpFlag::Unicode)); if (!re) { // Remove extra patterns added above to report with the original pattern. aPattern.Cut(0, 4); aPattern.Cut(aPattern.Length() - 2, 2); ReportPatternCompileFailure(aPattern, aDocument, cx); return true; }
--- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -1020,17 +1020,18 @@ class nsContentUtils { /** * Report simple error message to the browser console * @param aErrorText the error message * @param classification Name of the module reporting error */ static void LogSimpleConsoleError(const nsAString& aErrorText, const char* classification, - bool aFromPrivateWindow); + bool aFromPrivateWindow, + bool aFromChromeContext); /** * Report a non-localized error message to the error console. * @param aErrorText the error message * @param aErrorFlags See nsIScriptError. * @param aCategory Name of module reporting error. * @param aDocument Reference to the document which triggered the message. * @param [aURI=nullptr] (Optional) URI of resource containing error.
--- a/dom/base/nsFrameMessageManager.cpp +++ b/dom/base/nsFrameMessageManager.cpp @@ -404,17 +404,18 @@ bool nsFrameMessageManager::GetParamsFor uint32_t lineno = 0, column = 0; nsJSUtils::GetCallingLocation(aCx, filename, &lineno, &column); nsCOMPtr<nsIScriptError> error( do_CreateInstance(NS_SCRIPTERROR_CONTRACTID)); error->Init(NS_LITERAL_STRING("Sending message that cannot be cloned. Are " "you trying to send an XPCOM object?"), filename, EmptyString(), lineno, column, nsIScriptError::warningFlag, "chrome javascript", - false /* from private window */); + false /* from private window */, + true /* from chrome context */); console->LogMessage(error); } // Not clonable, try JSON // XXX This is ugly but currently structured cloning doesn't handle // properly cases when interface is implemented in JS and used // as a dictionary. nsAutoString json; @@ -819,17 +820,18 @@ void nsFrameMessageManager::ReceiveMessa nsCOMPtr<nsIConsoleService> console( do_GetService(NS_CONSOLESERVICE_CONTRACTID)); if (console) { nsCOMPtr<nsIScriptError> error( do_CreateInstance(NS_SCRIPTERROR_CONTRACTID)); error->Init(msg, EmptyString(), EmptyString(), 0, 0, nsIScriptError::warningFlag, "chrome javascript", - false /* from private window */); + false /* from private window */, + true /* from chrome context */); console->LogMessage(error); } JS_ClearPendingException(cx); continue; } } }
--- a/dom/base/nsGlobalWindowOuter.cpp +++ b/dom/base/nsGlobalWindowOuter.cpp @@ -5946,17 +5946,18 @@ bool nsGlobalWindowOuter::GetPrincipalFo } nsContentUtils::LogSimpleConsoleError( NS_ConvertUTF8toUTF16(nsPrintfCString( R"(Attempting to post a message to window with url "%s" and )" R"(origin "%s" from a system principal scope with mismatched )" R"(origin "%s".)", targetURL.get(), targetOrigin.get(), sourceOrigin.get())), - "DOM", !!principal->PrivateBrowsingId()); + "DOM", !!principal->PrivateBrowsingId(), + nsContentUtils::IsSystemPrincipal(principal)); attrs = principal->OriginAttributesRef(); } } // Create a nsIPrincipal inheriting the app/browser attributes from the // caller. providedPrincipal =
--- a/dom/base/test/mochitest.ini +++ b/dom/base/test/mochitest.ini @@ -753,17 +753,17 @@ tags = audiochannel [test_NodeIterator_mutations_3.html] [test_nodelist_holes.html] [test_noWebAudioNotification.html] tags = audiochannel [test_open_null_features.html] [test_openDialogChromeOnly.html] tags = openwindow [test_plugin_freezing.html] -skip-if = toolkit == 'android' #CLICK_TO_PLAY +skip-if = toolkit == 'android' || (os == 'win' && processor == 'aarch64') #CLICK_TO_PLAY, aarch64 due to 1538785 [test_pluginAudioNotification.html] tags = audiochannel skip-if = toolkit == 'android' # Plugins don't work on Android [test_pluginMutedBeforePlay.html] tags = audiochannel skip-if = toolkit == 'android' # Plugins don't work on Android [test_postMessage_solidus.html] [test_postMessages.html]
--- a/dom/bindings/nsIScriptError.idl +++ b/dom/bindings/nsIScriptError.idl @@ -88,16 +88,18 @@ interface nsIScriptError : nsIConsoleMes readonly attribute unsigned long long outerWindowID; /* Get the inner window id this was initialized with. Zero will be returned if init() was used instead of initWithWindowID(). */ readonly attribute unsigned long long innerWindowID; readonly attribute boolean isFromPrivateWindow; + readonly attribute boolean isFromChromeContext; + attribute jsval stack; /** * If |stack| is an object, then stackGlobal must be a global object that's * same-compartment with |stack|. This can be used to enter the correct * realm when working with the stack object. We can't use the object itself * because it might be a cross-compartment wrapper and CCWs are not * associated with a single realm/global. @@ -126,17 +128,18 @@ interface nsIScriptError : nsIConsoleMes void init(in AString message, in AString sourceName, in AString sourceLine, in uint32_t lineNumber, in uint32_t columnNumber, in uint32_t flags, in string category, - [optional] in bool fromPrivateWindow); + [optional] in bool fromPrivateWindow, + [optional] in bool fromChromeContext); /* This should be called instead of nsIScriptError.init to * initialize with a window id. The window id should be for the * inner window associated with this error. * * This function will check whether sourceName is a uri and sanitize it if * needed. If you know the source name is sanitized already, use * initWithSanitizedSource.
--- a/dom/bindings/nsScriptError.cpp +++ b/dom/bindings/nsScriptError.cpp @@ -40,17 +40,18 @@ nsScriptErrorBase::nsScriptErrorBase() mColumnNumber(0), mFlags(0), mCategory(), mOuterWindowID(0), mInnerWindowID(0), mTimeStamp(0), mTimeWarpTarget(0), mInitializedOnMainThread(false), - mIsFromPrivateWindow(false) {} + mIsFromPrivateWindow(false), + mIsFromChromeContext(false) {} nsScriptErrorBase::~nsScriptErrorBase() {} void nsScriptErrorBase::AddNote(nsIScriptErrorNote* note) { mNotes.AppendObject(note); } void nsScriptErrorBase::InitializeOnMainThread() { @@ -58,17 +59,17 @@ void nsScriptErrorBase::InitializeOnMain MOZ_ASSERT(!mInitializedOnMainThread); if (mInnerWindowID) { nsGlobalWindowInner* window = nsGlobalWindowInner::GetInnerWindowWithId(mInnerWindowID); if (window) { nsPIDOMWindowOuter* outer = window->GetOuterWindow(); if (outer) mOuterWindowID = outer->WindowID(); - + mIsFromChromeContext = ComputeIsFromChromeContext(window); mIsFromPrivateWindow = ComputeIsFromPrivateWindow(window); } } mInitializedOnMainThread = true; } NS_IMETHODIMP @@ -212,23 +213,25 @@ static void AssignSourceNameHelper(nsIUR aSourceNameDest.AssignLiteral("[nsIURI::GetSpec failed]"); } } NS_IMETHODIMP nsScriptErrorBase::Init(const nsAString& message, const nsAString& sourceName, const nsAString& sourceLine, uint32_t lineNumber, uint32_t columnNumber, uint32_t flags, - const char* category, bool fromPrivateWindow) { + const char* category, bool fromPrivateWindow, + bool fromChromeContext) { InitializationHelper(message, sourceLine, lineNumber, columnNumber, flags, category ? nsDependentCString(category) : EmptyCString(), 0 /* inner Window ID */); AssignSourceNameHelper(mSourceName, sourceName); mIsFromPrivateWindow = fromPrivateWindow; + mIsFromChromeContext = fromChromeContext; return NS_OK; } void nsScriptErrorBase::InitializationHelper( const nsAString& message, const nsAString& sourceLine, uint32_t lineNumber, uint32_t columnNumber, uint32_t flags, const nsACString& category, uint64_t aInnerWindowID) { mMessage.Assign(message); @@ -389,16 +392,28 @@ nsScriptErrorBase::SetTimeWarpTarget(uin NS_IMETHODIMP nsScriptErrorBase::GetTimeWarpTarget(uint64_t* aTarget) { *aTarget = mTimeWarpTarget; return NS_OK; } NS_IMETHODIMP +nsScriptErrorBase::GetIsFromChromeContext(bool* aIsFromChromeContext) { + NS_WARNING_ASSERTION(NS_IsMainThread() || mInitializedOnMainThread, + "This can't be safely determined off the main thread, " + "returning an inaccurate value!"); + if (!mInitializedOnMainThread && NS_IsMainThread()) { + InitializeOnMainThread(); + } + *aIsFromChromeContext = mIsFromChromeContext; + return NS_OK; +} + +NS_IMETHODIMP nsScriptErrorBase::GetNotes(nsIArray** aNotes) { nsresult rv = NS_OK; nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); uint32_t len = mNotes.Length(); for (uint32_t i = 0; i < len; i++) array->AppendElement(mNotes[i]); array.forget(aNotes); @@ -411,16 +426,23 @@ bool nsScriptErrorBase::ComputeIsFromPri nsGlobalWindowInner* aWindow) { // Never mark exceptions from chrome windows as having come from private // windows, since we always want them to be reported. nsIPrincipal* winPrincipal = aWindow->GetPrincipal(); return aWindow->IsPrivateBrowsing() && !nsContentUtils::IsSystemPrincipal(winPrincipal); } +/* static */ +bool nsScriptErrorBase::ComputeIsFromChromeContext( + nsGlobalWindowInner* aWindow) { + nsIPrincipal* winPrincipal = aWindow->GetPrincipal(); + return nsContentUtils::IsSystemPrincipal(winPrincipal); +} + NS_IMPL_ISUPPORTS(nsScriptError, nsIConsoleMessage, nsIScriptError) nsScriptErrorNote::nsScriptErrorNote() : mMessage(), mSourceName(), mSourceId(0), mLineNumber(0), mColumnNumber(0) {}
--- a/dom/bindings/nsScriptError.h +++ b/dom/bindings/nsScriptError.h @@ -50,16 +50,18 @@ class nsScriptErrorBase : public nsIScri NS_DECL_NSICONSOLEMESSAGE NS_DECL_NSISCRIPTERROR void AddNote(nsIScriptErrorNote* note); static bool ComputeIsFromPrivateWindow(nsGlobalWindowInner* aWindow); + static bool ComputeIsFromChromeContext(nsGlobalWindowInner* aWindow); + protected: virtual ~nsScriptErrorBase(); void InitializeOnMainThread(); void InitializationHelper(const nsAString& message, const nsAString& sourceLine, uint32_t lineNumber, uint32_t columnNumber, uint32_t flags, @@ -77,20 +79,21 @@ class nsScriptErrorBase : public nsIScri uint32_t mColumnNumber; uint32_t mFlags; nsCString mCategory; // mOuterWindowID is set on the main thread from InitializeOnMainThread(). uint64_t mOuterWindowID; uint64_t mInnerWindowID; int64_t mTimeStamp; uint64_t mTimeWarpTarget; - // mInitializedOnMainThread and mIsFromPrivateWindow are set on the main - // thread from InitializeOnMainThread(). + // mInitializedOnMainThread, mIsFromPrivateWindow and mIsFromChromeContext are + // set on the main thread from InitializeOnMainThread(). mozilla::Atomic<bool> mInitializedOnMainThread; bool mIsFromPrivateWindow; + bool mIsFromChromeContext; }; class nsScriptError final : public nsScriptErrorBase { public: nsScriptError() {} NS_DECL_THREADSAFE_ISUPPORTS private:
--- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -3906,18 +3906,18 @@ gfxFontGroup* CanvasRenderingContext2D:: gfxTextPerfMetrics* tp = nullptr; if (presShell && !presShell->IsDestroying()) { tp = presShell->GetPresContext()->GetTextPerfMetrics(); } int32_t perDevPixel, perCSSPixel; GetAppUnitsValues(&perDevPixel, &perCSSPixel); gfxFloat devToCssSize = gfxFloat(perDevPixel) / gfxFloat(perCSSPixel); CurrentState().fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup( - FontFamilyList(eFamily_sans_serif), &style, tp, nullptr, - devToCssSize); + FontFamilyList(StyleGenericFontFamily::SansSerif), &style, tp, + nullptr, devToCssSize); if (CurrentState().fontGroup) { CurrentState().font = kDefaultFontStyle; } else { NS_ERROR("Default canvas font is invalid"); } } }
--- a/dom/console/Console.cpp +++ b/dom/console/Console.cpp @@ -1271,16 +1271,17 @@ void Console::ProfileMethodInternal(JSCo // static void Console::ProfileMethodMainthread(JSContext* aCx, const nsAString& aAction, const Sequence<JS::Value>& aData) { MOZ_ASSERT(NS_IsMainThread()); ConsoleCommon::ClearException ce(aCx); RootedDictionary<ConsoleProfileEvent> event(aCx); event.mAction = aAction; + event.mChromeContext = nsContentUtils::ThreadsafeIsSystemCaller(aCx); event.mArguments.Construct(); Sequence<JS::Value>& sequence = event.mArguments.Value(); for (uint32_t i = 0; i < aData.Length(); ++i) { if (!sequence.AppendElement(aData[i], fallible)) { return; } @@ -1678,16 +1679,18 @@ bool Console::PopulateConsoleNotificatio ConsoleCommon::ClearException ce(aCx); RootedDictionary<ConsoleEvent> event(aCx); event.mAddonId = aData->mAddonId; event.mID.Construct(); event.mInnerID.Construct(); + event.mChromeContext = nsContentUtils::ThreadsafeIsSystemCaller(aCx); + if (aData->mIDType == ConsoleCallData::eString) { event.mID.Value().SetAsString() = aData->mOuterIDString; event.mInnerID.Value().SetAsString() = aData->mInnerIDString; } else if (aData->mIDType == ConsoleCallData::eNumber) { event.mID.Value().SetAsUnsignedLongLong() = aData->mOuterIDNumber; event.mInnerID.Value().SetAsUnsignedLongLong() = aData->mInnerIDNumber; } else { // aData->mIDType can be eUnknown when we dispatch notifications via
--- a/dom/console/ConsoleInstance.cpp +++ b/dom/console/ConsoleInstance.cpp @@ -34,28 +34,30 @@ ConsoleLogLevel PrefToValue(const nsAStr nsAutoCString value; nsresult rv = Preferences::GetCString(pref.get(), value); if (NS_WARN_IF(NS_FAILED(rv))) { nsString message; message.AssignLiteral( "Console.maxLogLevelPref used with a non-existing pref: "); message.Append(aPref); - nsContentUtils::LogSimpleConsoleError(message, "chrome", false); + nsContentUtils::LogSimpleConsoleError(message, "chrome", false, + true /* from chrome context*/); return ConsoleLogLevel::All; } int index = FindEnumStringIndexImpl(value.get(), value.Length(), ConsoleLogLevelValues::strings); if (NS_WARN_IF(index < 0)) { nsString message; message.AssignLiteral("Invalid Console.maxLogLevelPref value: "); message.Append(NS_ConvertUTF8toUTF16(value)); - nsContentUtils::LogSimpleConsoleError(message, "chrome", false); + nsContentUtils::LogSimpleConsoleError(message, "chrome", false, + true /* from chrome context*/); return ConsoleLogLevel::All; } MOZ_ASSERT(index < (int)ConsoleLogLevel::EndGuard_); return static_cast<ConsoleLogLevel>(index); } ConsoleUtils::Level WebIDLevelToConsoleUtilsLevel(ConsoleLevel aLevel) {
--- a/dom/console/tests/test_console_binding.html +++ b/dom/console/tests/test_console_binding.html @@ -13,16 +13,17 @@ function consoleListener() { SpecialPowers.addObserver(this, "console-api-log-event"); } var order = 0; consoleListener.prototype = { observe(aSubject, aTopic, aData) { if (aTopic == "console-api-log-event") { var obj = aSubject.wrappedJSObject; + ok(!obj.chromeContext, "Thils is not a chrome context"); if (order + 1 == parseInt(obj.arguments[0])) { ok(true, "Message received: " + obj.arguments[0]); order++; } if (order == 3) { SpecialPowers.removeObserver(this, "console-api-log-event"); SimpleTest.finish();
--- a/dom/console/tests/test_devtools_pref.html +++ b/dom/console/tests/test_devtools_pref.html @@ -10,16 +10,17 @@ <script type="application/javascript"> function consoleListener(expected) { var messages = []; return new Promise(done => { let observer = { observe: function listener(aSubject, aTopic, aData) { var obj = aSubject.wrappedJSObject; + ok(!obj.chromeContext, "This is not a chrome context"); messages.push(parseInt(obj.arguments[0])); if (messages.length == expected) { SpecialPowers.removeObserver(observer, "console-api-log-event"); SpecialPowers.removeObserver(observer, "console-api-profiler"); done(messages); } }, };
--- a/dom/console/tests/test_jsm.xul +++ b/dom/console/tests/test_jsm.xul @@ -29,16 +29,18 @@ function consoleListener() { } consoleListener.prototype = { count: 0, observe: function(aSubject, aTopic, aData) { if (aTopic == "console-api-log-event") { var obj = aSubject.wrappedJSObject; + ok(obj.chromeContext, "JSM is always a chrome context"); + if (obj.innerID == JSM) { is(obj.ID, "jsm", "ID and InnerID are correctly set."); is(obj.arguments[0], "Hello world!", "Message matches"); is(obj.consoleID, "", "No consoleID for console API"); is(obj.prefix, "", "prefix is empty by default"); // We want to see 2 messages from this innerID, the first is generated // by console.log, the second one from createInstance().log();
--- a/dom/events/test/test_slotted_mouse_event.html +++ b/dom/events/test/test_slotted_mouse_event.html @@ -1,61 +1,97 @@ <!doctype html> <meta charset="utf-8"> <title>Bug 1481500: mouse enter / leave events in slotted content</title> <script src="/tests/SimpleTest/SimpleTest.js"></script> <script src="/tests/SimpleTest/EventUtils.js"></script> <link rel="stylesheet" href="/tests/SimpleTest/test.css"> <script> +// We move the mouse from the #host to #target, then to #child-target. +// +// By the time we get to #child-target, we shouldn't have fired any mouseleave. function runTests() { let iframe = document.createElement('iframe'); + iframe.style.width = "600px"; + iframe.style.height = "600px"; document.body.appendChild(iframe); iframe.onload = () => frameLoaded(iframe); - iframe.srcdoc = - `<div id="host"><div id="target"></div></div>` + iframe.srcdoc = ` + <style> + #child-target { + width: 80px; + height: 80px; + background: yellow; + } + </style> + <div id="host"><div id="target"><div id="child-target"></div></div></div> + `; } function frameLoaded(iframe) { let host = iframe.contentDocument.getElementById('host'); let target = iframe.contentDocument.getElementById('target'); + let childTarget = iframe.contentDocument.getElementById('child-target'); + let sawHost = false; + let sawTarget = false; let finished = false; host.attachShadow({ mode: 'open' }).innerHTML = ` <style> :host { - width: 300px; - height: 300px; + width: 500px; + height: 500px; background: purple; } ::slotted(div) { - width: 100px; - height: 100px; + width: 200px; + height: 200px; background: green; } </style> <slot></slot> `; + host.addEventListener("mouseenter", e => { + if (finished) + return; + sawHost = true; + ok(true, "Should fire mouseenter on the host."); + }); + host.addEventListener("mouseleave", e => { if (finished) return; ok(false, "Should not fire mouseleave when moving the cursor to the slotted target"); }); target.addEventListener("mouseenter", () => { if (finished) return; + ok(sawHost, "Should've seen the hostmouseenter already"); + sawTarget = true; ok(true, "Moving the mouse into the target should trigger a mouseenter there"); - setTimeout(() => { - finished = true; - SimpleTest.finish() - }, 0); + }); + + target.addEventListener("mouseleave", () => { + if (finished) + return; + ok(false, "Should not fire mouseleave when moving the cursor to the slotted target's child"); + }); + + childTarget.addEventListener("mouseenter", () => { + if (finished) + return; + ok(sawTarget, "Should've seen the target mouseenter already"); + finished = true; + SimpleTest.finish(); }); synthesizeMouseAtCenter(host, { type: "mousemove" }); synthesizeMouseAtCenter(target, { type: "mousemove" }); + synthesizeMouseAtCenter(childTarget, { type: "mousemove" }); } SimpleTest.waitForExplicitFinish(); window.onload = () => { SimpleTest.waitForFocus(runTests); }; </script>
--- a/dom/indexedDB/ReportInternalError.cpp +++ b/dom/indexedDB/ReportInternalError.cpp @@ -21,14 +21,15 @@ void ReportInternalError(const char* aFi if (*p == '/' && *(p + 1)) { aFile = p + 1; } } nsContentUtils::LogSimpleConsoleError( NS_ConvertUTF8toUTF16( nsPrintfCString("IndexedDB %s: %s:%" PRIu32, aStr, aFile, aLine)), - "indexedDB", false /* no IDB in private window */); + "indexedDB", false /* no IDB in private window */, + true /* Internal errors are chrome context only */); } } // namespace indexedDB } // namespace dom } // namespace mozilla
--- a/dom/indexedDB/ScriptErrorHelper.cpp +++ b/dom/indexedDB/ScriptErrorHelper.cpp @@ -106,17 +106,18 @@ class ScriptErrorRunnable final : public aMessage, aFilename, /* aSourceLine */ EmptyString(), aLineNumber, aColumnNumber, aSeverityFlag, category, aInnerWindowID)); } else { MOZ_ALWAYS_SUCCEEDS(scriptError->Init( aMessage, aFilename, /* aSourceLine */ EmptyString(), aLineNumber, aColumnNumber, aSeverityFlag, category.get(), - /* IDB doesn't run on Private browsing mode */ false)); + /* IDB doesn't run on Private browsing mode */ false, + /* from chrome context */ aIsChrome)); } MOZ_ALWAYS_SUCCEEDS(consoleService->LogMessage(scriptError)); } NS_IMETHOD Run() override { MOZ_ASSERT(NS_IsMainThread());
--- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -438,17 +438,17 @@ ConsoleListener::Observe(nsIConsoleMessa return NS_OK; } nsCOMPtr<nsIScriptError> scriptError = do_QueryInterface(aMessage); if (scriptError) { nsAutoString msg, sourceName, sourceLine; nsCString category; uint32_t lineNum, colNum, flags; - bool fromPrivateWindow; + bool fromPrivateWindow, fromChromeContext; nsresult rv = scriptError->GetErrorMessage(msg); NS_ENSURE_SUCCESS(rv, rv); TruncateString(msg); rv = scriptError->GetSourceName(sourceName); NS_ENSURE_SUCCESS(rv, rv); TruncateString(sourceName); rv = scriptError->GetSourceLine(sourceLine); @@ -460,16 +460,18 @@ ConsoleListener::Observe(nsIConsoleMessa rv = scriptError->GetLineNumber(&lineNum); NS_ENSURE_SUCCESS(rv, rv); rv = scriptError->GetColumnNumber(&colNum); NS_ENSURE_SUCCESS(rv, rv); rv = scriptError->GetFlags(&flags); NS_ENSURE_SUCCESS(rv, rv); rv = scriptError->GetIsFromPrivateWindow(&fromPrivateWindow); NS_ENSURE_SUCCESS(rv, rv); + rv = scriptError->GetIsFromChromeContext(&fromChromeContext); + NS_ENSURE_SUCCESS(rv, rv); { AutoJSAPI jsapi; jsapi.Init(); JSContext* cx = jsapi.cx(); JS::RootedValue stack(cx); rv = scriptError->GetStack(&stack); @@ -491,25 +493,25 @@ ConsoleListener::Observe(nsIConsoleMessa return err.StealNSResult(); } ClonedMessageData cloned; if (!data.BuildClonedMessageDataForChild(mChild, cloned)) { return NS_ERROR_FAILURE; } - mChild->SendScriptErrorWithStack(msg, sourceName, sourceLine, lineNum, - colNum, flags, category, - fromPrivateWindow, cloned); + mChild->SendScriptErrorWithStack( + msg, sourceName, sourceLine, lineNum, colNum, flags, category, + fromPrivateWindow, fromChromeContext, cloned); return NS_OK; } } mChild->SendScriptError(msg, sourceName, sourceLine, lineNum, colNum, flags, - category, fromPrivateWindow); + category, fromPrivateWindow, fromChromeContext); return NS_OK; } nsString msg; nsresult rv = aMessage->GetMessageMoz(msg); NS_ENSURE_SUCCESS(rv, rv); mChild->SendConsoleMessage(msg); return NS_OK;
--- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -4095,39 +4095,40 @@ mozilla::ipc::IPCResult ContentParent::R consoleService->LogMessageWithMode(msg, nsConsoleService::SuppressLog); return IPC_OK(); } mozilla::ipc::IPCResult ContentParent::RecvScriptError( const nsString& aMessage, const nsString& aSourceName, const nsString& aSourceLine, const uint32_t& aLineNumber, const uint32_t& aColNumber, const uint32_t& aFlags, - const nsCString& aCategory, const bool& aFromPrivateWindow) { + const nsCString& aCategory, const bool& aFromPrivateWindow, + const bool& aFromChromeContext) { return RecvScriptErrorInternal(aMessage, aSourceName, aSourceLine, aLineNumber, aColNumber, aFlags, aCategory, - aFromPrivateWindow); + aFromPrivateWindow, aFromChromeContext); } mozilla::ipc::IPCResult ContentParent::RecvScriptErrorWithStack( const nsString& aMessage, const nsString& aSourceName, const nsString& aSourceLine, const uint32_t& aLineNumber, const uint32_t& aColNumber, const uint32_t& aFlags, const nsCString& aCategory, const bool& aFromPrivateWindow, - const ClonedMessageData& aFrame) { - return RecvScriptErrorInternal(aMessage, aSourceName, aSourceLine, - aLineNumber, aColNumber, aFlags, aCategory, - aFromPrivateWindow, &aFrame); + const bool& aFromChromeContext, const ClonedMessageData& aFrame) { + return RecvScriptErrorInternal( + aMessage, aSourceName, aSourceLine, aLineNumber, aColNumber, aFlags, + aCategory, aFromPrivateWindow, aFromChromeContext, &aFrame); } mozilla::ipc::IPCResult ContentParent::RecvScriptErrorInternal( const nsString& aMessage, const nsString& aSourceName, const nsString& aSourceLine, const uint32_t& aLineNumber, const uint32_t& aColNumber, const uint32_t& aFlags, const nsCString& aCategory, const bool& aFromPrivateWindow, - const ClonedMessageData* aStack) { + const bool& aFromChromeContext, const ClonedMessageData* aStack) { RefPtr<nsConsoleService> consoleService = GetConsoleService(); if (!consoleService) { return IPC_OK(); } nsCOMPtr<nsIScriptError> msg; if (aStack) { @@ -4152,19 +4153,19 @@ mozilla::ipc::IPCResult ContentParent::R MOZ_ASSERT(JS::IsUnwrappedSavedFrame(stackObj)); JS::RootedObject stackGlobal(cx, JS::GetNonCCWObjectGlobal(stackObj)); msg = new nsScriptErrorWithStack(stackObj, stackGlobal); } else { msg = new nsScriptError(); } - nsresult rv = - msg->Init(aMessage, aSourceName, aSourceLine, aLineNumber, aColNumber, - aFlags, aCategory.get(), aFromPrivateWindow); + nsresult rv = msg->Init(aMessage, aSourceName, aSourceLine, aLineNumber, + aColNumber, aFlags, aCategory.get(), + aFromPrivateWindow, aFromChromeContext); if (NS_FAILED(rv)) return IPC_OK(); consoleService->LogMessageWithMode(msg, nsConsoleService::SuppressLog); return IPC_OK(); } mozilla::ipc::IPCResult ContentParent::RecvPrivateDocShellsExist( const bool& aExist) {
--- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -1002,31 +1002,33 @@ class ContentParent final : public PCont mozilla::ipc::IPCResult RecvSetGeolocationHigherAccuracy(const bool& aEnable); mozilla::ipc::IPCResult RecvConsoleMessage(const nsString& aMessage); mozilla::ipc::IPCResult RecvScriptError( const nsString& aMessage, const nsString& aSourceName, const nsString& aSourceLine, const uint32_t& aLineNumber, const uint32_t& aColNumber, const uint32_t& aFlags, - const nsCString& aCategory, const bool& aIsFromPrivateWindow); + const nsCString& aCategory, const bool& aIsFromPrivateWindow, + const bool& aIsFromChromeContext); mozilla::ipc::IPCResult RecvScriptErrorWithStack( const nsString& aMessage, const nsString& aSourceName, const nsString& aSourceLine, const uint32_t& aLineNumber, const uint32_t& aColNumber, const uint32_t& aFlags, const nsCString& aCategory, const bool& aIsFromPrivateWindow, - const ClonedMessageData& aStack); + const bool& aIsFromChromeContext, const ClonedMessageData& aStack); private: mozilla::ipc::IPCResult RecvScriptErrorInternal( const nsString& aMessage, const nsString& aSourceName, const nsString& aSourceLine, const uint32_t& aLineNumber, const uint32_t& aColNumber, const uint32_t& aFlags, const nsCString& aCategory, const bool& aIsFromPrivateWindow, + const bool& aIsFromChromeContext, const ClonedMessageData* aStack = nullptr); public: mozilla::ipc::IPCResult RecvPrivateDocShellsExist(const bool& aExist); mozilla::ipc::IPCResult RecvCommitBrowsingContextTransaction( BrowsingContext* aContext, BrowsingContext::Transaction&& aTransaction, BrowsingContext::FieldEpochs&& aEpochs);
--- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -931,21 +931,22 @@ parent: async AddGeolocationListener(Principal principal, bool highAccuracy); async RemoveGeolocationListener(); async SetGeolocationHigherAccuracy(bool enable); async ConsoleMessage(nsString message); async ScriptError(nsString message, nsString sourceName, nsString sourceLine, uint32_t lineNumber, uint32_t colNumber, uint32_t flags, - nsCString category, bool privateWindow); + nsCString category, bool privateWindow, + bool fromChromeContext); async ScriptErrorWithStack(nsString message, nsString sourceName, nsString sourceLine, uint32_t lineNumber, uint32_t colNumber, uint32_t flags, nsCString category, bool privateWindow, - ClonedMessageData stack); + bool fromChromeContext, ClonedMessageData stack); // Places the items within dataTransfer on the clipboard. async SetClipboard(IPCDataTransfer aDataTransfer, bool aIsPrivateData, Principal aRequestingPrincipal, uint32_t aContentPolicyType, int32_t aWhichClipboard);
--- a/dom/localstorage/ReportInternalError.cpp +++ b/dom/localstorage/ReportInternalError.cpp @@ -21,14 +21,14 @@ void ReportInternalError(const char* aFi if (*p == '/' && *(p + 1)) { aFile = p + 1; } } nsContentUtils::LogSimpleConsoleError( NS_ConvertUTF8toUTF16( nsPrintfCString("LocalStorage %s: %s:%" PRIu32, aStr, aFile, aLine)), - "localstorage", false); + "localstorage", false, true /* Internal errors are chrome context only*/); } } // namespace localstorage } // namespace dom } // namespace mozilla
--- a/dom/media/webaudio/AudioContext.cpp +++ b/dom/media/webaudio/AudioContext.cpp @@ -87,16 +87,20 @@ namespace dom { // 0 is a special value that MediaStreams use to denote they are not part of a // AudioContext. static dom::AudioContext::AudioContextId gAudioContextId = 1; NS_IMPL_CYCLE_COLLECTION_CLASS(AudioContext) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioContext) + // The destination node and AudioContext form a cycle and so the destination + // stream will be destroyed. mWorklet must be shut down before the stream + // is destroyed. Do this before clearing mWorklet. + tmp->ShutdownWorklet(); NS_IMPL_CYCLE_COLLECTION_UNLINK(mDestination) NS_IMPL_CYCLE_COLLECTION_UNLINK(mListener) NS_IMPL_CYCLE_COLLECTION_UNLINK(mWorklet) NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromiseGripArray) NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingResumePromises) if (!tmp->mIsStarted) { NS_IMPL_CYCLE_COLLECTION_UNLINK(mActiveNodes) } @@ -627,16 +631,22 @@ MediaStreamGraph* AudioContext::Graph() AudioNodeStream* AudioContext::DestinationStream() const { if (Destination()) { return Destination()->Stream(); } return nullptr; } +void AudioContext::ShutdownWorklet() { + if (mWorklet) { + mWorklet->Impl()->NotifyWorkletFinished(); + } +} + double AudioContext::CurrentTime() { MediaStream* stream = Destination()->Stream(); double rawTime = stream->StreamTimeToSeconds(stream->GetCurrentTime()); // CurrentTime increments in intervals of 128/sampleRate. If the Timer // Precision Reduction is smaller than this interval, the jittered time // can always be reversed to the raw step of the interval. In that case @@ -698,16 +708,22 @@ void AudioContext::Shutdown() { mPendingResumePromises.Clear(); } // Release references to active nodes. // Active AudioNodes don't unregister in destructors, at which point the // Node is already unregistered. mActiveNodes.Clear(); + // On process shutdown, the MSG thread shuts down before the destination + // stream is destroyed, but AudioWorklet needs to release objects on the MSG + // thread. AudioContext::Shutdown() is invoked on processing the + // PBrowser::Destroy() message before xpcom shutdown begins. + ShutdownWorklet(); + // For offline contexts, we can destroy the MediaStreamGraph at this point. if (mIsOffline && mDestination) { mDestination->OfflineShutdown(); } } StateChangeTask::StateChangeTask(AudioContext* aAudioContext, void* aPromise, AudioContextState aNewState)
--- a/dom/media/webaudio/AudioContext.h +++ b/dom/media/webaudio/AudioContext.h @@ -305,16 +305,17 @@ class AudioContext final : public DOMEve void RegisterNode(AudioNode* aNode); void UnregisterNode(AudioNode* aNode); void OnStateChanged(void* aPromise, AudioContextState aNewState); BasicWaveFormCache* GetBasicWaveFormCache(); + void ShutdownWorklet(); // Steals from |aParamMap| void SetParamMapForWorkletName(const nsAString& aName, AudioParamDescriptorMap* aParamMap); const AudioParamDescriptorMap* GetParamMapForWorkletName( const nsAString& aName) { return mWorkletParamDescriptors.GetValue(aName); }
--- a/dom/media/webaudio/AudioDestinationNode.cpp +++ b/dom/media/webaudio/AudioDestinationNode.cpp @@ -396,16 +396,18 @@ void AudioDestinationNode::DestroyAudioC } } void AudioDestinationNode::DestroyMediaStream() { DestroyAudioChannelAgent(); if (!mStream) return; + Context()->ShutdownWorklet(); + mStream->RemoveMainThreadListener(this); MediaStreamGraph* graph = mStream->Graph(); if (graph->IsNonRealtime()) { MediaStreamGraph::DestroyNonRealtimeInstance(graph); } AudioNode::DestroyMediaStream(); }
--- a/dom/plugins/test/mochitest/mochitest.ini +++ b/dom/plugins/test/mochitest/mochitest.ini @@ -55,16 +55,17 @@ skip-if = toolkit == 'android' # needs p [test_bug854082.html] [test_bug863792.html] [test_bug967694.html] [test_bug985859.html] [test_bug986930.html] [test_bug1092842.html] skip-if = (verify && (os == 'win')) [test_bug1165981.html] +skip-if = (processor == 'aarch64' && os == 'win') # aarch64 due to 1538785 [test_bug1245545.html] [test_bug1307694.html] skip-if = verify [test_cocoa_focus.html] skip-if = toolkit != "cocoa" || e10s # Bug 1194534 support-files = cocoa_focus.html [test_cocoa_window_focus.html] skip-if = toolkit != "cocoa" # Bug 1194534 @@ -88,16 +89,17 @@ skip-if = (verify && !debug && (os == 'l skip-if = !crashreporter || e10s [test_hidden_plugin.html] [test_instance_re-parent.html] [test_instance_unparent1.html] [test_instance_unparent2.html] [test_instance_unparent3.html] [test_instantiation.html] [test_mixed_case_mime.html] +skip-if = (processor == 'aarch64' && os == 'win') # aarch64 due to 1538785 [test_multipleinstanceobjects.html] [test_newstreamondestroy.html] [test_npn_timers.html] [test_npobject_getters.html] [test_NPNVdocumentOrigin.html] [test_NPPVpluginWantsAllNetworkStreams.html] [test_npruntime_construct.html] [test_npruntime_identifiers.html]
--- a/dom/plugins/test/unit/xpcshell.ini +++ b/dom/plugins/test/unit/xpcshell.ini @@ -16,10 +16,10 @@ fail-if = os == "android" [test_nice_plugin_name.js] # Bug 676953: test fails consistently on Android fail-if = os == "android" [test_persist_in_prefs.js] skip-if = appname == "thunderbird" reason = plugins are disabled by default in Thunderbird [test_bug854467.js] [test_plugin_default_state.js] -skip-if = appname == "thunderbird" -reason = plugins are disabled by default in Thunderbird +skip-if = appname == "thunderbird" || (processor == 'aarch64' && os == 'win') # aarch64 due to 1538785 +reason = plugins are disabled by default in Thunderbird and Windows10-aarch64
--- a/dom/push/test/mochitest.ini +++ b/dom/push/test/mochitest.ini @@ -11,16 +11,17 @@ support-files = [test_has_permissions.html] [test_permissions.html] [test_register.html] skip-if = os == "win" # Bug 1373346 [test_register_key.html] [test_multiple_register.html] [test_multiple_register_during_service_activation.html] +skip-if = (os == "win") || (os == "linux") || (os == "mac") #Bug 1274773 [test_unregister.html] [test_multiple_register_different_scope.html] [test_subscription_change.html] skip-if = os == "win" # Bug 1373346 [test_data.html] skip-if = os == "win" # Bug 1373346 [test_try_registering_offline_disabled.html] skip-if = os == "win" # Bug 1373346
--- a/dom/quota/ActorsParent.cpp +++ b/dom/quota/ActorsParent.cpp @@ -1363,18 +1363,18 @@ void ReportInternalError(const char* aFi if (*p == '/' && *(p + 1)) { aFile = p + 1; } } nsContentUtils::LogSimpleConsoleError( NS_ConvertUTF8toUTF16( nsPrintfCString("Quota %s: %s:%" PRIu32, aStr, aFile, aLine)), - "quota", - false /* Quota Manager is not active in private browsing mode */); + "quota", false /* Quota Manager is not active in private browsing mode */, + true /* Quota Manager runs always in a chrome context */); } namespace { StaticAutoPtr<nsString> gBaseDirPath; #ifdef DEBUG bool gQuotaManagerInitialized = false;
--- a/dom/security/nsCSPUtils.cpp +++ b/dom/security/nsCSPUtils.cpp @@ -154,17 +154,18 @@ void CSP_LogMessage(const nsAString& aMe nsresult rv; if (aInnerWindowID > 0) { rv = error->InitWithWindowID(cspMsg, aSourceName, aSourceLine, aLineNumber, aColumnNumber, aFlags, category, aInnerWindowID); } else { rv = error->Init(cspMsg, aSourceName, aSourceLine, aLineNumber, - aColumnNumber, aFlags, category.get(), aFromPrivateWindow); + aColumnNumber, aFlags, category.get(), aFromPrivateWindow, + true /* from chrome context */); } if (NS_FAILED(rv)) { return; } console->LogMessage(error); } /**
--- a/dom/tests/mochitest/bugs/mochitest.ini +++ b/dom/tests/mochitest/bugs/mochitest.ini @@ -65,17 +65,17 @@ skip-if = toolkit == 'android' #TIMED_OU [test_bug393974.html] [test_bug394769.html] [test_bug396843.html] [test_bug400204.html] [test_bug404748.html] [test_bug414291.html] tags = openwindow [test_bug427744.html] -skip-if = toolkit == 'android' +skip-if = toolkit == 'android' || (processor == 'aarch64' && os == 'win') # aarch64 due to 1538785 [test_bug42976.html] [test_bug430276.html] [test_bug440572.html] [test_bug456151.html] [test_bug458091.html] skip-if = toolkit == 'android' && !is_fennec # Bug 1525959 [test_bug459848.html] [test_bug465263.html]
--- a/dom/u2f/U2F.cpp +++ b/dom/u2f/U2F.cpp @@ -46,18 +46,26 @@ NS_NAMED_LITERAL_STRING( NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(U2F) NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY NS_INTERFACE_MAP_END_INHERITING(WebAuthnManagerBase) NS_IMPL_ADDREF_INHERITED(U2F, WebAuthnManagerBase) NS_IMPL_RELEASE_INHERITED(U2F, WebAuthnManagerBase) -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_INHERITED(U2F, WebAuthnManagerBase, - mTransaction) +NS_IMPL_CYCLE_COLLECTION_CLASS(U2F) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(U2F, WebAuthnManagerBase) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mTransaction) + NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER + tmp->ClearTransaction(); +NS_IMPL_CYCLE_COLLECTION_UNLINK_END +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(U2F, WebAuthnManagerBase) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransaction) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END +NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(U2F) /*********************************************************************** * Utility Functions **********************************************************************/ static ErrorCode ConvertNSResultToErrorCode(const nsresult& aError) { if (aError == NS_ERROR_DOM_TIMEOUT_ERR) { return ErrorCode::TIMEOUT; @@ -508,17 +516,17 @@ void U2F::FinishGetAssertion(const uint6 nsMainThreadPtrHandle<U2FSignCallback> callback( mTransaction.ref().GetSignCallback()); ClearTransaction(); ExecuteCallback(response, callback); } void U2F::ClearTransaction() { - if (!NS_WARN_IF(mTransaction.isNothing())) { + if (!mTransaction.isNothing()) { StopListeningForVisibilityEvents(); } mTransaction.reset(); } void U2F::RejectTransaction(const nsresult& aError) { if (NS_WARN_IF(mTransaction.isNothing())) {
--- a/dom/u2f/U2F.h +++ b/dom/u2f/U2F.h @@ -136,20 +136,21 @@ class U2F final : public WebAuthnManager private: MOZ_CAN_RUN_SCRIPT ~U2F(); template <typename T, typename C> MOZ_CAN_RUN_SCRIPT void ExecuteCallback(T& aResp, nsMainThreadPtrHandle<C>& aCb); + // Rejects the current transaction and clears it. + MOZ_CAN_RUN_SCRIPT void RejectTransaction(const nsresult& aError); + // Clears all information we have about the current transaction. void ClearTransaction(); - // Rejects the current transaction and clears it. - MOZ_CAN_RUN_SCRIPT void RejectTransaction(const nsresult& aError); nsString mOrigin; // The current transaction, if any. Maybe<U2FTransaction> mTransaction; }; inline void ImplCycleCollectionTraverse(
--- a/dom/webauthn/WebAuthnManager.cpp +++ b/dom/webauthn/WebAuthnManager.cpp @@ -33,18 +33,28 @@ namespace dom { namespace { static mozilla::LazyLogModule gWebAuthnManagerLog("webauthnmanager"); } NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(WebAuthnManager, WebAuthnManagerBase) -NS_IMPL_CYCLE_COLLECTION_INHERITED(WebAuthnManager, WebAuthnManagerBase, - mFollowingSignal, mTransaction) +NS_IMPL_CYCLE_COLLECTION_CLASS(WebAuthnManager) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WebAuthnManager, + WebAuthnManagerBase) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mFollowingSignal) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mTransaction) + tmp->ClearTransaction(); +NS_IMPL_CYCLE_COLLECTION_UNLINK_END +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WebAuthnManager, + WebAuthnManagerBase) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFollowingSignal) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransaction) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END /*********************************************************************** * Utility Functions **********************************************************************/ static nsresult AssembleClientData( const nsAString& aOrigin, const CryptoBuffer& aChallenge, const nsAString& aType, @@ -151,17 +161,17 @@ nsresult RelaxSameOrigin(nsPIDOMWindowIn return NS_OK; } /*********************************************************************** * WebAuthnManager Implementation **********************************************************************/ void WebAuthnManager::ClearTransaction() { - if (!NS_WARN_IF(mTransaction.isNothing())) { + if (!mTransaction.isNothing()) { StopListeningForVisibilityEvents(); } mTransaction.reset(); Unfollow(); } void WebAuthnManager::RejectTransaction(const nsresult& aError) {
--- a/dom/webauthn/WebAuthnManager.h +++ b/dom/webauthn/WebAuthnManager.h @@ -111,20 +111,21 @@ class WebAuthnManager final : public Web // parent) and rejects it by calling RejectTransaction(). void CancelTransaction(const nsresult& aError); // Upon a visibility change, makes note of it in the current transaction. void HandleVisibilityChange() override; private: virtual ~WebAuthnManager(); + // Rejects the current transaction and calls ClearTransaction(). + void RejectTransaction(const nsresult& aError); + // Clears all information we have about the current transaction. void ClearTransaction(); - // Rejects the current transaction and calls ClearTransaction(). - void RejectTransaction(const nsresult& aError); // The current transaction, if any. Maybe<WebAuthnTransaction> mTransaction; }; inline void ImplCycleCollectionTraverse( nsCycleCollectionTraversalCallback& aCallback, WebAuthnTransaction& aTransaction, const char* aName, uint32_t aFlags = 0) {
--- a/dom/webidl/Console.webidl +++ b/dom/webidl/Console.webidl @@ -102,22 +102,24 @@ dictionary ConsoleEvent { // consumers expect to see own properties on it, which would mean making the // props unforgeable, which means lots of JSFunction allocations. Maybe we // should fix those consumers, of course.... // sequence<ConsoleStackEntry> stacktrace; DOMString groupName = ""; any timer = null; any counter = null; DOMString prefix = ""; + boolean chromeContext = false; }; // Event for profile operations dictionary ConsoleProfileEvent { DOMString action = ""; sequence<any> arguments; + boolean chromeContext = false; }; // This dictionary is used to manage stack trace data. dictionary ConsoleStackEntry { DOMString filename = ""; // Unique identifier within the process for the script source this entry is // associated with, or zero. unsigned long sourceId = 0;
--- a/dom/websocket/WebSocket.cpp +++ b/dom/websocket/WebSocket.cpp @@ -97,16 +97,17 @@ class WebSocketImpl final : public nsIIn mDisconnectingOrDisconnected(false), mCloseEventWasClean(false), mCloseEventCode(nsIWebSocketChannel::CLOSE_ABNORMAL), mPort(0), mScriptLine(0), mScriptColumn(0), mInnerWindowID(0), mPrivateBrowsing(false), + mIsChromeContext(false), mIsMainThread(true), mMutex("WebSocketImpl::mMutex"), mWorkerShuttingDown(false) { if (!NS_IsMainThread()) { mIsMainThread = false; } } @@ -196,16 +197,17 @@ class WebSocketImpl final : public nsIIn // - the ID of the inner window where the script lives. Note that this may not // be the same as the Web Socket owner window. // These attributes are used for error reporting. nsCString mScriptFile; uint32_t mScriptLine; uint32_t mScriptColumn; uint64_t mInnerWindowID; bool mPrivateBrowsing; + bool mIsChromeContext; RefPtr<ThreadSafeWorkerRef> mWorkerRef; nsWeakPtr mWeakLoadGroup; bool mIsMainThread; // This mutex protects mWorkerShuttingDown. @@ -339,17 +341,17 @@ void WebSocketImpl::PrintErrorOnConsole( if (mInnerWindowID) { rv = errorObject->InitWithWindowID( message, NS_ConvertUTF8toUTF16(mScriptFile), EmptyString(), mScriptLine, mScriptColumn, nsIScriptError::errorFlag, "Web Socket", mInnerWindowID); } else { rv = errorObject->Init(message, NS_ConvertUTF8toUTF16(mScriptFile), EmptyString(), mScriptLine, mScriptColumn, nsIScriptError::errorFlag, "Web Socket", - mPrivateBrowsing); + mPrivateBrowsing, mIsChromeContext); } NS_ENSURE_SUCCESS_VOID(rv); // print the error message directly to the JS console rv = console->LogMessage(errorObject); NS_ENSURE_SUCCESS_VOID(rv); } @@ -1500,16 +1502,17 @@ nsresult WebSocketImpl::Init(JSContext* // If we don't have aCx, we are window-less, so we don't have a // inner-windowID. This can happen in sharedWorkers and ServiceWorkers or in // DedicateWorkers created by JSM. if (aCx) { mInnerWindowID = nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(aCx); } mPrivateBrowsing = !!aPrincipal->OriginAttributesRef().mPrivateBrowsingId; + mIsChromeContext = nsContentUtils::IsSystemPrincipal(aPrincipal); // parses the url rv = ParseURL(aURL); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<Document> originDoc = mWebSocket->GetDocumentIfCurrent(); if (!originDoc) { rv = mWebSocket->CheckCurrentGlobalCorrectness();
--- a/dom/worklet/Worklet.cpp +++ b/dom/worklet/Worklet.cpp @@ -321,34 +321,31 @@ class WorkletFetchHandler final : public }; NS_IMPL_ISUPPORTS(WorkletFetchHandler, nsIStreamLoaderObserver) NS_IMETHODIMP ExecutionRunnable::Run() { // WorkletThread::IsOnWorkletThread() cannot be used here because it depends // on a WorkletJSContext having been created for this thread. That does not - // happen until the first time RunOnWorkletThread() is called. + // happen until the global scope is created the first time + // RunOnWorkletThread() is called. if (!NS_IsMainThread()) { RunOnWorkletThread(); return NS_DispatchToMainThread(this); } RunOnMainThread(); return NS_OK; } void ExecutionRunnable::RunOnWorkletThread() { WorkletThread::EnsureCycleCollectedJSContext(mParentRuntime); - AutoJSAPI jsapi; - jsapi.Init(); - - RefPtr<WorkletGlobalScope> globalScope = - mWorkletImpl->CreateGlobalScope(jsapi.cx()); + WorkletGlobalScope* globalScope = mWorkletImpl->GetGlobalScope(); MOZ_ASSERT(globalScope); AutoEntryScript aes(globalScope, "Worklet"); JSContext* cx = aes.cx(); JS::Rooted<JSObject*> globalObj(cx, globalScope->GetGlobalJSObject()); NS_ConvertUTF16toUTF8 url(mHandler->URL());
--- a/dom/worklet/Worklet.h +++ b/dom/worklet/Worklet.h @@ -41,16 +41,18 @@ class Worklet final : public nsISupports virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; already_AddRefed<Promise> AddModule(const nsAString& aModuleURL, const WorkletOptions& aOptions, CallerType aCallerType, ErrorResult& aRv); + WorkletImpl* Impl() const { return mImpl; } + private: ~Worklet(); WorkletFetchHandler* GetImportFetchHandler(const nsACString& aURI); void AddImportFetchHandler(const nsACString& aURI, WorkletFetchHandler* aHandler);
--- a/dom/worklet/WorkletImpl.cpp +++ b/dom/worklet/WorkletImpl.cpp @@ -6,16 +6,17 @@ #include "WorkletImpl.h" #include "Worklet.h" #include "WorkletThread.h" #include "mozilla/BasePrincipal.h" #include "mozilla/dom/RegisterWorkletBindings.h" +#include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/WorkletBinding.h" namespace mozilla { // --------------------------------------------------------------------------- // WorkletLoadInfo WorkletLoadInfo::WorkletLoadInfo(nsPIDOMWindowInner* aWindow, @@ -37,48 +38,64 @@ WorkletLoadInfo::~WorkletLoadInfo() { } // --------------------------------------------------------------------------- // WorkletImpl WorkletImpl::WorkletImpl(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal) : mWorkletLoadInfo(aWindow, aPrincipal), mTerminated(false) {} -WorkletImpl::~WorkletImpl() = default; +WorkletImpl::~WorkletImpl() { MOZ_ASSERT(!mGlobalScope); } JSObject* WorkletImpl::WrapWorklet(JSContext* aCx, dom::Worklet* aWorklet, JS::Handle<JSObject*> aGivenProto) { MOZ_ASSERT(NS_IsMainThread()); return dom::Worklet_Binding::Wrap(aCx, aWorklet, aGivenProto); } -already_AddRefed<dom::WorkletGlobalScope> WorkletImpl::CreateGlobalScope( - JSContext* aCx) { +dom::WorkletGlobalScope* WorkletImpl::GetGlobalScope() { dom::WorkletThread::AssertIsOnWorkletThread(); - RefPtr<dom::WorkletGlobalScope> scope = ConstructGlobalScope(); + if (mGlobalScope) { + return mGlobalScope; + } - JS::Rooted<JSObject*> global(aCx); - NS_ENSURE_TRUE(scope->WrapGlobalObject(aCx, &global), nullptr); + dom::AutoJSAPI jsapi; + jsapi.Init(); + JSContext* cx = jsapi.cx(); - JSAutoRealm ar(aCx, global); + mGlobalScope = ConstructGlobalScope(); + + JS::Rooted<JSObject*> global(cx); + NS_ENSURE_TRUE(mGlobalScope->WrapGlobalObject(cx, &global), nullptr); + + JSAutoRealm ar(cx, global); // Init Web IDL bindings - if (!dom::RegisterWorkletBindings(aCx, global)) { + if (!dom::RegisterWorkletBindings(cx, global)) { return nullptr; } - JS_FireOnNewGlobalObject(aCx, global); + JS_FireOnNewGlobalObject(cx, global); - return scope.forget(); + return mGlobalScope; } void WorkletImpl::NotifyWorkletFinished() { MOZ_ASSERT(NS_IsMainThread()); + if (mTerminated) { + return; + } + + // Release global scope on its thread. + SendControlMessage(NS_NewRunnableFunction( + "WorkletImpl::NotifyWorkletFinished", + [self = RefPtr<WorkletImpl>(this)]() { self->mGlobalScope = nullptr; })); + mTerminated = true; if (mWorkletThread) { mWorkletThread->Terminate(); mWorkletThread = nullptr; } mWorkletLoadInfo.mPrincipal = nullptr; } @@ -88,17 +105,17 @@ nsresult WorkletImpl::SendControlMessage // TODO: bug 1492011 re ConsoleWorkletRunnable. if (mTerminated) { return NS_ERROR_ILLEGAL_DURING_SHUTDOWN; } if (!mWorkletThread) { // Thread creation. FIXME: this will change. - mWorkletThread = dom::WorkletThread::Create(); + mWorkletThread = dom::WorkletThread::Create(this); if (!mWorkletThread) { return NS_ERROR_UNEXPECTED; } } return mWorkletThread->DispatchRunnable(std::move(aRunnable)); }
--- a/dom/worklet/WorkletImpl.h +++ b/dom/worklet/WorkletImpl.h @@ -69,17 +69,17 @@ class WorkletImpl { virtual JSObject* WrapWorklet(JSContext* aCx, dom::Worklet* aWorklet, JS::Handle<JSObject*> aGivenProto); virtual nsresult SendControlMessage(already_AddRefed<nsIRunnable> aRunnable); void NotifyWorkletFinished(); // Execution thread only. - already_AddRefed<dom::WorkletGlobalScope> CreateGlobalScope(JSContext* aCx); + dom::WorkletGlobalScope* GetGlobalScope(); // Any thread. const WorkletLoadInfo& LoadInfo() const { return mWorkletLoadInfo; } protected: WorkletImpl(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal); virtual ~WorkletImpl(); @@ -88,13 +88,16 @@ class WorkletImpl { // The only WorkletLoadInfo member modified is mPrincipal which is accessed // on only the parent thread. WorkletLoadInfo mWorkletLoadInfo; // Parent thread only. RefPtr<dom::WorkletThread> mWorkletThread; bool mTerminated; + + // Execution thread only. + RefPtr<dom::WorkletGlobalScope> mGlobalScope; }; } // namespace mozilla #endif // mozilla_dom_worklet_WorkletImpl_h
--- a/dom/worklet/WorkletThread.cpp +++ b/dom/worklet/WorkletThread.cpp @@ -205,34 +205,36 @@ class WorkletThread::TerminateRunnable f mWorkletThread->TerminateInternal(); return NS_OK; } private: RefPtr<WorkletThread> mWorkletThread; }; -WorkletThread::WorkletThread() +WorkletThread::WorkletThread(WorkletImpl* aWorkletImpl) : nsThread(MakeNotNull<ThreadEventQueue<mozilla::EventQueue>*>( MakeUnique<mozilla::EventQueue>()), nsThread::NOT_MAIN_THREAD, kWorkletStackSize), + mWorkletImpl(aWorkletImpl), mExitLoop(false), mIsTerminating(false) { MOZ_ASSERT(NS_IsMainThread()); nsContentUtils::RegisterShutdownObserver(this); } WorkletThread::~WorkletThread() { // This should be set during the termination step. MOZ_ASSERT(mExitLoop); } // static -already_AddRefed<WorkletThread> WorkletThread::Create() { - RefPtr<WorkletThread> thread = new WorkletThread(); +already_AddRefed<WorkletThread> WorkletThread::Create( + WorkletImpl* aWorkletImpl) { + RefPtr<WorkletThread> thread = new WorkletThread(aWorkletImpl); if (NS_WARN_IF(NS_FAILED(thread->Init()))) { return nullptr; } RefPtr<PrimaryRunnable> runnable = new PrimaryRunnable(thread); if (NS_WARN_IF(NS_FAILED(thread->DispatchRunnable(runnable.forget())))) { return nullptr; } @@ -363,16 +365,18 @@ void WorkletThread::AssertIsOnWorkletThr } // nsIObserver NS_IMETHODIMP WorkletThread::Observe(nsISupports* aSubject, const char* aTopic, const char16_t*) { MOZ_ASSERT(strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0); - Terminate(); + // The WorkletImpl will terminate the worklet thread after sending a message + // to release worklet thread objects. + mWorkletImpl->NotifyWorkletFinished(); return NS_OK; } NS_IMPL_ISUPPORTS_INHERITED(WorkletThread, nsThread, nsIObserver) } // namespace dom } // namespace mozilla
--- a/dom/worklet/WorkletThread.h +++ b/dom/worklet/WorkletThread.h @@ -6,46 +6,47 @@ #ifndef mozilla_dom_worklet_WorkletThread_h #define mozilla_dom_worklet_WorkletThread_h #include "mozilla/Attributes.h" #include "mozilla/CondVar.h" #include "mozilla/RefPtr.h" #include "mozilla/UniquePtr.h" +#include "mozilla/dom/WorkletImpl.h" #include "nsThread.h" class nsIRunnable; namespace mozilla { namespace dom { class WorkletThread final : public nsThread, public nsIObserver { public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIOBSERVER - static already_AddRefed<WorkletThread> Create(); + static already_AddRefed<WorkletThread> Create(WorkletImpl* aWorkletImpl); // Threads that call EnsureCycleCollectedJSContext must call // DeleteCycleCollectedJSContext::Get() before terminating. Clients of // Create() do not need to do this as Terminate() will ensure this happens. static void EnsureCycleCollectedJSContext(JSRuntime* aParentRuntime); static void DeleteCycleCollectedJSContext(); static bool IsOnWorkletThread(); static void AssertIsOnWorkletThread(); nsresult DispatchRunnable(already_AddRefed<nsIRunnable> aRunnable); void Terminate(); private: - WorkletThread(); + explicit WorkletThread(WorkletImpl* aWorkletImpl); ~WorkletThread(); void RunEventLoop(); class PrimaryRunnable; void TerminateInternal(); class TerminateRunnable; @@ -55,16 +56,18 @@ class WorkletThread final : public nsThr Dispatch(already_AddRefed<nsIRunnable> aRunnable, uint32_t aFlags) override; NS_IMETHOD DispatchFromScript(nsIRunnable* aRunnable, uint32_t aFlags) override; NS_IMETHOD DelayedDispatch(already_AddRefed<nsIRunnable>, uint32_t) override; + const RefPtr<WorkletImpl> mWorkletImpl; + bool mExitLoop; // worklet execution thread bool mIsTerminating; // main thread }; } // namespace dom } // namespace mozilla
--- a/gfx/gl/GLScreenBuffer.cpp +++ b/gfx/gl/GLScreenBuffer.cpp @@ -83,19 +83,17 @@ UniquePtr<SurfaceFactory> GLScreenBuffer factory = SurfaceFactory_IOSurface::Create(gl, caps, ipcChannel, flags); #elif defined(MOZ_X11) if (sGLXLibrary.UseTextureFromPixmap()) factory = SurfaceFactory_GLXDrawable::Create(gl, caps, ipcChannel, flags); #elif defined(MOZ_WIDGET_UIKIT) factory = MakeUnique<SurfaceFactory_GLTexture>(mGLContext, caps, ipcChannel, mFlags); #elif defined(MOZ_WIDGET_ANDROID) - // XXX WebRender does not support SurfaceFactory_EGLImage usage. - if (XRE_IsParentProcess() && !gfxPrefs::WebGLSurfaceTextureEnabled() && - backend != layers::LayersBackend::LAYERS_WR) { + if (XRE_IsParentProcess() && !gfxPrefs::WebGLSurfaceTextureEnabled()) { factory = SurfaceFactory_EGLImage::Create(gl, caps, ipcChannel, flags); } else { factory = SurfaceFactory_SurfaceTexture::Create(gl, caps, ipcChannel, flags); } #else if (gl->GetContextType() == GLContextType::EGL) { if (XRE_IsParentProcess()) {
--- a/gfx/layers/opengl/TextureHostOGL.cpp +++ b/gfx/layers/opengl/TextureHostOGL.cpp @@ -11,16 +11,17 @@ #include "GLLibraryEGL.h" // for GLLibraryEGL #include "GLUploadHelpers.h" #include "GLReadTexImageHelper.h" #include "gfx2DGlue.h" // for ContentForFormat, etc #include "mozilla/gfx/2D.h" // for DataSourceSurface #include "mozilla/gfx/BaseSize.h" // for BaseSize #include "mozilla/gfx/Logging.h" // for gfxCriticalError #include "mozilla/layers/ISurfaceAllocator.h" +#include "mozilla/webrender/RenderEGLImageTextureHost.h" #include "mozilla/webrender/WebRenderAPI.h" #include "nsRegion.h" // for nsIntRegion #include "AndroidSurfaceTexture.h" #include "GfxTexturesReporter.h" // for GfxTexturesReporter #include "GLBlitTextureImageHelper.h" #include "GeckoProfiler.h" #ifdef XP_MACOSX @@ -812,16 +813,54 @@ void EGLImageTextureHost::SetTextureSour } gfx::SurfaceFormat EGLImageTextureHost::GetFormat() const { MOZ_ASSERT(mTextureSource); return mTextureSource ? mTextureSource->GetFormat() : gfx::SurfaceFormat::UNKNOWN; } +void EGLImageTextureHost::CreateRenderTexture( + const wr::ExternalImageId& aExternalImageId) { + RefPtr<wr::RenderTextureHost> texture = + new wr::RenderEGLImageTextureHost(mImage, mSync, mSize); + wr::RenderThread::Get()->RegisterExternalImage(wr::AsUint64(aExternalImageId), + texture.forget()); +} + +void EGLImageTextureHost::PushResourceUpdates( + wr::TransactionBuilder& aResources, ResourceUpdateOp aOp, + const Range<wr::ImageKey>& aImageKeys, const wr::ExternalImageId& aExtID) { + auto method = aOp == TextureHost::ADD_IMAGE + ? &wr::TransactionBuilder::AddExternalImage + : &wr::TransactionBuilder::UpdateExternalImage; + auto bufferType = wr::WrExternalImageBufferType::TextureExternalHandle; + + gfx::SurfaceFormat format = + mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8 : gfx::SurfaceFormat::R8G8B8X8; + + MOZ_ASSERT(aImageKeys.length() == 1); + // XXX Add RGBA handling. Temporary hack to avoid crash + // With BGRA format setting, rendering works without problem. + auto formatTmp = format == gfx::SurfaceFormat::R8G8B8A8 + ? gfx::SurfaceFormat::B8G8R8A8 + : gfx::SurfaceFormat::B8G8R8X8; + wr::ImageDescriptor descriptor(GetSize(), formatTmp); + (aResources.*method)(aImageKeys[0], descriptor, aExtID, bufferType, 0); +} + +void EGLImageTextureHost::PushDisplayItems( + wr::DisplayListBuilder& aBuilder, const wr::LayoutRect& aBounds, + const wr::LayoutRect& aClip, wr::ImageRendering aFilter, + const Range<wr::ImageKey>& aImageKeys) { + MOZ_ASSERT(aImageKeys.length() == 1); + aBuilder.PushImage(aBounds, aClip, true, aFilter, aImageKeys[0], + !(mFlags & TextureFlags::NON_PREMULTIPLIED)); +} + // GLTextureHost::GLTextureHost(TextureFlags aFlags, GLuint aTextureHandle, GLenum aTarget, GLsync aSync, gfx::IntSize aSize, bool aHasAlpha) : TextureHost(aFlags), mTexture(aTextureHandle), mTarget(aTarget),
--- a/gfx/layers/opengl/TextureHostOGL.h +++ b/gfx/layers/opengl/TextureHostOGL.h @@ -540,16 +540,30 @@ class EGLImageTextureHost final : public } gl::GLContext* gl() const; virtual gfx::IntSize GetSize() const override { return mSize; } virtual const char* Name() override { return "EGLImageTextureHost"; } + virtual void CreateRenderTexture( + const wr::ExternalImageId& aExternalImageId) override; + + virtual void PushResourceUpdates(wr::TransactionBuilder& aResources, + ResourceUpdateOp aOp, + const Range<wr::ImageKey>& aImageKeys, + const wr::ExternalImageId& aExtID) override; + + virtual void PushDisplayItems(wr::DisplayListBuilder& aBuilder, + const wr::LayoutRect& aBounds, + const wr::LayoutRect& aClip, + wr::ImageRendering aFilter, + const Range<wr::ImageKey>& aImageKeys) override; + protected: const EGLImage mImage; const EGLSync mSync; const gfx::IntSize mSize; const bool mHasAlpha; RefPtr<EGLImageTextureSource> mTextureSource; };
--- a/gfx/src/nsFont.cpp +++ b/gfx/src/nsFont.cpp @@ -16,17 +16,17 @@ #include "mozilla/ArrayUtils.h" #include "mozilla/gfx/2D.h" using namespace mozilla; nsFont::nsFont(const FontFamilyList& aFontlist, nscoord aSize) : fontlist(aFontlist), size(aSize) {} -nsFont::nsFont(FontFamilyType aGenericType, nscoord aSize) +nsFont::nsFont(StyleGenericFontFamily aGenericType, nscoord aSize) : fontlist(aGenericType), size(aSize) {} nsFont::nsFont(const nsFont& aOther) = default; nsFont::nsFont() {} nsFont::~nsFont() {}
--- a/gfx/src/nsFont.h +++ b/gfx/src/nsFont.h @@ -16,32 +16,16 @@ #include "mozilla/FontPropertyTypes.h" #include "mozilla/RefPtr.h" // for RefPtr #include "nsColor.h" // for nsColor and NS_RGBA #include "nsCoord.h" // for nscoord #include "nsTArray.h" // for nsTArray struct gfxFontStyle; -// IDs for generic fonts -// NOTE: 0, 1 are reserved for the special IDs of the default variable -// and fixed fonts in the presentation context, see nsPresContext.h -const uint8_t kGenericFont_NONE = 0x00; -// Special -const uint8_t kGenericFont_moz_variable = - 0x00; // for the default variable width font -const uint8_t kGenericFont_moz_fixed = - 0x01; // our special "use the user's fixed font" -// CSS -const uint8_t kGenericFont_serif = 0x02; -const uint8_t kGenericFont_sans_serif = 0x04; -const uint8_t kGenericFont_monospace = 0x08; -const uint8_t kGenericFont_cursive = 0x10; -const uint8_t kGenericFont_fantasy = 0x20; - // Font structure. struct nsFont { typedef mozilla::FontStretch FontStretch; typedef mozilla::FontSlantStyle FontSlantStyle; typedef mozilla::FontWeight FontWeight; // List of font families, either named or generic. // This contains a RefPtr and a uint32_t field. @@ -112,17 +96,17 @@ struct nsFont { // Force this font to not be considered a 'generic' font, even if // the name is the same as a CSS generic font family. bool systemFont = false; // initialize the font with a fontlist nsFont(const mozilla::FontFamilyList& aFontlist, nscoord aSize); // initialize the font with a single generic - nsFont(mozilla::FontFamilyType aGenericType, nscoord aSize); + nsFont(mozilla::StyleGenericFontFamily, nscoord aSize); // Make a copy of the given font nsFont(const nsFont& aFont); // leave members uninitialized nsFont(); ~nsFont();
--- a/gfx/thebes/gfxFcPlatformFontList.cpp +++ b/gfx/thebes/gfxFcPlatformFontList.cpp @@ -1967,25 +1967,20 @@ bool gfxFcPlatformFontList::GetStandardF } } // didn't find localized name, leave family name blank return true; } void gfxFcPlatformFontList::AddGenericFonts( - mozilla::FontFamilyType aGenericType, nsAtom* aLanguage, + mozilla::StyleGenericFontFamily aGenericType, nsAtom* aLanguage, nsTArray<FamilyAndGeneric>& aFamilyList) { bool usePrefFontList = false; - // treat -moz-fixed as monospace - if (aGenericType == eFamily_moz_fixed) { - aGenericType = eFamily_monospace; - } - const char* generic = GetGenericName(aGenericType); NS_ASSERTION(generic, "weird generic font type"); if (!generic) { return; } // By default, most font prefs on Linux map to "use fontconfig" // keywords. So only need to explicitly lookup font pref if
--- a/gfx/thebes/gfxFcPlatformFontList.h +++ b/gfx/thebes/gfxFcPlatformFontList.h @@ -296,17 +296,17 @@ class gfxFcPlatformFontList : public gfx gfxFloat aDevToCssSize = 1.0) override; bool GetStandardFamilyName(const nsCString& aFontName, nsACString& aFamilyName) override; FcConfig* GetLastConfig() const { return mLastConfig; } // override to use fontconfig lookup for generics - void AddGenericFonts(mozilla::FontFamilyType aGenericType, nsAtom* aLanguage, + void AddGenericFonts(mozilla::StyleGenericFontFamily, nsAtom* aLanguage, nsTArray<FamilyAndGeneric>& aFamilyList) override; void ClearLangGroupPrefFonts() override; // clear out cached generic-lang ==> family-list mappings void ClearGenericMappings() { mGenericMappings.Clear(); } // map lang group ==> lang string
--- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -4,16 +4,17 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "gfxFont.h" #include "mozilla/BinarySearch.h" #include "mozilla/DebugOnly.h" #include "mozilla/FontPropertyTypes.h" #include "mozilla/gfx/2D.h" +#include "mozilla/IntegerRange.h" #include "mozilla/MathAlgorithms.h" #include "mozilla/StaticPrefs.h" #include "mozilla/SVGContextPaint.h" #include "mozilla/Logging.h" #include "nsITimer.h" @@ -3995,28 +3996,29 @@ bool gfxFont::TryGetMathTable() { return !!mMathTable; } /* static */ void SharedFontList::Initialize() { sEmpty = new SharedFontList(); - for (uint8_t i = 0; i < uint8_t(eFamily_generic_count_including_special); - ++i) { - auto type = static_cast<FontFamilyType>(i + uint8_t(eFamily_generic_first)); - sSingleGenerics[i] = new SharedFontList(type); + for (auto i : IntegerRange(ArrayLength(sSingleGenerics))) { + auto type = static_cast<StyleGenericFontFamily>(i); + if (type != StyleGenericFontFamily::None) { + sSingleGenerics[i] = new SharedFontList(type); + } } } /* static */ void SharedFontList::Shutdown() { sEmpty = nullptr; for (auto& sharedFontList : sSingleGenerics) { sharedFontList = nullptr; } } StaticRefPtr<SharedFontList> SharedFontList::sEmpty; StaticRefPtr<SharedFontList> - SharedFontList::sSingleGenerics[eFamily_generic_count_including_special]; + SharedFontList::sSingleGenerics[size_t(StyleGenericFontFamily::MozEmoji)];
--- a/gfx/thebes/gfxFontEntry.h +++ b/gfx/thebes/gfxFontEntry.h @@ -932,33 +932,33 @@ struct FontFamily { bool mIsShared; }; // Struct used in the gfxFontGroup font list to keep track of a font family // together with the CSS generic (if any) that was mapped to it in this // particular case (so it can be reported to the DevTools font inspector). struct FamilyAndGeneric final { FamilyAndGeneric() - : mFamily(), mGeneric(mozilla::FontFamilyType::eFamily_none) {} + : mFamily(), mGeneric(mozilla::StyleGenericFontFamily::None) {} FamilyAndGeneric(const FamilyAndGeneric& aOther) : mFamily(aOther.mFamily), mGeneric(aOther.mGeneric) {} - explicit FamilyAndGeneric( - gfxFontFamily* aFamily, - mozilla::FontFamilyType aGeneric = mozilla::FontFamilyType::eFamily_none) + explicit FamilyAndGeneric(gfxFontFamily* aFamily, + mozilla::StyleGenericFontFamily aGeneric = + mozilla::StyleGenericFontFamily::None) : mFamily(aFamily), mGeneric(aGeneric) {} - explicit FamilyAndGeneric( - mozilla::fontlist::Family* aFamily, - mozilla::FontFamilyType aGeneric = mozilla::FontFamilyType::eFamily_none) + explicit FamilyAndGeneric(mozilla::fontlist::Family* aFamily, + mozilla::StyleGenericFontFamily aGeneric = + mozilla::StyleGenericFontFamily::None) : mFamily(aFamily), mGeneric(aGeneric) {} - explicit FamilyAndGeneric( - const FontFamily& aFamily, - mozilla::FontFamilyType aGeneric = mozilla::FontFamilyType::eFamily_none) + explicit FamilyAndGeneric(const FontFamily& aFamily, + mozilla::StyleGenericFontFamily aGeneric = + mozilla::StyleGenericFontFamily::None) : mFamily(aFamily), mGeneric(aGeneric) {} bool operator==(const FamilyAndGeneric& aOther) const { - return (mFamily == aOther.mFamily && mGeneric == aOther.mGeneric); + return mFamily == aOther.mFamily && mGeneric == aOther.mGeneric; } FontFamily mFamily; - mozilla::FontFamilyType mGeneric; + mozilla::StyleGenericFontFamily mGeneric; }; #endif
--- a/gfx/thebes/gfxFontFamilyList.h +++ b/gfx/thebes/gfxFontFamilyList.h @@ -5,213 +5,158 @@ #ifndef GFX_FONT_FAMILY_LIST_H #define GFX_FONT_FAMILY_LIST_H #include "nsAtom.h" #include "nsDebug.h" #include "nsISupportsImpl.h" #include "nsString.h" +#include "nsStyleConsts.h" #include "nsUnicharUtils.h" #include "nsTArray.h" #include "mozilla/MemoryReporting.h" #include "mozilla/NotNull.h" #include "mozilla/StaticPtr.h" #include "mozilla/TimeStamp.h" namespace mozilla { /** - * type of font family name, either a name (e.g. Helvetica) or a - * generic (e.g. serif, sans-serif), with the ability to distinguish - * between unquoted and quoted names for serializaiton - */ - -enum FontFamilyType : uint8_t { - eFamily_none = 0, // used when finding generics - - // explicitly named font family (e.g. Helvetica) - eFamily_named, - eFamily_named_quoted, - - // generics - eFamily_serif, // pref font code relies on this ordering!!! - eFamily_sans_serif, - eFamily_monospace, - eFamily_cursive, - eFamily_fantasy, - - // special - eFamily_moz_variable, - eFamily_moz_fixed, - eFamily_moz_emoji, - - eFamily_generic_first = eFamily_serif, - eFamily_generic_last = eFamily_fantasy, - eFamily_generic_last_including_special = eFamily_moz_emoji, - - eFamily_generic_count = eFamily_generic_last - eFamily_generic_first + 1, - eFamily_generic_count_including_special = - eFamily_generic_last_including_special - eFamily_generic_first + 1, -}; - -enum QuotedName { eQuotedName, eUnquotedName }; - -/** * font family name, an Atom for the name if not a generic and * a font type indicated named family or which generic family */ struct FontFamilyName final { - FontFamilyName() : mType(eFamily_none) {} + using Syntax = StyleFontFamilyNameSyntax; + + FontFamilyName() = delete; // named font family - e.g. Helvetica - explicit FontFamilyName(nsAtom* aFamilyName, - QuotedName aQuoted = eUnquotedName) { - mType = (aQuoted == eQuotedName) ? eFamily_named_quoted : eFamily_named; - mName = aFamilyName; - } + explicit FontFamilyName(nsAtom* aFamilyName, Syntax aSyntax) + : mName(aFamilyName), mSyntax(aSyntax) {} - explicit FontFamilyName(const nsACString& aFamilyName, - QuotedName aQuoted = eUnquotedName) { - mType = (aQuoted == eQuotedName) ? eFamily_named_quoted : eFamily_named; - mName = NS_Atomize(aFamilyName); - } + explicit FontFamilyName(const nsACString& aFamilyName, Syntax aSyntax) + : mName(NS_Atomize(aFamilyName)), mSyntax(aSyntax) {} // generic font family - e.g. sans-serif - explicit FontFamilyName(FontFamilyType aType) { - NS_ASSERTION(aType != eFamily_named && aType != eFamily_named_quoted && - aType != eFamily_none, - "expected a generic font type"); - mName = nullptr; - mType = aType; + explicit FontFamilyName(StyleGenericFontFamily aGeneric) + : mGeneric(aGeneric) { + MOZ_ASSERT(mGeneric != StyleGenericFontFamily::None); } - FontFamilyName(const FontFamilyName& aCopy) { - mType = aCopy.mType; - mName = aCopy.mName; - } + FontFamilyName(const FontFamilyName&) = default; - bool IsNamed() const { - return mType == eFamily_named || mType == eFamily_named_quoted; - } + bool IsNamed() const { return !!mName; } bool IsGeneric() const { return !IsNamed(); } void AppendToString(nsACString& aFamilyList, bool aQuotes = true) const { - switch (mType) { - case eFamily_named: - aFamilyList.Append(nsAtomCString(mName)); - break; - case eFamily_named_quoted: - if (aQuotes) { - aFamilyList.Append('"'); - } - aFamilyList.Append(nsAtomCString(mName)); - if (aQuotes) { - aFamilyList.Append('"'); - } - break; - case eFamily_serif: + if (IsNamed()) { + if (mSyntax == Syntax::Identifiers) { + return aFamilyList.Append(nsAtomCString(mName)); + } + if (aQuotes) { + aFamilyList.Append('"'); + } + aFamilyList.Append(nsAtomCString(mName)); + if (aQuotes) { + aFamilyList.Append('"'); + } + return; + } + switch (mGeneric) { + case StyleGenericFontFamily::None: + case StyleGenericFontFamily::MozEmoji: + MOZ_FALLTHROUGH_ASSERT("Should never appear in a font-family name!"); + case StyleGenericFontFamily::Serif: aFamilyList.AppendLiteral("serif"); break; - case eFamily_sans_serif: + case StyleGenericFontFamily::SansSerif: aFamilyList.AppendLiteral("sans-serif"); break; - case eFamily_monospace: + case StyleGenericFontFamily::Monospace: aFamilyList.AppendLiteral("monospace"); break; - case eFamily_cursive: + case StyleGenericFontFamily::Cursive: aFamilyList.AppendLiteral("cursive"); break; - case eFamily_fantasy: + case StyleGenericFontFamily::Fantasy: aFamilyList.AppendLiteral("fantasy"); break; - case eFamily_moz_fixed: - aFamilyList.AppendLiteral("-moz-fixed"); - break; default: + MOZ_ASSERT_UNREACHABLE("Unknown generic font-family!"); break; } } // helper method that converts generic names to the right enum value static FontFamilyName Convert(const nsACString& aFamilyOrGenericName) { // should only be passed a single font - not entirely correct, a family // *could* have a comma in it but in practice never does so // for debug purposes this is fine NS_ASSERTION(aFamilyOrGenericName.FindChar(',') == -1, "Convert method should only be passed a single family name"); - FontFamilyType genericType = eFamily_none; + auto genericType = StyleGenericFontFamily::None; if (aFamilyOrGenericName.LowerCaseEqualsLiteral("serif")) { - genericType = eFamily_serif; + genericType = StyleGenericFontFamily::Serif; } else if (aFamilyOrGenericName.LowerCaseEqualsLiteral("sans-serif")) { - genericType = eFamily_sans_serif; - } else if (aFamilyOrGenericName.LowerCaseEqualsLiteral("monospace")) { - genericType = eFamily_monospace; + genericType = StyleGenericFontFamily::SansSerif; + } else if (aFamilyOrGenericName.LowerCaseEqualsLiteral("monospace") || + aFamilyOrGenericName.LowerCaseEqualsLiteral("-moz-fixed")) { + genericType = StyleGenericFontFamily::Monospace; } else if (aFamilyOrGenericName.LowerCaseEqualsLiteral("cursive")) { - genericType = eFamily_cursive; + genericType = StyleGenericFontFamily::Cursive; } else if (aFamilyOrGenericName.LowerCaseEqualsLiteral("fantasy")) { - genericType = eFamily_fantasy; - } else if (aFamilyOrGenericName.LowerCaseEqualsLiteral("-moz-fixed")) { - genericType = eFamily_moz_fixed; + genericType = StyleGenericFontFamily::Fantasy; } else { - return FontFamilyName(aFamilyOrGenericName, eUnquotedName); + return FontFamilyName(aFamilyOrGenericName, Syntax::Identifiers); } return FontFamilyName(genericType); } - FontFamilyType mType; - RefPtr<nsAtom> mName; // null if mType != eFamily_named + RefPtr<nsAtom> mName; // null if mGeneric != Default + StyleFontFamilyNameSyntax mSyntax = StyleFontFamilyNameSyntax::Quoted; + StyleGenericFontFamily mGeneric = StyleGenericFontFamily::None; }; inline bool operator==(const FontFamilyName& a, const FontFamilyName& b) { - return a.mType == b.mType && a.mName == b.mName; + return a.mName == b.mName && a.mSyntax == b.mSyntax && + a.mGeneric == b.mGeneric; } /** * A refcounted array of FontFamilyNames. We use this to store the specified * and computed value of the font-family property. * * TODO(heycam): It might better to define this type (and FontFamilyList and * FontFamilyName) in Rust. */ class SharedFontList { + using Syntax = StyleFontFamilyNameSyntax; + public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedFontList); - SharedFontList() {} + SharedFontList() = default; - explicit SharedFontList(FontFamilyType aGenericType) + explicit SharedFontList(StyleGenericFontFamily aGenericType) : mNames{FontFamilyName(aGenericType)} {} - SharedFontList(nsAtom* aFamilyName, QuotedName aQuoted) - : mNames{FontFamilyName(aFamilyName, aQuoted)} {} + SharedFontList(nsAtom* aFamilyName, Syntax aSyntax) + : mNames{FontFamilyName(aFamilyName, aSyntax)} {} - SharedFontList(const nsACString& aFamilyName, QuotedName aQuoted) - : mNames{FontFamilyName(aFamilyName, aQuoted)} {} - - explicit SharedFontList(const FontFamilyName& aName) : mNames{aName} {} + SharedFontList(const nsACString& aFamilyName, Syntax aSyntax) + : mNames{FontFamilyName(aFamilyName, aSyntax)} {} explicit SharedFontList(nsTArray<FontFamilyName>&& aNames) : mNames(std::move(aNames)) {} - FontFamilyType FirstGeneric() const { - for (const FontFamilyName& name : mNames) { - if (name.IsGeneric()) { - return name.mType; - } - } - return eFamily_none; - } - - bool HasGeneric() const { return FirstGeneric() != eFamily_none; } - size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { size_t n = 0; n += aMallocSizeOf(this); n += mNames.ShallowSizeOfExcludingThis(aMallocSizeOf); return n; } size_t SizeOfIncludingThisIfUnshared(MallocSizeOf aMallocSizeOf) const { @@ -223,59 +168,51 @@ class SharedFontList { } const nsTArray<FontFamilyName> mNames; static void Initialize(); static void Shutdown(); static StaticRefPtr<SharedFontList> sEmpty; static StaticRefPtr<SharedFontList> - sSingleGenerics[eFamily_generic_count_including_special]; + sSingleGenerics[size_t(StyleGenericFontFamily::MozEmoji)]; private: ~SharedFontList() = default; }; /** * font family list, array of font families and a default font type. * font family names are either named strings or generics. the default * font type is used to preserve the variable font fallback behavior */ class FontFamilyList { + using Syntax = StyleFontFamilyNameSyntax; + public: - FontFamilyList() - : mFontlist(WrapNotNull(SharedFontList::sEmpty.get())), - mDefaultFontType(eFamily_none) {} - - explicit FontFamilyList(FontFamilyType aGenericType) - : mFontlist(MakeNotNull<SharedFontList*>(aGenericType)), - mDefaultFontType(eFamily_none) {} + FontFamilyList() : mFontlist(WrapNotNull(SharedFontList::sEmpty.get())) {} - FontFamilyList(nsAtom* aFamilyName, QuotedName aQuoted) - : mFontlist(MakeNotNull<SharedFontList*>(aFamilyName, aQuoted)), - mDefaultFontType(eFamily_none) {} + explicit FontFamilyList(StyleGenericFontFamily aGenericType) + : mFontlist(MakeNotNull<SharedFontList*>(aGenericType)) {} - FontFamilyList(const nsACString& aFamilyName, QuotedName aQuoted) - : mFontlist(MakeNotNull<SharedFontList*>(aFamilyName, aQuoted)), - mDefaultFontType(eFamily_none) {} + FontFamilyList(nsAtom* aFamilyName, Syntax aSyntax) + : mFontlist(MakeNotNull<SharedFontList*>(aFamilyName, aSyntax)) {} - explicit FontFamilyList(const FontFamilyName& aName) - : mFontlist(MakeNotNull<SharedFontList*>(aName)), - mDefaultFontType(eFamily_none) {} + FontFamilyList(const nsACString& aFamilyName, Syntax aSyntax) + : mFontlist(MakeNotNull<SharedFontList*>(aFamilyName, aSyntax)) {} explicit FontFamilyList(nsTArray<FontFamilyName>&& aNames) - : mFontlist(MakeNotNull<SharedFontList*>(std::move(aNames))), - mDefaultFontType(eFamily_none) {} + : mFontlist(MakeNotNull<SharedFontList*>(std::move(aNames))) {} FontFamilyList(const FontFamilyList& aOther) : mFontlist(aOther.mFontlist), mDefaultFontType(aOther.mDefaultFontType) {} explicit FontFamilyList(NotNull<SharedFontList*> aFontList) - : mFontlist(aFontList), mDefaultFontType(eFamily_none) {} + : mFontlist(aFontList) {} void SetFontlist(nsTArray<FontFamilyName>&& aNames) { mFontlist = MakeNotNull<SharedFontList*>(std::move(aNames)); } void SetFontlist(NotNull<SharedFontList*> aFontlist) { mFontlist = aFontlist; } @@ -287,77 +224,77 @@ class FontFamilyList { NotNull<SharedFontList*> GetFontlist() const { return mFontlist; } bool Equals(const FontFamilyList& aFontlist) const { return (mFontlist == aFontlist.mFontlist || mFontlist->mNames == aFontlist.mFontlist->mNames) && mDefaultFontType == aFontlist.mDefaultFontType; } - FontFamilyType FirstGeneric() const { return mFontlist->FirstGeneric(); } - - bool HasGeneric() const { return mFontlist->HasGeneric(); } - bool HasDefaultGeneric() const { + if (mDefaultFontType == StyleGenericFontFamily::None) { + return false; + } for (const FontFamilyName& name : mFontlist->mNames) { - if (name.mType == mDefaultFontType) { + if (name.mGeneric == mDefaultFontType) { return true; } } return false; } // Find the first generic (but ignoring cursive and fantasy, as they are // rarely configured in any useful way) in the list. // If found, move it to the start and return true; else return false. bool PrioritizeFirstGeneric() { uint32_t len = mFontlist->mNames.Length(); for (uint32_t i = 0; i < len; i++) { const FontFamilyName name = mFontlist->mNames[i]; if (name.IsGeneric()) { - if (name.mType == eFamily_cursive || name.mType == eFamily_fantasy) { + if (name.mGeneric == StyleGenericFontFamily::Cursive || + name.mGeneric == StyleGenericFontFamily::Fantasy) { continue; } if (i > 0) { nsTArray<FontFamilyName> names; names.AppendElements(mFontlist->mNames); names.RemoveElementAt(i); names.InsertElementAt(0, name); SetFontlist(std::move(names)); } return true; } } return false; } - void PrependGeneric(FontFamilyType aType) { + void PrependGeneric(StyleGenericFontFamily aGeneric) { nsTArray<FontFamilyName> names; names.AppendElements(mFontlist->mNames); - names.InsertElementAt(0, FontFamilyName(aType)); + names.InsertElementAt(0, FontFamilyName(aGeneric)); SetFontlist(std::move(names)); } void ToString(nsACString& aFamilyList, bool aQuotes = true, bool aIncludeDefault = false) const { const nsTArray<FontFamilyName>& names = mFontlist->mNames; aFamilyList.Truncate(); uint32_t len = names.Length(); for (uint32_t i = 0; i < len; i++) { if (i != 0) { aFamilyList.Append(','); } const FontFamilyName& name = names[i]; name.AppendToString(aFamilyList, aQuotes); } - if (aIncludeDefault && mDefaultFontType != eFamily_none) { + if (aIncludeDefault && mDefaultFontType != StyleGenericFontFamily::None) { if (!aFamilyList.IsEmpty()) { aFamilyList.Append(','); } - if (mDefaultFontType == eFamily_serif) { + if (mDefaultFontType == StyleGenericFontFamily::Serif) { aFamilyList.AppendLiteral("serif"); } else { aFamilyList.AppendLiteral("sans-serif"); } } } // searches for a specific non-generic name, case-insensitive comparison @@ -370,20 +307,21 @@ class FontFamilyList { nsDependentAtomString listname(name.mName); if (listname.Equals(fam, nsCaseInsensitiveStringComparator())) { return true; } } return false; } - FontFamilyType GetDefaultFontType() const { return mDefaultFontType; } - void SetDefaultFontType(FontFamilyType aType) { - NS_ASSERTION(aType == eFamily_none || aType == eFamily_serif || - aType == eFamily_sans_serif, + StyleGenericFontFamily GetDefaultFontType() const { return mDefaultFontType; } + void SetDefaultFontType(StyleGenericFontFamily aType) { + NS_ASSERTION(aType == StyleGenericFontFamily::None || + aType == StyleGenericFontFamily::Serif || + aType == StyleGenericFontFamily::SansSerif, "default font type must be either serif or sans-serif"); mDefaultFontType = aType; } // memory reporting size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { size_t n = 0; n += mFontlist->SizeOfIncludingThisIfUnshared(aMallocSizeOf); @@ -391,17 +329,18 @@ class FontFamilyList { } size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); } protected: NotNull<RefPtr<SharedFontList>> mFontlist; - FontFamilyType mDefaultFontType; // none, serif or sans-serif + StyleGenericFontFamily mDefaultFontType = + StyleGenericFontFamily::None; // or serif, or sans-serif }; inline bool operator==(const FontFamilyList& a, const FontFamilyList& b) { return a.Equals(b); } inline bool operator!=(const FontFamilyList& a, const FontFamilyList& b) { return !a.Equals(b);
--- a/gfx/thebes/gfxPlatformFontList.cpp +++ b/gfx/thebes/gfxPlatformFontList.cpp @@ -886,17 +886,17 @@ void gfxPlatformFontList::RemoveCmap(con CharMapHashKey* found = mSharedCmaps.GetEntry(const_cast<gfxCharacterMap*>(aCharMap)); if (found && found->GetKey() == aCharMap) { mSharedCmaps.RemoveEntry(found); } } void gfxPlatformFontList::ResolveGenericFontNames( - FontFamilyType aGenericType, eFontPrefLang aPrefLang, + StyleGenericFontFamily aGenericType, eFontPrefLang aPrefLang, PrefFontList* aGenericFamilies) { const char* langGroupStr = GetPrefLangName(aPrefLang); const char* generic = GetGenericName(aGenericType); if (!generic) { return; } @@ -952,44 +952,40 @@ void gfxPlatformFontList::GetFontFamilie if (!aGenericFamilies->Contains(f.mFamily)) { aGenericFamilies->AppendElement(f.mFamily); } } } } gfxPlatformFontList::PrefFontList* gfxPlatformFontList::GetPrefFontsLangGroup( - mozilla::FontFamilyType aGenericType, eFontPrefLang aPrefLang) { - // treat -moz-fixed as monospace - if (aGenericType == eFamily_moz_fixed) { - aGenericType = eFamily_monospace; - } - - if (aGenericType == eFamily_moz_emoji) { + StyleGenericFontFamily aGenericType, eFontPrefLang aPrefLang) { + if (aGenericType == StyleGenericFontFamily::MozEmoji) { // Emoji font has no lang PrefFontList* prefFonts = mEmojiPrefFont.get(); if (MOZ_UNLIKELY(!prefFonts)) { prefFonts = new PrefFontList; ResolveEmojiFontNames(prefFonts); mEmojiPrefFont.reset(prefFonts); } return prefFonts; } - PrefFontList* prefFonts = mLangGroupPrefFonts[aPrefLang][aGenericType].get(); + auto index = static_cast<size_t>(aGenericType); + PrefFontList* prefFonts = mLangGroupPrefFonts[aPrefLang][index].get(); if (MOZ_UNLIKELY(!prefFonts)) { prefFonts = new PrefFontList; ResolveGenericFontNames(aGenericType, aPrefLang, prefFonts); - mLangGroupPrefFonts[aPrefLang][aGenericType].reset(prefFonts); + mLangGroupPrefFonts[aPrefLang][index].reset(prefFonts); } return prefFonts; } void gfxPlatformFontList::AddGenericFonts( - mozilla::FontFamilyType aGenericType, nsAtom* aLanguage, + mozilla::StyleGenericFontFamily aGenericType, nsAtom* aLanguage, nsTArray<FamilyAndGeneric>& aFamilyList) { // map lang ==> langGroup nsAtom* langGroup = GetLangGroup(aLanguage); // langGroup ==> prefLang eFontPrefLang prefLang = GetFontPrefLangFor(langGroup); // lookup pref fonts @@ -1277,42 +1273,42 @@ void gfxPlatformFontList::AppendPrefLang } if (i == aLen) { aPrefLangs[aLen] = aAddLang; aLen++; } } -mozilla::FontFamilyType gfxPlatformFontList::GetDefaultGeneric( +mozilla::StyleGenericFontFamily gfxPlatformFontList::GetDefaultGeneric( eFontPrefLang aLang) { if (aLang == eFontPrefLang_Emoji) { - return eFamily_moz_emoji; + return StyleGenericFontFamily::MozEmoji; } // initialize lang group pref font defaults (i.e. serif/sans-serif) if (MOZ_UNLIKELY(mDefaultGenericsLangGroup.IsEmpty())) { mDefaultGenericsLangGroup.AppendElements(ArrayLength(gPrefLangNames)); for (uint32_t i = 0; i < ArrayLength(gPrefLangNames); i++) { nsAutoCString prefDefaultFontType("font.default."); prefDefaultFontType.Append(GetPrefLangName(eFontPrefLang(i))); nsAutoCString serifOrSans; Preferences::GetCString(prefDefaultFontType.get(), serifOrSans); if (serifOrSans.EqualsLiteral("sans-serif")) { - mDefaultGenericsLangGroup[i] = eFamily_sans_serif; + mDefaultGenericsLangGroup[i] = StyleGenericFontFamily::SansSerif; } else { - mDefaultGenericsLangGroup[i] = eFamily_serif; + mDefaultGenericsLangGroup[i] = StyleGenericFontFamily::Serif; } } } if (uint32_t(aLang) < ArrayLength(gPrefLangNames)) { return mDefaultGenericsLangGroup[uint32_t(aLang)]; } - return eFamily_serif; + return StyleGenericFontFamily::Serif; } FontFamily gfxPlatformFontList::GetDefaultFont(const gfxFontStyle* aStyle) { FontFamily family = GetDefaultFontForPlatform(aStyle); if (!family.mIsShared && family.mUnshared) { return family; } // Something has gone wrong and we were unable to retrieve a default font @@ -1338,50 +1334,40 @@ nsAtom* gfxPlatformFontList::GetLangGrou } if (!langGroup) { langGroup = nsGkAtoms::Unicode; } return langGroup; } /* static */ const char* gfxPlatformFontList::GetGenericName( - FontFamilyType aGenericType) { + StyleGenericFontFamily aGenericType) { static const char kGeneric_serif[] = "serif"; static const char kGeneric_sans_serif[] = "sans-serif"; static const char kGeneric_monospace[] = "monospace"; static const char kGeneric_cursive[] = "cursive"; static const char kGeneric_fantasy[] = "fantasy"; // type should be standard generic type at this point - NS_ASSERTION(aGenericType >= eFamily_serif && aGenericType <= eFamily_fantasy, - "standard generic font family type required"); - // map generic type to string - const char* generic = nullptr; switch (aGenericType) { - case eFamily_serif: - generic = kGeneric_serif; - break; - case eFamily_sans_serif: - generic = kGeneric_sans_serif; - break; - case eFamily_monospace: - generic = kGeneric_monospace; - break; - case eFamily_cursive: - generic = kGeneric_cursive; - break; - case eFamily_fantasy: - generic = kGeneric_fantasy; - break; + case StyleGenericFontFamily::Serif: + return kGeneric_serif; + case StyleGenericFontFamily::SansSerif: + return kGeneric_sans_serif; + case StyleGenericFontFamily::Monospace: + return kGeneric_monospace; + case StyleGenericFontFamily::Cursive: + return kGeneric_cursive; + case StyleGenericFontFamily::Fantasy: + return kGeneric_fantasy; default: - break; + MOZ_ASSERT_UNREACHABLE("Unknown generic"); + return nullptr; } - - return generic; } void gfxPlatformFontList::InitLoader() { GetFontFamilyNames(mFontInfo->mFontFamiliesToLoad); mStartIndex = 0; mNumFamilies = mFontInfo->mFontFamiliesToLoad.Length(); memset(&(mFontInfo->mLoadStats), 0, sizeof(mFontInfo->mLoadStats)); } @@ -1499,19 +1485,18 @@ void gfxPlatformFontList::RebuildLocalFo it.Get()->GetKey()->RebuildLocalRules(); } } void gfxPlatformFontList::ClearLangGroupPrefFonts() { for (uint32_t i = eFontPrefLang_First; i < eFontPrefLang_First + eFontPrefLang_Count; i++) { auto& prefFontsLangGroup = mLangGroupPrefFonts[i]; - for (uint32_t j = eFamily_generic_first; - j < eFamily_generic_first + eFamily_generic_count; j++) { - prefFontsLangGroup[j] = nullptr; + for (auto& pref : prefFontsLangGroup) { + pref = nullptr; } } mCJKPrefLangs.Clear(); mEmojiPrefFont = nullptr; } // Support for memory reporting @@ -1559,19 +1544,17 @@ void gfxPlatformFontList::AddSizeOfExclu mExtraNames->mFullnames, aMallocSizeOf); aSizes->mFontListSize += SizeOfFontEntryTableExcludingThis( mExtraNames->mPostscriptNames, aMallocSizeOf); } for (uint32_t i = eFontPrefLang_First; i < eFontPrefLang_First + eFontPrefLang_Count; i++) { auto& prefFontsLangGroup = mLangGroupPrefFonts[i]; - for (uint32_t j = eFamily_generic_first; - j < eFamily_generic_first + eFamily_generic_count; j++) { - PrefFontList* pf = prefFontsLangGroup[j].get(); + for (const UniquePtr<PrefFontList>& pf : prefFontsLangGroup) { if (pf) { aSizes->mFontListSize += pf->ShallowSizeOfExcludingThis(aMallocSizeOf); } } } aSizes->mFontListSize += mCodepointsWithNoFonts.SizeOfExcludingThis(aMallocSizeOf);
--- a/gfx/thebes/gfxPlatformFontList.h +++ b/gfx/thebes/gfxPlatformFontList.h @@ -253,22 +253,22 @@ class gfxPlatformFontList : public gfxFo static const gfxFontEntry::ScriptRange sComplexScriptRanges[]; void GetFontlistInitInfo(uint32_t& aNumInits, uint32_t& aLoaderState) { aNumInits = mFontlistInitCount; aLoaderState = (uint32_t)mState; } - virtual void AddGenericFonts(mozilla::FontFamilyType aGenericType, + virtual void AddGenericFonts(mozilla::StyleGenericFontFamily aGenericType, nsAtom* aLanguage, nsTArray<FamilyAndGeneric>& aFamilyList); - PrefFontList* GetPrefFontsLangGroup(mozilla::FontFamilyType aGenericType, - eFontPrefLang aPrefLang); + PrefFontList* GetPrefFontsLangGroup( + mozilla::StyleGenericFontFamily aGenericType, eFontPrefLang aPrefLang); // in some situations, need to make decisions about ambiguous characters, may // need to look at multiple pref langs void GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t& aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang); // convert a lang group to enum constant (i.e. "zh-TW" ==> // eFontPrefLang_ChineseTW) @@ -290,27 +290,28 @@ class gfxPlatformFontList : public gfxFo // returns true if a pref lang is CJK static bool IsLangCJK(eFontPrefLang aLang); // helper method to add a pref lang to an array, if not already in array static void AppendPrefLang(eFontPrefLang aPrefLangs[], uint32_t& aLen, eFontPrefLang aAddLang); // default serif/sans-serif choice based on font.default.xxx prefs - mozilla::FontFamilyType GetDefaultGeneric(eFontPrefLang aLang); + mozilla::StyleGenericFontFamily GetDefaultGeneric(eFontPrefLang aLang); // Returns true if the font family whitelist is not empty. bool IsFontFamilyWhitelistActive(); static void FontWhitelistPrefChanged(const char* aPref, void* aClosure); bool AddWithLegacyFamilyName(const nsACString& aLegacyName, gfxFontEntry* aFontEntry); - static const char* GetGenericName(mozilla::FontFamilyType aGenericType); + static const char* GetGenericName( + mozilla::StyleGenericFontFamily aGenericType); protected: class InitOtherFamilyNamesRunnable : public mozilla::CancelableRunnable { public: InitOtherFamilyNamesRunnable() : CancelableRunnable( "gfxPlatformFontList::InitOtherFamilyNamesRunnable"), mIsCanceled(false) {} @@ -481,17 +482,17 @@ class gfxPlatformFontList : public gfxFo // read the loader initialization prefs, and start it void GetPrefsAndStartLoader(); // for font list changes that affect all documents void ForceGlobalReflow() { gfxPlatform::ForceGlobalReflow(); } void RebuildLocalFonts(); - void ResolveGenericFontNames(mozilla::FontFamilyType aGenericType, + void ResolveGenericFontNames(mozilla::StyleGenericFontFamily aGenericType, eFontPrefLang aPrefLang, PrefFontList* aGenericFamilies); void ResolveEmojiFontNames(PrefFontList* aGenericFamilies); void GetFontFamiliesFromGenericFamilies(nsTArray<nsCString>& aGenericFamilies, nsAtom* aLangGroup, PrefFontList* aFontFamilies); @@ -547,18 +548,19 @@ class gfxPlatformFontList : public gfxFo // face names missed when face name loading takes a long time mozilla::UniquePtr<nsTHashtable<nsCStringHashKey>> mFaceNamesMissed; // localized family names missed when face name loading takes a long time mozilla::UniquePtr<nsTHashtable<nsCStringHashKey>> mOtherNamesMissed; typedef mozilla::RangedArray<mozilla::UniquePtr<PrefFontList>, - mozilla::eFamily_generic_first, - mozilla::eFamily_generic_count> + size_t(mozilla::StyleGenericFontFamily::None), + size_t( + mozilla::StyleGenericFontFamily::MozEmoji)> PrefFontsForLangGroup; mozilla::RangedArray<PrefFontsForLangGroup, eFontPrefLang_First, eFontPrefLang_Count> mLangGroupPrefFonts; mozilla::UniquePtr<PrefFontList> mEmojiPrefFont; // when system-wide font lookup fails for a character, cache it to skip future // searches @@ -584,16 +586,16 @@ class gfxPlatformFontList : public gfxFo // see bugs 636957, 1070983, 1189129 uint32_t mFontlistInitCount; // num times InitFontList called nsTHashtable<nsPtrHashKey<gfxUserFontSet>> mUserFontSetList; nsLanguageAtomService* mLangService; nsTArray<uint32_t> mCJKPrefLangs; - nsTArray<mozilla::FontFamilyType> mDefaultGenericsLangGroup; + nsTArray<mozilla::StyleGenericFontFamily> mDefaultGenericsLangGroup; bool mFontFamilyWhitelistActive; }; MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxPlatformFontList::FindFamiliesFlags) #endif /* GFXPLATFORMFONTLIST_H_ */
--- a/gfx/thebes/gfxTextRun.cpp +++ b/gfx/thebes/gfxTextRun.cpp @@ -1530,17 +1530,17 @@ void gfxTextRun::SetSpaceGlyph(gfxFont* bool vertical = !!(GetFlags() & gfx::ShapedTextFlags::TEXT_ORIENT_VERTICAL_UPRIGHT); gfxFontShaper::RoundingFlags roundingFlags = aFont->GetRoundOffsetsToPixels(aDrawTarget); gfxShapedWord* sw = aFont->GetShapedWord( aDrawTarget, &space, 1, gfxShapedWord::HashMix(0, ' '), Script::LATIN, vertical, mAppUnitsPerDevUnit, flags, roundingFlags, nullptr); if (sw) { - AddGlyphRun(aFont, FontMatchType::kFontGroup, aCharIndex, false, + AddGlyphRun(aFont, FontMatchType::Kind::kFontGroup, aCharIndex, false, aOrientation); CopyGlyphDataFrom(sw, aCharIndex); GetCharacterGlyphs()[aCharIndex].SetIsSpace(); } } bool gfxTextRun::SetSpaceGlyphIfSimple(gfxFont* aFont, uint32_t aCharIndex, char16_t aSpaceChar, @@ -1555,17 +1555,17 @@ bool gfxTextRun::SetSpaceGlyphIfSimple(g ? nsFontMetrics::eVertical : nsFontMetrics::eHorizontal; uint32_t spaceWidthAppUnits = NS_lroundf( aFont->GetMetrics(fontOrientation).spaceWidth * mAppUnitsPerDevUnit); if (!CompressedGlyph::IsSimpleAdvance(spaceWidthAppUnits)) { return false; } - AddGlyphRun(aFont, FontMatchType::kFontGroup, aCharIndex, false, + AddGlyphRun(aFont, FontMatchType::Kind::kFontGroup, aCharIndex, false, aOrientation); CompressedGlyph g = CompressedGlyph::MakeSimpleGlyph(spaceWidthAppUnits, spaceGlyph); if (aSpaceChar == ' ') { g.SetIsSpace(); } GetCharacterGlyphs()[aCharIndex] = g; return true; @@ -1710,25 +1710,25 @@ void gfxFontGroup::BuildFontList() { for (const FontFamilyName& name : mFamilyList.GetFontlist()->mNames) { if (name.IsNamed()) { if (name.mName) { AddPlatformFont(nsAtomCString(name.mName), fonts); } else { MOZ_ASSERT_UNREACHABLE("broken FontFamilyName, no atom!"); } } else { - pfl->AddGenericFonts(name.mType, mStyle.language, fonts); + pfl->AddGenericFonts(name.mGeneric, mStyle.language, fonts); if (mTextPerf) { mTextPerf->current.genericLookups++; } } } // if necessary, append default generic onto the end - if (mFamilyList.GetDefaultFontType() != eFamily_none && + if (mFamilyList.GetDefaultFontType() != StyleGenericFontFamily::None && !mFamilyList.HasDefaultGeneric()) { pfl->AddGenericFonts(mFamilyList.GetDefaultFontType(), mStyle.language, fonts); if (mTextPerf) { mTextPerf->current.genericLookups++; } } @@ -1756,17 +1756,17 @@ void gfxFontGroup::AddPlatformFont(const // Not known in the user font set ==> check system fonts gfxPlatformFontList::PlatformFontList()->FindAndAddFamilies( aName, &aFamilyList, gfxPlatformFontList::FindFamiliesFlags(0), &mStyle, mDevToCssSize); } void gfxFontGroup::AddFamilyToFontList(gfxFontFamily* aFamily, - FontFamilyType aGeneric) { + StyleGenericFontFamily aGeneric) { if (!aFamily) { MOZ_ASSERT_UNREACHABLE("don't try to add a null font family!"); return; } AutoTArray<gfxFontEntry*, 4> fontEntryList; aFamily->FindAllFontsForStyle(mStyle, fontEntryList); // add these to the fontlist for (gfxFontEntry* fe : fontEntryList) { @@ -1958,17 +1958,17 @@ gfxFont* gfxFontGroup::GetDefaultFont() familiesString.get()); MOZ_CRASH_UNSAFE(msg); } return mDefaultFont.get(); } gfxFont* gfxFontGroup::GetFirstValidFont(uint32_t aCh, - FontFamilyType* aGeneric) { + StyleGenericFontFamily* aGeneric) { uint32_t count = mFonts.Length(); for (uint32_t i = 0; i < count; ++i) { FamilyFace& ff = mFonts[i]; if (ff.IsInvalid()) { continue; } // already have a font? @@ -2001,17 +2001,17 @@ gfxFont* gfxFontGroup::GetFirstValidFont if (font) { if (aGeneric) { *aGeneric = mFonts[i].Generic(); } return font; } } if (aGeneric) { - *aGeneric = eFamily_none; + *aGeneric = StyleGenericFontFamily::None; } return GetDefaultFont(); } gfxFont* gfxFontGroup::GetFirstMathFont() { uint32_t count = mFonts.Length(); for (uint32_t i = 0; i < count; ++i) { gfxFont* font = GetFontAt(i); @@ -2073,17 +2073,17 @@ already_AddRefed<gfxTextRun> gfxFontGrou } gfxFont* font = GetFirstValidFont(); if (MOZ_UNLIKELY(GetStyle()->size == 0) || MOZ_UNLIKELY(GetStyle()->sizeAdjust == 0.0f)) { // Short-circuit for size-0 fonts, as Windows and ATSUI can't handle // them, and always create at least size 1 fonts, i.e. they still // render something for size 0 fonts. - textRun->AddGlyphRun(font, FontMatchType::kFontGroup, 0, false, + textRun->AddGlyphRun(font, FontMatchType::Kind::kFontGroup, 0, false, orientation); } else { if (font->GetSpaceGlyph()) { // Normally, the font has a cached space glyph, so we can avoid // the cost of calling FindFontForChar. textRun->SetSpaceGlyph(font, aParams->mDrawTarget, 0, orientation); } else { // In case the primary font doesn't have <space> (bug 970891), @@ -2111,18 +2111,18 @@ already_AddRefed<gfxTextRun> gfxFontGrou if (!textRun) { return nullptr; } gfx::ShapedTextFlags orientation = aFlags & ShapedTextFlags::TEXT_ORIENT_MASK; if (orientation == ShapedTextFlags::TEXT_ORIENT_VERTICAL_MIXED) { orientation = ShapedTextFlags::TEXT_ORIENT_VERTICAL_UPRIGHT; } - textRun->AddGlyphRun(GetFirstValidFont(), FontMatchType::kFontGroup, 0, false, - orientation); + textRun->AddGlyphRun(GetFirstValidFont(), FontMatchType::Kind::kFontGroup, 0, + false, orientation); return textRun.forget(); } already_AddRefed<gfxTextRun> gfxFontGroup::MakeHyphenTextRun( DrawTarget* aDrawTarget, uint32_t aAppUnitsPerDevUnit) { // only use U+2010 if it is supported by the first font in the group; // it's better to use ASCII '-' from the primary font than to fall back to // U+2010 from some other, possibly poorly-matching face @@ -2269,19 +2269,20 @@ void gfxFontGroup::InitTextRun(DrawTarge nsAutoString styleString; nsStyleUtil::AppendFontSlantStyle(mStyle.style, styleString); MOZ_LOG( log, LogLevel::Warning, ("(%s) fontgroup: [%s] default: %s lang: %s script: %d " "len %d weight: %g stretch: %g%% style: %s size: %6.2f %zu-byte " "TEXTRUN [%s] ENDTEXTRUN\n", (mStyle.systemFont ? "textrunui" : "textrun"), families.get(), - (mFamilyList.GetDefaultFontType() == eFamily_serif + (mFamilyList.GetDefaultFontType() == StyleGenericFontFamily::Serif ? "serif" - : (mFamilyList.GetDefaultFontType() == eFamily_sans_serif + : (mFamilyList.GetDefaultFontType() == + StyleGenericFontFamily::SansSerif ? "sans-serif" : "none")), lang.get(), static_cast<int>(Script::LATIN), aLength, mStyle.weight.ToFloat(), mStyle.stretch.Percentage(), NS_ConvertUTF16toUTF8(styleString).get(), mStyle.size, sizeof(T), str.get())); } @@ -2315,19 +2316,21 @@ void gfxFontGroup::InitTextRun(DrawTarge nsStyleUtil::AppendFontSlantStyle(mStyle.style, styleString); uint32_t runLen = runLimit - runStart; MOZ_LOG( log, LogLevel::Warning, ("(%s) fontgroup: [%s] default: %s lang: %s script: %d " "len %d weight: %g stretch: %g%% style: %s size: %6.2f " "%zu-byte TEXTRUN [%s] ENDTEXTRUN\n", (mStyle.systemFont ? "textrunui" : "textrun"), families.get(), - (mFamilyList.GetDefaultFontType() == eFamily_serif + (mFamilyList.GetDefaultFontType() == + StyleGenericFontFamily::Serif ? "serif" - : (mFamilyList.GetDefaultFontType() == eFamily_sans_serif + : (mFamilyList.GetDefaultFontType() == + StyleGenericFontFamily::SansSerif ? "sans-serif" : "none")), lang.get(), static_cast<int>(runScript), runLen, mStyle.weight.ToFloat(), mStyle.stretch.Percentage(), NS_ConvertUTF16toUTF8(styleString).get(), mStyle.size, sizeof(T), NS_ConvertUTF16toUTF8(textPtr + runStart, runLen).get())); } @@ -2495,17 +2498,17 @@ void gfxFontGroup::InitScriptRun(DrawTar if (!matchedFont->SplitAndInitTextRun( aDrawTarget, aTextRun, aString + runStart, aOffset + runStart, matchedLength, aRunScript, range.orientation)) { // glyph layout failed! treat as missing glyphs matchedFont = nullptr; } } } else { - aTextRun->AddGlyphRun(mainFont, FontMatchType::kFontGroup, + aTextRun->AddGlyphRun(mainFont, FontMatchType::Kind::kFontGroup, aOffset + runStart, (matchedLength > 0), range.orientation); } if (!matchedFont) { // We need to set cluster boundaries (and mark spaces) so that // surrogate pairs, combining characters, etc behave properly, // even if we don't have glyphs for them @@ -2702,34 +2705,32 @@ gfxFont* gfxFontGroup::FindFontForChar(u bool isJoinControl = gfxFontUtils::IsJoinControl(aCh); bool wasJoinCauser = gfxFontUtils::IsJoinCauser(aPrevCh); bool isVarSelector = gfxFontUtils::IsVarSelector(aCh); if (!isJoinControl && !wasJoinCauser && !isVarSelector) { gfxFont* firstFont = GetFontAt(0, aCh); if (firstFont) { if (firstFont->HasCharacter(aCh)) { - *aMatchType = - FontMatchType::kFontGroup | FontMatchType(mFonts[0].Generic()); + *aMatchType = {FontMatchType::Kind::kFontGroup, mFonts[0].Generic()}; return firstFont; } gfxFont* font = nullptr; if (mFonts[0].CheckForFallbackFaces()) { font = FindFallbackFaceForChar(mFonts[0].Family(), aCh); } else if (!firstFont->GetFontEntry()->IsUserFont()) { // For platform fonts (but not userfonts), we may need to do // fallback within the family to handle cases where some faces // such as Italic or Black have reduced character sets compared // to the family's Regular face. font = FindFallbackFaceForChar(mFonts[0].Family(), aCh); } if (font) { - *aMatchType = - FontMatchType::kFontGroup | FontMatchType(mFonts[0].Generic()); + *aMatchType = {FontMatchType::Kind::kFontGroup, mFonts[0].Generic()}; return font; } } // we don't need to check the first font again below ++nextIndex; } @@ -2769,17 +2770,17 @@ gfxFont* gfxFontGroup::FindFontForChar(u if (ff.IsInvalid() || ff.IsLoading()) { continue; } // if available, use already made gfxFont and check for character gfxFont* font = ff.Font(); if (font) { if (font->HasCharacter(aCh)) { - *aMatchType = FontMatchType::kFontGroup | FontMatchType(ff.Generic()); + *aMatchType = {FontMatchType::Kind::kFontGroup, ff.Generic()}; return font; } continue; } // don't have a gfxFont yet, test before building gfxFontEntry* fe = ff.FontEntry(); if (fe->mIsUserFontContainer) { @@ -2798,96 +2799,94 @@ gfxFont* gfxFontGroup::FindFontForChar(u !mSkipDrawing && !FontLoadingForFamily(ff.Family(), aCh)) { ufe->Load(); ff.CheckState(mSkipDrawing); } gfxFontEntry* pfe = ufe->GetPlatformFontEntry(); if (pfe && pfe->HasCharacter(aCh)) { font = GetFontAt(i, aCh); if (font) { - *aMatchType = - FontMatchType::kFontGroup | FontMatchType(mFonts[i].Generic()); + *aMatchType = {FontMatchType::Kind::kFontGroup, mFonts[i].Generic()}; return font; } } } else if (fe->HasCharacter(aCh)) { // for normal platform fonts, after checking the cmap // build the font via GetFontAt font = GetFontAt(i, aCh); if (font) { - *aMatchType = - FontMatchType::kFontGroup | FontMatchType(mFonts[i].Generic()); + *aMatchType = {FontMatchType::Kind::kFontGroup, mFonts[i].Generic()}; return font; } } // check other family faces if needed if (ff.CheckForFallbackFaces()) { NS_ASSERTION(i == 0 ? true : !mFonts[i - 1].CheckForFallbackFaces() || !mFonts[i - 1].Family()->Name().Equals( ff.Family()->Name()), "should only do fallback once per font family"); font = FindFallbackFaceForChar(ff.Family(), aCh); if (font) { - *aMatchType = FontMatchType::kFontGroup | FontMatchType(ff.Generic()); + *aMatchType = {FontMatchType::Kind::kFontGroup, ff.Generic()}; return font; } } else { // For platform fonts, but not user fonts, consider intra-family // fallback to handle styles with reduced character sets (see // also above). fe = ff.FontEntry(); if (!fe->mIsUserFontContainer && !fe->IsUserFont()) { font = FindFallbackFaceForChar(ff.Family(), aCh); if (font) { - *aMatchType = FontMatchType::kFontGroup | FontMatchType(ff.Generic()); + *aMatchType = {FontMatchType::Kind::kFontGroup, ff.Generic()}; return font; } } } } if (fontListLength == 0) { gfxFont* defaultFont = GetDefaultFont(); if (defaultFont->HasCharacter(aCh)) { - *aMatchType = FontMatchType::kFontGroup; + *aMatchType = FontMatchType::Kind::kFontGroup; return defaultFont; } } // if character is in Private Use Area, don't do matching against pref or // system fonts if ((aCh >= 0xE000 && aCh <= 0xF8FF) || (aCh >= 0xF0000 && aCh <= 0x10FFFD)) return nullptr; // 2. search pref fonts gfxFont* font = WhichPrefFontSupportsChar(aCh, aNextCh); if (font) { - *aMatchType = FontMatchType::kPrefsFallback; + *aMatchType = FontMatchType::Kind::kPrefsFallback; return font; } // 3. use fallback fonts // -- before searching for something else check the font used for the // previous character if (aPrevMatchedFont && aPrevMatchedFont->HasCharacter(aCh)) { - *aMatchType = FontMatchType::kSystemFallback; + *aMatchType = FontMatchType::Kind::kSystemFallback; return aPrevMatchedFont; } // for known "space" characters, don't do a full system-fallback search; // we'll synthesize appropriate-width spaces instead of missing-glyph boxes if (GetGeneralCategory(aCh) == HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR && GetFirstValidFont()->SynthesizeSpaceWidth(aCh) >= 0.0) { return nullptr; } // -- otherwise look for other stuff - *aMatchType = FontMatchType::kSystemFallback; + *aMatchType = FontMatchType::Kind::kSystemFallback; return WhichSystemFontSupportsChar(aCh, aNextCh, aRunScript); } template <typename T> void gfxFontGroup::ComputeRanges(nsTArray<TextRange>& aRanges, const T* aString, uint32_t aLength, Script aRunScript, gfx::ShapedTextFlags aOrientation) { NS_ASSERTION(aRanges.Length() == 0, "aRanges must be initially empty"); @@ -2901,22 +2900,22 @@ void gfxFontGroup::ComputeRanges(nsTArra nextCh = SURROGATE_TO_UCS4(nextCh, aString[1]); } } int32_t lastRangeIndex = -1; // initialize prevFont to the group's primary font, so that this will be // used for string-initial control chars, etc rather than risk hitting font // fallback for these (bug 716229) - FontFamilyType generic = eFamily_none; + StyleGenericFontFamily generic = StyleGenericFontFamily::None; gfxFont* prevFont = GetFirstValidFont(' ', &generic); // if we use the initial value of prevFont, we treat this as a match from // the font group; fixes bug 978313 - FontMatchType matchType = FontMatchType::kFontGroup | FontMatchType(generic); + FontMatchType matchType = {FontMatchType::Kind::kFontGroup, generic}; for (uint32_t i = 0; i < aLength; i++) { const uint32_t origI = i; // save off in case we increase for surrogate // set up current ch uint32_t ch = nextCh; // Get next char (if any) so that FindFontForChar can look ahead @@ -2953,28 +2952,27 @@ void gfxFontGroup::ComputeRanges(nsTArra // the special cases where FindFontForChar will attempt to propagate // the font selected for an adjacent character. if ((font = GetFontAt(0, ch)) != nullptr && font->HasCharacter(ch) && (sizeof(T) == sizeof(uint8_t) || (!IsClusterExtender(ch) && ch != NARROW_NO_BREAK_SPACE && !gfxFontUtils::IsJoinControl(ch) && !gfxFontUtils::IsJoinCauser(prevCh) && !gfxFontUtils::IsVarSelector(ch)))) { - matchType = - FontMatchType::kFontGroup | FontMatchType(mFonts[0].Generic()); + matchType = {FontMatchType::Kind::kFontGroup, mFonts[0].Generic()}; } else { font = FindFontForChar(ch, prevCh, nextCh, aRunScript, prevFont, &matchType); } #ifndef RELEASE_OR_BETA if (MOZ_UNLIKELY(mTextPerf)) { - if (matchType & FontMatchType::kPrefsFallback) { + if (matchType.kind == FontMatchType::Kind::kPrefsFallback) { mTextPerf->current.fallbackPrefs++; - } else if (matchType & FontMatchType::kSystemFallback) { + } else if (matchType.kind == FontMatchType::Kind::kSystemFallback) { mTextPerf->current.fallbackSystem++; } } #endif prevCh = ch; ShapedTextFlags orient = aOrientation; @@ -3046,43 +3044,44 @@ void gfxFontGroup::ComputeRanges(nsTArra nsAutoCString families; mFamilyList.ToString(families); // collect the font matched for each range nsAutoCString fontMatches; for (size_t i = 0, i_end = aRanges.Length(); i < i_end; i++) { const TextRange& r = aRanges[i]; nsAutoCString matchTypes; - if (r.matchType & FontMatchType::kFontGroup) { + if (r.matchType.kind & FontMatchType::Kind::kFontGroup) { matchTypes.AppendLiteral("list"); } - if (r.matchType & FontMatchType::kPrefsFallback) { + if (r.matchType.kind & FontMatchType::Kind::kPrefsFallback) { if (!matchTypes.IsEmpty()) { matchTypes.AppendLiteral(","); } matchTypes.AppendLiteral("prefs"); } - if (r.matchType & FontMatchType::kPrefsFallback) { + if (r.matchType.kind & FontMatchType::Kind::kPrefsFallback) { if (!matchTypes.IsEmpty()) { matchTypes.AppendLiteral(","); } matchTypes.AppendLiteral("sys"); } fontMatches.AppendPrintf( " [%u:%u] %.200s (%s)", r.start, r.end, (r.font.get() ? r.font->GetName().get() : "<null>"), matchTypes.get()); } MOZ_LOG(log, LogLevel::Debug, ("(%s-fontmatching) fontgroup: [%s] default: %s lang: %s script: %d" "%s\n", (mStyle.systemFont ? "textrunui" : "textrun"), families.get(), - (mFamilyList.GetDefaultFontType() == eFamily_serif + (mFamilyList.GetDefaultFontType() == StyleGenericFontFamily::Serif ? "serif" - : (mFamilyList.GetDefaultFontType() == eFamily_sans_serif + : (mFamilyList.GetDefaultFontType() == + StyleGenericFontFamily::SansSerif ? "sans-serif" : "none")), lang.get(), static_cast<int>(aRunScript), fontMatches.get())); } #endif } gfxUserFontSet* gfxFontGroup::GetUserFontSet() { return mUserFontSet; } @@ -3170,18 +3169,17 @@ gfxFont* gfxFontGroup::WhichPrefFontSupp // based on char lang and page lang, set up list of pref lang fonts to check eFontPrefLang prefLangs[kMaxLenPrefLangList]; uint32_t i, numLangs = 0; pfl->GetLangPrefs(prefLangs, numLangs, charLang, mPageLang); for (i = 0; i < numLangs; i++) { eFontPrefLang currentLang = prefLangs[i]; - mozilla::FontFamilyType defaultGeneric = - pfl->GetDefaultGeneric(currentLang); + StyleGenericFontFamily defaultGeneric = pfl->GetDefaultGeneric(currentLang); gfxPlatformFontList::PrefFontList* families = pfl->GetPrefFontsLangGroup(defaultGeneric, currentLang); NS_ASSERTION(families, "no pref font families found"); // find the first pref font that includes the character uint32_t j, numPrefs; numPrefs = families->Length(); for (j = 0; j < numPrefs; j++) {
--- a/gfx/thebes/gfxTextRun.h +++ b/gfx/thebes/gfxTextRun.h @@ -846,18 +846,18 @@ class gfxFontGroup final : public gfxTex gfxUserFontSet* aUserFontSet, gfxFloat aDevToCssSize); virtual ~gfxFontGroup(); // Returns first valid font in the fontlist or default font. // Initiates userfont loads if userfont not loaded. // aGeneric: if non-null, returns the CSS generic type that was mapped to // this font - gfxFont* GetFirstValidFont(uint32_t aCh = 0x20, - mozilla::FontFamilyType* aGeneric = nullptr); + gfxFont* GetFirstValidFont( + uint32_t aCh = 0x20, mozilla::StyleGenericFontFamily* aGeneric = nullptr); // Returns the first font in the font-group that has an OpenType MATH table, // or null if no such font is available. The GetMathConstant methods may be // called on the returned font. gfxFont* GetFirstMathFont(); const gfxFontStyle* GetStyle() const { return &mStyle; } @@ -1019,39 +1019,39 @@ class gfxFontGroup final : public gfxTex uint32_t aLength, Script aRunScript, mozilla::gfx::ShapedTextFlags aOrientation); class FamilyFace { public: FamilyFace() : mFamily(nullptr), mFontEntry(nullptr), - mGeneric(mozilla::eFamily_none), + mGeneric(mozilla::StyleGenericFontFamily::None), mFontCreated(false), mLoading(false), mInvalid(false), mCheckForFallbackFaces(false) {} FamilyFace(gfxFontFamily* aFamily, gfxFont* aFont, - mozilla::FontFamilyType aGeneric) + mozilla::StyleGenericFontFamily aGeneric) : mFamily(aFamily), mGeneric(aGeneric), mFontCreated(true), mLoading(false), mInvalid(false), mCheckForFallbackFaces(false) { NS_ASSERTION(aFont, "font pointer must not be null"); NS_ASSERTION(!aFamily || aFamily->ContainsFace(aFont->GetFontEntry()), "font is not a member of the given family"); mFont = aFont; NS_ADDREF(aFont); } FamilyFace(gfxFontFamily* aFamily, gfxFontEntry* aFontEntry, - mozilla::FontFamilyType aGeneric) + mozilla::StyleGenericFontFamily aGeneric) : mFamily(aFamily), mGeneric(aGeneric), mFontCreated(false), mLoading(false), mInvalid(false), mCheckForFallbackFaces(false) { NS_ASSERTION(aFontEntry, "font entry pointer must not be null"); NS_ASSERTION(!aFamily || aFamily->ContainsFace(aFontEntry), @@ -1110,17 +1110,17 @@ class gfxFontGroup final : public gfxTex gfxFontFamily* Family() const { return mFamily.get(); } gfxFont* Font() const { return mFontCreated ? mFont : nullptr; } gfxFontEntry* FontEntry() const { return mFontCreated ? mFont->GetFontEntry() : mFontEntry; } - mozilla::FontFamilyType Generic() const { return mGeneric; } + mozilla::StyleGenericFontFamily Generic() const { return mGeneric; } bool IsUserFontContainer() const { return FontEntry()->mIsUserFontContainer; } bool IsLoading() const { return mLoading; } bool IsInvalid() const { return mInvalid; } void CheckState(bool& aSkipDrawing); void SetLoading(bool aIsLoading) { mLoading = aIsLoading; } @@ -1147,17 +1147,17 @@ class gfxFontGroup final : public gfxTex RefPtr<gfxFontFamily> mFamily; // either a font or a font entry exists union { // Whichever of these fields is actually present will be a strong // reference, with refcounting handled manually. gfxFont* MOZ_OWNING_REF mFont; gfxFontEntry* MOZ_OWNING_REF mFontEntry; }; - mozilla::FontFamilyType mGeneric; + mozilla::StyleGenericFontFamily mGeneric; bool mFontCreated : 1; bool mLoading : 1; bool mInvalid : 1; bool mCheckForFallbackFaces : 1; }; // List of font families, either named or generic. // Generic names map to system pref fonts based on language. @@ -1256,17 +1256,17 @@ class gfxFontGroup final : public gfxTex // helper methods for looking up fonts // lookup and add a font with a given name (i.e. *not* a generic!) void AddPlatformFont(const nsACString& aName, nsTArray<FamilyAndGeneric>& aFamilyList); // do style selection and add entries to list void AddFamilyToFontList(gfxFontFamily* aFamily, - mozilla::FontFamilyType aGeneric); + mozilla::StyleGenericFontFamily aGeneric); }; // A "missing font recorder" is to be used during text-run creation to keep // a record of any scripts encountered for which font coverage was lacking; // when Flush() is called, it sends a notification that front-end code can use // to download fonts on demand (or whatever else it wants to do). #define GFX_MISSING_FONTS_NOTIFY_PREF "gfx.missing_fonts.notify"
--- a/gfx/thebes/gfxTypes.h +++ b/gfx/thebes/gfxTypes.h @@ -3,16 +3,17 @@ * 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 GFX_TYPES_H #define GFX_TYPES_H #include <stdint.h> #include "mozilla/TypedEnumBits.h" +#include "nsStyleConsts.h" typedef struct _cairo_surface cairo_surface_t; typedef struct _cairo_user_data_key cairo_user_data_key_t; typedef void (*thebes_destroy_func_t)(void *data); /** * Currently needs to be 'double' for Cairo compatibility. Could @@ -82,24 +83,47 @@ enum class gfxAlphaType { Premult, NonPremult, }; /** * Type used to record how a particular font is selected during the font- * matching process, so that this can be exposed to the Inspector. */ -enum class FontMatchType : uint16_t { - // The CSS generic that mapped to this font, if any. This field of - // the MatchType stores a FontFamilyType value as defined in the enum - // in gfxFontFamilyList.h. - kGenericMask = 0x00ff, +struct FontMatchType { + enum class Kind : uint8_t { + kFontGroup = 1, + kPrefsFallback = 1 << 1, + kSystemFallback = 1 << 2, + }; + + inline FontMatchType& operator|=(const FontMatchType& aOther); + + bool operator==(const FontMatchType& aOther) const { + return kind == aOther.kind && generic == aOther.generic; + } - // Flags for recording the kind of font-matching that was used. - // Note that multiple flags may be set on a single range. - kFontGroup = 0x0100, - kPrefsFallback = 0x0200, - kSystemFallback = 0x0400 + bool operator!=(const FontMatchType& aOther) const { + return !(*this == aOther); + } + + MOZ_IMPLICIT FontMatchType() = default; + MOZ_IMPLICIT FontMatchType(Kind aKind) : kind(aKind) {} + FontMatchType(Kind aKind, mozilla::StyleGenericFontFamily aGeneric) + : kind(aKind), generic(aGeneric) {} + + Kind kind = static_cast<Kind>(0); + mozilla::StyleGenericFontFamily generic = + mozilla::StyleGenericFontFamily::None; }; -MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(FontMatchType) +MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(FontMatchType::Kind) + +FontMatchType& FontMatchType::operator|=(const FontMatchType& aOther) { + kind |= aOther.kind; + // We only keep track of one generic. + if (generic != aOther.generic) { + generic = mozilla::StyleGenericFontFamily::None; + } + return *this; +} #endif /* GFX_TYPES_H */
--- a/gfx/webrender_bindings/RenderCompositor.cpp +++ b/gfx/webrender_bindings/RenderCompositor.cpp @@ -35,17 +35,22 @@ UniquePtr<RenderCompositor> RenderCompos #if defined(MOZ_WAYLAND) || defined(MOZ_WIDGET_ANDROID) UniquePtr<RenderCompositor> eglCompositor = RenderCompositorEGL::Create(aWidget); if (eglCompositor) { return eglCompositor; } #endif +#if defined(MOZ_WIDGET_ANDROID) + // RenderCompositorOGL is not used on android + return nullptr; +#else return RenderCompositorOGL::Create(std::move(aWidget)); +#endif } RenderCompositor::RenderCompositor(RefPtr<widget::CompositorWidget>&& aWidget) : mWidget(aWidget) {} RenderCompositor::~RenderCompositor() {} bool RenderCompositor::MakeCurrent() { return gl()->MakeCurrent(); }
--- a/gfx/webrender_bindings/RenderCompositorOGL.cpp +++ b/gfx/webrender_bindings/RenderCompositorOGL.cpp @@ -42,36 +42,18 @@ bool RenderCompositorOGL::BeginFrame() { } return true; } void RenderCompositorOGL::EndFrame() { mGL->SwapBuffers(); } void RenderCompositorOGL::WaitForGPU() {} -void RenderCompositorOGL::Pause() { -#ifdef MOZ_WIDGET_ANDROID - if (!mGL || mGL->IsDestroyed()) { - return; - } - // ReleaseSurface internally calls MakeCurrent. - mGL->ReleaseSurface(); -#endif -} +void RenderCompositorOGL::Pause() {} -bool RenderCompositorOGL::Resume() { -#ifdef MOZ_WIDGET_ANDROID - if (!mGL || mGL->IsDestroyed()) { - return false; - } - // RenewSurface internally calls MakeCurrent. - return mGL->RenewSurface(mWidget); -#else - return true; -#endif -} +bool RenderCompositorOGL::Resume() { return true; } LayoutDeviceIntSize RenderCompositorOGL::GetBufferSize() { return mWidget->GetClientSize(); } } // namespace wr } // namespace mozilla
new file mode 100644 --- /dev/null +++ b/gfx/webrender_bindings/RenderEGLImageTextureHost.cpp @@ -0,0 +1,109 @@ +/* -*- 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 "RenderEGLImageTextureHost.h" + +#include "mozilla/gfx/Logging.h" +#include "GLContext.h" +#include "GLLibraryEGL.h" + +namespace mozilla { +namespace wr { + +RenderEGLImageTextureHost::RenderEGLImageTextureHost(EGLImage aImage, + EGLSync aSync, + gfx::IntSize aSize) + : mImage(aImage), + mSync(aSync), + mSize(aSize), + mTextureTarget(LOCAL_GL_TEXTURE_2D), + mTextureHandle(0) { + MOZ_COUNT_CTOR_INHERITED(RenderEGLImageTextureHost, RenderTextureHostOGL); +} + +RenderEGLImageTextureHost::~RenderEGLImageTextureHost() { + MOZ_COUNT_DTOR_INHERITED(RenderEGLImageTextureHost, RenderTextureHostOGL); + DeleteTextureHandle(); +} + +GLuint RenderEGLImageTextureHost::GetGLHandle(uint8_t aChannelIndex) const { + return mTextureHandle; +} + +gfx::IntSize RenderEGLImageTextureHost::GetSize(uint8_t aChannelIndex) const { + return mSize; +} + +wr::WrExternalImage RenderEGLImageTextureHost::Lock( + uint8_t aChannelIndex, gl::GLContext* aGL, wr::ImageRendering aRendering) { + MOZ_ASSERT(aChannelIndex == 0); + + if (mGL.get() != aGL) { + if (mGL) { + // This should not happen. SharedSurface_EGLImage is created only in + // parent process. + MOZ_ASSERT_UNREACHABLE("Unexpected GL context"); + return InvalidToWrExternalImage(); + } + mGL = aGL; + } + + if (!mImage || !mGL || !mGL->MakeCurrent()) { + return InvalidToWrExternalImage(); + } + + EGLint status = LOCAL_EGL_CONDITION_SATISFIED; + if (mSync) { + auto* egl = gl::GLLibraryEGL::Get(); + MOZ_ASSERT(egl->IsExtensionSupported(gl::GLLibraryEGL::KHR_fence_sync)); + status = egl->fClientWaitSync(egl->Display(), mSync, 0, LOCAL_EGL_FOREVER); + // We do not need to delete sync here. It is deleted by + // SharedSurface_EGLImage. + mSync = 0; + } + + if (status != LOCAL_EGL_CONDITION_SATISFIED) { + MOZ_ASSERT( + status != 0, + "ClientWaitSync generated an error. Has mSync already been destroyed?"); + return InvalidToWrExternalImage(); + } + + if (!mTextureHandle) { + mTextureTarget = mGL->GetPreferredEGLImageTextureTarget(); + MOZ_ASSERT(mTextureTarget == LOCAL_GL_TEXTURE_2D || + mTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL); + + mGL->fGenTextures(1, &mTextureHandle); + // Cache rendering filter. + mCachedRendering = aRendering; + ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0, mTextureTarget, + mTextureHandle, aRendering); + mGL->fEGLImageTargetTexture2D(mTextureTarget, mImage); + } else if (IsFilterUpdateNecessary(aRendering)) { + // Cache new rendering filter. + mCachedRendering = aRendering; + ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0, mTextureTarget, + mTextureHandle, aRendering); + } + + return NativeTextureToWrExternalImage(mTextureHandle, 0, 0, mSize.width, + mSize.height); +} + +void RenderEGLImageTextureHost::Unlock() {} + +void RenderEGLImageTextureHost::DeleteTextureHandle() { + if (mTextureHandle) { + // XXX recycle gl texture, since SharedSurface_EGLImage and + // RenderEGLImageTextureHost is not recycled. + mGL->fDeleteTextures(1, &mTextureHandle); + mTextureHandle = 0; + } +} + +} // namespace wr +} // namespace mozilla
new file mode 100644 --- /dev/null +++ b/gfx/webrender_bindings/RenderEGLImageTextureHost.h @@ -0,0 +1,46 @@ +/* -*- 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/. */ + +#ifndef MOZILLA_GFX_RENDEREGLIMAGETEXTUREHOSTOGL_H +#define MOZILLA_GFX_RENDEREGLIMAGETEXTUREHOSTOGL_H + +#include "mozilla/layers/TextureHostOGL.h" +#include "RenderTextureHostOGL.h" + +namespace mozilla { + +namespace wr { + +// RenderEGLImageTextureHost is created only for SharedSurface_EGLImage that is +// created in parent process. +class RenderEGLImageTextureHost final : public RenderTextureHostOGL { + public: + RenderEGLImageTextureHost(EGLImage aImage, EGLSync aSync, gfx::IntSize aSize); + + wr::WrExternalImage Lock(uint8_t aChannelIndex, gl::GLContext* aGL, + wr::ImageRendering aRendering) override; + void Unlock() override; + + virtual gfx::IntSize GetSize(uint8_t aChannelIndex) const override; + virtual GLuint GetGLHandle(uint8_t aChannelIndex) const override; + + private: + virtual ~RenderEGLImageTextureHost(); + void DeleteTextureHandle(); + + const EGLImage mImage; + EGLSync mSync; + const gfx::IntSize mSize; + + RefPtr<gl::GLContext> mGL; + GLenum mTextureTarget; + GLuint mTextureHandle; +}; + +} // namespace wr +} // namespace mozilla + +#endif // MOZILLA_GFX_RENDEREGLIMAGETEXTUREHOSTOGL_H
--- a/gfx/webrender_bindings/moz.build +++ b/gfx/webrender_bindings/moz.build @@ -6,16 +6,17 @@ with Files('**'): BUG_COMPONENT = ('Core', 'Graphics: WebRender') EXPORTS.mozilla.webrender += [ 'RenderBufferTextureHost.h', 'RenderCompositor.h', 'RenderCompositorOGL.h', + 'RenderEGLImageTextureHost.h', 'RendererOGL.h', 'RendererScreenshotGrabber.h', 'RenderSharedSurfaceTextureHost.h', 'RenderTextureHost.h', 'RenderTextureHostOGL.h', 'RenderTextureHostWrapper.h', 'RenderThread.h', 'webrender_ffi.h', @@ -23,16 +24,17 @@ EXPORTS.mozilla.webrender += [ 'WebRenderTypes.h', ] UNIFIED_SOURCES += [ 'Moz2DImageRenderer.cpp', 'RenderBufferTextureHost.cpp', 'RenderCompositor.cpp', 'RenderCompositorOGL.cpp', + 'RenderEGLImageTextureHost.cpp', 'RendererOGL.cpp', 'RendererScreenshotGrabber.cpp', 'RenderSharedSurfaceTextureHost.cpp', 'RenderTextureHost.cpp', 'RenderTextureHostOGL.cpp', 'RenderTextureHostWrapper.cpp', 'RenderThread.cpp', 'WebRenderAPI.cpp',
--- a/image/test/mochitest/test_discardAnimatedImage.html +++ b/image/test/mochitest/test_discardAnimatedImage.html @@ -109,32 +109,34 @@ function step4() { function checkIfFinished() { if (gFinished) { return; } if ((gNumFrameUpdates[0] >= kNumFrameUpdatesToExpect) && (gNumFrameUpdates[1] >= kNumFrameUpdatesToExpect) && + (gNumFrameUpdates[2] >= kNumFrameUpdatesToExpect) && (gNumSnapShotChanges[0] >= kNumFrameUpdatesToExpect) && - (gNumSnapShotChanges[1] >= kNumFrameUpdatesToExpect)) { + (gNumSnapShotChanges[1] >= kNumFrameUpdatesToExpect) && + (gNumSnapShotChanges[2] >= kNumFrameUpdatesToExpect)) { ok(true, "got expected frame updates"); gFinished = true; SimpleTest.finish(); } } // arrayIndex is the index into the arrays gNumFrameUpdates and gNumDecodes // to increment when a frame update notification is received. function addCallbacks(anImage, arrayIndex) { var observer = new ImageDecoderObserverStub(); observer.discard = function () { gNumDiscards++; ok(true, "got image discard"); - if (arrayIndex >= 2) { + if (arrayIndex >= 3) { // The last two images are finite, so we don't expect any frame updates, // this image is done the test, so remove the observer. if (!gRemovedObserver[arrayIndex]) { gRemovedObserver[arrayIndex] = true; imgLoadingContent.removeObserver(scriptedObserver); } } if (gNumDiscards == gImgs.length) {
--- a/js/ipc/JavaScriptParent.cpp +++ b/js/ipc/JavaScriptParent.cpp @@ -93,17 +93,18 @@ bool JavaScriptParent::allowMessage(JSCo if (console) { nsAutoString filename; uint32_t lineno = 0, column = 0; nsJSUtils::GetCallingLocation(cx, filename, &lineno, &column); nsCOMPtr<nsIScriptError> error( do_CreateInstance(NS_SCRIPTERROR_CONTRACTID)); error->Init(NS_LITERAL_STRING("unsafe/forbidden CPOW usage"), filename, EmptyString(), lineno, column, nsIScriptError::warningFlag, - "chrome javascript", false /* from private window */); + "chrome javascript", false /* from private window */, + true /* from chrome context */); console->LogMessage(error); } else { NS_WARNING("Unsafe synchronous IPC message"); } } return true; }
--- a/js/ipc/WrapperAnswer.cpp +++ b/js/ipc/WrapperAnswer.cpp @@ -767,17 +767,17 @@ bool WrapperAnswer::RecvRegExpToShared(c return fail(jsapi, rs); } nsAutoJSString sourceStr; if (!sourceStr.init(cx, sourceJSStr)) { return fail(jsapi, rs); } source->Assign(sourceStr); - *flags = JS::GetRegExpFlags(cx, obj); + *flags = JS::GetRegExpFlags(cx, obj).value(); return ok(rs); } bool WrapperAnswer::RecvGetPropertyKeys(const ObjectId& objId, const uint32_t& flags, ReturnStatus* rs, nsTArray<JSIDVariant>* ids) { if (!IsInAutomation()) {
--- a/js/ipc/WrapperOwner.cpp +++ b/js/ipc/WrapperOwner.cpp @@ -7,16 +7,17 @@ #include "WrapperOwner.h" #include "JavaScriptLogging.h" #include "mozilla/Unused.h" #include "mozilla/dom/BindingUtils.h" #include "jsfriendapi.h" #include "js/CharacterEncoding.h" #include "js/RegExp.h" +#include "js/RegExpFlags.h" #include "xpcprivate.h" #include "WrapperFactory.h" #include "nsIDocShellTreeItem.h" #include "mozilla/dom/Document.h" using namespace js; using namespace JS; @@ -828,17 +829,18 @@ RegExpShared* WrapperOwner::regexp_toSha } LOG_STACK(); if (!ok(cx, status)) { return nullptr; } RootedObject regexp(cx); - regexp = JS::NewUCRegExpObject(cx, source.get(), source.Length(), flags); + regexp = JS::NewUCRegExpObject(cx, source.get(), source.Length(), + RegExpFlags(flags)); if (!regexp) { return nullptr; } return js::RegExpToSharedNonInline(cx, regexp); } void CPOWProxyHandler::finalize(JSFreeOp* fop, JSObject* proxy) const {
--- a/js/public/RegExp.h +++ b/js/public/RegExp.h @@ -8,64 +8,39 @@ #ifndef js_RegExp_h #define js_RegExp_h #include <stddef.h> // size_t #include "jstypes.h" // JS_PUBLIC_API +#include "js/RegExpFlags.h" // JS::RegExpFlags #include "js/RootingAPI.h" // JS::{,Mutable}Handle #include "js/Value.h" // JS::Value struct JSContext; class JSString; namespace JS { /** - * A namespace for all regular expression flags as they appear in the APIs below - * as flags values. - */ -struct RegExpFlags { - public: - /** - * Interpret regular expression source text case-insensitively by folding - * uppercase letters to lowercase, i.e. /i. - */ - static constexpr unsigned IgnoreCase = 0b0'0001; - - /** - * Act globally and find *all* matches (rather than stopping after just the - * first one), i.e. /g. - */ - static constexpr unsigned Global = 0b0'0010; - - /** Treat ^ and $ as begin and end of line, i.e. /m. */ - static constexpr unsigned Multiline = 0b0'0100; - - /** Only match starting from <regular expression>.lastIndex, i.e. /y. */ - static constexpr unsigned Sticky = 0b0'1000; - - /** Use Unicode semantics, i.e. /u. */ - static constexpr unsigned Unicode = 0b1'0000; -}; - -/** * Create a new RegExp for the given Latin-1-encoded bytes and flags. */ extern JS_PUBLIC_API JSObject* NewRegExpObject(JSContext* cx, const char* bytes, - size_t length, unsigned flags); + size_t length, + RegExpFlags flags); /** * Create a new RegExp for the given source and flags. */ extern JS_PUBLIC_API JSObject* NewUCRegExpObject(JSContext* cx, const char16_t* chars, - size_t length, unsigned flags); + size_t length, + RegExpFlags flags); extern JS_PUBLIC_API bool SetRegExpInput(JSContext* cx, Handle<JSObject*> obj, Handle<JSString*> input); extern JS_PUBLIC_API bool ClearRegExpStatics(JSContext* cx, Handle<JSObject*> obj); extern JS_PUBLIC_API bool ExecuteRegExp(JSContext* cx, Handle<JSObject*> obj, @@ -90,20 +65,20 @@ extern JS_PUBLIC_API bool ExecuteRegExpN * This method returns true with |*isRegExp == false| when passed an ES6 proxy * whose target is a RegExp, or when passed a revoked proxy. */ extern JS_PUBLIC_API bool ObjectIsRegExp(JSContext* cx, Handle<JSObject*> obj, bool* isRegExp); /** * Given a RegExp object (or a wrapper around one), return the set of all - * JS::RegExpFlags::* for it. + * JS::RegExpFlag::* for it. */ -extern JS_PUBLIC_API unsigned GetRegExpFlags(JSContext* cx, - Handle<JSObject*> obj); +extern JS_PUBLIC_API RegExpFlags GetRegExpFlags(JSContext* cx, + Handle<JSObject*> obj); /** * Return the source text for a RegExp object (or a wrapper around one), or null * on failure. */ extern JS_PUBLIC_API JSString* GetRegExpSource(JSContext* cx, Handle<JSObject*> obj);
copy from js/public/RegExp.h copy to js/public/RegExpFlags.h --- a/js/public/RegExp.h +++ b/js/public/RegExpFlags.h @@ -1,112 +1,124 @@ /* -*- 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/. */ -/* Regular expression-related operations. */ +/* Regular expression flags. */ -#ifndef js_RegExp_h -#define js_RegExp_h - -#include <stddef.h> // size_t +#ifndef js_RegExpFlags_h +#define js_RegExpFlags_h -#include "jstypes.h" // JS_PUBLIC_API +#include "mozilla/Assertions.h" // MOZ_ASSERT +#include "mozilla/Attributes.h" // MOZ_IMPLICIT -#include "js/RootingAPI.h" // JS::{,Mutable}Handle -#include "js/Value.h" // JS::Value - -struct JSContext; -class JSString; +#include <stdint.h> // uint8_t namespace JS { /** - * A namespace for all regular expression flags as they appear in the APIs below - * as flags values. + * Regular expression flag values, suitable for initializing a collection of + * regular expression flags as defined below in |RegExpFlags|. Flags are listed + * in alphabetical order by syntax -- /g, /i, /m, /u, /y. */ -struct RegExpFlags { +class RegExpFlag { + // WARNING TO SPIDERMONKEY HACKERS (embedders must assume these values can + // change): + // + // Flag-bit values appear in XDR and structured clone data formats, so none of + // these values can be changed (including to assign values in numerically + // ascending order) unless you also add a translation layer. + public: /** - * Interpret regular expression source text case-insensitively by folding - * uppercase letters to lowercase, i.e. /i. - */ - static constexpr unsigned IgnoreCase = 0b0'0001; - - /** * Act globally and find *all* matches (rather than stopping after just the * first one), i.e. /g. */ - static constexpr unsigned Global = 0b0'0010; + static constexpr uint8_t Global = 0b0'0010; + + /** + * Interpret regular expression source text case-insensitively by folding + * uppercase letters to lowercase, i.e. /i. + */ + static constexpr uint8_t IgnoreCase = 0b0'0001; /** Treat ^ and $ as begin and end of line, i.e. /m. */ - static constexpr unsigned Multiline = 0b0'0100; + static constexpr uint8_t Multiline = 0b0'0100; + + /** Use Unicode semantics, i.e. /u. */ + static constexpr uint8_t Unicode = 0b1'0000; /** Only match starting from <regular expression>.lastIndex, i.e. /y. */ - static constexpr unsigned Sticky = 0b0'1000; + static constexpr uint8_t Sticky = 0b0'1000; - /** Use Unicode semantics, i.e. /u. */ - static constexpr unsigned Unicode = 0b1'0000; + /** No regular expression flags. */ + static constexpr uint8_t NoFlags = 0b0'0000; + + /** All regular expression flags. */ + static constexpr uint8_t AllFlags = 0b1'1111; }; /** - * Create a new RegExp for the given Latin-1-encoded bytes and flags. + * A collection of regular expression flags. Individual flag values may be + * combined into a collection using bitwise operators. */ -extern JS_PUBLIC_API JSObject* NewRegExpObject(JSContext* cx, const char* bytes, - size_t length, unsigned flags); +class RegExpFlags { + public: + using Flag = uint8_t; -/** - * Create a new RegExp for the given source and flags. - */ -extern JS_PUBLIC_API JSObject* NewUCRegExpObject(JSContext* cx, - const char16_t* chars, - size_t length, unsigned flags); + private: + Flag flags_; + + public: + RegExpFlags() = default; -extern JS_PUBLIC_API bool SetRegExpInput(JSContext* cx, Handle<JSObject*> obj, - Handle<JSString*> input); + MOZ_IMPLICIT RegExpFlags(Flag flags) : flags_(flags) { + MOZ_ASSERT((flags & RegExpFlag::AllFlags) == flags, + "flags must not contain unrecognized flags"); + } -extern JS_PUBLIC_API bool ClearRegExpStatics(JSContext* cx, - Handle<JSObject*> obj); + RegExpFlags(const RegExpFlags&) = default; -extern JS_PUBLIC_API bool ExecuteRegExp(JSContext* cx, Handle<JSObject*> obj, - Handle<JSObject*> reobj, - char16_t* chars, size_t length, - size_t* indexp, bool test, - MutableHandle<Value> rval); + bool operator==(const RegExpFlags& other) const { + return flags_ == other.flags_; + } -/* RegExp interface for clients without a global object. */ + bool operator!=(const RegExpFlags& other) const { return !(*this == other); } + + RegExpFlags operator&(Flag flag) const { return RegExpFlags(flags_ & flag); } + + RegExpFlags operator|(Flag flag) const { return RegExpFlags(flags_ | flag); } -extern JS_PUBLIC_API bool ExecuteRegExpNoStatics(JSContext* cx, - Handle<JSObject*> reobj, - char16_t* chars, size_t length, - size_t* indexp, bool test, - MutableHandle<Value> rval); + RegExpFlags operator^(Flag flag) const { return RegExpFlags(flags_ ^ flag); } + + RegExpFlags operator~() const { return RegExpFlags(~flags_); } + + bool global() const { return flags_ & RegExpFlag::Global; } + bool ignoreCase() const { return flags_ & RegExpFlag::IgnoreCase; } + bool multiline() const { return flags_ & RegExpFlag::Multiline; } + bool unicode() const { return flags_ & RegExpFlag::Unicode; } + bool sticky() const { return flags_ & RegExpFlag::Sticky; } + + explicit operator bool() const { return flags_ != 0; } + + Flag value() const { return flags_; } +}; -/** - * On success, returns true, setting |*isRegExp| to true if |obj| is a RegExp - * object or a wrapper around one, or to false if not. Returns false on - * failure. - * - * This method returns true with |*isRegExp == false| when passed an ES6 proxy - * whose target is a RegExp, or when passed a revoked proxy. - */ -extern JS_PUBLIC_API bool ObjectIsRegExp(JSContext* cx, Handle<JSObject*> obj, - bool* isRegExp); +inline RegExpFlags& operator&=(RegExpFlags& flags, RegExpFlags::Flag flag) { + flags = flags & flag; + return flags; +} -/** - * Given a RegExp object (or a wrapper around one), return the set of all - * JS::RegExpFlags::* for it. - */ -extern JS_PUBLIC_API unsigned GetRegExpFlags(JSContext* cx, - Handle<JSObject*> obj); +inline RegExpFlags& operator|=(RegExpFlags& flags, RegExpFlags::Flag flag) { + flags = flags | flag; + return flags; +} -/** - * Return the source text for a RegExp object (or a wrapper around one), or null - * on failure. - */ -extern JS_PUBLIC_API JSString* GetRegExpSource(JSContext* cx, - Handle<JSObject*> obj); +inline RegExpFlags& operator^=(RegExpFlags& flags, RegExpFlags::Flag flag) { + flags = flags ^ flag; + return flags; +} } // namespace JS -#endif // js_RegExp_h +#endif // js_RegExpFlags_h
--- a/js/src/builtin/RegExp.cpp +++ b/js/src/builtin/RegExp.cpp @@ -1,40 +1,45 @@ /* -*- 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 "builtin/RegExp.h" +#include "mozilla/Casting.h" #include "mozilla/CheckedInt.h" #include "mozilla/TypeTraits.h" #include "frontend/TokenStream.h" #include "irregexp/RegExpParser.h" #include "jit/InlinableNatives.h" #include "js/PropertySpec.h" +#include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags #include "util/StringBuffer.h" #include "util/Unicode.h" #include "vm/JSContext.h" #include "vm/RegExpStatics.h" #include "vm/SelfHosting.h" #include "vm/EnvironmentObject-inl.h" #include "vm/JSObject-inl.h" #include "vm/NativeObject-inl.h" #include "vm/ObjectOperations-inl.h" using namespace js; +using mozilla::AssertedCast; using mozilla::CheckedInt; using mozilla::IsAsciiDigit; using JS::CompileOptions; +using JS::RegExpFlag; +using JS::RegExpFlags; /* * ES 2017 draft rev 6a13789aa9e7c6de4e96b7d3e24d9e6eba6584ad 21.2.5.2.2 * steps 3, 16-25. */ bool js::CreateRegExpMatchResult(JSContext* cx, HandleString input, const MatchPairs& matches, MutableHandleValue rval) { @@ -182,26 +187,26 @@ bool js::ExecuteRegExpLegacy(JSContext* rval.setBoolean(true); return true; } return CreateRegExpMatchResult(cx, input, matches, rval); } static bool CheckPatternSyntaxSlow(JSContext* cx, HandleAtom pattern, - RegExpFlag flags) { + RegExpFlags flags) { LifoAllocScope allocScope(&cx->tempLifoAlloc()); CompileOptions options(cx); frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr); return irregexp::ParsePatternSyntax(dummyTokenStream, allocScope.alloc(), - pattern, flags & UnicodeFlag); + pattern, flags.unicode()); } static RegExpShared* CheckPatternSyntax(JSContext* cx, HandleAtom pattern, - RegExpFlag flags) { + RegExpFlags flags) { // If we already have a RegExpShared for this pattern/flags, we can // avoid the much slower CheckPatternSyntaxSlow call. if (RegExpShared* shared = cx->zone()->regExps().maybeGet(pattern, flags)) { #ifdef DEBUG // Assert the pattern is valid. if (!CheckPatternSyntaxSlow(cx, pattern, flags)) { MOZ_ASSERT(cx->isThrowingOutOfMemory() || cx->isThrowingOverRecursed()); @@ -247,17 +252,17 @@ static bool RegExpInitializeIgnoringLast /* Step 2. */ pattern = ToAtom<CanGC>(cx, patternValue); if (!pattern) { return false; } } /* Step 3. */ - RegExpFlag flags = RegExpFlag(0); + RegExpFlags flags = RegExpFlag::NoFlags; if (!flagsValue.isUndefined()) { /* Step 4. */ RootedString flagStr(cx, ToString<CanGC>(cx, flagsValue)); if (!flagStr) { return false; } /* Step 5. */ @@ -358,17 +363,17 @@ MOZ_ALWAYS_INLINE bool regexp_compile_im } // Beware! |patternObj| might be a proxy into another compartment, so // don't assume |patternObj.is<RegExpObject>()|. For the same reason, // don't reuse the RegExpShared below. RootedObject patternObj(cx, &patternValue.toObject()); RootedAtom sourceAtom(cx); - RegExpFlag flags; + RegExpFlags flags = RegExpFlag::NoFlags; { // Step 3b. RegExpShared* shared = RegExpToShared(cx, patternObj); if (!shared) { return false; } sourceAtom = shared->getSource(); @@ -456,17 +461,17 @@ bool js::regexp_construct(JSContext* cx, return false; } if (cls == ESClass::RegExp) { // Beware! |patternObj| might be a proxy into another compartment, so // don't assume |patternObj.is<RegExpObject>()|. RootedObject patternObj(cx, &patternValue.toObject()); RootedAtom sourceAtom(cx); - RegExpFlag flags; + RegExpFlags flags; RootedRegExpShared shared(cx); { // Step 4.a. shared = RegExpToShared(cx, patternObj); if (!shared) { return false; } sourceAtom = shared->getSource(); @@ -490,31 +495,31 @@ bool js::regexp_construct(JSContext* cx, Rooted<RegExpObject*> regexp(cx, RegExpAlloc(cx, GenericObject, proto)); if (!regexp) { return false; } // Step 8. if (args.hasDefined(1)) { // Step 4.c / 21.2.3.2.2 RegExpInitialize step 4. - RegExpFlag flagsArg = RegExpFlag(0); + RegExpFlags flagsArg = RegExpFlag::NoFlags; RootedString flagStr(cx, ToString<CanGC>(cx, args[1])); if (!flagStr) { return false; } if (!ParseRegExpFlags(cx, flagStr, &flagsArg)) { return false; } // Don't reuse the RegExpShared if we have different flags. if (flags != flagsArg) { shared = nullptr; } - if (!(flags & UnicodeFlag) && flagsArg & UnicodeFlag) { + if (!flags.unicode() && flagsArg.unicode()) { // Have to check syntax again when adding 'u' flag. // ES 2017 draft rev 9b49a888e9dfe2667008a01b2754c3662059ae56 // 21.2.3.2.2 step 7. shared = CheckPatternSyntax(cx, sourceAtom, flagsArg); if (!shared) { return false; } @@ -589,26 +594,26 @@ bool js::regexp_construct_raw_flags(JSCo // Step 4.a. RootedAtom sourceAtom(cx, AtomizeString(cx, args[0].toString())); if (!sourceAtom) { return false; } // Step 4.c. - int32_t flags = int32_t(args[1].toNumber()); + RegExpFlags flags = AssertedCast<uint8_t>(int32_t(args[1].toNumber())); // Step 7. RegExpObject* regexp = RegExpAlloc(cx, GenericObject); if (!regexp) { return false; } // Step 8. - regexp->initAndZeroLastIndex(sourceAtom, RegExpFlag(flags), cx); + regexp->initAndZeroLastIndex(sourceAtom, flags, cx); args.rval().setObject(*regexp); return true; } MOZ_ALWAYS_INLINE bool IsRegExpPrototype(HandleValue v, JSContext* cx) { return (v.isObject() && cx->global()->maybeGetRegExpPrototype() == &v.toObject()); }
--- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -44,16 +44,17 @@ #include "js/ArrayBuffer.h" // JS::{DetachArrayBuffer,GetArrayBufferLengthAndData,NewArrayBufferWithContents} #include "js/CharacterEncoding.h" #include "js/CompilationAndEvaluation.h" #include "js/CompileOptions.h" #include "js/Debug.h" #include "js/HashTable.h" #include "js/LocaleSensitive.h" #include "js/PropertySpec.h" +#include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags #include "js/SourceText.h" #include "js/StableStringChars.h" #include "js/StructuredClone.h" #include "js/UbiNode.h" #include "js/UbiNodeBreadthFirst.h" #include "js/UbiNodeShortestPaths.h" #include "js/UniquePtr.h" #include "js/Vector.h" @@ -92,16 +93,18 @@ using namespace js; using mozilla::ArrayLength; using mozilla::Maybe; using JS::AutoStableStringChars; using JS::CompileOptions; +using JS::RegExpFlag; +using JS::RegExpFlags; using JS::SourceOwnership; using JS::SourceText; // If fuzzingSafe is set, remove functionality that could cause problems with // fuzzers. Set this via the environment variable MOZ_FUZZING_SAFE. mozilla::Atomic<bool> fuzzingSafe(false); // If disableOOMFunctions is set, disable functionality that causes artificial @@ -4847,17 +4850,17 @@ static bool ParseRegExp(JSContext* cx, u return false; } if (!args[0].isString()) { ReportUsageErrorASCII(cx, callee, "First argument must be a String"); return false; } - RegExpFlag flags = RegExpFlag(0); + RegExpFlags flags = RegExpFlag::NoFlags; if (!args.get(1).isUndefined()) { if (!args.get(1).isString()) { ReportUsageErrorASCII(cx, callee, "Second argument, if present, must be a String"); return false; } RootedString flagStr(cx, args[1].toString()); if (!ParseRegExpFlags(cx, flagStr, &flags)) { @@ -4882,19 +4885,17 @@ static bool ParseRegExp(JSContext* cx, u CompileOptions options(cx); frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr); // Data lifetime is controlled by LifoAllocScope. LifoAllocScope allocScope(&cx->tempLifoAlloc()); irregexp::RegExpCompileData data; if (!irregexp::ParsePattern(dummyTokenStream, allocScope.alloc(), pattern, - flags & MultilineFlag, match_only, - flags & UnicodeFlag, flags & IgnoreCaseFlag, - flags & GlobalFlag, flags & StickyFlag, &data)) { + match_only, flags, &data)) { return false; } RootedObject obj( cx, ConvertRegExpTreeToObject(cx, allocScope.alloc(), data.tree)); if (!obj) { return false; }
--- a/js/src/frontend/BinAST.yaml +++ b/js/src/frontend/BinAST.yaml @@ -39,21 +39,24 @@ cpp: #include "mozilla/Vector.h" #include "frontend/BinAST-macros.h" #include "frontend/BinASTTokenReaderMultipart.h" #include "frontend/FullParseHandler.h" #include "frontend/ParseNode.h" #include "frontend/Parser.h" #include "frontend/SharedContext.h" - + #include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags #include "vm/RegExpObject.h" #include "frontend/ParseContext-inl.h" + using JS::RegExpFlag; + using JS::RegExpFlags; + namespace js { namespace frontend { // Compare a bunch of `uint8_t` values (as returned by the tokenizer_) with // a string literal (and ONLY a string literal). template<typename Tok, size_t N> bool operator==(const typename Tok::Chars& left, const char (&right)[N]) { return Tok::equals(left, right); @@ -1276,28 +1279,28 @@ LiteralPropertyName: LiteralRegExpExpression: fields: flags: block: replace: | Chars flags(cx_); MOZ_TRY(tokenizer_->readChars(flags)); build: | - RegExpFlag reflags = NoFlags; + RegExpFlags reflags = RegExpFlag::NoFlags; for (auto c : flags) { - if (c == 'g' && !(reflags & GlobalFlag)) { - reflags = RegExpFlag(reflags | GlobalFlag); - } else if (c == 'i' && !(reflags & IgnoreCaseFlag)) { - reflags = RegExpFlag(reflags | IgnoreCaseFlag); - } else if (c == 'm' && !(reflags & MultilineFlag)) { - reflags = RegExpFlag(reflags | MultilineFlag); - } else if (c == 'y' && !(reflags & StickyFlag)) { - reflags = RegExpFlag(reflags | StickyFlag); - } else if (c == 'u' && !(reflags & UnicodeFlag)) { - reflags = RegExpFlag(reflags | UnicodeFlag); + if (c == 'g' && !reflags.global()) { + reflags |= RegExpFlag::Global; + } else if (c == 'i' && !reflags.ignoreCase()) { + reflags |= RegExpFlag::IgnoreCase; + } else if (c == 'm' && !reflags.multiline()) { + reflags |= RegExpFlag::Multiline; + } else if (c == 'u' && !reflags.unicode()) { + reflags |= RegExpFlag::Unicode; + } else if (c == 'y' && !reflags.sticky()) { + reflags |= RegExpFlag::Sticky; } else { return raiseError("Invalid regexp flags"); } } Rooted<RegExpObject*> reobj(cx_); BINJS_TRY_VAR(reobj,
--- a/js/src/frontend/BinASTParser.cpp +++ b/js/src/frontend/BinASTParser.cpp @@ -19,21 +19,24 @@ #include "mozilla/Vector.h" #include "frontend/BinAST-macros.h" #include "frontend/BinASTTokenReaderMultipart.h" #include "frontend/FullParseHandler.h" #include "frontend/ParseNode.h" #include "frontend/Parser.h" #include "frontend/SharedContext.h" - +#include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags #include "vm/RegExpObject.h" #include "frontend/ParseContext-inl.h" +using JS::RegExpFlag; +using JS::RegExpFlags; + namespace js { namespace frontend { // Compare a bunch of `uint8_t` values (as returned by the tokenizer_) with // a string literal (and ONLY a string literal). template <typename Tok, size_t N> bool operator==(const typename Tok::Chars& left, const char (&right)[N]) { return Tok::equals(left, right); @@ -3517,28 +3520,28 @@ JS::Result<ParseNode*> BinASTParser<Tok> MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields)); #endif // defined(DEBUG) RootedAtom pattern(cx_); MOZ_TRY_VAR(pattern, tokenizer_->readAtom()); Chars flags(cx_); MOZ_TRY(tokenizer_->readChars(flags)); - RegExpFlag reflags = NoFlags; + RegExpFlags reflags = RegExpFlag::NoFlags; for (auto c : flags) { - if (c == 'g' && !(reflags & GlobalFlag)) { - reflags = RegExpFlag(reflags | GlobalFlag); - } else if (c == 'i' && !(reflags & IgnoreCaseFlag)) { - reflags = RegExpFlag(reflags | IgnoreCaseFlag); - } else if (c == 'm' && !(reflags & MultilineFlag)) { - reflags = RegExpFlag(reflags | MultilineFlag); - } else if (c == 'y' && !(reflags & StickyFlag)) { - reflags = RegExpFlag(reflags | StickyFlag); - } else if (c == 'u' && !(reflags & UnicodeFlag)) { - reflags = RegExpFlag(reflags | UnicodeFlag); + if (c == 'g' && !reflags.global()) { + reflags |= RegExpFlag::Global; + } else if (c == 'i' && !reflags.ignoreCase()) { + reflags |= RegExpFlag::IgnoreCase; + } else if (c == 'm' && !reflags.multiline()) { + reflags |= RegExpFlag::Multiline; + } else if (c == 'u' && !reflags.unicode()) { + reflags |= RegExpFlag::Unicode; + } else if (c == 'y' && !reflags.sticky()) { + reflags |= RegExpFlag::Sticky; } else { return raiseError("Invalid regexp flags"); } } Rooted<RegExpObject*> reobj(cx_); BINJS_TRY_VAR(reobj, RegExpObject::create(cx_, pattern, reflags, TenuredObject));
--- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -37,16 +37,17 @@ #include "builtin/ModuleObject.h" #include "builtin/SelfHostingDefines.h" #include "frontend/BytecodeCompiler.h" #include "frontend/FoldConstants.h" #include "frontend/ModuleSharedContext.h" #include "frontend/ParseNode.h" #include "frontend/TokenStream.h" #include "irregexp/RegExpParser.h" +#include "js/RegExpFlags.h" // JS::RegExpFlags #include "vm/BytecodeUtil.h" #include "vm/JSAtom.h" #include "vm/JSContext.h" #include "vm/JSFunction.h" #include "vm/JSScript.h" #include "vm/RegExpObject.h" #include "vm/StringType.h" #include "wasm/AsmJS.h" @@ -65,16 +66,17 @@ using mozilla::PodCopy; using mozilla::PodZero; using mozilla::PointerRangeSize; using mozilla::Some; using mozilla::Unused; using mozilla::Utf8Unit; using JS::AutoGCRooter; using JS::ReadOnlyCompileOptions; +using JS::RegExpFlags; namespace js { namespace frontend { using DeclaredNamePtr = ParseContext::Scope::DeclaredNamePtr; using AddDeclaredNamePtr = ParseContext::Scope::AddDeclaredNamePtr; using BindingIter = ParseContext::Scope::BindingIter; using UsedNamePtr = UsedNameTracker::UsedNameMap::Ptr; @@ -9252,17 +9254,17 @@ GeneralParser<ParseHandler, Unit>::noSub } template <typename Unit> RegExpLiteral* Parser<FullParseHandler, Unit>::newRegExp() { MOZ_ASSERT(!options().selfHostingMode); // Create the regexp and check its syntax. const auto& chars = tokenStream.getCharBuffer(); - RegExpFlag flags = anyChars.currentToken().regExpFlags(); + RegExpFlags flags = anyChars.currentToken().regExpFlags(); Rooted<RegExpObject*> reobj(cx_); reobj = RegExpObject::create(cx_, chars.begin(), chars.length(), flags, anyChars, TenuredObject); if (!reobj) { return null(); } @@ -9271,23 +9273,23 @@ RegExpLiteral* Parser<FullParseHandler, template <typename Unit> SyntaxParseHandler::RegExpLiteralType Parser<SyntaxParseHandler, Unit>::newRegExp() { MOZ_ASSERT(!options().selfHostingMode); // Only check the regexp's syntax, but don't create a regexp object. const auto& chars = tokenStream.getCharBuffer(); - RegExpFlag flags = anyChars.currentToken().regExpFlags(); + RegExpFlags flags = anyChars.currentToken().regExpFlags(); mozilla::Range<const char16_t> source(chars.begin(), chars.length()); { LifoAllocScope scopeAlloc(&alloc_); if (!js::irregexp::ParsePatternSyntax(anyChars, scopeAlloc.alloc(), source, - flags & UnicodeFlag)) { + flags.unicode())) { return null(); } } return handler_.newRegExp(SyntaxParseHandler::NodeGeneric, pos(), *this); } template <class ParseHandler, typename Unit>
--- a/js/src/frontend/TokenStream.cpp +++ b/js/src/frontend/TokenStream.cpp @@ -29,16 +29,17 @@ #include "jsexn.h" #include "jsnum.h" #include "frontend/BytecodeCompiler.h" #include "frontend/Parser.h" #include "frontend/ReservedWords.h" #include "js/CharacterEncoding.h" +#include "js/RegExpFlags.h" // JS::RegExpFlags #include "js/UniquePtr.h" #include "util/StringBuffer.h" #include "util/Unicode.h" #include "vm/HelperThreads.h" #include "vm/JSAtom.h" #include "vm/JSContext.h" #include "vm/Realm.h" @@ -51,16 +52,18 @@ using mozilla::IsAsciiDigit; using mozilla::IsTrailingUnit; using mozilla::MakeScopeExit; using mozilla::MakeSpan; using mozilla::Maybe; using mozilla::PointerRangeSize; using mozilla::Utf8Unit; using JS::ReadOnlyCompileOptions; +using JS::RegExpFlag; +using JS::RegExpFlags; struct ReservedWordInfo { const char* chars; // C string with reserved word text js::frontend::TokenKind tokentype; }; static const ReservedWordInfo reservedWords[] = { #define RESERVED_WORD_INFO(word, name, type) \ @@ -2314,44 +2317,44 @@ MOZ_MUST_USE bool TokenStreamSpecific<Un MOZ_ASSERT(!IsLineTerminator(AssertedCast<char32_t>(unit))); if (!this->charBuffer.append(unit)) { return badToken(); } } while (true); int32_t unit; - RegExpFlag reflags = NoFlags; + RegExpFlags reflags = RegExpFlag::NoFlags; while (true) { - RegExpFlag flag; + uint8_t flag; unit = getCodeUnit(); if (unit == 'g') { - flag = GlobalFlag; + flag = RegExpFlag::Global; } else if (unit == 'i') { - flag = IgnoreCaseFlag; + flag = RegExpFlag::IgnoreCase; } else if (unit == 'm') { - flag = MultilineFlag; + flag = RegExpFlag::Multiline; + } else if (unit == 'u') { + flag = RegExpFlag::Unicode; } else if (unit == 'y') { - flag = StickyFlag; - } else if (unit == 'u') { - flag = UnicodeFlag; + flag = RegExpFlag::Sticky; } else if (IsAsciiAlpha(unit)) { - flag = NoFlags; + flag = RegExpFlag::NoFlags; } else { break; } - if ((reflags & flag) || flag == NoFlags) { + if ((reflags & flag) || flag == RegExpFlag::NoFlags) { ungetCodeUnit(unit); char buf[2] = {char(unit), '\0'}; error(JSMSG_BAD_REGEXP_FLAG, buf); return badToken(); } - reflags = RegExpFlag(reflags | flag); + reflags |= flag; } ungetCodeUnit(unit); newRegExpToken(reflags, start, out); return true; } template <typename Unit, class AnyCharsAccess>
--- a/js/src/frontend/TokenStream.h +++ b/js/src/frontend/TokenStream.h @@ -201,23 +201,23 @@ #include <stdint.h> #include <stdio.h> #include "jspubtd.h" #include "frontend/ErrorReporter.h" #include "frontend/TokenKind.h" #include "js/CompileOptions.h" +#include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags #include "js/UniquePtr.h" #include "js/Vector.h" #include "util/Text.h" #include "util/Unicode.h" #include "vm/ErrorReporting.h" #include "vm/JSAtom.h" -#include "vm/RegExpConstants.h" #include "vm/StringType.h" struct JSContext; struct KeywordInfo; namespace js { class AutoKeepAtoms; @@ -375,17 +375,17 @@ struct Token { /** Numeric literal's value. */ double value; /** Does the numeric literal contain a '.'? */ DecimalPoint decimalPoint; } number; /** Regular expression flags; use charBuffer to access source chars. */ - RegExpFlag reflags; + JS::RegExpFlags reflags; } u; #ifdef DEBUG /** The modifier used to get this token. */ Modifier modifier; /** * Exception for this modifier to permit modifier mismatches in certain @@ -402,19 +402,18 @@ struct Token { } void setAtom(JSAtom* atom) { MOZ_ASSERT(type == TokenKind::String || type == TokenKind::TemplateHead || type == TokenKind::NoSubsTemplate); u.atom = atom; } - void setRegExpFlags(RegExpFlag flags) { + void setRegExpFlags(JS::RegExpFlags flags) { MOZ_ASSERT(type == TokenKind::RegExp); - MOZ_ASSERT((flags & AllFlags) == flags); u.reflags = flags; } void setNumber(double n, DecimalPoint decimalPoint) { MOZ_ASSERT(type == TokenKind::Number); u.number.value = n; u.number.decimalPoint = decimalPoint; } @@ -427,19 +426,18 @@ struct Token { } JSAtom* atom() const { MOZ_ASSERT(type == TokenKind::String || type == TokenKind::TemplateHead || type == TokenKind::NoSubsTemplate); return u.atom; } - RegExpFlag regExpFlags() const { + JS::RegExpFlags regExpFlags() const { MOZ_ASSERT(type == TokenKind::RegExp); - MOZ_ASSERT((u.reflags & AllFlags) == u.reflags); return u.reflags; } double number() const { MOZ_ASSERT(type == TokenKind::Number); return u.number.value; } @@ -1994,17 +1992,18 @@ class GeneralTokenStreamChars : public S void newPrivateNameToken(PropertyName* name, TokenStart start, TokenStreamShared::Modifier modifier, TokenKind* out) { Token* token = newToken(TokenKind::PrivateName, start, modifier, out); token->setName(name); } - void newRegExpToken(RegExpFlag reflags, TokenStart start, TokenKind* out) { + void newRegExpToken(JS::RegExpFlags reflags, TokenStart start, + TokenKind* out) { Token* token = newToken(TokenKind::RegExp, start, TokenStreamShared::Operand, out); token->setRegExpFlags(reflags); } MOZ_COLD bool badToken(); /** @@ -2797,17 +2796,18 @@ class MOZ_STACK_CLASS TokenStreamSpecifi // (Unit, AnyCharsAccess) pairs -- and that gets super-messy as AnyCharsAccess // *itself* is templated. This symbol really isn't that huge compared to some // defined inline in TokenStreamSpecific, so just rely on the linker commoning // stuff up. template <typename Unit> template <class AnyCharsAccess> inline TokenStreamPosition<Unit>::TokenStreamPosition( AutoKeepAtoms& keepAtoms, - TokenStreamSpecific<Unit, AnyCharsAccess>& tokenStream) { + TokenStreamSpecific<Unit, AnyCharsAccess>& tokenStream) + : currentToken(tokenStream.anyCharsAccess().currentToken()) { TokenStreamAnyChars& anyChars = tokenStream.anyCharsAccess(); buf = tokenStream.sourceUnits.addressOfNextCodeUnit(/* allowPoisoned = */ true); flags = anyChars.flags; lineno = anyChars.lineno; linebase = anyChars.linebase; prevLinebase = anyChars.prevLinebase;
--- a/js/src/gc/GC.cpp +++ b/js/src/gc/GC.cpp @@ -1801,16 +1801,17 @@ bool GCRuntime::addBlackRootsTracer(JSTr } void GCRuntime::removeBlackRootsTracer(JSTraceDataOp traceOp, void* data) { // Can be called from finalizers for (size_t i = 0; i < blackRootTracers.ref().length(); i++) { Callback<JSTraceDataOp>* e = &blackRootTracers.ref()[i]; if (e->op == traceOp && e->data == data) { blackRootTracers.ref().erase(e); + break; } } } void GCRuntime::setGrayRootsTracer(JSTraceDataOp traceOp, void* data) { AssertHeapIsIdle(); grayRootTracer.op = traceOp; grayRootTracer.data = data;
--- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -987,27 +987,26 @@ void LazyScript::traceChildren(JSTracer* TraceGenericPointerRoot( trc, reinterpret_cast<Cell**>( enclosingLazyScriptOrScope_.unsafeUnbarrieredForTracing()), "enclosingScope or enclosingLazyScript"); } // We rely on the fact that atoms are always tenured. - JSAtom** closedOverBindings = this->closedOverBindings(); - for (auto i : IntegerRange(numClosedOverBindings())) { - if (closedOverBindings[i]) { - TraceManuallyBarrieredEdge(trc, &closedOverBindings[i], - "closedOverBinding"); + for (GCPtrAtom& closedOverBinding : closedOverBindings()) { + if (closedOverBinding) { + TraceEdge(trc, &closedOverBinding, "closedOverBinding"); } } - GCPtrFunction* innerFunctions = this->innerFunctions(); - for (auto i : IntegerRange(numInnerFunctions())) { - TraceEdge(trc, &innerFunctions[i], "lazyScriptInnerFunction"); + for (GCPtrFunction& innerFunction : innerFunctions()) { + if (innerFunction) { + TraceEdge(trc, &innerFunction, "lazyScriptInnerFunction"); + } } if (trc->isMarkingTracer()) { GCMarker::fromTracer(trc)->markImplicitEdges(this); } } inline void js::GCMarker::eagerlyMarkChildren(LazyScript* thing) { if (thing->script_) { @@ -1026,26 +1025,26 @@ inline void js::GCMarker::eagerlyMarkChi TraceManuallyBarrieredGenericPointerEdge( this, reinterpret_cast<Cell**>( thing->enclosingLazyScriptOrScope_.unsafeUnbarrieredForTracing()), "enclosingScope or enclosingLazyScript"); } // We rely on the fact that atoms are always tenured. - JSAtom** closedOverBindings = thing->closedOverBindings(); - for (auto i : IntegerRange(thing->numClosedOverBindings())) { - if (closedOverBindings[i]) { - traverseEdge(thing, static_cast<JSString*>(closedOverBindings[i])); + for (GCPtrAtom& closedOverBinding : thing->closedOverBindings()) { + if (closedOverBinding) { + traverseEdge(thing, static_cast<JSString*>(closedOverBinding)); } } - GCPtrFunction* innerFunctions = thing->innerFunctions(); - for (auto i : IntegerRange(thing->numInnerFunctions())) { - traverseEdge(thing, static_cast<JSObject*>(innerFunctions[i])); + for (GCPtrFunction& innerFunction : thing->innerFunctions()) { + if (innerFunction) { + traverseEdge(thing, static_cast<JSObject*>(innerFunction)); + } } markImplicitEdges(thing); } void Shape::traceChildren(JSTracer* trc) { TraceEdge(trc, &base_, "base"); TraceEdge(trc, &propidRef(), "propid");
--- a/js/src/gc/PublicIterators.cpp +++ b/js/src/gc/PublicIterators.cpp @@ -81,21 +81,17 @@ void js::IterateChunks(JSContext* cx, vo chunkCallback(cx->runtime(), data, chunk); } } static void TraverseInnerLazyScriptsForLazyScript( JSContext* cx, void* data, LazyScript* enclosingLazyScript, IterateLazyScriptCallback lazyScriptCallback, const JS::AutoRequireNoGC& nogc) { - GCPtrFunction* innerFunctions = enclosingLazyScript->innerFunctions(); - for (size_t i = 0, len = enclosingLazyScript->numInnerFunctions(); i < len; - i++) { - JSFunction* fun = innerFunctions[i]; - + for (JSFunction* fun : enclosingLazyScript->innerFunctions()) { // LazyScript::CreateForXDR temporarily initializes innerFunctions with // its own function, but it should be overwritten with correct // inner functions before getting inserted into parent's innerFunctions. MOZ_ASSERT(fun != enclosingLazyScript->functionNonDelazifying()); if (!fun->isInterpretedLazy()) { return; }
--- a/js/src/irregexp/RegExpParser.cpp +++ b/js/src/irregexp/RegExpParser.cpp @@ -33,27 +33,31 @@ #include "mozilla/ArrayUtils.h" #include "mozilla/Casting.h" #include "mozilla/Move.h" #include "mozilla/Range.h" #include "frontend/TokenStream.h" #include "gc/GC.h" #include "irregexp/RegExpCharacters.h" +#include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags #include "util/StringBuffer.h" #include "util/Text.h" #include "util/Unicode.h" #include "vm/ErrorReporting.h" using namespace js; using namespace js::irregexp; using mozilla::AssertedCast; using mozilla::PointerRangeSize; +using JS::RegExpFlag; +using JS::RegExpFlags; + // ---------------------------------------------------------------------------- // RegExpBuilder RegExpBuilder::RegExpBuilder(LifoAlloc* alloc) : alloc(alloc), pending_empty_(false), characters_(nullptr) #ifdef DEBUG @@ -235,31 +239,31 @@ RegExpBuilder::AddQuantifierToAtom(int m last_added_ = ADD_TERM; #endif } // ---------------------------------------------------------------------------- // RegExpParser template <typename CharT> -RegExpParser<CharT>::RegExpParser(frontend::TokenStreamAnyChars& ts, LifoAlloc* alloc, - const CharT* chars, const CharT* end, bool multiline_mode, - bool unicode, bool ignore_case) +RegExpParser<CharT>::RegExpParser(frontend::TokenStreamAnyChars& ts, + LifoAlloc* alloc, RegExpFlags flags, + const CharT* chars, const CharT* end) : ts(ts), alloc(alloc), captures_(nullptr), start_(chars), next_pos_(start_), end_(end), current_(kEndMarker), capture_count_(0), has_more_(true), - multiline_(multiline_mode), - unicode_(unicode), - ignore_case_(ignore_case), + multiline_(flags.multiline()), + unicode_(flags.unicode()), + ignore_case_(flags.ignoreCase()), simple_(false), contains_anchor_(false), is_scanned_for_captures_(false) { Advance(); } static size_t ComputeColumn(const Latin1Char* begin, const Latin1Char* end) { @@ -1926,23 +1930,22 @@ RegExpParser<CharT>::ParseDisjunction() } template class irregexp::RegExpParser<Latin1Char>; template class irregexp::RegExpParser<char16_t>; template <typename CharT> static bool ParsePattern(frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc, - const CharT* chars, size_t length, - bool multiline, bool match_only, bool unicode, bool ignore_case, - bool global, bool sticky, RegExpCompileData* data) + const CharT* chars, size_t length, bool match_only, + RegExpFlags flags, RegExpCompileData* data) { // We shouldn't strip pattern for exec, or test with global/sticky, // to reflect correct match position and lastIndex. - if (match_only && !global && !sticky) { + if (match_only && !flags.global() && !flags.sticky()) { // Try to strip a leading '.*' from the RegExp, but only if it is not // followed by a '?' (which will affect how the .* is parsed). This // pattern will affect the captures produced by the RegExp, but not // whether there is a match or not. if (length >= 3 && chars[0] == '.' && chars[1] == '*' && chars[2] != '?') { chars += 2; length -= 2; } @@ -1953,46 +1956,47 @@ ParsePattern(frontend::TokenStreamAnyCha // are sure this will not affect how the RegExp is parsed. if (length >= 3 && !HasRegExpMetaChars(chars, length - 2) && chars[length - 2] == '.' && chars[length - 1] == '*') { length -= 2; } } - RegExpParser<CharT> parser(ts, &alloc, chars, chars + length, multiline, unicode, ignore_case); + RegExpParser<CharT> parser(ts, &alloc, flags, chars, chars + length); data->tree = parser.ParsePattern(); if (!data->tree) return false; data->simple = parser.simple(); data->contains_anchor = parser.contains_anchor(); data->capture_count = parser.captures_started(); return true; } bool -irregexp::ParsePattern(frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc, JSAtom* str, - bool multiline, bool match_only, bool unicode, bool ignore_case, - bool global, bool sticky, RegExpCompileData* data) +irregexp::ParsePattern(frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc, + JSAtom* str, bool match_only, RegExpFlags flags, + RegExpCompileData* data) { JS::AutoCheckCannotGC nogc; return str->hasLatin1Chars() ? ::ParsePattern(ts, alloc, str->latin1Chars(nogc), str->length(), - multiline, match_only, unicode, ignore_case, global, sticky, data) + match_only, flags, data) : ::ParsePattern(ts, alloc, str->twoByteChars(nogc), str->length(), - multiline, match_only, unicode, ignore_case, global, sticky, data); + match_only, flags, data); } template <typename CharT> static bool ParsePatternSyntax(frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc, const CharT* chars, size_t length, bool unicode) { - RegExpParser<CharT> parser(ts, &alloc, chars, chars + length, false, unicode, false); + RegExpParser<CharT> parser(ts, &alloc, unicode ? RegExpFlag::Unicode : 0, + chars, chars + length); return parser.ParsePattern() != nullptr; } bool irregexp::ParsePatternSyntax(frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc, JSAtom* str, bool unicode) { JS::AutoCheckCannotGC nogc;
--- a/js/src/irregexp/RegExpParser.h +++ b/js/src/irregexp/RegExpParser.h @@ -31,29 +31,29 @@ #ifndef V8_PARSER_H_ #define V8_PARSER_H_ #include "mozilla/Range.h" #include <stdarg.h> #include "irregexp/RegExpAST.h" +#include "js/RegExpFlags.h" namespace js { namespace frontend { class TokenStreamAnyChars; } namespace irregexp { extern bool ParsePattern(frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc, JSAtom* str, - bool multiline, bool match_only, bool unicode, bool ignore_case, - bool global, bool sticky, RegExpCompileData* data); + bool match_only, JS::RegExpFlags flags, RegExpCompileData* data); extern bool ParsePatternSyntax(frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc, JSAtom* str, bool unicode); extern bool ParsePatternSyntax(frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc, const mozilla::Range<const char16_t> chars, bool unicode); @@ -180,18 +180,17 @@ class RegExpBuilder // Characters parsed by RegExpParser can be either char16_t or kEndMarker. typedef uint32_t widechar; template <typename CharT> class RegExpParser { public: RegExpParser(frontend::TokenStreamAnyChars& ts, LifoAlloc* alloc, - const CharT* chars, const CharT* end, bool multiline_mode, bool unicode, - bool ignore_case); + JS::RegExpFlags flags, const CharT* chars, const CharT* end); RegExpTree* ParsePattern(); RegExpTree* ParseDisjunction(); RegExpTree* ParseCharacterClass(); // Parses a {...,...} quantifier and stores the range in the given // out parameters. bool ParseIntervalQuantifier(int* min_out, int* max_out);
--- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -39,16 +39,17 @@ #include "jit/Linker.h" #include "jit/Lowering.h" #include "jit/MIRGenerator.h" #include "jit/MoveEmitter.h" #include "jit/RangeAnalysis.h" #include "jit/SharedICHelpers.h" #include "jit/StackSlotAllocator.h" #include "jit/VMFunctions.h" +#include "js/RegExpFlags.h" // JS::RegExpFlag #include "util/Unicode.h" #include "vm/AsyncFunction.h" #include "vm/AsyncIteration.h" #include "vm/EqualityOperations.h" // js::SameValue #include "vm/MatchPairs.h" #include "vm/RegExpObject.h" #include "vm/RegExpStatics.h" #include "vm/StringType.h" @@ -1938,17 +1939,17 @@ static bool PrepareAndExecuteRegExp( // ES6 21.2.2.2 step 2. // See RegExp.cpp ExecuteRegExp for more detail. { Label done; masm.branchTest32(Assembler::Zero, Address(temp1, RegExpShared::offsetOfFlags()), - Imm32(UnicodeFlag), &done); + Imm32(int32_t(JS::RegExpFlag::Unicode)), &done); // If input is latin1, there should not be surrogate pair. masm.branchLatin1String(input, &done); // Check if |lastIndex > 0 && lastIndex < input->length()|. // lastIndex should already have no sign here. masm.branchTest32(Assembler::Zero, lastIndex, lastIndex, &done); masm.loadStringLength(input, temp2);
--- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -19,16 +19,17 @@ #include "builtin/TestingFunctions.h" #include "builtin/TypedObject.h" #include "jit/BaselineInspector.h" #include "jit/InlinableNatives.h" #include "jit/IonBuilder.h" #include "jit/Lowering.h" #include "jit/MIR.h" #include "jit/MIRGraph.h" +#include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags #include "vm/ArgumentsObject.h" #include "vm/ArrayBufferObject.h" #include "vm/JSObject.h" #include "vm/ProxyObject.h" #include "vm/SelfHosting.h" #include "vm/SharedArrayObject.h" #include "vm/TypedArrayObject.h" #include "wasm/WasmInstance.h" @@ -38,16 +39,18 @@ #include "vm/NativeObject-inl.h" #include "vm/StringObject-inl.h" using mozilla::ArrayLength; using mozilla::AssertedCast; using mozilla::Maybe; using JS::DoubleNaNValue; +using JS::RegExpFlag; +using JS::RegExpFlags; using JS::TrackedOutcome; namespace js { namespace jit { // Returns true if |native| can be inlined cross-realm. Especially inlined // natives that can allocate objects or throw exceptions shouldn't be inlined // cross-realm without a careful analysis because we might use the wrong realm! @@ -619,28 +622,28 @@ IonBuilder::InliningResult IonBuilder::i } MInstruction* byteOffset = addTypedArrayByteOffset(thisArg); current->push(byteOffset); return InliningStatus_Inlined; } // Try to optimize RegExp getters. - RegExpFlag mask = NoFlags; + RegExpFlags mask = RegExpFlag::NoFlags; if (RegExpObject::isOriginalFlagGetter(native, &mask)) { const Class* clasp = thisTypes->getKnownClass(constraints()); if (clasp != &RegExpObject::class_) { return InliningStatus_NotInlined; } MLoadFixedSlot* flags = MLoadFixedSlot::New(alloc(), thisArg, RegExpObject::flagsSlot()); current->add(flags); flags->setResultType(MIRType::Int32); - MConstant* maskConst = MConstant::New(alloc(), Int32Value(mask)); + MConstant* maskConst = MConstant::New(alloc(), Int32Value(mask.value())); current->add(maskConst); MBitAnd* maskedFlag = MBitAnd::New(alloc(), flags, maskConst); maskedFlag->setInt32Specialization(); current->add(maskedFlag); MDefinition* result = convertToBoolean(maskedFlag); current->push(result); return InliningStatus_Inlined;
--- a/js/src/jsapi-tests/testRegExp.cpp +++ b/js/src/jsapi-tests/testRegExp.cpp @@ -1,13 +1,14 @@ /* 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 "js/RegExp.h" +#include "js/RegExpFlags.h" #include "jsapi-tests/tests.h" BEGIN_TEST(testObjectIsRegExp) { JS::RootedValue val(cx); bool isRegExp; EVAL("new Object", &val); @@ -25,26 +26,29 @@ BEGIN_TEST(testObjectIsRegExp) { END_TEST(testObjectIsRegExp) BEGIN_TEST(testGetRegExpFlags) { JS::RootedValue val(cx); JS::RootedObject obj(cx); EVAL("/foopy/", &val); obj = val.toObjectOrNull(); - CHECK_EQUAL(JS::GetRegExpFlags(cx, obj), 0u); + CHECK_EQUAL(JS::GetRegExpFlags(cx, obj), + JS::RegExpFlags(JS::RegExpFlag::NoFlags)); EVAL("/foopy/g", &val); obj = val.toObjectOrNull(); - CHECK(JS::GetRegExpFlags(cx, obj) == JS::RegExpFlags::Global); + CHECK_EQUAL(JS::GetRegExpFlags(cx, obj), + JS::RegExpFlags(JS::RegExpFlag::Global)); EVAL("/foopy/gi", &val); obj = val.toObjectOrNull(); - CHECK(JS::GetRegExpFlags(cx, obj) == - (JS::RegExpFlags::Global | JS::RegExpFlags::IgnoreCase)); + CHECK_EQUAL( + JS::GetRegExpFlags(cx, obj), + JS::RegExpFlags(JS::RegExpFlag::Global | JS::RegExpFlag::IgnoreCase)); return true; } END_TEST(testGetRegExpFlags) BEGIN_TEST(testGetRegExpSource) { JS::RootedValue val(cx); JS::RootedObject obj(cx);
--- a/js/src/jsapi-tests/tests.h +++ b/js/src/jsapi-tests/tests.h @@ -15,16 +15,17 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "gc/GC.h" #include "js/AllocPolicy.h" #include "js/CharacterEncoding.h" #include "js/Equality.h" // JS::SameValue +#include "js/RegExpFlags.h" // JS::RegExpFlags #include "js/Vector.h" #include "vm/JSContext.h" /* Note: Aborts on OOM. */ class JSAPITestString { js::Vector<char, 0, js::SystemAllocPolicy> chars; public: @@ -154,16 +155,36 @@ class JSAPITest { } JSAPITestString toSource(int v) { return toSource((long)v); } JSAPITestString toSource(bool v) { return JSAPITestString(v ? "true" : "false"); } + JSAPITestString toSource(JS::RegExpFlags flags) { + JSAPITestString str; + if (flags.global()) { + str += "g"; + } + if (flags.ignoreCase()) { + str += "i"; + } + if (flags.multiline()) { + str += "m"; + } + if (flags.unicode()) { + str += "u"; + } + if (flags.sticky()) { + str += "y"; + } + return str; + } + JSAPITestString toSource(JSAtom* v) { JS::RootedValue val(cx, JS::StringValue((JSString*)v)); return jsvalToSource(val); } // Note that in some still-supported GCC versions (we think anything before // GCC 4.6), this template does not work when the second argument is // nullptr. It infers type U = long int. Use CHECK_NULL instead.
--- a/js/src/moz.build +++ b/js/src/moz.build @@ -156,16 +156,17 @@ EXPORTS.js += [ '../public/PropertyDescriptor.h', '../public/PropertySpec.h', '../public/ProtoKey.h', '../public/Proxy.h', '../public/Realm.h', '../public/RealmOptions.h', '../public/RefCounted.h', '../public/RegExp.h', + '../public/RegExpFlags.h', '../public/RequiredDefines.h', '../public/Result.h', '../public/RootingAPI.h', '../public/SavedFrameAPI.h', '../public/SharedArrayBuffer.h', '../public/SliceBudget.h', '../public/SourceText.h', '../public/StableStringChars.h',
--- a/js/src/vm/JSScript.cpp +++ b/js/src/vm/JSScript.cpp @@ -231,33 +231,33 @@ template XDRResult js::XDRScriptConst(XD MutableHandleValue); // Code LazyScript's closed over bindings. template <XDRMode mode> static XDRResult XDRLazyClosedOverBindings(XDRState<mode>* xdr, MutableHandle<LazyScript*> lazy) { JSContext* cx = xdr->cx(); RootedAtom atom(cx); - for (size_t i = 0; i < lazy->numClosedOverBindings(); i++) { + for (GCPtrAtom& elem : lazy->closedOverBindings()) { uint8_t endOfScopeSentinel; if (mode == XDR_ENCODE) { - atom = lazy->closedOverBindings()[i]; + atom = elem.get(); endOfScopeSentinel = !atom; } MOZ_TRY(xdr->codeUint8(&endOfScopeSentinel)); if (endOfScopeSentinel) { atom = nullptr; } else { MOZ_TRY(XDRAtom(xdr, &atom)); } if (mode == XDR_DECODE) { - lazy->closedOverBindings()[i] = atom; + elem.init(atom); } } return Ok(); } // Code the missing part needed to re-create a LazyScript from a JSScript. template <XDRMode mode> @@ -266,28 +266,30 @@ static XDRResult XDRRelazificationInfo(X HandleScope enclosingScope, MutableHandle<LazyScript*> lazy) { MOZ_ASSERT_IF(mode == XDR_ENCODE, script->isRelazifiableIgnoringJitCode() && script->maybeLazyScript()); MOZ_ASSERT_IF(mode == XDR_ENCODE, !lazy->numInnerFunctions()); JSContext* cx = xdr->cx(); - uint64_t packedFields; + uint32_t immutableFlags; + uint32_t numClosedOverBindings; { uint32_t sourceStart = script->sourceStart(); uint32_t sourceEnd = script->sourceEnd(); uint32_t toStringStart = script->toStringStart(); uint32_t toStringEnd = script->toStringEnd(); uint32_t lineno = script->lineno(); uint32_t column = script->column(); uint32_t numFieldInitializers; if (mode == XDR_ENCODE) { - packedFields = lazy->packedFieldsForXDR(); + immutableFlags = lazy->immutableFlags(); + numClosedOverBindings = lazy->numClosedOverBindings(); MOZ_ASSERT(sourceStart == lazy->sourceStart()); MOZ_ASSERT(sourceEnd == lazy->sourceEnd()); MOZ_ASSERT(toStringStart == lazy->toStringStart()); MOZ_ASSERT(toStringEnd == lazy->toStringEnd()); MOZ_ASSERT(lineno == lazy->lineno()); MOZ_ASSERT(column == lazy->column()); // We can assert we have no inner functions because we don't // relazify scripts with inner functions. See @@ -296,29 +298,30 @@ static XDRResult XDRRelazificationInfo(X if (fun->kind() == JSFunction::FunctionKind::ClassConstructor) { numFieldInitializers = (uint32_t)lazy->getFieldInitializers().numFieldInitializers; } else { numFieldInitializers = UINT32_MAX; } } - MOZ_TRY(xdr->codeUint64(&packedFields)); + MOZ_TRY(xdr->codeUint32(&immutableFlags)); MOZ_TRY(xdr->codeUint32(&numFieldInitializers)); + MOZ_TRY(xdr->codeUint32(&numClosedOverBindings)); if (mode == XDR_DECODE) { RootedScriptSourceObject sourceObject(cx, script->sourceObject()); lazy.set(LazyScript::CreateForXDR( - cx, fun, script, enclosingScope, sourceObject, packedFields, - sourceStart, sourceEnd, toStringStart, lineno, column)); + cx, numClosedOverBindings, /* numInnerFunctions = */ 0, fun, script, + enclosingScope, sourceObject, immutableFlags, sourceStart, sourceEnd, + toStringStart, toStringEnd, lineno, column)); if (!lazy) { return xdr->fail(JS::TranscodeResult_Throw); } - lazy->setToStringEnd(toStringEnd); if (numFieldInitializers != UINT32_MAX) { lazy->setFieldInitializers( FieldInitializers((size_t)numFieldInitializers)); } } } // Code binding names. @@ -1046,85 +1049,91 @@ XDRResult js::XDRLazyScript(XDRState<mod { uint32_t sourceStart; uint32_t sourceEnd; uint32_t toStringStart; uint32_t toStringEnd; uint32_t lineno; uint32_t column; - uint64_t packedFields; + uint32_t immutableFlags; uint32_t numFieldInitializers; + uint32_t numClosedOverBindings; + uint32_t numInnerFunctions; if (mode == XDR_ENCODE) { // Note: it's possible the LazyScript has a non-null script_ pointer // to a JSScript. We don't encode it: we can just delazify the // lazy script. MOZ_ASSERT(fun == lazy->functionNonDelazifying()); sourceStart = lazy->sourceStart(); sourceEnd = lazy->sourceEnd(); toStringStart = lazy->toStringStart(); toStringEnd = lazy->toStringEnd(); lineno = lazy->lineno(); column = lazy->column(); - packedFields = lazy->packedFieldsForXDR(); + immutableFlags = lazy->immutableFlags(); if (fun->kind() == JSFunction::FunctionKind::ClassConstructor) { numFieldInitializers = (uint32_t)lazy->getFieldInitializers().numFieldInitializers; } else { numFieldInitializers = UINT32_MAX; } + numClosedOverBindings = lazy->numClosedOverBindings(); + numInnerFunctions = lazy->numInnerFunctions(); } MOZ_TRY(xdr->codeUint32(&sourceStart)); MOZ_TRY(xdr->codeUint32(&sourceEnd)); MOZ_TRY(xdr->codeUint32(&toStringStart)); MOZ_TRY(xdr->codeUint32(&toStringEnd)); MOZ_TRY(xdr->codeUint32(&lineno)); MOZ_TRY(xdr->codeUint32(&column)); - MOZ_TRY(xdr->codeUint64(&packedFields)); + MOZ_TRY(xdr->codeUint32(&immutableFlags)); MOZ_TRY(xdr->codeUint32(&numFieldInitializers)); + MOZ_TRY(xdr->codeUint32(&numClosedOverBindings)); + MOZ_TRY(xdr->codeUint32(&numInnerFunctions)); if (mode == XDR_DECODE) { lazy.set(LazyScript::CreateForXDR( - cx, fun, nullptr, enclosingScope, sourceObject, packedFields, - sourceStart, sourceEnd, toStringStart, lineno, column)); + cx, numClosedOverBindings, numInnerFunctions, fun, nullptr, + enclosingScope, sourceObject, immutableFlags, sourceStart, sourceEnd, + toStringStart, toStringEnd, lineno, column)); if (!lazy) { return xdr->fail(JS::TranscodeResult_Throw); } - lazy->setToStringEnd(toStringEnd); + if (numFieldInitializers != UINT32_MAX) { lazy->setFieldInitializers( FieldInitializers((size_t)numFieldInitializers)); } + fun->initLazyScript(lazy); } } // Code closed-over bindings. MOZ_TRY(XDRLazyClosedOverBindings(xdr, lazy)); // Code inner functions. { RootedFunction func(cx); - GCPtrFunction* innerFunctions = lazy->innerFunctions(); - size_t numInnerFunctions = lazy->numInnerFunctions(); - for (size_t i = 0; i < numInnerFunctions; i++) { + for (GCPtrFunction& elem : lazy->innerFunctions()) { if (mode == XDR_ENCODE) { - func = innerFunctions[i]; + func = elem.get(); } MOZ_TRY(XDRInterpretedFunction(xdr, nullptr, sourceObject, &func)); if (mode == XDR_DECODE) { - innerFunctions[i] = func; - if (innerFunctions[i]->isInterpretedLazy()) { - innerFunctions[i]->lazyScript()->setEnclosingLazyScript(lazy); + elem.init(func); + if (elem->isInterpretedLazy()) { + elem->lazyScript()->setEnclosingLazyScript(lazy); } } } } return Ok(); } @@ -4580,17 +4589,17 @@ void JSScript::traceChildren(JSTracer* t jit::TraceJitScripts(trc, this); if (trc->isMarkingTracer()) { GCMarker::fromTracer(trc)->markImplicitEdges(this); } } -void LazyScript::finalize(FreeOp* fop) { fop->free_(table_); } +void LazyScript::finalize(FreeOp* fop) { fop->free_(lazyData_); } size_t JSScript::calculateLiveFixed(jsbytecode* pc) { size_t nlivefixed = numAlwaysLiveFixedSlots(); if (nfixed() != nlivefixed) { Scope* scope = lookupScope(pc); if (scope) { scope = MaybeForwarded(scope); @@ -4804,26 +4813,110 @@ bool JSScript::formalIsAliased(unsigned } MOZ_CRASH("Argument slot not found"); } bool JSScript::formalLivesInArgumentsObject(unsigned argSlot) { return argsObjAliasesFormals() && !formalIsAliased(argSlot); } +/* static */ size_t LazyScriptData::AllocationSize( + uint32_t numClosedOverBindings, uint32_t numInnerFunctions) { + size_t size = sizeof(LazyScriptData); + + size += numClosedOverBindings * sizeof(GCPtrAtom); + size += numInnerFunctions * sizeof(GCPtrFunction); + + return size; +} + +// Placement-new elements of an array. This should optimize away for types with +// trivial default initiation. +template <typename T> +void LazyScriptData::initElements(size_t offset, size_t length) { + void* raw = offsetToPointer<void>(offset); + DefaultInitializeElements<T>(raw, length); +} + +LazyScriptData::LazyScriptData(uint32_t numClosedOverBindings, + uint32_t numInnerFunctions) + : numClosedOverBindings_(numClosedOverBindings), + numInnerFunctions_(numInnerFunctions) { + // Variable-length data begins immediately after LazyScriptData itself. + size_t cursor = sizeof(*this); + + // Default-initialize trailing arrays. + + static_assert(alignof(LazyScriptData) >= alignof(GCPtrAtom), + "Incompatible alignment"); + initElements<GCPtrAtom>(cursor, numClosedOverBindings); + cursor += numClosedOverBindings * sizeof(GCPtrAtom); + + static_assert(alignof(GCPtrAtom) >= alignof(GCPtrFunction), + "Incompatible alignment"); + initElements<GCPtrFunction>(cursor, numInnerFunctions); + cursor += numInnerFunctions * sizeof(GCPtrFunction); + + // Sanity check + MOZ_ASSERT(AllocationSize(numClosedOverBindings, numInnerFunctions) == + cursor); +} + +/* static */ LazyScriptData* LazyScriptData::new_( + JSContext* cx, uint32_t numClosedOverBindings, uint32_t numInnerFunctions) { + // Compute size including trailing arrays + size_t size = AllocationSize(numClosedOverBindings, numInnerFunctions); + + // Allocate contiguous raw buffer + void* raw = cx->pod_malloc<uint8_t>(size); + MOZ_ASSERT(uintptr_t(raw) % alignof(LazyScriptData) == 0); + if (!raw) { + return nullptr; + } + + // Constuct the LazyScriptData. Trailing arrays are uninitialized but + // GCPtrs are put into a safe state. + return new (raw) LazyScriptData(numClosedOverBindings, numInnerFunctions); +} + +mozilla::Span<GCPtrAtom> LazyScriptData::closedOverBindings() { + size_t offset = sizeof(LazyScriptData); + return mozilla::MakeSpan(offsetToPointer<GCPtrAtom>(offset), + numClosedOverBindings_); +} + +mozilla::Span<GCPtrFunction> LazyScriptData::innerFunctions() { + size_t offset = + sizeof(LazyScriptData) + sizeof(GCPtrAtom) * numClosedOverBindings_; + return mozilla::MakeSpan(offsetToPointer<GCPtrFunction>(offset), + numInnerFunctions_); +} + +void LazyScriptData::trace(JSTracer* trc) { + if (numClosedOverBindings_) { + auto array = closedOverBindings(); + TraceRange(trc, array.size(), array.data(), "closedOverBindings"); + } + + if (numInnerFunctions_) { + auto array = innerFunctions(); + TraceRange(trc, array.size(), array.data(), "innerFunctions"); + } +} + LazyScript::LazyScript(JSFunction* fun, ScriptSourceObject& sourceObject, - void* table, uint64_t packedFields, uint32_t sourceStart, - uint32_t sourceEnd, uint32_t toStringStart, - uint32_t lineno, uint32_t column) + LazyScriptData* data, uint32_t immutableFlags, + uint32_t sourceStart, uint32_t sourceEnd, + uint32_t toStringStart, uint32_t lineno, uint32_t column) : script_(nullptr), function_(fun), sourceObject_(&sourceObject), - table_(table), - packedFields_(packedFields), - fieldInitializers_(FieldInitializers::Invalid()), + lazyData_(data), + immutableFlags_(immutableFlags), + mutableFlags_(0), sourceStart_(sourceStart), sourceEnd_(sourceEnd), toStringStart_(toStringStart), toStringEnd_(sourceEnd), lineno_(lineno), column_(column) { MOZ_ASSERT(function_); MOZ_ASSERT(sourceObject_); @@ -4869,158 +4962,103 @@ ScriptSourceObject& LazyScript::sourceOb ScriptSource* LazyScript::maybeForwardedScriptSource() const { JSObject* source = MaybeForwarded(&sourceObject()); return UncheckedUnwrapWithoutExpose(source) ->as<ScriptSourceObject>() .source(); } -uint64_t LazyScript::packedFieldsForXDR() const { - union { - PackedView p; - uint64_t packedFields; - }; - - packedFields = packedFields_; - - // Reset runtime flags - p.hasBeenCloned = false; - - return packedFields; -} - /* static */ -LazyScript* LazyScript::CreateRaw(JSContext* cx, HandleFunction fun, +LazyScript* LazyScript::CreateRaw(JSContext* cx, uint32_t numClosedOverBindings, + uint32_t numInnerFunctions, + HandleFunction fun, HandleScriptSourceObject sourceObject, - uint64_t packedFields, uint32_t sourceStart, + uint32_t immutableFlags, uint32_t sourceStart, uint32_t sourceEnd, uint32_t toStringStart, uint32_t lineno, uint32_t column) { cx->check(fun); MOZ_ASSERT(sourceObject); - union { - PackedView p; - uint64_t packed; - }; - - packed = packedFields; - - // Reset runtime flags to obtain a fresh LazyScript. - p.hasBeenCloned = false; - - size_t bytes = (p.numClosedOverBindings * sizeof(JSAtom*)) + - (p.numInnerFunctions * sizeof(GCPtrFunction)); - - UniquePtr<uint8_t, JS::FreePolicy> table; - if (bytes) { - table.reset(cx->pod_malloc<uint8_t>(bytes)); - if (!table) { + + // Allocate a LazyScriptData if it will not be empty. Lazy class constructors + // also need LazyScriptData for field lists. + Rooted<UniquePtr<LazyScriptData>> data(cx); + if (numClosedOverBindings || numInnerFunctions || fun->isClassConstructor()) { + data.reset( + LazyScriptData::new_(cx, numClosedOverBindings, numInnerFunctions)); + if (!data) { return nullptr; } } LazyScript* res = Allocate<LazyScript>(cx); if (!res) { return nullptr; } cx->realm()->scheduleDelazificationForDebugger(); return new (res) - LazyScript(fun, *sourceObject, table.release(), packed, sourceStart, - sourceEnd, toStringStart, lineno, column); + LazyScript(fun, *sourceObject, data.release(), immutableFlags, + sourceStart, sourceEnd, toStringStart, lineno, column); } /* static */ LazyScript* LazyScript::Create(JSContext* cx, HandleFunction fun, HandleScriptSourceObject sourceObject, const frontend::AtomVector& closedOverBindings, Handle<GCVector<JSFunction*, 8>> innerFunctions, uint32_t sourceStart, uint32_t sourceEnd, uint32_t toStringStart, uint32_t lineno, uint32_t column, frontend::ParseGoal parseGoal) { - union { - PackedView p; - uint64_t packedFields; - }; - - p.shouldDeclareArguments = false; - p.hasThisBinding = false; - p.isAsync = false; - p.hasRest = false; - p.numClosedOverBindings = closedOverBindings.length(); - p.numInnerFunctions = innerFunctions.length(); - p.isGenerator = false; - p.strict = false; - p.bindingsAccessedDynamically = false; - p.hasDebuggerStatement = false; - p.hasDirectEval = false; - p.isLikelyConstructorWrapper = false; - p.treatAsRunOnce = false; - p.isDerivedClassConstructor = false; - p.needsHomeObject = false; - p.isBinAST = false; - p.parseGoal = uint32_t(parseGoal); - - LazyScript* res = - LazyScript::CreateRaw(cx, fun, sourceObject, packedFields, sourceStart, - sourceEnd, toStringStart, lineno, column); + uint32_t immutableFlags = 0; + if (parseGoal == frontend::ParseGoal::Module) { + immutableFlags |= uint32_t(ImmutableFlags::IsModule); + } + + LazyScript* res = LazyScript::CreateRaw( + cx, closedOverBindings.length(), innerFunctions.length(), fun, + sourceObject, immutableFlags, sourceStart, sourceEnd, toStringStart, + lineno, column); if (!res) { return nullptr; } - JSAtom** resClosedOverBindings = res->closedOverBindings(); + mozilla::Span<GCPtrAtom> resClosedOverBindings = res->closedOverBindings(); for (size_t i = 0; i < res->numClosedOverBindings(); i++) { - resClosedOverBindings[i] = closedOverBindings[i]; - } - - GCPtrFunction* resInnerFunctions = res->innerFunctions(); + resClosedOverBindings[i].init(closedOverBindings[i]); + } + + mozilla::Span<GCPtrFunction> resInnerFunctions = res->innerFunctions(); for (size_t i = 0; i < res->numInnerFunctions(); i++) { resInnerFunctions[i].init(innerFunctions[i]); if (resInnerFunctions[i]->isInterpretedLazy()) { resInnerFunctions[i]->lazyScript()->setEnclosingLazyScript(res); } } return res; } /* static */ LazyScript* LazyScript::CreateForXDR( - JSContext* cx, HandleFunction fun, HandleScript script, - HandleScope enclosingScope, HandleScriptSourceObject sourceObject, - uint64_t packedFields, uint32_t sourceStart, uint32_t sourceEnd, - uint32_t toStringStart, uint32_t lineno, uint32_t column) { - // Dummy atom which is not a valid property name. - RootedAtom dummyAtom(cx, cx->names().comma); - - // Dummy function which is not a valid function as this is the one which is - // holding this lazy script. - HandleFunction dummyFun = fun; - - LazyScript* res = - LazyScript::CreateRaw(cx, fun, sourceObject, packedFields, sourceStart, - sourceEnd, toStringStart, lineno, column); + JSContext* cx, uint32_t numClosedOverBindings, uint32_t numInnerFunctions, + HandleFunction fun, HandleScript script, HandleScope enclosingScope, + HandleScriptSourceObject sourceObject, uint32_t immutableFlags, + uint32_t sourceStart, uint32_t sourceEnd, uint32_t toStringStart, + uint32_t toStringEnd, uint32_t lineno, uint32_t column) { + LazyScript* res = LazyScript::CreateRaw( + cx, numClosedOverBindings, numInnerFunctions, fun, sourceObject, + immutableFlags, sourceStart, sourceEnd, toStringStart, lineno, column); if (!res) { return nullptr; } - // Fill with dummies, to be GC-safe after the initialization of the free - // variables and inner functions. - size_t i, num; - JSAtom** closedOverBindings = res->closedOverBindings(); - for (i = 0, num = res->numClosedOverBindings(); i < num; i++) { - closedOverBindings[i] = dummyAtom; - } - - GCPtrFunction* functions = res->innerFunctions(); - for (i = 0, num = res->numInnerFunctions(); i < num; i++) { - functions[i].init(dummyFun); - } + res->setToStringEnd(toStringEnd); // Set the enclosing scope of the lazy function. This value should only be // set if we have a non-lazy enclosing script at this point. // LazyScript::enclosingScriptHasEverBeenCompiled relies on the enclosing // scope being non-null if we have ever been nested inside non-lazy // function. MOZ_ASSERT(!res->hasEnclosingScope()); if (enclosingScope) {
--- a/js/src/vm/JSScript.h +++ b/js/src/vm/JSScript.h @@ -1764,16 +1764,22 @@ class JSScript : public js::gc::TenuredC // Script came from eval(). IsForEval = 1 << 22, // Whether this is a top-level module script. IsModule = 1 << 23, // Whether this function needs a call object or named lambda environment. NeedsFunctionEnvironmentObjects = 1 << 24, + + // LazyScript flags + ShouldDeclareArguments = 1 << 25, + IsBinAST = 1 << 26, + HasDebuggerStatement = 1 << 27, + HasDirectEval = 1 << 28, }; private: // Note: don't make this a bitfield! It makes it hard to read these flags // from JIT code. uint32_t immutableFlags_ = 0; // Mutable flags typically store information about runtime or deoptimization @@ -2873,16 +2879,57 @@ struct FieldInitializers { : #ifdef DEBUG valid(false), #endif numFieldInitializers(0) { } }; +// Variable-length data for LazyScripts. Contains vector of inner functions and +// vector of captured property ids. +class alignas(uintptr_t) LazyScriptData final { + private: + uint32_t numClosedOverBindings_ = 0; + uint32_t numInnerFunctions_ = 0; + + FieldInitializers fieldInitializers_ = FieldInitializers::Invalid(); + + // Size to allocate + static size_t AllocationSize(uint32_t numClosedOverBindings, + uint32_t numInnerFunctions); + + // Translate an offset into a concrete pointer. + template <typename T> + T* offsetToPointer(size_t offset) { + uintptr_t base = reinterpret_cast<uintptr_t>(this); + return reinterpret_cast<T*>(base + offset); + } + + template <typename T> + void initElements(size_t offset, size_t length); + + LazyScriptData(uint32_t numClosedOverBindings, uint32_t numInnerFunctions); + + public: + static LazyScriptData* new_(JSContext* cx, uint32_t numClosedOverBindings, + uint32_t numInnerFunctions); + + friend class LazyScript; + + mozilla::Span<GCPtrAtom> closedOverBindings(); + mozilla::Span<GCPtrFunction> innerFunctions(); + + void trace(JSTracer* trc); + + // LazyScriptData has trailing data so isn't copyable or movable. + LazyScriptData(const LazyScriptData&) = delete; + LazyScriptData& operator=(const LazyScriptData&) = delete; +}; + // Information about a script which may be (or has been) lazily compiled to // bytecode from its source. class LazyScript : public gc::TenuredCell { // If non-nullptr, the script has been compiled and this is a forwarding // pointer to the result. This is a weak pointer: after relazification, we // can collect the script if there are no other pointers to it. WeakRef<JSScript*> script_; @@ -2965,115 +3012,97 @@ class LazyScript : public gc::TenuredCel // | enclosing Scope |<-------------+ // +-----------------+ GCPtr<TenuredCell*> enclosingLazyScriptOrScope_; // ScriptSourceObject. We leave this set to nullptr until we generate // bytecode for our immediate parent. GCPtr<ScriptSourceObject*> sourceObject_; - // Heap allocated table with any free variables or inner functions. - void* table_; + // Heap allocated table with any free variables, inner functions, or class + // fields. This will be nullptr if none exist. + LazyScriptData* lazyData_; static const uint32_t NumClosedOverBindingsBits = 20; static const uint32_t NumInnerFunctionsBits = 20; - struct PackedView { - uint32_t shouldDeclareArguments : 1; - uint32_t hasThisBinding : 1; - uint32_t isAsync : 1; - uint32_t isBinAST : 1; - - uint32_t numClosedOverBindings : NumClosedOverBindingsBits; - - // -- 32bit boundary -- - - uint32_t numInnerFunctions : NumInnerFunctionsBits; - - // N.B. These are booleans but need to be uint32_t to pack correctly on - // MSVC. If you add another boolean here, make sure to initialize it in - // LazyScript::Create(). - uint32_t isGenerator : 1; - uint32_t strict : 1; - uint32_t bindingsAccessedDynamically : 1; - uint32_t hasDebuggerStatement : 1; - uint32_t hasDirectEval : 1; - uint32_t isLikelyConstructorWrapper : 1; - uint32_t treatAsRunOnce : 1; - uint32_t isDerivedClassConstructor : 1; - uint32_t needsHomeObject : 1; - uint32_t hasRest : 1; - uint32_t parseGoal : 1; - - // Runtime flags - uint32_t hasBeenCloned : 1; - }; - - union { - PackedView p_; - uint64_t packedFields_; - }; - - FieldInitializers fieldInitializers_; + // See: JSScript::ImmutableFlags / MutableFlags. + // NOTE: Lazy script only defines and uses a subset of these flags. + using ImmutableFlags = JSScript::ImmutableFlags; + using MutableFlags = JSScript::MutableFlags; + + uint32_t immutableFlags_; + uint32_t mutableFlags_; + + MOZ_MUST_USE bool hasFlag(MutableFlags flag) const { + return mutableFlags_ & uint32_t(flag); + } + void setFlag(MutableFlags flag) { mutableFlags_ |= uint32_t(flag); } + + MOZ_MUST_USE bool hasFlag(ImmutableFlags flag) const { + return immutableFlags_ & uint32_t(flag); + } + void setFlag(ImmutableFlags flag) { immutableFlags_ |= uint32_t(flag); } // Source location for the script. // See the comment in JSScript for the details uint32_t sourceStart_; uint32_t sourceEnd_; uint32_t toStringStart_; uint32_t toStringEnd_; // Line and column of |begin_| position, that is the position where we // start parsing. uint32_t lineno_; uint32_t column_; - LazyScript(JSFunction* fun, ScriptSourceObject& sourceObject, void* table, - uint64_t packedFields, uint32_t begin, uint32_t end, - uint32_t toStringStart, uint32_t lineno, uint32_t column); + LazyScript(JSFunction* fun, ScriptSourceObject& sourceObject, + LazyScriptData* data, uint32_t immutableFlags, + uint32_t sourceStart, uint32_t sourceEnd, uint32_t toStringStart, + uint32_t lineno, uint32_t column); // Create a LazyScript without initializing the closedOverBindings and the // innerFunctions. To be GC-safe, the caller must initialize both vectors // with valid atoms and functions. - static LazyScript* CreateRaw(JSContext* cx, HandleFunction fun, + static LazyScript* CreateRaw(JSContext* cx, uint32_t numClosedOverBindings, + uint32_t numInnerFunctions, HandleFunction fun, HandleScriptSourceObject sourceObject, - uint64_t packedData, uint32_t begin, - uint32_t end, uint32_t toStringStart, + uint32_t immutableFlags, uint32_t sourceStart, + uint32_t sourceEnd, uint32_t toStringStart, uint32_t lineno, uint32_t column); public: static const uint32_t NumClosedOverBindingsLimit = 1 << NumClosedOverBindingsBits; static const uint32_t NumInnerFunctionsLimit = 1 << NumInnerFunctionsBits; // Create a LazyScript and initialize closedOverBindings and innerFunctions // with the provided vectors. static LazyScript* Create(JSContext* cx, HandleFunction fun, HandleScriptSourceObject sourceObject, const frontend::AtomVector& closedOverBindings, Handle<GCVector<JSFunction*, 8>> innerFunctions, - uint32_t begin, uint32_t end, + uint32_t sourceStart, uint32_t sourceEnd, uint32_t toStringStart, uint32_t lineno, uint32_t column, frontend::ParseGoal parseGoal); // Create a LazyScript and initialize the closedOverBindings and the // innerFunctions with dummy values to be replaced in a later initialization // phase. // // The "script" argument to this function can be null. If it's non-null, // then this LazyScript should be associated with the given JSScript. // // The sourceObject and enclosingScope arguments may be null if the // enclosing function is also lazy. - static LazyScript* CreateForXDR(JSContext* cx, HandleFunction fun, - HandleScript script, - HandleScope enclosingScope, - HandleScriptSourceObject sourceObject, - uint64_t packedData, uint32_t begin, - uint32_t end, uint32_t toStringStart, - uint32_t lineno, uint32_t column); + static LazyScript* CreateForXDR( + JSContext* cx, uint32_t numClosedOverBindings, uint32_t numInnerFunctions, + HandleFunction fun, HandleScript script, HandleScope enclosingScope, + HandleScriptSourceObject sourceObject, uint32_t immutableFlags, + uint32_t sourceStart, uint32_t sourceEnd, uint32_t toStringStart, + uint32_t toStringEnd, uint32_t lineno, uint32_t column); static inline JSFunction* functionDelazifying(JSContext* cx, Handle<LazyScript*>); JSFunction* functionNonDelazifying() const { return function_; } JS::Compartment* compartment() const; JS::Compartment* maybeCompartment() const { return compartment(); } Realm* realm() const; @@ -3111,106 +3140,143 @@ class LazyScript : public gc::TenuredCel return enclosingScope()->hasOnChain(ScopeKind::NonSyntactic); } ScriptSourceObject& sourceObject() const; ScriptSource* scriptSource() const { return sourceObject().source(); } ScriptSource* maybeForwardedScriptSource() const; bool mutedErrors() const { return scriptSource()->mutedErrors(); } - uint32_t numClosedOverBindings() const { return p_.numClosedOverBindings; } - JSAtom** closedOverBindings() { return (JSAtom**)table_; } - - uint32_t numInnerFunctions() const { return p_.numInnerFunctions; } - GCPtrFunction* innerFunctions() { - return (GCPtrFunction*)&closedOverBindings()[numClosedOverBindings()]; + mozilla::Span<GCPtrAtom> closedOverBindings() { + return lazyData_ ? lazyData_->closedOverBindings() + : mozilla::Span<GCPtrAtom>(); + } + uint32_t numClosedOverBindings() const { + return lazyData_ ? lazyData_->closedOverBindings().size() : 0; + }; + + mozilla::Span<GCPtrFunction> innerFunctions() { + return lazyData_ ? lazyData_->innerFunctions() + : mozilla::Span<GCPtrFunction>(); + } + uint32_t numInnerFunctions() const { + return lazyData_ ? lazyData_->innerFunctions().size() : 0; } GeneratorKind generatorKind() const { - return p_.isGenerator ? GeneratorKind::Generator - : GeneratorKind::NotGenerator; + return hasFlag(ImmutableFlags::IsGenerator) ? GeneratorKind::Generator + : GeneratorKind::NotGenerator; } bool isGenerator() const { return generatorKind() == GeneratorKind::Generator; } void setGeneratorKind(GeneratorKind kind) { // A script only gets its generator kind set as part of initialization, // so it can only transition from NotGenerator. MOZ_ASSERT(!isGenerator()); - p_.isGenerator = kind == GeneratorKind::Generator; + if (kind == GeneratorKind::Generator) { + setFlag(ImmutableFlags::IsGenerator); + } } + bool isAsync() const { return hasFlag(ImmutableFlags::IsAsync); } FunctionAsyncKind asyncKind() const { - return p_.isAsync ? FunctionAsyncKind::AsyncFunction - : FunctionAsyncKind::SyncFunction; + return isAsync() ? FunctionAsyncKind::AsyncFunction + : FunctionAsyncKind::SyncFunction; } - bool isAsync() const { return p_.isAsync; } void setAsyncKind(FunctionAsyncKind kind) { - p_.isAsync = kind == FunctionAsyncKind::AsyncFunction; + if (kind == FunctionAsyncKind::AsyncFunction) { + setFlag(ImmutableFlags::IsAsync); + } } - bool hasRest() const { return p_.hasRest; } - void setHasRest() { p_.hasRest = true; } + bool hasRest() const { return hasFlag(ImmutableFlags::HasRest); } + void setHasRest() { setFlag(ImmutableFlags::HasRest); } frontend::ParseGoal parseGoal() const { - return frontend::ParseGoal(p_.parseGoal); + if (hasFlag(ImmutableFlags::IsModule)) { + return frontend::ParseGoal::Module; + } + return frontend::ParseGoal::Script; } - bool isBinAST() const { return p_.isBinAST; } - void setIsBinAST() { p_.isBinAST = true; } - - bool strict() const { return p_.strict; } - void setStrict() { p_.strict = true; } + bool isBinAST() const { return hasFlag(ImmutableFlags::IsBinAST); } + void setIsBinAST() { setFlag(ImmutableFlags::IsBinAST); } + + bool strict() const { return hasFlag(ImmutableFlags::Strict); } + void setStrict() { setFlag(ImmutableFlags::Strict); } bool bindingsAccessedDynamically() const { - return p_.bindingsAccessedDynamically; + return hasFlag(ImmutableFlags::BindingsAccessedDynamically); } void setBindingsAccessedDynamically() { - p_.bindingsAccessedDynamically = true; + setFlag(ImmutableFlags::BindingsAccessedDynamically); + } + + bool hasDebuggerStatement() const { + return hasFlag(ImmutableFlags::HasDebuggerStatement); } - - bool hasDebuggerStatement() const { return p_.hasDebuggerStatement; } - void setHasDebuggerStatement() { p_.hasDebuggerStatement = true; } - - bool hasDirectEval() const { return p_.hasDirectEval; } - void setHasDirectEval() { p_.hasDirectEval = true; } + void setHasDebuggerStatement() { + setFlag(ImmutableFlags::HasDebuggerStatement); + } + + bool hasDirectEval() const { return hasFlag(ImmutableFlags::HasDirectEval); } + void setHasDirectEval() { setFlag(ImmutableFlags::HasDirectEval); } bool isLikelyConstructorWrapper() const { - return p_.isLikelyConstructorWrapper; + return hasFlag(ImmutableFlags::IsLikelyConstructorWrapper); + } + void setLikelyConstructorWrapper() { + setFlag(ImmutableFlags::IsLikelyConstructorWrapper); } - void setLikelyConstructorWrapper() { p_.isLikelyConstructorWrapper = true; } - - bool hasBeenCloned() const { return p_.hasBeenCloned; } - void setHasBeenCloned() { p_.hasBeenCloned = true; } - - bool treatAsRunOnce() const { return p_.treatAsRunOnce; } - void setTreatAsRunOnce() { p_.treatAsRunOnce = true; } + + bool hasBeenCloned() const { return hasFlag(MutableFlags::HasBeenCloned); } + void setHasBeenCloned() { setFlag(MutableFlags::HasBeenCloned); } + + bool treatAsRunOnce() const { + return hasFlag(ImmutableFlags::TreatAsRunOnce); + } + void setTreatAsRunOnce() { setFlag(ImmutableFlags::TreatAsRunOnce); } bool isDerivedClassConstructor() const { - return p_.isDerivedClassConstructor; + return hasFlag(ImmutableFlags::IsDerivedClassConstructor); + } + void setIsDerivedClassConstructor() { + setFlag(ImmutableFlags::IsDerivedClassConstructor); + } + + bool needsHomeObject() const { + return hasFlag(ImmutableFlags::NeedsHomeObject); } - void setIsDerivedClassConstructor() { p_.isDerivedClassConstructor = true; } - - bool needsHomeObject() const { return p_.needsHomeObject; } - void setNeedsHomeObject() { p_.needsHomeObject = true; } - - bool shouldDeclareArguments() const { return p_.shouldDeclareArguments; } - void setShouldDeclareArguments() { p_.shouldDeclareArguments = true; } - - bool hasThisBinding() const { return p_.hasThisBinding; } - void setHasThisBinding() { p_.hasThisBinding = true; } + void setNeedsHomeObject() { setFlag(ImmutableFlags::NeedsHomeObject); } + + bool shouldDeclareArguments() const { + return hasFlag(ImmutableFlags::ShouldDeclareArguments); + } + void setShouldDeclareArguments() { + setFlag(ImmutableFlags::ShouldDeclareArguments); + } + + bool hasThisBinding() const { + return hasFlag(ImmutableFlags::FunctionHasThisBinding); + } + void setHasThisBinding() { setFlag(ImmutableFlags::FunctionHasThisBinding); } void setFieldInitializers(FieldInitializers fieldInitializers) { - fieldInitializers_ = fieldInitializers; + MOZ_ASSERT(lazyData_); + lazyData_->fieldInitializers_ = fieldInitializers; } - FieldInitializers getFieldInitializers() const { return fieldInitializers_; } + FieldInitializers getFieldInitializers() const { + return lazyData_ ? lazyData_->fieldInitializers_ + : FieldInitializers::Invalid(); + } const char* filename() const { return scriptSource()->filename(); } uint32_t sourceStart() const { return sourceStart_; } uint32_t sourceEnd() const { return sourceEnd_; } uint32_t sourceLength() const { return sourceEnd_ - sourceStart_; } uint32_t toStringStart() const { return toStringStart_; } uint32_t toStringEnd() const { return toStringEnd_; } uint32_t lineno() const { return lineno_; } @@ -3234,20 +3300,20 @@ class LazyScript : public gc::TenuredCel friend class GCMarker; void traceChildren(JSTracer* trc); void finalize(js::FreeOp* fop); static const JS::TraceKind TraceKind = JS::TraceKind::LazyScript; size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) { - return mallocSizeOf(table_); + return mallocSizeOf(lazyData_); } - uint64_t packedFieldsForXDR() const; + uint32_t immutableFlags() const { return immutableFlags_; } }; /* If this fails, add/remove padding within LazyScript. */ static_assert(sizeof(LazyScript) % js::gc::CellAlignBytes == 0, "Size of LazyScript must be an integral multiple of " "js::gc::CellAlignBytes"); struct ScriptAndCounts {
--- a/js/src/vm/RegExpConstants.h +++ b/js/src/vm/RegExpConstants.h @@ -6,34 +6,16 @@ #ifndef vm_RegExpConstants_h #define vm_RegExpConstants_h #include "builtin/SelfHostingDefines.h" namespace js { -enum RegExpFlag : uint8_t { - IgnoreCaseFlag = 0x01, - GlobalFlag = 0x02, - MultilineFlag = 0x04, - StickyFlag = 0x08, - UnicodeFlag = 0x10, - - NoFlags = 0x00, - AllFlags = 0x1f -}; - -static_assert(IgnoreCaseFlag == REGEXP_IGNORECASE_FLAG && - GlobalFlag == REGEXP_GLOBAL_FLAG && - MultilineFlag == REGEXP_MULTILINE_FLAG && - StickyFlag == REGEXP_STICKY_FLAG && - UnicodeFlag == REGEXP_UNICODE_FLAG, - "Flag values should be in sync with self-hosted JS"); - enum RegExpRunStatus { RegExpRunStatus_Error, RegExpRunStatus_Success, RegExpRunStatus_Success_NotFound }; } /* namespace js */
--- a/js/src/vm/RegExpObject.cpp +++ b/js/src/vm/RegExpObject.cpp @@ -10,24 +10,26 @@ #include "mozilla/PodOperations.h" #include "builtin/String.h" #ifdef DEBUG # include "jsutil.h" #endif #include "builtin/RegExp.h" +#include "builtin/SelfHostingDefines.h" // REGEXP_*_FLAG #include "frontend/TokenStream.h" #include "gc/HashUtil.h" #ifdef DEBUG # include "irregexp/RegExpBytecode.h" #endif #include "irregexp/RegExpParser.h" #include "jit/VMFunctions.h" #include "js/RegExp.h" +#include "js/RegExpFlags.h" // JS::RegExpFlags #include "js/StableStringChars.h" #include "util/StringBuffer.h" #include "vm/MatchPairs.h" #include "vm/RegExpStatics.h" #include "vm/StringType.h" #include "vm/TraceLogging.h" #ifdef DEBUG # include "util/Unicode.h" @@ -37,33 +39,35 @@ #include "vm/JSObject-inl.h" #include "vm/NativeObject-inl.h" #include "vm/Shape-inl.h" using namespace js; using JS::AutoStableStringChars; using JS::CompileOptions; +using JS::RegExpFlag; +using JS::RegExpFlags; using js::frontend::TokenStream; using mozilla::ArrayLength; using mozilla::DebugOnly; using mozilla::PodCopy; using JS::AutoCheckCannotGC; -static_assert(IgnoreCaseFlag == JS::RegExpFlags::IgnoreCase, - "public/internal /i flag bits must agree"); -static_assert(GlobalFlag == JS::RegExpFlags::Global, - "public/internal /g flag bits must agree"); -static_assert(MultilineFlag == JS::RegExpFlags::Multiline, - "public/internal /m flag bits must agree"); -static_assert(StickyFlag == JS::RegExpFlags::Sticky, - "public/internal /y flag bits must agree"); -static_assert(UnicodeFlag == JS::RegExpFlags::Unicode, - "public/internal /u flag bits must agree"); +static_assert(RegExpFlag::Global == REGEXP_GLOBAL_FLAG, + "self-hosted JS and /g flag bits must agree"); +static_assert(RegExpFlag::IgnoreCase == REGEXP_IGNORECASE_FLAG, + "self-hosted JS and /i flag bits must agree"); +static_assert(RegExpFlag::Multiline == REGEXP_MULTILINE_FLAG, + "self-hosted JS and /m flag bits must agree"); +static_assert(RegExpFlag::Unicode == REGEXP_UNICODE_FLAG, + "self-hosted JS and /u flag bits must agree"); +static_assert(RegExpFlag::Sticky == REGEXP_STICKY_FLAG, + "self-hosted JS and /y flag bits must agree"); RegExpObject* js::RegExpAlloc(JSContext* cx, NewObjectKind newKind, HandleObject proto /* = nullptr */) { Rooted<RegExpObject*> regexp( cx, NewObjectWithClassProto<RegExpObject>(cx, proto, newKind)); if (!regexp) { return nullptr; } @@ -112,35 +116,35 @@ RegExpShared* RegExpObject::getShared(JS if (regexp->hasShared()) { return regexp->sharedRef(); } return createShared(cx, regexp); } /* static */ -bool RegExpObject::isOriginalFlagGetter(JSNative native, RegExpFlag* mask) { +bool RegExpObject::isOriginalFlagGetter(JSNative native, RegExpFlags* mask) { if (native == regexp_global) { - *mask = GlobalFlag; + *mask = RegExpFlag::Global; return true; } if (native == regexp_ignoreCase) { - *mask = IgnoreCaseFlag; + *mask = RegExpFlag::IgnoreCase; return true; } if (native == regexp_multiline) { - *mask = MultilineFlag; + *mask = RegExpFlag::Multiline; return true; } if (native == regexp_sticky) { - *mask = StickyFlag; + *mask = RegExpFlag::Sticky; return true; } if (native == regexp_unicode) { - *mask = UnicodeFlag; + *mask = RegExpFlag::Unicode; return true; } return false; } /* static */ void RegExpObject::trace(JSTracer* trc, JSObject* obj) { @@ -193,83 +197,83 @@ const Class RegExpObject::class_ = { &RegExpObjectClassOps, &RegExpObjectClassSpec}; const Class RegExpObject::protoClass_ = { js_Object_str, JSCLASS_HAS_CACHED_PROTO(JSProto_RegExp), JS_NULL_CLASS_OPS, &RegExpObjectClassSpec}; template <typename CharT> RegExpObject* RegExpObject::create(JSContext* cx, const CharT* chars, - size_t length, RegExpFlag flags, + size_t length, RegExpFlags flags, frontend::TokenStreamAnyChars& tokenStream, NewObjectKind newKind) { static_assert(mozilla::IsSame<CharT, char16_t>::value, "this code may need updating if/when CharT encodes UTF-8"); RootedAtom source(cx, AtomizeChars(cx, chars, length)); if (!source) { return nullptr; } return create(cx, source, flags, tokenStream, newKind); } template RegExpObject* RegExpObject::create( - JSContext* cx, const char16_t* chars, size_t length, RegExpFlag flags, + JSContext* cx, const char16_t* chars, size_t length, RegExpFlags flags, frontend::TokenStreamAnyChars& tokenStream, NewObjectKind newKind); template <typename CharT> RegExpObject* RegExpObject::create(JSContext* cx, const CharT* chars, - size_t length, RegExpFlag flags, + size_t length, RegExpFlags flags, NewObjectKind newKind) { static_assert(mozilla::IsSame<CharT, char16_t>::value, "this code may need updating if/when CharT encodes UTF-8"); RootedAtom source(cx, AtomizeChars(cx, chars, length)); if (!source) { return nullptr; } return create(cx, source, flags, newKind); } template RegExpObject* RegExpObject::create(JSContext* cx, const char16_t* chars, - size_t length, RegExpFlag flags, + size_t length, RegExpFlags flags, NewObjectKind newKind); RegExpObject* RegExpObject::create(JSContext* cx, HandleAtom source, - RegExpFlag flags, + RegExpFlags flags, frontend::TokenStreamAnyChars& tokenStream, NewObjectKind newKind) { LifoAllocScope allocScope(&cx->tempLifoAlloc()); if (!irregexp::ParsePatternSyntax(tokenStream, allocScope.alloc(), source, - flags & UnicodeFlag)) { + flags.unicode())) { return nullptr; } Rooted<RegExpObject*> regexp(cx, RegExpAlloc(cx, newKind)); if (!regexp) { return nullptr; } regexp->initAndZeroLastIndex(source, flags, cx); return regexp; } RegExpObject* RegExpObject::create(JSContext* cx, HandleAtom source, - RegExpFlag flags, NewObjectKind newKind) { + RegExpFlags flags, NewObjectKind newKind) { CompileOptions dummyOptions(cx); TokenStream dummyTokenStream(cx, dummyOptions, (const char16_t*)nullptr, 0, nullptr); LifoAllocScope allocScope(&cx->tempLifoAlloc()); if (!irregexp::ParsePatternSyntax(dummyTokenStream, allocScope.alloc(), - source, flags & UnicodeFlag)) { + source, flags.unicode())) { return nullptr; } Rooted<RegExpObject*> regexp(cx, RegExpAlloc(cx, newKind)); if (!regexp) { return nullptr; } @@ -299,26 +303,26 @@ Shape* RegExpObject::assignInitialShape( JS_STATIC_ASSERT(LAST_INDEX_SLOT == 0); /* The lastIndex property alone is writable but non-configurable. */ return NativeObject::addDataProperty(cx, self, cx->names().lastIndex, LAST_INDEX_SLOT, JSPROP_PERMANENT); } -void RegExpObject::initIgnoringLastIndex(JSAtom* source, RegExpFlag flags) { +void RegExpObject::initIgnoringLastIndex(JSAtom* source, RegExpFlags flags) { // If this is a re-initialization with an existing RegExpShared, 'flags' // may not match getShared()->flags, so forget the RegExpShared. sharedRef() = nullptr; setSource(source); setFlags(flags); } -void RegExpObject::initAndZeroLastIndex(JSAtom* source, RegExpFlag flags, +void RegExpObject::initAndZeroLastIndex(JSAtom* source, RegExpFlags flags, JSContext* cx) { initIgnoringLastIndex(source, flags); zeroLastIndex(cx); } static MOZ_ALWAYS_INLINE bool IsRegExpLineTerminator(const JS::Latin1Char c) { return c == '\n' || c == '\r'; } @@ -893,17 +897,17 @@ bool js::StringHasRegExpMetaChars(JSLine return HasRegExpMetaChars(str->latin1Chars(nogc), str->length()); } return HasRegExpMetaChars(str->twoByteChars(nogc), str->length()); } /* RegExpShared */ -RegExpShared::RegExpShared(JSAtom* source, RegExpFlag flags) +RegExpShared::RegExpShared(JSAtom* source, RegExpFlags flags) : source(source), flags(flags), canStringMatch(false), parenCount(0) {} void RegExpShared::traceChildren(JSTracer* trc) { // Discard code to avoid holding onto ExecutablePools. if (IsMarkingTrace(trc) && trc->runtime()->gc.isShrinkingGC()) { discardJitCode(); } @@ -951,19 +955,17 @@ bool RegExpShared::compile(JSContext* cx CompileOptions options(cx); frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr); /* Parse the pattern. The RegExpCompileData is allocated in LifoAlloc and * will only be live while LifoAllocScope is on stack. */ LifoAllocScope allocScope(&cx->tempLifoAlloc()); irregexp::RegExpCompileData data; if (!irregexp::ParsePattern(dummyTokenStream, allocScope.alloc(), pattern, - re->multiline(), mode == MatchOnly, re->unicode(), - re->ignoreCase(), re->global(), re->sticky(), - &data)) { + mode == MatchOnly, re->getFlags(), &data)) { return false; } re->parenCount = data.capture_count; JitCodeTables tables; irregexp::RegExpCode code = irregexp::CompilePattern( cx, allocScope.alloc(), re, &data, input, false /* global() */, @@ -1245,17 +1247,17 @@ void RegExpRealm::sweep() { if (optimizableRegExpInstanceShape_ && IsAboutToBeFinalized(&optimizableRegExpInstanceShape_)) { optimizableRegExpInstanceShape_.set(nullptr); } } RegExpShared* RegExpZone::get(JSContext* cx, HandleAtom source, - RegExpFlag flags) { + RegExpFlags flags) { DependentAddPtr<Set> p(cx, set_, Key(source, flags)); if (p) { return *p; } auto shared = Allocate<RegExpShared>(cx); if (!shared) { return nullptr; @@ -1267,17 +1269,17 @@ RegExpShared* RegExpZone::get(JSContext* ReportOutOfMemory(cx); return nullptr; } return shared; } RegExpShared* RegExpZone::get(JSContext* cx, HandleAtom atom, JSString* opt) { - RegExpFlag flags = RegExpFlag(0); + RegExpFlags flags = RegExpFlag::NoFlags; if (opt && !ParseRegExpFlags(cx, opt, &flags)) { return nullptr; } return get(cx, atom, flags); } size_t RegExpZone::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) { @@ -1310,53 +1312,53 @@ JSObject* js::CloneRegExpObject(JSContex clone->initAndZeroLastIndex(shared->getSource(), shared->getFlags(), cx); clone->setShared(*shared); return clone; } template <typename CharT> static bool ParseRegExpFlags(const CharT* chars, size_t length, - RegExpFlag* flagsOut, char16_t* invalidFlag) { - *flagsOut = RegExpFlag(0); + RegExpFlags* flagsOut, char16_t* invalidFlag) { + *flagsOut = RegExpFlag::NoFlags; for (size_t i = 0; i < length; i++) { - RegExpFlag flag; + uint8_t flag; switch (chars[i]) { + case 'g': + flag = RegExpFlag::Global; + break; case 'i': - flag = IgnoreCaseFlag; - break; - case 'g': - flag = GlobalFlag; + flag = RegExpFlag::IgnoreCase; break; case 'm': - flag = MultilineFlag; + flag = RegExpFlag::Multiline; + break; + case 'u': + flag = RegExpFlag::Unicode; break; case 'y': - flag = StickyFlag; - break; - case 'u': - flag = UnicodeFlag; + flag = RegExpFlag::Sticky; break; default: *invalidFlag = chars[i]; return false; } if (*flagsOut & flag) { *invalidFlag = chars[i]; return false; } - *flagsOut = RegExpFlag(*flagsOut | flag); + *flagsOut |= flag; } return true; } bool js::ParseRegExpFlags(JSContext* cx, JSString* flagStr, - RegExpFlag* flagsOut) { + RegExpFlags* flagsOut) { JSLinearString* linear = flagStr->ensureLinear(cx); if (!linear) { return false; } size_t len = linear->length(); bool ok; @@ -1386,29 +1388,29 @@ bool js::ParseRegExpFlags(JSContext* cx, } template <XDRMode mode> XDRResult js::XDRScriptRegExpObject(XDRState<mode>* xdr, MutableHandle<RegExpObject*> objp) { /* NB: Keep this in sync with CloneScriptRegExpObject. */ RootedAtom source(xdr->cx()); - uint32_t flagsword = 0; + uint8_t flags = 0; if (mode == XDR_ENCODE) { MOZ_ASSERT(objp); RegExpObject& reobj = *objp; source = reobj.getSource(); - flagsword = reobj.getFlags(); + flags = reobj.getFlags().value(); } MOZ_TRY(XDRAtom(xdr, &source)); - MOZ_TRY(xdr->codeUint32(&flagsword)); + MOZ_TRY(xdr->codeUint8(&flags)); if (mode == XDR_DECODE) { RegExpObject* reobj = RegExpObject::create( - xdr->cx(), source, RegExpFlag(flagsword), TenuredObject); + xdr->cx(), source, RegExpFlags(flags), TenuredObject); if (!reobj) { return xdr->fail(JS::TranscodeResult_Throw); } objp.set(reobj); } return Ok(); } @@ -1438,37 +1440,36 @@ JS::ubi::Node::Size JS::ubi::Concrete<Re return js::gc::Arena::thingSize(gc::AllocKind::REGEXP_SHARED) + get().sizeOfExcludingThis(mallocSizeOf); } /* * Regular Expressions. */ JS_PUBLIC_API JSObject* JS::NewRegExpObject(JSContext* cx, const char* bytes, - size_t length, unsigned flags) { + size_t length, RegExpFlags flags) { AssertHeapIsIdle(); CHECK_THREAD(cx); UniqueTwoByteChars chars(InflateString(cx, bytes, length)); if (!chars) { return nullptr; } - return RegExpObject::create(cx, chars.get(), length, RegExpFlag(flags), - GenericObject); + return RegExpObject::create(cx, chars.get(), length, flags, GenericObject); } JS_PUBLIC_API JSObject* JS::NewUCRegExpObject(JSContext* cx, const char16_t* chars, - size_t length, unsigned flags) { + size_t length, + RegExpFlags flags) { AssertHeapIsIdle(); CHECK_THREAD(cx); - return RegExpObject::create(cx, chars, length, RegExpFlag(flags), - GenericObject); + return RegExpObject::create(cx, chars, length, flags, GenericObject); } JS_PUBLIC_API bool JS::SetRegExpInput(JSContext* cx, HandleObject obj, HandleString input) { AssertHeapIsIdle(); CHECK_THREAD(cx); cx->check(input); @@ -1543,23 +1544,23 @@ JS_PUBLIC_API bool JS::ObjectIsRegExp(JS if (!GetBuiltinClass(cx, obj, &cls)) { return false; } *isRegExp = cls == ESClass::RegExp; return true; } -JS_PUBLIC_API unsigned JS::GetRegExpFlags(JSContext* cx, HandleObject obj) { +JS_PUBLIC_API RegExpFlags JS::GetRegExpFlags(JSContext* cx, HandleObject obj) { AssertHeapIsIdle(); CHECK_THREAD(cx); RegExpShared* shared = RegExpToShared(cx, obj); if (!shared) { - return false; + return RegExpFlag::NoFlags; } return shared->getFlags(); } JS_PUBLIC_API JSString* JS::GetRegExpSource(JSContext* cx, HandleObject obj) { AssertHeapIsIdle(); CHECK_THREAD(cx);
--- a/js/src/vm/RegExpObject.h +++ b/js/src/vm/RegExpObject.h @@ -10,16 +10,17 @@ #define vm_RegExpObject_h #include "mozilla/Attributes.h" #include "mozilla/MemoryReporting.h" #include "builtin/SelfHostingDefines.h" #include "gc/Marking.h" #include "js/GCHashTable.h" +#include "js/RegExpFlags.h" #include "proxy/Proxy.h" #include "vm/ArrayObject.h" #include "vm/JSContext.h" #include "vm/RegExpShared.h" #include "vm/Shape.h" /* * JavaScript Regular Expressions @@ -65,29 +66,29 @@ class RegExpObject : public NativeObject static const Class protoClass_; // The maximum number of pairs a MatchResult can have, without having to // allocate a bigger MatchResult. static const size_t MaxPairCount = 14; template <typename CharT> static RegExpObject* create(JSContext* cx, const CharT* chars, size_t length, - RegExpFlag flags, NewObjectKind newKind); + JS::RegExpFlags flags, NewObjectKind newKind); template <typename CharT> static RegExpObject* create(JSContext* cx, const CharT* chars, size_t length, - RegExpFlag flags, + JS::RegExpFlags flags, frontend::TokenStreamAnyChars& ts, NewObjectKind kind); static RegExpObject* create(JSContext* cx, HandleAtom source, - RegExpFlag flags, NewObjectKind newKind); + JS::RegExpFlags flags, NewObjectKind newKind); static RegExpObject* create(JSContext* cx, HandleAtom source, - RegExpFlag flags, + JS::RegExpFlags flags, frontend::TokenStreamAnyChars& ts, NewObjectKind newKind); /* * Compute the initial shape to associate with fresh RegExp objects, * encoding their initial properties. Return the shape after * changing |obj|'s last property to it. */ @@ -126,28 +127,30 @@ class RegExpObject : public NativeObject } void setSource(JSAtom* source) { setSlot(SOURCE_SLOT, StringValue(source)); } /* Flags. */ static unsigned flagsSlot() { return FLAGS_SLOT; } - RegExpFlag getFlags() const { - return RegExpFlag(getFixedSlot(FLAGS_SLOT).toInt32()); + JS::RegExpFlags getFlags() const { + return JS::RegExpFlags(getFixedSlot(FLAGS_SLOT).toInt32()); } - void setFlags(RegExpFlag flags) { setSlot(FLAGS_SLOT, Int32Value(flags)); } + void setFlags(JS::RegExpFlags flags) { + setFixedSlot(FLAGS_SLOT, Int32Value(flags.value())); + } - bool ignoreCase() const { return getFlags() & IgnoreCaseFlag; } - bool global() const { return getFlags() & GlobalFlag; } - bool multiline() const { return getFlags() & MultilineFlag; } - bool sticky() const { return getFlags() & StickyFlag; } - bool unicode() const { return getFlags() & UnicodeFlag; } + bool global() const { return getFlags().global(); } + bool ignoreCase() const { return getFlags().ignoreCase(); } + bool multiline() const { return getFlags().multiline(); } + bool unicode() const { return getFlags().unicode(); } + bool sticky() const { return getFlags().sticky(); } - static bool isOriginalFlagGetter(JSNative native, RegExpFlag* mask); + static bool isOriginalFlagGetter(JSNative native, JS::RegExpFlags* mask); static RegExpShared* getShared(JSContext* cx, Handle<RegExpObject*> regexp); bool hasShared() { return !!sharedRef(); } void setShared(RegExpShared& shared) { MOZ_ASSERT(!hasShared()); sharedRef().init(&shared); @@ -156,22 +159,23 @@ class RegExpObject : public NativeObject HeapPtrRegExpShared& sharedRef() { auto& ref = NativeObject::privateRef(PRIVATE_SLOT); return reinterpret_cast<HeapPtrRegExpShared&>(ref); } static void trace(JSTracer* trc, JSObject* obj); void trace(JSTracer* trc); - void initIgnoringLastIndex(JSAtom* source, RegExpFlag flags); + void initIgnoringLastIndex(JSAtom* source, JS::RegExpFlags flags); // NOTE: This method is *only* safe to call on RegExps that haven't been // exposed to script, because it requires that the "lastIndex" // property be writable. - void initAndZeroLastIndex(JSAtom* source, RegExpFlag flags, JSContext* cx); + void initAndZeroLastIndex(JSAtom* source, JS::RegExpFlags flags, + JSContext* cx); #ifdef DEBUG static MOZ_MUST_USE bool dumpBytecode(JSContext* cx, Handle<RegExpObject*> regexp, bool match_only, HandleLinearString input); #endif @@ -188,17 +192,18 @@ class RegExpObject : public NativeObject }; /* * Parse regexp flags. Report an error and return false if an invalid * sequence of flags is encountered (repeat/invalid flag). * * N.B. flagStr must be rooted. */ -bool ParseRegExpFlags(JSContext* cx, JSString* flagStr, RegExpFlag* flagsOut); +bool ParseRegExpFlags(JSContext* cx, JSString* flagStr, + JS::RegExpFlags* flagsOut); // Assuming GetBuiltinClass(obj) is ESClass::RegExp, return a RegExpShared for // obj. inline RegExpShared* RegExpToShared(JSContext* cx, HandleObject obj) { if (obj->is<RegExpObject>()) { return RegExpObject::getShared(cx, obj.as<RegExpObject>()); }
--- a/js/src/vm/RegExpShared.h +++ b/js/src/vm/RegExpShared.h @@ -16,16 +16,17 @@ #include "mozilla/Assertions.h" #include "mozilla/MemoryReporting.h" #include "gc/Barrier.h" #include "gc/Heap.h" #include "gc/Marking.h" #include "gc/Zone.h" #include "js/AllocPolicy.h" +#include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags #include "js/UbiNode.h" #include "js/Vector.h" #include "vm/ArrayObject.h" #include "vm/JSAtom.h" #include "vm/RegExpConstants.h" namespace js { @@ -78,17 +79,17 @@ class RegExpShared : public gc::TenuredC bool compiled(ForceByteCodeEnum force = DontForceByteCode) const { return byteCode || (force == DontForceByteCode && jitCode); } }; /* Source to the RegExp, for lazy compilation. */ GCPtr<JSAtom*> source; - RegExpFlag flags; + JS::RegExpFlags flags; bool canStringMatch; size_t parenCount; RegExpCompilation compilationArray[4]; static int CompilationIndex(CompilationMode mode, bool latin1) { switch (mode) { case Normal: @@ -98,17 +99,17 @@ class RegExpShared : public gc::TenuredC } MOZ_CRASH(); } // Tables referenced by JIT code. JitCodeTables tables; /* Internal functions. */ - RegExpShared(JSAtom* source, RegExpFlag flags); + RegExpShared(JSAtom* source, JS::RegExpFlags flags); static bool compile(JSContext* cx, MutableHandleRegExpShared res, HandleLinearString input, CompilationMode mode, ForceByteCodeEnum force); static bool compile(JSContext* cx, MutableHandleRegExpShared res, HandleAtom pattern, HandleLinearString input, CompilationMode mode, ForceByteCodeEnum force); @@ -143,22 +144,23 @@ class RegExpShared : public gc::TenuredC MOZ_ASSERT(isCompiled()); return parenCount; } /* Accounts for the "0" (whole match) pair. */ size_t pairCount() const { return getParenCount() + 1; } JSAtom* getSource() const { return source; } - RegExpFlag getFlags() const { return flags; } - bool ignoreCase() const { return flags & IgnoreCaseFlag; } - bool global() const { return flags & GlobalFlag; } - bool multiline() const { return flags & MultilineFlag; } - bool sticky() const { return flags & StickyFlag; } - bool unicode() const { return flags & UnicodeFlag; } + JS::RegExpFlags getFlags() const { return flags; } + + bool global() const { return flags.global(); } + bool ignoreCase() const { return flags.ignoreCase(); } + bool multiline() const { return flags.multiline(); } + bool unicode() const { return flags.unicode(); } + bool sticky() const { return flags.sticky(); } bool isCompiled(CompilationMode mode, bool latin1, ForceByteCodeEnum force = DontForceByteCode) const { return compilation(mode, latin1).compiled(force); } bool isCompiled() const { return isCompiled(Normal, true) || isCompiled(Normal, false) || isCompiled(MatchOnly, true) || isCompiled(MatchOnly, false); @@ -192,32 +194,32 @@ class RegExpShared : public gc::TenuredC #ifdef DEBUG static bool dumpBytecode(JSContext* cx, MutableHandleRegExpShared res, bool match_only, HandleLinearString input); #endif }; class RegExpZone { struct Key { - JSAtom* atom; - uint16_t flag; + JSAtom* atom = nullptr; + JS::RegExpFlags flags = JS::RegExpFlag::NoFlags; - Key() : atom(nullptr), flag(0) {} - Key(JSAtom* atom, RegExpFlag flag) : atom(atom), flag(flag) {} + Key() = default; + Key(JSAtom* atom, JS::RegExpFlags flags) : atom(atom), flags(flags) {} MOZ_IMPLICIT Key(const ReadBarriered<RegExpShared*>& shared) : atom(shared.unbarrieredGet()->getSource()), - flag(shared.unbarrieredGet()->getFlags()) {} + flags(shared.unbarrieredGet()->getFlags()) {} typedef Key Lookup; static HashNumber hash(const Lookup& l) { HashNumber hash = DefaultHasher<JSAtom*>::hash(l.atom); - return mozilla::AddToHash(hash, l.flag); + return mozilla::AddToHash(hash, l.flags.value()); } static bool match(Key l, Key r) { - return l.atom == r.atom && l.flag == r.flag; + return l.atom == r.atom && l.flags == r.flags; } }; /* * The set of all RegExpShareds in the zone. On every GC, every RegExpShared * that was not marked is deleted and removed from the set. */ using Set = JS::WeakCache< @@ -226,22 +228,22 @@ class RegExpZone { public: explicit RegExpZone(Zone* zone); ~RegExpZone() { MOZ_ASSERT(set_.empty()); } bool empty() const { return set_.empty(); } - RegExpShared* maybeGet(JSAtom* source, RegExpFlag flags) const { + RegExpShared* maybeGet(JSAtom* source, JS::RegExpFlags flags) const { Set::Ptr p = set_.lookup(Key(source, flags)); return p ? *p : nullptr; } - RegExpShared* get(JSContext* cx, HandleAtom source, RegExpFlag flags); + RegExpShared* get(JSContext* cx, HandleAtom source, JS::RegExpFlags flags); /* Like 'get', but compile 'maybeOpt' (if non-null). */ RegExpShared* get(JSContext* cx, HandleAtom source, JSString* maybeOpt); #ifdef DEBUG void clear() { set_.clear(); } #endif
--- a/js/src/vm/RegExpStatics.h +++ b/js/src/vm/RegExpStatics.h @@ -24,17 +24,17 @@ class RegExpStatics { HeapPtr<JSLinearString*> matchesInput; /* * The previous RegExp input, used to resolve lazy state. * A raw RegExpShared cannot be stored because it may be in * a different compartment via evalcx(). */ HeapPtr<JSAtom*> lazySource; - RegExpFlag lazyFlags; + JS::RegExpFlags lazyFlags; size_t lazyIndex; /* The latest RegExp input, set before execution. */ HeapPtr<JSString*> pendingInput; /* * If non-zero, |matchesInput| and the |lazy*| fields may be used * to replay the last executed RegExp, and |matches| is invalid. @@ -269,17 +269,17 @@ inline bool RegExpStatics::updateFromMat return true; } inline void RegExpStatics::clear() { matches.forgetArray(); matchesInput = nullptr; lazySource = nullptr; - lazyFlags = RegExpFlag(0); + lazyFlags = JS::RegExpFlag::NoFlags; lazyIndex = size_t(-1); pendingInput = nullptr; pendingLazyEvaluation = false; } inline void RegExpStatics::setPendingInput(JSString* newInput) { pendingInput = newInput; }
--- a/js/src/vm/StructuredClone.cpp +++ b/js/src/vm/StructuredClone.cpp @@ -23,16 +23,17 @@ * We serialize objects that appear in multiple places in the input as * backreferences, using sequential integer indexes. * See `JSStructuredCloneReader::allObjs`, our take on the "memory" map * in the spec's StructuredDeserialize. */ #include "js/StructuredClone.h" +#include "mozilla/Casting.h" #include "mozilla/CheckedInt.h" #include "mozilla/EndianUtils.h" #include "mozilla/FloatingPoint.h" #include "mozilla/RangedPtr.h" #include "mozilla/Unused.h" #include <algorithm> #include <memory> @@ -41,16 +42,17 @@ #include "jsapi.h" #include "jsdate.h" #include "builtin/DataViewObject.h" #include "builtin/MapObject.h" #include "js/ArrayBuffer.h" // JS::{ArrayBufferHasData,DetachArrayBuffer,IsArrayBufferObject,New{,Mapped}ArrayBufferWithContents,ReleaseMappedArrayBufferContents} #include "js/Date.h" #include "js/GCHashTable.h" +#include "js/RegExpFlags.h" // JS::RegExpFlags #include "js/SharedArrayBuffer.h" // JS::IsSharedArrayBufferObject #include "js/Wrapper.h" #include "vm/BigIntType.h" #include "vm/JSContext.h" #include "vm/RegExpObject.h" #include "vm/SavedFrame.h" #include "vm/SharedArrayObject.h" #include "vm/TypedArrayObject.h" @@ -59,17 +61,19 @@ #include "vm/InlineCharBuffer-inl.h" #include "vm/JSContext-inl.h" #include "vm/JSObject-inl.h" using namespace js; using JS::CanonicalizeNaN; +using JS::RegExpFlags; using JS::RootedValueVector; +using mozilla::AssertedCast; using mozilla::BitwiseCast; using mozilla::NativeEndian; using mozilla::NumbersAreIdentical; using mozilla::RangedPtr; // When you make updates here, make sure you consider whether you need to bump // the value of JS_STRUCTURED_CLONE_VERSION in js/public/StructuredClone.h. You // will likely need to increment the version if anything at all changes in the @@ -1664,17 +1668,17 @@ bool JSStructuredCloneWriter::startWrite } return out.writePair(SCTAG_BOOLEAN_OBJECT, unboxed.toBoolean()); } case ESClass::RegExp: { RegExpShared* re = RegExpToShared(context(), obj); if (!re) { return false; } - return out.writePair(SCTAG_REGEXP_OBJECT, re->getFlags()) && + return out.writePair(SCTAG_REGEXP_OBJECT, re->getFlags().value()) && writeString(SCTAG_STRING, re->getSource()); } case ESClass::ArrayBuffer: { if (JS::IsArrayBufferObject(obj) && JS::ArrayBufferHasData(obj)) { return writeArrayBuffer(obj); } break; } @@ -2443,17 +2447,17 @@ bool JSStructuredCloneReader::startRead( if (!obj) { return false; } vp.setObject(*obj); break; } case SCTAG_REGEXP_OBJECT: { - RegExpFlag flags = RegExpFlag(data); + RegExpFlags flags = AssertedCast<uint8_t>(data); uint32_t tag2, stringData; if (!in.readPair(&tag2, &stringData)) { return false; } if (tag2 != SCTAG_STRING) { JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr, JSMSG_SC_BAD_SERIALIZED_DATA, "regexp"); return false;
--- a/js/src/vm/TypeInference.cpp +++ b/js/src/vm/TypeInference.cpp @@ -2657,18 +2657,24 @@ void TypeZone::processPendingRecompiles( MOZ_ASSERT(recompiles.empty()); } void TypeZone::addPendingRecompile(JSContext* cx, const RecompileInfo& info) { InferSpew(ISpewOps, "addPendingRecompile: %p:%s:%u", info.script(), info.script()->filename(), info.script()->lineno()); AutoEnterOOMUnsafeRegion oomUnsafe; - if (!cx->zone()->types.activeAnalysis->pendingRecompiles.append(info)) { - oomUnsafe.crash("Could not update pendingRecompiles"); + RecompileInfoVector& vector = + cx->zone()->types.activeAnalysis->pendingRecompiles; + if (!vector.append(info)) { + // BUG 1536159: For diagnostics, compute the size of the failed allocation. + // This presumes the vector growth strategy is to double. This is only used + // for crash reporting so not a problem if we get it wrong. + size_t allocSize = 2 * sizeof(RecompileInfo) * vector.capacity(); + oomUnsafe.crash(allocSize, "Could not update pendingRecompiles"); } } void TypeZone::addPendingRecompile(JSContext* cx, JSScript* script) { MOZ_ASSERT(script); CancelOffThreadIonCompile(script);
--- a/js/xpconnect/src/XPCWrappedNativeInfo.cpp +++ b/js/xpconnect/src/XPCWrappedNativeInfo.cpp @@ -235,17 +235,18 @@ already_AddRefed<XPCNativeInterface> XPC nsAutoString filename; uint32_t lineno = 0, column = 0; nsJSUtils::GetCallingLocation(cx, filename, &lineno, &column); nsCOMPtr<nsIScriptError> error( do_CreateInstance(NS_SCRIPTERROR_CONTRACTID)); error->Init(NS_ConvertUTF8toUTF16(errorMsg), filename, EmptyString(), lineno, column, nsIScriptError::warningFlag, - "chrome javascript", false /* from private window */); + "chrome javascript", false /* from private window */, + true /* from chrome context */); console->LogMessage(error); } } uint16_t methodCount = aInfo->MethodCount(); uint16_t constCount = aInfo->ConstantCount(); // If the interface does not have nsISupports in its inheritance chain
--- a/layout/base/PresShell.cpp +++ b/layout/base/PresShell.cpp @@ -10202,17 +10202,18 @@ void ReflowCountMgr::PaintCount(const ch gfxPoint devPixelOffset = nsLayoutUtils::PointToGfxPoint(aOffset, appUnitsPerDevPixel); aRenderingContext->SetMatrixDouble( aRenderingContext->CurrentMatrixDouble().PreTranslate( devPixelOffset)); // We don't care about the document language or user fonts here; // just get a default Latin font. - nsFont font(eFamily_serif, nsPresContext::CSSPixelsToAppUnits(11)); + nsFont font(StyleGenericFontFamily::Serif, + nsPresContext::CSSPixelsToAppUnits(11)); nsFontMetrics::Params params; params.language = nsGkAtoms::x_western; params.textPerf = aPresContext->GetTextPerfMetrics(); params.featureValueLookup = aPresContext->GetFontFeatureValuesLookup(); RefPtr<nsFontMetrics> fm = aPresContext->DeviceContext()->GetMetricsFor(font, params); char buf[16];
--- a/layout/base/StaticPresData.cpp +++ b/layout/base/StaticPresData.cpp @@ -35,29 +35,27 @@ StaticPresData::StaticPresData() { #define MAKE_FONT_PREF_KEY(_pref, _s0, _s1) \ _pref.Assign(_s0); \ _pref.Append(_s1); // clang-format off static const char* const kGenericFont[] = { ".variable.", - ".fixed.", ".serif.", ".sans-serif.", ".monospace.", ".cursive.", ".fantasy." }; // clang-format on // These are private, use the list in nsFont.h if you want a public list. enum { eDefaultFont_Variable, - eDefaultFont_Fixed, eDefaultFont_Serif, eDefaultFont_SansSerif, eDefaultFont_Monospace, eDefaultFont_Cursive, eDefaultFont_Fantasy, eDefaultFont_COUNT }; @@ -88,31 +86,30 @@ void LangGroupFontPrefs::Initialize(nsSt font.minimum-size.[langGroup] = integer settable by the user */ nsAutoCString langGroup; aLangGroupAtom->ToUTF8String(langGroup); mDefaultVariableFont.size = nsPresContext::CSSPixelsToAppUnits(16); - mDefaultFixedFont.size = nsPresContext::CSSPixelsToAppUnits(13); + mDefaultMonospaceFont.size = nsPresContext::CSSPixelsToAppUnits(13); nsAutoCString pref; // get font.minimum-size.[langGroup] MAKE_FONT_PREF_KEY(pref, "font.minimum-size.", langGroup); int32_t size = Preferences::GetInt(pref.get()); mMinimumFontSize = nsPresContext::CSSPixelsToAppUnits(size); // clang-format off nsFont* fontTypes[] = { &mDefaultVariableFont, - &mDefaultFixedFont, &mDefaultSerifFont, &mDefaultSansSerifFont, &mDefaultMonospaceFont, &mDefaultCursiveFont, &mDefaultFantasyFont }; // clang-format on static_assert(MOZ_ARRAY_LENGTH(fontTypes) == eDefaultFont_COUNT, @@ -136,50 +133,43 @@ void LangGroupFontPrefs::Initialize(nsSt if (eType == eDefaultFont_Variable) { // XXX "font.name.variable."? There is no such pref... MAKE_FONT_PREF_KEY(pref, "font.name.variable.", langGroup); nsAutoCString value; Preferences::GetCString(pref.get(), value); if (!value.IsEmpty()) { FontFamilyName defaultVariableName = FontFamilyName::Convert(value); - FontFamilyType defaultType = defaultVariableName.mType; - NS_ASSERTION( - defaultType == eFamily_serif || defaultType == eFamily_sans_serif, - "default type must be serif or sans-serif"); + StyleGenericFontFamily defaultType = defaultVariableName.mGeneric; + NS_ASSERTION(defaultType == StyleGenericFontFamily::Serif || + defaultType == StyleGenericFontFamily::SansSerif, + "default type must be serif or sans-serif"); mDefaultVariableFont.fontlist = FontFamilyList(); mDefaultVariableFont.fontlist.SetDefaultFontType(defaultType); // We create mDefaultVariableFont.fontlist with defaultType as the // fallback font, and not as part of the font list proper. This way, // it can be overwritten should there be a language change. } else { MAKE_FONT_PREF_KEY(pref, "font.default.", langGroup); Preferences::GetCString(pref.get(), value); if (!value.IsEmpty()) { FontFamilyName defaultVariableName = FontFamilyName::Convert(value); - FontFamilyType defaultType = defaultVariableName.mType; - NS_ASSERTION( - defaultType == eFamily_serif || defaultType == eFamily_sans_serif, - "default type must be serif or sans-serif"); + StyleGenericFontFamily defaultType = defaultVariableName.mGeneric; + NS_ASSERTION(defaultType == StyleGenericFontFamily::Serif || + defaultType == StyleGenericFontFamily::SansSerif, + "default type must be serif or sans-serif"); mDefaultVariableFont.fontlist = FontFamilyList(); mDefaultVariableFont.fontlist.SetDefaultFontType(defaultType); // We create mDefaultVariableFont.fontlist with defaultType as the // (fallback) font, and not as part of the font list proper. This way, // it can be overwritten should there be a language change. } } } else { - if (eType == eDefaultFont_Monospace) { - // This takes care of the confusion whereby people often expect - // "monospace" to have the same default font-size as "-moz-fixed" (this - // tentative size may be overwritten with the specific value for - // "monospace" when "font.size.monospace.[langGroup]" is read -- see - // below) - mDefaultMonospaceFont.size = mDefaultFixedFont.size; - } else if (eType != eDefaultFont_Fixed) { + if (eType != eDefaultFont_Monospace) { // all the other generic fonts are initialized with the size of the // variable font, but their specific size can supersede later -- see // below font->size = mDefaultVariableFont.size; } } // Bug 84398: for spec purists, a different font-size only applies to the
--- a/layout/base/StaticPresData.h +++ b/layout/base/StaticPresData.h @@ -17,23 +17,23 @@ namespace mozilla { struct LangGroupFontPrefs { // Font sizes default to zero; they will be set in GetFontPreferences LangGroupFontPrefs() : mLangGroup(nullptr), mMinimumFontSize(0), mDefaultVariableFont(), - mDefaultFixedFont(mozilla::eFamily_monospace, 0), - mDefaultSerifFont(mozilla::eFamily_serif, 0), - mDefaultSansSerifFont(mozilla::eFamily_sans_serif, 0), - mDefaultMonospaceFont(mozilla::eFamily_monospace, 0), - mDefaultCursiveFont(mozilla::eFamily_cursive, 0), - mDefaultFantasyFont(mozilla::eFamily_fantasy, 0) { - mDefaultVariableFont.fontlist.SetDefaultFontType(mozilla::eFamily_serif); + mDefaultSerifFont(StyleGenericFontFamily::Serif, 0), + mDefaultSansSerifFont(StyleGenericFontFamily::SansSerif, 0), + mDefaultMonospaceFont(StyleGenericFontFamily::Monospace, 0), + mDefaultCursiveFont(StyleGenericFontFamily::Cursive, 0), + mDefaultFantasyFont(StyleGenericFontFamily::Fantasy, 0) { + mDefaultVariableFont.fontlist.SetDefaultFontType( + StyleGenericFontFamily::Serif); // We create mDefaultVariableFont.fontlist with defaultType as the // fallback font, and not as part of the font list proper. This way, // it can be overwritten should there be a language change. } void Reset() { // Throw away any other LangGroupFontPrefs objects: mNext = nullptr; @@ -62,58 +62,47 @@ struct LangGroupFontPrefs { void Initialize(nsStaticAtom* aLangGroupAtom); /** * Get the default font for the given language and generic font ID. * aLanguage may not be nullptr. * * This object is read-only, you must copy the font to modify it. * - * When aFontID is kPresContext_DefaultVariableFontID or - * kPresContext_DefaultFixedFontID (which equals - * kGenericFont_moz_fixed, which is used for the -moz-fixed generic), - * the nsFont returned has its name as a CSS generic family (serif or - * sans-serif for the former, monospace for the latter), and its size - * as the default font size for variable or fixed fonts for the - * language group. - * * For aFontID corresponding to a CSS Generic, the nsFont returned has * its name set to that generic font's name, and its size set to * the user's preference for font size for that generic and the * given language. */ - const nsFont* GetDefaultFont(uint8_t aFontID) const { - switch (aFontID) { + const nsFont* GetDefaultFont(StyleGenericFontFamily aFamily) const { + switch (aFamily) { // Special (our default variable width font and fixed width font) - case kGenericFont_moz_variable: + case StyleGenericFontFamily::None: return &mDefaultVariableFont; - case kGenericFont_moz_fixed: - return &mDefaultFixedFont; // CSS - case kGenericFont_serif: + case StyleGenericFontFamily::Serif: return &mDefaultSerifFont; - case kGenericFont_sans_serif: + case StyleGenericFontFamily::SansSerif: return &mDefaultSansSerifFont; - case kGenericFont_monospace: + case StyleGenericFontFamily::Monospace: return &mDefaultMonospaceFont; - case kGenericFont_cursive: + case StyleGenericFontFamily::Cursive: return &mDefaultCursiveFont; - case kGenericFont_fantasy: + case StyleGenericFontFamily::Fantasy: return &mDefaultFantasyFont; break; default: MOZ_ASSERT_UNREACHABLE("invalid font id"); return nullptr; } } nsStaticAtom* mLangGroup; nscoord mMinimumFontSize; nsFont mDefaultVariableFont; - nsFont mDefaultFixedFont; nsFont mDefaultSerifFont; nsFont mDefaultSansSerifFont; nsFont mDefaultMonospaceFont; nsFont mDefaultCursiveFont; nsFont mDefaultFantasyFont; mozilla::UniquePtr<LangGroupFontPrefs> mNext; };
--- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -10578,17 +10578,18 @@ void nsCSSFrameConstructor::ConstructBlo // // ColumnSet linkage described in 3): B -> G -> Q // // Block linkage described in 4): C -> H -> R and I -> S // // clang-format on nsBlockFrame* blockFrame = do_QueryFrame(*aNewFrame); - MOZ_ASSERT(blockFrame->IsBlockFrame() || blockFrame->IsDetailsFrame(), + MOZ_ASSERT(blockFrame && + (blockFrame->IsBlockFrame() || blockFrame->IsDetailsFrame()), "not a block frame nor a details frame?"); // Create column hierarchy if necessary. const bool needsColumn = aComputedStyle->StyleColumn()->IsColumnContainerStyle(); if (needsColumn) { *aNewFrame = BeginBuildingColumns(aState, aContent, aParentFrame, blockFrame, aComputedStyle);
--- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -9744,18 +9744,19 @@ already_AddRefed<nsFontMetrics> nsLayout void nsLayoutUtils::ComputeSystemFont(nsFont* aSystemFont, LookAndFeel::FontID aFontID, const nsFont* aDefaultVariableFont) { gfxFontStyle fontStyle; nsAutoString systemFontName; if (LookAndFeel::GetFont(aFontID, systemFontName, fontStyle)) { systemFontName.Trim("\"'"); aSystemFont->fontlist = - FontFamilyList(NS_ConvertUTF16toUTF8(systemFontName), eUnquotedName); - aSystemFont->fontlist.SetDefaultFontType(eFamily_none); + FontFamilyList(NS_ConvertUTF16toUTF8(systemFontName), + StyleFontFamilyNameSyntax::Identifiers); + aSystemFont->fontlist.SetDefaultFontType(StyleGenericFontFamily::None); aSystemFont->style = fontStyle.style; aSystemFont->systemFont = fontStyle.systemFont; aSystemFont->weight = fontStyle.weight; aSystemFont->stretch = fontStyle.stretch; aSystemFont->size = CSSPixel::ToAppUnits(fontStyle.size); // aSystemFont->langGroup = fontStyle.langGroup; aSystemFont->sizeAdjust = fontStyle.sizeAdjust;
--- a/layout/generic/nsInlineFrame.cpp +++ b/layout/generic/nsInlineFrame.cpp @@ -850,21 +850,18 @@ nsIFrame::LogicalSides nsInlineFrame::Ge nscoord nsInlineFrame::GetLogicalBaseline( mozilla::WritingMode aWritingMode) const { return mBaseline; } #ifdef ACCESSIBILITY a11y::AccType nsInlineFrame::AccessibleType() { - // Broken image accessibles are created here, because layout - // replaces the image or image control frame with an inline frame - if (mContent->IsHTMLElement( - nsGkAtoms::input)) // Broken <input type=image ... /> - return a11y::eHTMLButtonType; + // FIXME(emilio): This is broken, if the image has its default `display` value + // overridden. Should be somewhere else. if (mContent->IsHTMLElement( nsGkAtoms::img)) // Create accessible for broken <img> return a11y::eHyperTextType; return a11y::eNoType; } #endif
--- a/layout/generic/nsSimplePageSequenceFrame.cpp +++ b/layout/generic/nsSimplePageSequenceFrame.cpp @@ -48,23 +48,22 @@ nsSimplePageSequenceFrame::nsSimplePageS ComputedStyle* aStyle, nsPresContext* aPresContext) : nsContainerFrame(aStyle, aPresContext, kClassID), mTotalPages(-1), mCalledBeginPage(false), mCurrentCanvasListSetup(false) { nscoord halfInch = PresContext()->CSSTwipsToAppUnits(NS_INCHES_TO_TWIPS(0.5)); mMargin.SizeTo(halfInch, halfInch, halfInch, halfInch); - // XXX Unsafe to assume successful allocation mPageData = new nsSharedPageData(); mPageData->mHeadFootFont = *PresContext() ->Document() ->GetFontPrefsForLang(aStyle->StyleFont()->mLanguage) - ->GetDefaultFont(kGenericFont_serif); + ->GetDefaultFont(StyleGenericFontFamily::Serif); mPageData->mHeadFootFont.size = nsPresContext::CSSPointsToAppUnits(10); // Doing this here so we only have to go get these formats once SetPageNumberFormat("pagenumber", "%1$d", true); SetPageNumberFormat("pageofpages", "%1$d of %2$d", false); } nsSimplePageSequenceFrame::~nsSimplePageSequenceFrame() {
--- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -5726,17 +5726,17 @@ gfxFloat nsTextFrame::ComputeSelectionUn // metrics. It should be constant pixels value which is decided from the // default font size. Note that if the actual font size is smaller than // the default font size, we should use the actual font size because the // computed value from the default font size can be too thick for the // current font size. nscoord defaultFontSize = aPresContext->Document() ->GetFontPrefsForLang(nullptr) - ->GetDefaultFont(kPresContext_DefaultVariableFont_ID) + ->GetDefaultFont(StyleGenericFontFamily::None) ->size; int32_t zoomedFontSize = aPresContext->AppUnitsToDevPixels( nsStyleFont::ZoomText(*aPresContext->Document(), defaultFontSize)); gfxFloat fontSize = std::min(gfxFloat(zoomedFontSize), aFontMetrics.emHeight); fontSize = std::max(fontSize, 1.0); return ceil(fontSize / 20); }
--- a/layout/inspector/InspectorFontFace.cpp +++ b/layout/inspector/InspectorFontFace.cpp @@ -26,45 +26,43 @@ InspectorFontFace::InspectorFontFace(gfx FontMatchType aMatchType) : mFontEntry(aFontEntry), mFontGroup(aFontGroup), mMatchType(aMatchType) { MOZ_COUNT_CTOR(InspectorFontFace); } InspectorFontFace::~InspectorFontFace() { MOZ_COUNT_DTOR(InspectorFontFace); } bool InspectorFontFace::FromFontGroup() { - return bool(mMatchType & FontMatchType::kFontGroup); + return bool(mMatchType.kind & FontMatchType::Kind::kFontGroup); } bool InspectorFontFace::FromLanguagePrefs() { - return bool(mMatchType & FontMatchType::kPrefsFallback); + return bool(mMatchType.kind & FontMatchType::Kind::kPrefsFallback); } bool InspectorFontFace::FromSystemFallback() { - return bool(mMatchType & FontMatchType::kSystemFallback); + return bool(mMatchType.kind & FontMatchType::Kind::kSystemFallback); } void InspectorFontFace::GetName(nsAString& aName) { if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) { NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData"); aName.Append(NS_ConvertUTF8toUTF16(mFontEntry->mUserFontData->mRealName)); } else { aName.Append(NS_ConvertUTF8toUTF16(mFontEntry->RealFaceName())); } } void InspectorFontFace::GetCSSFamilyName(nsAString& aCSSFamilyName) { aCSSFamilyName.Append(NS_ConvertUTF8toUTF16(mFontEntry->FamilyName())); } void InspectorFontFace::GetCSSGeneric(nsAString& aName) { - auto genericType = FontFamilyType(mMatchType & FontMatchType::kGenericMask); - if (genericType >= FontFamilyType::eFamily_generic_first && - genericType <= FontFamilyType::eFamily_generic_last) { - aName.AssignASCII(gfxPlatformFontList::GetGenericName(genericType)); + if (mMatchType.generic != StyleGenericFontFamily::None) { + aName.AssignASCII(gfxPlatformFontList::GetGenericName(mMatchType.generic)); } else { aName.Truncate(0); } } CSSFontFaceRule* InspectorFontFace::GetRule() { if (!mRule) { // check whether this font entry is associated with an @font-face rule
--- a/layout/mathml/nsMathMLChar.cpp +++ b/layout/mathml/nsMathMLChar.cpp @@ -51,23 +51,23 @@ using namespace mozilla::image; // BUG 848725 Drawing failure with stretchy horizontal parenthesis when no fonts // are installed. "kMaxScaleFactor" is required to limit the scale for the // vertical and horizontal stretchy operators. static const float kMaxScaleFactor = 20.0; static const float kLargeOpFactor = float(M_SQRT2); static const float kIntegralFactor = 2.0; static void NormalizeDefaultFont(nsFont& aFont, float aFontSizeInflation) { - if (aFont.fontlist.GetDefaultFontType() != eFamily_none) { + if (aFont.fontlist.GetDefaultFontType() != StyleGenericFontFamily::None) { nsTArray<FontFamilyName> names; names.AppendElements(aFont.fontlist.GetFontlist()->mNames); names.AppendElement(FontFamilyName(aFont.fontlist.GetDefaultFontType())); aFont.fontlist.SetFontlist(std::move(names)); - aFont.fontlist.SetDefaultFontType(eFamily_none); + aFont.fontlist.SetDefaultFontType(StyleGenericFontFamily::None); } aFont.size = NSToCoordRound(aFont.size * aFontSizeInflation); } // ----------------------------------------------------------------------------- static const nsGlyphCode kNullGlyph = {{{0, 0}}, 0}; // ----------------------------------------------------------------------------- @@ -161,18 +161,18 @@ static nsresult LoadProperties(const nsA uriStr); } class nsPropertiesTable final : public nsGlyphTable { public: explicit nsPropertiesTable(const nsACString& aPrimaryFontName) : mState(NS_TABLE_STATE_EMPTY) { MOZ_COUNT_CTOR(nsPropertiesTable); - mGlyphCodeFonts.AppendElement( - FontFamilyName(aPrimaryFontName, eUnquotedName)); + mGlyphCodeFonts.AppendElement(FontFamilyName( + aPrimaryFontName, StyleFontFamilyNameSyntax::Identifiers)); } ~nsPropertiesTable() { MOZ_COUNT_DTOR(nsPropertiesTable); } const FontFamilyName& PrimaryFontName() const { return mGlyphCodeFonts[0]; } const FontFamilyName& FontNameFor( const nsGlyphCode& aGlyphCode) const override { @@ -281,17 +281,18 @@ nsGlyphCode nsPropertiesTable::ElementAt for (int32_t i = 1;; i++) { key.AssignLiteral("external."); key.AppendInt(i, 10); rv = mGlyphProperties->GetStringProperty(key, value); if (NS_FAILED(rv)) break; Clean(value); mGlyphCodeFonts.AppendElement(FontFamilyName( NS_ConvertUTF16toUTF8(value), - eUnquotedName)); // i.e., mGlyphCodeFonts[i] holds this font name + StyleFontFamilyNameSyntax::Identifiers)); // i.e., mGlyphCodeFonts[i] + // holds this font name } } // Update our cache if it is not associated to this character if (mCharCache != aChar) { // The key in the property file is interpreted as ASCII and kept // as such ... char key[10]; @@ -414,17 +415,18 @@ class nsOpenTypeTable final : public nsG private: RefPtr<gfxFont> mFont; FontFamilyName mFontFamilyName; uint32_t mGlyphID; explicit nsOpenTypeTable(gfxFont* aFont) : mFont(aFont), - mFontFamilyName(aFont->GetFontEntry()->FamilyName(), eUnquotedName), + mFontFamilyName(aFont->GetFontEntry()->FamilyName(), + StyleFontFamilyNameSyntax::Identifiers), mGlyphID(0) { MOZ_COUNT_CTOR(nsOpenTypeTable); } void UpdateCache(DrawTarget* aDrawTarget, int32_t aAppUnitsPerDevPixel, gfxFontGroup* aFontGroup, char16_t aChar); }; @@ -511,17 +513,17 @@ already_AddRefed<gfxTextRun> nsOpenTypeT "nsOpenTypeTable can only access glyphs by id"); gfxTextRunFactory::Parameters params = { aDrawTarget, nullptr, nullptr, nullptr, 0, aAppUnitsPerDevPixel}; RefPtr<gfxTextRun> textRun = gfxTextRun::Create(¶ms, 1, aFontGroup, gfx::ShapedTextFlags(), nsTextFrameUtils::Flags()); textRun->AddGlyphRun(aFontGroup->GetFirstValidFont(), - FontMatchType::kFontGroup, 0, false, + FontMatchType::Kind::kFontGroup, 0, false, gfx::ShapedTextFlags::TEXT_ORIENT_HORIZONTAL); // We don't care about CSS writing mode here; // math runs are assumed to be horizontal. gfxTextRun::DetailedGlyph detailedGlyph; detailedGlyph.mGlyphID = aGlyph.glyphID; detailedGlyph.mAdvance = NSToCoordRound( aAppUnitsPerDevPixel * aFontGroup->GetFirstValidFont()->GetGlyphHAdvance( aDrawTarget, aGlyph.glyphID)); @@ -885,17 +887,17 @@ bool nsMathMLChar::SetFontFamily(nsPresC params.textPerf = aPresContext->GetTextPerfMetrics(); params.featureValueLookup = aPresContext->GetFontFeatureValuesLookup(); RefPtr<nsFontMetrics> fm = aPresContext->DeviceContext()->GetMetricsFor(font, params); // Set the font if it is an unicode table // or if the same family name has been found gfxFont* firstFont = fm->GetThebesFontGroup()->GetFirstValidFont(); FontFamilyList firstFontList(firstFont->GetFontEntry()->FamilyName(), - eUnquotedName); + StyleFontFamilyNameSyntax::Identifiers); if (aGlyphTable == &gGlyphTableList->mUnicodeTable || firstFontList == familyList) { aFont.fontlist = familyList; *aFontGroup = fm->GetThebesFontGroup(); } else { return false; // We did not set the font } } @@ -1275,27 +1277,27 @@ bool nsMathMLChar::StretchEnumContext::T // This is called for each family, whether it exists or not bool nsMathMLChar::StretchEnumContext::EnumCallback( const FontFamilyName& aFamily, bool aGeneric, void* aData) { StretchEnumContext* context = static_cast<StretchEnumContext*>(aData); // for comparisons, force use of unquoted names FontFamilyName unquotedFamilyName(aFamily); - if (unquotedFamilyName.mType == eFamily_named_quoted) { - unquotedFamilyName.mType = eFamily_named; + if (unquotedFamilyName.mSyntax == StyleFontFamilyNameSyntax::Quoted) { + unquotedFamilyName.mSyntax = StyleFontFamilyNameSyntax::Identifiers; } // Check font family if it is not a generic one // We test with the kNullGlyph ComputedStyle* sc = context->mChar->mComputedStyle; nsFont font = sc->StyleFont()->mFont; NormalizeDefaultFont(font, context->mFontSizeInflation); RefPtr<gfxFontGroup> fontGroup; - FontFamilyList family(unquotedFamilyName); + FontFamilyList family(nsTArray<FontFamilyName>{unquotedFamilyName}); if (!aGeneric && !context->mChar->SetFontFamily(context->mPresContext, nullptr, kNullGlyph, family, font, &fontGroup)) return true; // Could not set the family // Determine the glyph table to use for this font. nsAutoPtr<nsOpenTypeTable> openTypeTable; nsGlyphTable* glyphTable; @@ -1338,17 +1340,18 @@ bool nsMathMLChar::StretchEnumContext::E return false; // no need to continue return true; // true means continue } static void AppendFallbacks(nsTArray<FontFamilyName>& aNames, const nsTArray<nsCString>& aFallbacks) { for (const nsCString& fallback : aFallbacks) { - aNames.AppendElement(FontFamilyName(fallback, eUnquotedName)); + aNames.AppendElement( + FontFamilyName(fallback, StyleFontFamilyNameSyntax::Identifiers)); } } // insert math fallback families just before the first generic or at the end // when no generic present static void InsertMathFallbacks(FontFamilyList& aFamilyList, nsTArray<nsCString>& aFallbacks) { nsTArray<FontFamilyName> mergedList;
--- a/layout/style/GeckoBindings.cpp +++ b/layout/style/GeckoBindings.cpp @@ -86,19 +86,19 @@ using namespace mozilla::css; using namespace mozilla::dom; // Definitions of the global traversal stats. bool ServoTraversalStatistics::sActive = false; ServoTraversalStatistics ServoTraversalStatistics::sSingleton; static RWLock* sServoFFILock = nullptr; -static const nsFont* ThreadSafeGetDefaultFontHelper(const Document& aDocument, - nsAtom* aLanguage, - uint8_t aGenericId) { +static const nsFont* ThreadSafeGetDefaultFontHelper( + const Document& aDocument, nsAtom* aLanguage, + StyleGenericFontFamily aGenericId) { bool needsCache = false; const nsFont* retval; auto GetDefaultFont = [&](bool* aNeedsToCache) { auto* prefs = aDocument.GetFontPrefsForLang(aLanguage, aNeedsToCache); return prefs ? prefs->GetDefaultFont(aGenericId) : nullptr; }; @@ -957,24 +957,24 @@ nsAtom* Gecko_Atomize(const char* aStrin nsAtom* Gecko_Atomize16(const nsAString* aString) { return NS_Atomize(*aString).take(); } void Gecko_AddRefAtom(nsAtom* aAtom) { NS_ADDREF(aAtom); } void Gecko_ReleaseAtom(nsAtom* aAtom) { NS_RELEASE(aAtom); } -void Gecko_nsTArray_FontFamilyName_AppendNamed(nsTArray<FontFamilyName>* aNames, - nsAtom* aName, bool aQuoted) { - aNames->AppendElement( - FontFamilyName(aName, aQuoted ? eQuotedName : eUnquotedName)); +void Gecko_nsTArray_FontFamilyName_AppendNamed( + nsTArray<FontFamilyName>* aNames, nsAtom* aName, + StyleFontFamilyNameSyntax aSyntax) { + aNames->AppendElement(FontFamilyName(aName, aSyntax)); } void Gecko_nsTArray_FontFamilyName_AppendGeneric( - nsTArray<FontFamilyName>* aNames, FontFamilyType aType) { + nsTArray<FontFamilyName>* aNames, StyleGenericFontFamily aType) { aNames->AppendElement(FontFamilyName(aType)); } SharedFontList* Gecko_SharedFontList_Create() { RefPtr<SharedFontList> fontlist = new SharedFontList(); return fontlist.forget().take(); } @@ -997,35 +997,35 @@ NS_IMPL_THREADSAFE_FFI_REFCOUNTING(Share void Gecko_CopyFontFamilyFrom(nsFont* dst, const nsFont* src) { dst->fontlist = src->fontlist; } void Gecko_nsFont_InitSystem(nsFont* aDest, int32_t aFontId, const nsStyleFont* aFont, const Document* aDocument) { const nsFont* defaultVariableFont = ThreadSafeGetDefaultFontHelper( - *aDocument, aFont->mLanguage, kPresContext_DefaultVariableFont_ID); + *aDocument, aFont->mLanguage, StyleGenericFontFamily::None); // We have passed uninitialized memory to this function, // initialize it. We can't simply return an nsFont because then // we need to know its size beforehand. Servo cannot initialize nsFont // itself, so this will do. new (aDest) nsFont(*defaultVariableFont); LookAndFeel::FontID fontID = static_cast<LookAndFeel::FontID>(aFontId); AutoWriteLock guard(*sServoFFILock); nsLayoutUtils::ComputeSystemFont(aDest, fontID, defaultVariableFont); } void Gecko_nsFont_Destroy(nsFont* aDest) { aDest->~nsFont(); } -FontFamilyType Gecko_nsStyleFont_ComputeDefaultFontType(const Document* aDoc, - uint8_t aGenericId, - nsAtom* aLanguage) { +StyleGenericFontFamily Gecko_nsStyleFont_ComputeDefaultFontType( + const Document* aDoc, StyleGenericFontFamily aGenericId, + nsAtom* aLanguage) { const nsFont* defaultFont = ThreadSafeGetDefaultFontHelper(*aDoc, aLanguage, aGenericId); return defaultFont->fontlist.GetDefaultFontType(); } gfxFontFeatureValueSet* Gecko_ConstructFontFeatureValueSet() { return new gfxFontFeatureValueSet(); } @@ -1887,42 +1887,25 @@ void Gecko_nsStyleFont_SetLang(nsStyleFo aFont->mExplicitLanguage = true; } void Gecko_nsStyleFont_CopyLangFrom(nsStyleFont* aFont, const nsStyleFont* aSource) { aFont->mLanguage = aSource->mLanguage; } -void Gecko_nsStyleFont_PrioritizeUserFonts(nsStyleFont* aFont, - FontFamilyType aDefaultGeneric) { +void Gecko_nsStyleFont_PrioritizeUserFonts( + nsStyleFont* aFont, StyleGenericFontFamily aDefaultGeneric) { MOZ_ASSERT(!StaticPrefs::browser_display_use_document_fonts()); - MOZ_ASSERT(aDefaultGeneric != eFamily_none); + MOZ_ASSERT(aDefaultGeneric != StyleGenericFontFamily::None); if (!aFont->mFont.fontlist.PrioritizeFirstGeneric()) { aFont->mFont.fontlist.PrependGeneric(aDefaultGeneric); } } -void Gecko_nsStyleFont_PrefillDefaultForGeneric(nsStyleFont* aFont, - const Document* aDocument, - uint8_t aGenericId) { - const nsFont* defaultFont = - ThreadSafeGetDefaultFontHelper(*aDocument, aFont->mLanguage, aGenericId); - // In case of just the language changing, the parent could have had no - // generic, which Gecko just does regular cascading with. Do the same. This - // can only happen in the case where the language changed but the family did - // not - if (aGenericId != kGenericFont_NONE) { - aFont->mFont.fontlist = defaultFont->fontlist; - } else { - aFont->mFont.fontlist.SetDefaultFontType( - defaultFont->fontlist.GetDefaultFontType()); - } -} - nscoord Gecko_nsStyleFont_ComputeMinSize(const nsStyleFont* aFont, const Document* aDocument) { // Don't change font-size:0, since that would un-hide hidden text, nor chrome // docs, we assume those know what they do. if (aFont->mSize == 0 || nsContentUtils::IsChromeDoc(aDocument)) { return 0; } @@ -1949,17 +1932,16 @@ nscoord Gecko_nsStyleFont_ComputeMinSize return 0; } return (minFontSize * aFont->mMinFontSizeRatio) / 100; } void FontSizePrefs::CopyFrom(const LangGroupFontPrefs& prefs) { mDefaultVariableSize = prefs.mDefaultVariableFont.size; - mDefaultFixedSize = prefs.mDefaultFixedFont.size; mDefaultSerifSize = prefs.mDefaultSerifFont.size; mDefaultSansSerifSize = prefs.mDefaultSansSerifFont.size; mDefaultMonospaceSize = prefs.mDefaultMonospaceFont.size; mDefaultCursiveSize = prefs.mDefaultCursiveFont.size; mDefaultFantasySize = prefs.mDefaultFantasyFont.size; } FontSizePrefs Gecko_GetBaseSize(nsAtom* aLanguage) {
--- a/layout/style/GeckoBindings.h +++ b/layout/style/GeckoBindings.h @@ -261,20 +261,21 @@ nsAtom* Gecko_Atomize(const char* aStrin nsAtom* Gecko_Atomize16(const nsAString* aString); void Gecko_AddRefAtom(nsAtom* aAtom); void Gecko_ReleaseAtom(nsAtom* aAtom); // Font style void Gecko_CopyFontFamilyFrom(nsFont* dst, const nsFont* src); void Gecko_nsTArray_FontFamilyName_AppendNamed( - nsTArray<mozilla::FontFamilyName>* aNames, nsAtom* aName, bool aQuoted); + nsTArray<mozilla::FontFamilyName>* aNames, nsAtom* aName, + mozilla::StyleFontFamilyNameSyntax); void Gecko_nsTArray_FontFamilyName_AppendGeneric( - nsTArray<mozilla::FontFamilyName>* aNames, mozilla::FontFamilyType aType); + nsTArray<mozilla::FontFamilyName>* aNames, mozilla::StyleGenericFontFamily); // Returns an already-AddRefed SharedFontList with an empty mNames array. mozilla::SharedFontList* Gecko_SharedFontList_Create(); size_t Gecko_SharedFontList_SizeOfIncludingThis( mozilla::SharedFontList* fontlist); size_t Gecko_SharedFontList_SizeOfIncludingThisIfUnshared( @@ -673,28 +674,25 @@ void Gecko_nsStyleFont_CopyLangFrom(nsSt const nsStyleFont* aSource); // Moves the generic family in the font-family to the front, or prepends // aDefaultGeneric, so that user-configured fonts take precedent over document // fonts. // // Document fonts may still be used as fallback for unsupported glyphs though. void Gecko_nsStyleFont_PrioritizeUserFonts( - nsStyleFont* font, mozilla::FontFamilyType aDefaultGeneric); - -void Gecko_nsStyleFont_PrefillDefaultForGeneric(nsStyleFont* font, - const mozilla::dom::Document*, - uint8_t generic_id); + nsStyleFont* font, mozilla::StyleGenericFontFamily aDefaultGeneric); nscoord Gecko_nsStyleFont_ComputeMinSize(const nsStyleFont*, const mozilla::dom::Document*); // Computes the default generic font for a generic family and language. -mozilla::FontFamilyType Gecko_nsStyleFont_ComputeDefaultFontType( - const mozilla::dom::Document*, uint8_t generic_family, nsAtom* language); +mozilla::StyleGenericFontFamily Gecko_nsStyleFont_ComputeDefaultFontType( + const mozilla::dom::Document*, + mozilla::StyleGenericFontFamily generic_family, nsAtom* language); mozilla::FontSizePrefs Gecko_GetBaseSize(nsAtom* lang); // XBL related functions. const mozilla::dom::Element* Gecko_GetBindingParent( const mozilla::dom::Element*); const RawServoAuthorStyles* Gecko_XBLBinding_GetRawServoStyles(
--- a/layout/style/ServoBindings.toml +++ b/layout/style/ServoBindings.toml @@ -59,17 +59,16 @@ bitfield-enums = [ rusty-enums = [ "nsCompatibility", "mozilla::EffectCompositor_CascadeLevel", "mozilla::SheetType", "mozilla::dom::CallerType", "mozilla::dom::IterationCompositeOperation", "mozilla::dom::CompositeOperation", "mozilla::InheritTarget", - "mozilla::FontFamilyType", "mozilla::css::DocumentMatchingFunction", "mozilla::css::SheetParsingMode", "mozilla::StyleContentType", "nsStyleSVGOpacitySource", "nsStyleUnit", "nsCSSKeyword", "mozilla::dom::Document_DocumentTheme", "mozilla::dom::Document_Type", @@ -453,16 +452,18 @@ cbindgen-types = [ { gecko = "StyleRestyleHint", servo = "invalidation::element::restyle_hints::RestyleHint" }, { gecko = "StyleTouchAction", servo = "values::computed::TouchAction" },