author | Dorel Luca <dluca@mozilla.com> |
Sat, 21 Apr 2018 02:06:35 +0300 | |
changeset 468441 | e2da4a4bac5c9cdcbae8cb9bd08c08fd407cec87 |
parent 468440 | 25a807fa07d104fbf5a7796e8ea6e29ce94e9c35 (current diff) |
parent 468317 | 39ccabfd7d0712a45335325cb24b0e0b2ba498c7 (diff) |
child 468442 | 29419d3ec2915214734a505fbb6de31acc8c9fe5 |
push id | 9165 |
push user | asasaki@mozilla.com |
push date | Thu, 26 Apr 2018 21:04:54 +0000 |
treeherder | mozilla-beta@064c3804de2e [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
milestone | 61.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
devtools/client/aboutdebugging/modules/worker.js | file | annotate | diff | comparison | revisions | |
testing/web-platform/meta/MANIFEST.json | file | annotate | diff | comparison | revisions |
--- a/accessible/xul/XULFormControlAccessible.cpp +++ b/accessible/xul/XULFormControlAccessible.cpp @@ -99,24 +99,19 @@ XULButtonAccessible::NativeState() // Buttons can be checked -- they simply appear pressed in rather than checked nsCOMPtr<nsIDOMXULButtonElement> xulButtonElement(do_QueryInterface(mContent)); if (xulButtonElement) { nsAutoString type; xulButtonElement->GetType(type); if (type.EqualsLiteral("checkbox") || type.EqualsLiteral("radio")) { state |= states::CHECKABLE; bool checked = false; - int32_t checkState = 0; xulButtonElement->GetChecked(&checked); if (checked) { state |= states::PRESSED; - xulButtonElement->GetCheckState(&checkState); - if (checkState == nsIDOMXULButtonElement::CHECKSTATE_MIXED) { - state |= states::MIXED; - } } } } if (ContainsMenu()) state |= states::HASPOPUP; if (mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::_default)) @@ -336,20 +331,16 @@ XULCheckboxAccessible::NativeState() // Determine Checked state nsCOMPtr<nsIDOMXULCheckboxElement> xulCheckboxElement = do_QueryInterface(mContent); if (xulCheckboxElement) { bool checked = false; xulCheckboxElement->GetChecked(&checked); if (checked) { state |= states::CHECKED; - int32_t checkState = 0; - xulCheckboxElement->GetCheckState(&checkState); - if (checkState == nsIDOMXULCheckboxElement::CHECKSTATE_MIXED) - state |= states::MIXED; } } return state; } //////////////////////////////////////////////////////////////////////////////// // XULGroupboxAccessible
--- a/browser/components/migration/ESEDBReader.jsm +++ b/browser/components/migration/ESEDBReader.jsm @@ -113,16 +113,18 @@ function convertESEError(errorCode) { case -1002 /* JET_errInvalidName*/: case -1507 /* JET_errColumnNotFound */: // The DB format has changed and we haven't updated this migration code: return "The database format has changed, error code: " + errorCode; case -1032 /* JET_errFileAccessDenied */: case -1207 /* JET_errDatabaseLocked */: case -1302 /* JET_errTableLocked */: return "The database or table is locked, error code: " + errorCode; + case -1305 /* JET_errObjectNotFound */: + return "The table/object was not found."; case -1809 /* JET_errPermissionDenied*/: case -1907 /* JET_errAccessDenied */: return "Access or permission denied, error code: " + errorCode; case -1044 /* JET_errInvalidFilename */: return "Invalid file name"; case -1811 /* JET_errFileNotFound */: return "File not found"; case -550 /* JET_errDatabaseDirtyShutdown */:
--- a/browser/components/migration/EdgeProfileMigrator.js +++ b/browser/components/migration/EdgeProfileMigrator.js @@ -47,38 +47,38 @@ XPCOMUtils.defineLazyGetter(this, "gEdge /** * Get rows from a table in the Edge DB as an array of JS objects. * * @param {String} tableName the name of the table to read. * @param {String[]|function} columns a list of column specifiers * (see ESEDBReader.jsm) or a function that * generates them based on the database * reference once opened. - * @param {function} filterFn a function that is called for each row. + * @param {nsIFile} dbFile the database file to use. Defaults to + * the main Edge database. + * @param {function} filterFn Optional. A function that is called for each row. * Only rows for which it returns a truthy * value are included in the result. - * @param {nsIFile} dbFile the database file to use. Defaults to - * the main Edge database. * @returns {Array} An array of row objects. */ -function readTableFromEdgeDB(tableName, columns, filterFn, dbFile = gEdgeDatabase) { +function readTableFromEdgeDB(tableName, columns, dbFile = gEdgeDatabase, filterFn = null) { let database; let rows = []; try { let logFile = dbFile.parent; logFile.append("LogFiles"); database = ESEDBReader.openDB(dbFile.parent, dbFile, logFile); if (typeof columns == "function") { columns = columns(database); } let tableReader = database.tableItems(tableName, columns); for (let row of tableReader) { - if (filterFn(row)) { + if (!filterFn || filterFn(row)) { rows.push(row); } } } catch (ex) { Cu.reportError("Failed to extract items from table " + tableName + " in Edge database at " + dbFile.path + " due to the following error: " + ex); // Deliberately make this fail so we expose failure in the UI: throw ex; @@ -109,17 +109,17 @@ EdgeTypedURLMigrator.prototype = { migrate(aCallback) { let typedURLs = this._typedURLs; let pageInfos = []; for (let [urlString, time] of typedURLs) { let url; try { url = new URL(urlString); - if (!["http", "https", "ftp"].includes(url.scheme)) { + if (!["http:", "https:", "ftp:"].includes(url.protocol)) { continue; } } catch (ex) { Cu.reportError(ex); continue; } pageInfos.push({ @@ -137,16 +137,96 @@ EdgeTypedURLMigrator.prototype = { } MigrationUtils.insertVisitsWrapper(pageInfos).then( () => aCallback(true), () => aCallback(false)); }, }; +function EdgeTypedURLDBMigrator() { +} + +EdgeTypedURLDBMigrator.prototype = { + type: MigrationUtils.resourceTypes.HISTORY, + + get db() { return gEdgeDatabase; }, + + get exists() { + return !!this.db; + }, + + migrate(callback) { + this._migrateTypedURLsFromDB().then( + () => callback(true), + ex => { + Cu.reportError(ex); + callback(false); + } + ); + }, + + async _migrateTypedURLsFromDB() { + if (await ESEDBReader.dbLocked(this.db)) { + throw new Error("Edge seems to be running - its database is locked."); + } + let columns = [ + {name: "URL", type: "string"}, + {name: "AccessDateTimeUTC", type: "date"}, + ]; + + let typedUrls = []; + try { + typedUrls = readTableFromEdgeDB("TypedUrls", columns, this.db); + } catch (ex) { + // Maybe the table doesn't exist (older versions of Win10). + // Just fall through and we'll return because there's no data. + // The `readTableFromEdgeDB` helper will report errors to the + // console anyway. + } + if (!typedUrls.length) { + return; + } + + let pageInfos = []; + // Sometimes the values are bogus (e.g. 0 becomes some date in 1600), + // and places will throw *everything* away, not just the bogus ones, + // so deal with that by having a cutoff date. Also, there's not much + // point importing really old entries. The cut-off date is related to + // Edge's launch date. + const kDateCutOff = new Date("2016", 0, 1); + for (let typedUrlInfo of typedUrls) { + try { + let url = new URL(typedUrlInfo.URL); + if (!["http:", "https:", "ftp:"].includes(url.protocol)) { + continue; + } + + let date = typedUrlInfo.AccessDateTimeUTC; + if (!date) { + date = kDateCutOff; + } else if (date < kDateCutOff) { + continue; + } + + pageInfos.push({ + url, + visits: [{ + transition: PlacesUtils.history.TRANSITIONS.TYPED, + date, + }], + }); + } catch (ex) { + Cu.reportError(ex); + } + } + await MigrationUtils.insertVisitsWrapper(pageInfos); + }, +}; + function EdgeReadingListMigrator(dbOverride) { this.dbOverride = dbOverride; } EdgeReadingListMigrator.prototype = { type: MigrationUtils.resourceTypes.BOOKMARKS, get db() { return this.dbOverride || gEdgeDatabase; }, @@ -183,17 +263,17 @@ EdgeReadingListMigrator.prototype = { } return columns; }; let filterFn = row => { return !row.IsDeleted; }; - let readingListItems = readTableFromEdgeDB("ReadingList", columnFn, filterFn, this.db); + let readingListItems = readTableFromEdgeDB("ReadingList", columnFn, this.db, filterFn); if (!readingListItems.length) { return; } let destFolderGuid = await this._ensureReadingListFolder(parentGuid); let bookmarks = []; for (let item of readingListItems) { let dateAdded = item.AddedDate || new Date(); @@ -282,17 +362,17 @@ EdgeBookmarksMigrator.prototype = { if (row.IsDeleted) { return false; } if (row.IsFolder) { folderMap.set(row.ItemId, row); } return true; }; - let bookmarks = readTableFromEdgeDB(this.TABLE_NAME, columns, filterFn, this.db); + let bookmarks = readTableFromEdgeDB(this.TABLE_NAME, columns, this.db, filterFn); let toplevelBMs = [], toolbarBMs = []; for (let bookmark of bookmarks) { let bmToInsert; // Ignore invalid URLs: if (!bookmark.IsFolder) { try { new URL(bookmark.URL); } catch (ex) { @@ -352,16 +432,17 @@ EdgeProfileMigrator.prototype.getReading return new EdgeReadingListMigrator(dbOverride); }; EdgeProfileMigrator.prototype.getResources = function() { let resources = [ new EdgeBookmarksMigrator(), MSMigrationUtils.getCookiesMigrator(MSMigrationUtils.MIGRATION_TYPE_EDGE), new EdgeTypedURLMigrator(), + new EdgeTypedURLDBMigrator(), new EdgeReadingListMigrator(), ]; let windowsVaultFormPasswordsMigrator = MSMigrationUtils.getWindowsVaultFormPasswordsMigrator(); windowsVaultFormPasswordsMigrator.name = "EdgeVaultFormPasswords"; resources.push(windowsVaultFormPasswordsMigrator); return resources.filter(r => r.exists); };
--- a/browser/themes/osx/customizableui/panelUI.css +++ b/browser/themes/osx/customizableui/panelUI.css @@ -11,17 +11,17 @@ .subviewbutton { padding-inline-start: 18px; } .subviewbutton.download { padding-inline-start: 14px; } -panelmultiview .toolbaritem-combined-buttons > spacer { +panelmultiview .toolbaritem-combined-buttons > spacer.before-label { width: 42px; /* 18px toolbarbutton padding + 16px icon + 8px label padding start */ } #appMenu-addon-banners > .addon-banner-item, #appMenu-mainView > .panel-subview-body > .panel-banner-item { padding-inline-start: 18px; }
--- a/devtools/client/aboutdebugging/components/workers/Panel.js +++ b/devtools/client/aboutdebugging/components/workers/Panel.js @@ -2,21 +2,19 @@ * 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/. */ /* globals window */ "use strict"; loader.lazyImporter(this, "PrivateBrowsingUtils", "resource://gre/modules/PrivateBrowsingUtils.jsm"); -const { Ci } = require("chrome"); const { Component, createFactory } = require("devtools/client/shared/vendor/react"); const PropTypes = require("devtools/client/shared/vendor/react-prop-types"); const dom = require("devtools/client/shared/vendor/react-dom-factories"); -const { getWorkerForms } = require("../../modules/worker"); const Services = require("Services"); const PanelHeader = createFactory(require("../PanelHeader")); const TargetList = createFactory(require("../TargetList")); const WorkerTarget = createFactory(require("./Target")); const MultiE10SWarning = createFactory(require("./MultiE10sWarning")); const ServiceWorkerTarget = createFactory(require("./ServiceWorkerTarget")); @@ -43,17 +41,16 @@ class WorkersPanel extends Component { }; } constructor(props) { super(props); this.updateMultiE10S = this.updateMultiE10S.bind(this); this.updateWorkers = this.updateWorkers.bind(this); - this.getRegistrationForWorker = this.getRegistrationForWorker.bind(this); this.isE10S = this.isE10S.bind(this); this.renderServiceWorkersError = this.renderServiceWorkersError.bind(this); this.state = this.initialState; } componentDidMount() { let client = this.props.client; @@ -108,83 +105,29 @@ class WorkersPanel extends Component { // nsIXULRuntime.maxWebProcessCount. let processCount = Services.appinfo.maxWebProcessCount; this.setState({ processCount }); } updateWorkers() { let workers = this.initialState.workers; - getWorkerForms(this.props.client).then(forms => { - forms.registrations.forEach(form => { - workers.service.push({ - icon: WorkerIcon, - name: form.url, - url: form.url, - scope: form.scope, - fetch: form.fetch, - registrationActor: form.actor, - active: form.active - }); - }); - - forms.workers.forEach(form => { - let worker = { - icon: WorkerIcon, - name: form.url, - url: form.url, - workerActor: form.actor - }; - switch (form.type) { - case Ci.nsIWorkerDebugger.TYPE_SERVICE: - let registration = this.getRegistrationForWorker(form, workers.service); - if (registration) { - // XXX: Race, sometimes a ServiceWorkerRegistrationInfo doesn't - // have a scriptSpec, but its associated WorkerDebugger does. - if (!registration.url) { - registration.name = registration.url = form.url; - } - registration.workerActor = form.actor; - } else { - worker.fetch = form.fetch; - - // If a service worker registration could not be found, this means we are in - // e10s, and registrations are not forwarded to other processes until they - // reach the activated state. Augment the worker as a registration worker to - // display it in aboutdebugging. - worker.scope = form.scope; - worker.active = false; - workers.service.push(worker); - } - break; - case Ci.nsIWorkerDebugger.TYPE_SHARED: - workers.shared.push(worker); - break; - default: - workers.other.push(worker); - } - }); + this.props.client.mainRoot.listAllWorkers().then(({service, other, shared}) => { + workers.service = service.map(f => Object.assign({ icon: WorkerIcon }, f)); + workers.other = other.map(f => Object.assign({ icon: WorkerIcon }, f)); + workers.shared = shared.map(f => Object.assign({ icon: WorkerIcon }, f)); // XXX: Filter out the service worker registrations for which we couldn't // find the scriptSpec. workers.service = workers.service.filter(reg => !!reg.url); this.setState({ workers }); }); } - getRegistrationForWorker(form, registrations) { - for (let registration of registrations) { - if (registration.scope === form.scope) { - return registration; - } - } - return null; - } - isE10S() { return Services.appinfo.browserTabsRemoteAutostart; } renderServiceWorkersError() { let isWindowPrivate = PrivateBrowsingUtils.isContentWindowPrivate(window); let isPrivateBrowsingMode = PrivateBrowsingUtils.permanentPrivateBrowsing; let isServiceWorkerDisabled = !Services.prefs
--- a/devtools/client/aboutdebugging/components/workers/ServiceWorkerTarget.js +++ b/devtools/client/aboutdebugging/components/workers/ServiceWorkerTarget.js @@ -4,21 +4,22 @@ /* eslint-env browser */ "use strict"; const { Component } = require("devtools/client/shared/vendor/react"); const PropTypes = require("devtools/client/shared/vendor/react-prop-types"); const dom = require("devtools/client/shared/vendor/react-dom-factories"); -const { debugWorker } = require("../../modules/worker"); const Services = require("Services"); loader.lazyRequireGetter(this, "DebuggerClient", "devtools/shared/client/debugger-client", true); +loader.lazyRequireGetter(this, "gDevToolsBrowser", + "devtools/client/framework/devtools-browser", true); const Strings = Services.strings.createBundle( "chrome://devtools/locale/aboutdebugging.properties"); class ServiceWorkerTarget extends Component { static get propTypes() { return { client: PropTypes.instanceOf(DebuggerClient).isRequired, @@ -80,17 +81,17 @@ class ServiceWorkerTarget extends Compon debug() { if (!this.isRunning()) { // If the worker is not running, we can't debug it. return; } let { client, target } = this.props; - debugWorker(client, target.workerActor); + gDevToolsBrowser.openWorkerToolbox(client, target.workerActor); } push() { if (!this.isActive() || !this.isRunning()) { // If the worker is not running, we can't push to it. // If the worker is not active, the registration might be unavailable and the // push will not succeed. return;
--- a/devtools/client/aboutdebugging/components/workers/Target.js +++ b/devtools/client/aboutdebugging/components/workers/Target.js @@ -4,21 +4,22 @@ /* eslint-env browser */ "use strict"; const { Component } = require("devtools/client/shared/vendor/react"); const PropTypes = require("devtools/client/shared/vendor/react-prop-types"); const dom = require("devtools/client/shared/vendor/react-dom-factories"); -const { debugWorker } = require("../../modules/worker"); const Services = require("Services"); loader.lazyRequireGetter(this, "DebuggerClient", "devtools/shared/client/debugger-client", true); +loader.lazyRequireGetter(this, "gDevToolsBrowser", + "devtools/client/framework/devtools-browser", true); const Strings = Services.strings.createBundle( "chrome://devtools/locale/aboutdebugging.properties"); class WorkerTarget extends Component { static get propTypes() { return { client: PropTypes.instanceOf(DebuggerClient).isRequired, @@ -33,17 +34,17 @@ class WorkerTarget extends Component { constructor(props) { super(props); this.debug = this.debug.bind(this); } debug() { let { client, target } = this.props; - debugWorker(client, target.workerActor); + gDevToolsBrowser.openWorkerToolbox(client, target.workerActor); } render() { let { target, debugDisabled } = this.props; return dom.li({ className: "target-container" }, dom.img({ className: "target-icon",
--- a/devtools/client/aboutdebugging/modules/moz.build +++ b/devtools/client/aboutdebugging/modules/moz.build @@ -1,9 +1,8 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. DevToolsModules( 'addon.js', 'connect.js', - 'worker.js', )
deleted file mode 100644 --- a/devtools/client/aboutdebugging/modules/worker.js +++ /dev/null @@ -1,75 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -loader.lazyRequireGetter(this, "gDevTools", - "devtools/client/framework/devtools", true); -loader.lazyRequireGetter(this, "TargetFactory", - "devtools/client/framework/target", true); -loader.lazyRequireGetter(this, "Toolbox", - "devtools/client/framework/toolbox", true); - -/** - * Open a window-hosted toolbox to debug the worker associated to the provided - * worker actor. - * - * @param {DebuggerClient} client - * @param {Object} workerActor - * worker actor form to debug - */ -exports.debugWorker = function(client, workerActor) { - client.attachWorker(workerActor, (response, workerClient) => { - let workerTarget = TargetFactory.forWorker(workerClient); - gDevTools.showToolbox(workerTarget, "jsdebugger", Toolbox.HostType.WINDOW) - .then(toolbox => { - toolbox.once("destroy", () => workerClient.detach()); - }); - }); -}; - -/** - * Retrieve all service worker registrations as well as workers from the parent - * and child processes. - * - * @param {DebuggerClient} client - * @return {Object} - * - {Array} registrations - * Array of ServiceWorkerRegistrationActor forms - * - {Array} workers - * Array of WorkerActor forms - */ -exports.getWorkerForms = async function(client) { - let registrations = []; - let workers = []; - - try { - // List service worker registrations - ({ registrations } = - await client.mainRoot.listServiceWorkerRegistrations()); - - // List workers from the Parent process - ({ workers } = await client.mainRoot.listWorkers()); - - // And then from the Child processes - let { processes } = await client.mainRoot.listProcesses(); - for (let process of processes) { - // Ignore parent process - if (process.parent) { - continue; - } - let { form } = await client.getProcess(process.id); - let processActor = form.actor; - let response = await client.request({ - to: processActor, - type: "listWorkers" - }); - workers = workers.concat(response.workers); - } - } catch (e) { - // Something went wrong, maybe our client is disconnected? - } - - return { registrations, workers }; -};
--- a/devtools/client/aboutdebugging/test/browser_service_workers_multi_content_process.js +++ b/devtools/client/aboutdebugging/test/browser_service_workers_multi_content_process.js @@ -25,16 +25,21 @@ add_task(async function() { let swTab = await addTab(TAB_URL, { background: true }); info("Wait for service worker to appear in the list"); // Check that the service worker appears in the UI let serviceWorkerContainer = await waitUntilServiceWorkerContainer(SERVICE_WORKER, document); + info("Wait until the service worker is running and the Debug button appears"); + await waitUntil(() => { + return !!getDebugButton(serviceWorkerContainer); + }, 100); + info("Check that service worker buttons are disabled."); let debugButton = getDebugButton(serviceWorkerContainer); ok(debugButton.disabled, "Start/Debug button is disabled"); info("Update the preference to 1"); let onWarningCleared = waitUntil(() => { let hasWarning = document.querySelector(".service-worker-multi-process"); return !hasWarning && !debugButton.disabled;
new file mode 100644 --- /dev/null +++ b/devtools/client/application/application.css @@ -0,0 +1,23 @@ +/* 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/. */ + +@import "resource://devtools/client/application/src/components/App.css"; +@import "resource://devtools/client/application/src/components/Worker.css"; +@import "resource://devtools/client/application/src/components/WorkerList.css"; + +* { + box-sizing: border-box; +} + +html, +body, +#mount { + height: 100%; +} + +ul { + list-style: none; + margin: 0; + padding: 0; +} \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/devtools/client/application/index.html @@ -0,0 +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/. --> +<!DOCTYPE html> +<html dir=""> + <head> + <link rel="stylesheet" type="text/css" href="resource://devtools/client/application/application.css" /> + </head> + <body class="theme-body" role="application"> + <div id="mount"></div> + <script src="chrome://devtools/content/shared/theme-switching.js"></script> + <script src="initializer.js"></script> + </body> +</html>
new file mode 100644 --- /dev/null +++ b/devtools/client/application/initializer.js @@ -0,0 +1,74 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { BrowserLoader } = ChromeUtils.import("resource://devtools/client/shared/browser-loader.js", {}); +const require = BrowserLoader({ + baseURI: "resource://devtools/client/application/", + window, +}).require; + +const { createFactory } = require("devtools/client/shared/vendor/react"); +const { render, unmountComponentAtNode } = require("devtools/client/shared/vendor/react-dom"); +const Provider = createFactory(require("devtools/client/shared/vendor/react-redux").Provider); +const { bindActionCreators } = require("devtools/client/shared/vendor/redux"); + +const { configureStore } = require("./src/create-store"); +const actions = require("./src/actions/index"); + +const App = createFactory(require("./src/components/App")); + +/** + * Global Application object in this panel. This object is expected by panel.js and is + * called to start the UI for the panel. + */ +window.Application = { + async bootstrap({ toolbox, panel }) { + this.updateWorkers = this.updateWorkers.bind(this); + + this.mount = document.querySelector("#mount"); + this.toolbox = toolbox; + this.client = toolbox.target.client; + + this.store = configureStore(); + this.actions = bindActionCreators(actions, this.store.dispatch); + + const serviceContainer = { + openAboutDebugging() { + let win = toolbox.doc.defaultView.top; + win.openUILinkIn("about:debugging#workers", "tab", { relatedToCurrent: true }); + } + }; + + // Render the root Application component. + const app = App({ client: this.client, serviceContainer }); + render(Provider({ store: this.store }, app), this.mount); + + this.client.addListener("workerListChanged", this.updateWorkers); + this.client.addListener("serviceWorkerRegistrationListChanged", this.updateWorkers); + this.client.addListener("registration-changed", this.updateWorkers); + this.client.addListener("processListChanged", this.updateWorkers); + + await this.updateWorkers(); + }, + + async updateWorkers() { + let { service } = await this.client.mainRoot.listAllWorkers(); + this.actions.updateWorkers(service); + }, + + destroy() { + this.client.removeListener("workerListChanged", this.updateWorkers); + this.client.removeListener("serviceWorkerRegistrationListChanged", + this.updateWorkers); + this.client.removeListener("registration-changed", this.updateWorkers); + this.client.removeListener("processListChanged", this.updateWorkers); + + unmountComponentAtNode(this.mount); + this.mount = null; + this.toolbox = null; + this.client = null; + }, +};
new file mode 100644 --- /dev/null +++ b/devtools/client/application/moz.build @@ -0,0 +1,12 @@ +# 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/. + +DIRS += [ + 'src', +] + +DevToolsModules( + 'application.css', + 'panel.js' +)
new file mode 100644 --- /dev/null +++ b/devtools/client/application/panel.js @@ -0,0 +1,49 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/** + * DevTools panel responsible for the application tool, which lists and allows to debug + * service workers. + */ +class ApplicationPanel { + /** + * Constructor. + * + * @param {Window} panelWin + * The frame/window dedicated to this panel. + * @param {Toolbox} toolbox + * The toolbox instance responsible for this panel. + */ + constructor(panelWin, toolbox) { + this.panelWin = panelWin; + this.toolbox = toolbox; + } + + async open() { + if (!this.toolbox.target.isRemote) { + await this.toolbox.target.makeRemote(); + } + + await this.panelWin.Application.bootstrap({ + toolbox: this.toolbox, + panel: this, + }); + this.emit("ready"); + this.isReady = true; + return this; + } + + destroy() { + this.panelWin.Application.destroy(); + this.panelWin = null; + this.toolbox = null; + this.emit("destroyed"); + + return this; + } +} + +exports.ApplicationPanel = ApplicationPanel;
new file mode 100644 --- /dev/null +++ b/devtools/client/application/src/actions/index.js @@ -0,0 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const workers = require("./workers"); + +Object.assign(exports, + workers, +);
new file mode 100644 --- /dev/null +++ b/devtools/client/application/src/actions/moz.build @@ -0,0 +1,8 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DevToolsModules( + 'index.js', + 'workers.js', +)
new file mode 100644 --- /dev/null +++ b/devtools/client/application/src/actions/workers.js @@ -0,0 +1,20 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { + UPDATE_WORKERS, +} = require("../constants"); + +function updateWorkers(workers) { + return { + type: UPDATE_WORKERS, + workers + }; +} + +module.exports = { + updateWorkers, +};
new file mode 100644 --- /dev/null +++ b/devtools/client/application/src/components/App.css @@ -0,0 +1,44 @@ +/* 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/. */ + +/* + * The current layout of the application panel is + * + * +---------------------------------------------+ + * | (header) "Service workers" | + * +---------------------------------------------+ + * | Service worker 1 | + * | (...) | + * | Service worker N (see Worker.css) | + * +---------------------------------------------+ + * | Link to about:debugging | + * +---------------------------------------------+ + */ +.application { + height: 100%; + padding: 0 0 0 20px; + overflow: auto; + display: flex; + flex-direction: column; +} + +h1 { + font-size: 22px; + font-weight: normal; +} + +a, +a:hover, +a:visited { + color: var(--blue-60) !important; + margin: 0 10px; + cursor: pointer; +} + +a.disabled, +a.disabled:hover, +a.disabled:visited { + color: var(--grey-30) !important; + cursor: default; +}
new file mode 100644 --- /dev/null +++ b/devtools/client/application/src/components/App.js @@ -0,0 +1,38 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const PropTypes = require("devtools/client/shared/vendor/react-prop-types"); +const { createFactory, Component } = require("devtools/client/shared/vendor/react"); +const { connect } = require("devtools/client/shared/vendor/react-redux"); +const { div } = require("devtools/client/shared/vendor/react-dom-factories"); + +const WorkerList = createFactory(require("./WorkerList")); + +/** + * This is the main component for the application panel. + */ +class App extends Component { + static get propTypes() { + return { + client: PropTypes.object.isRequired, + workers: PropTypes.object.isRequired, + serviceContainer: PropTypes.object.isRequired, + }; + } + + render() { + let { workers, client, serviceContainer } = this.props; + + return div({className: "application"}, + WorkerList({ workers, client, serviceContainer })); + } +} + +// Exports + +module.exports = connect( + (state) => ({ workers: state.workers.list }), +)(App);
new file mode 100644 --- /dev/null +++ b/devtools/client/application/src/components/Worker.css @@ -0,0 +1,47 @@ +/* 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/. */ + + /* + * The current layout of a service worker item is + * + * +----------------------------+----------------+ + * | Service worker scope | Unregister btn | + * +---+----------+-------------+----------------| + * | | "Source" | script name | debug link | + * | |----------+-------------+----------------| + * | | "Status" | status | start link | + * +---+----------+-------------+----------------| + */ +.service-worker-container { + margin-bottom: 20px; + width: 100%; + max-width: 600px; + position: relative; + line-height: 1.5; + font-size: 13px; +} + +.service-worker-container > .service-worker-scope { + padding-inline-start: 30px; +} + +.service-worker-container > :not(.service-worker-scope) { + padding-inline-start: 70px; +} + +.service-worker-scope { + font-weight: bold; +} + +.service-worker-meta-name { + color: var(--grey-50); + min-width: 50px; + margin-inline-end: 10px; + display: inline-block; +} + +.unregister-button { + position: absolute; + right: 0; +}
new file mode 100644 --- /dev/null +++ b/devtools/client/application/src/components/Worker.js @@ -0,0 +1,157 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { Component } = require("devtools/client/shared/vendor/react"); +const PropTypes = require("devtools/client/shared/vendor/react-prop-types"); +const { a, button, div, li, span } = require("devtools/client/shared/vendor/react-dom-factories"); +const Services = require("Services"); + +loader.lazyRequireGetter(this, "DebuggerClient", + "devtools/shared/client/debugger-client", true); +loader.lazyRequireGetter(this, "gDevToolsBrowser", + "devtools/client/framework/devtools-browser", true); + +const Strings = Services.strings.createBundle( + "chrome://devtools/locale/aboutdebugging.properties"); + +/** + * This component is dedicated to display a worker, more accurately a service worker, in + * the list of workers displayed in the application panel. It displays information about + * the worker as well as action links and buttons to interact with the worker (e.g. debug, + * unregister, update etc...). + */ +class Worker extends Component { + static get propTypes() { + return { + client: PropTypes.instanceOf(DebuggerClient).isRequired, + debugDisabled: PropTypes.bool, + worker: PropTypes.shape({ + active: PropTypes.bool, + name: PropTypes.string.isRequired, + scope: PropTypes.string.isRequired, + // registrationActor can be missing in e10s. + registrationActor: PropTypes.string, + workerActor: PropTypes.string + }).isRequired + }; + } + + constructor(props) { + super(props); + + this.debug = this.debug.bind(this); + this.start = this.start.bind(this); + this.unregister = this.unregister.bind(this); + } + + debug() { + if (!this.isRunning()) { + console.log("Service workers cannot be debugged if they are not running"); + return; + } + + let { client, worker } = this.props; + gDevToolsBrowser.openWorkerToolbox(client, worker.workerActor); + } + + start() { + if (!this.isActive() || this.isRunning()) { + console.log("Running or inactive service workers cannot be started"); + return; + } + + let { client, worker } = this.props; + client.request({ + to: worker.registrationActor, + type: "start" + }); + } + + unregister() { + let { client, worker } = this.props; + client.request({ + to: worker.registrationActor, + type: "unregister" + }); + } + + isRunning() { + // We know the worker is running if it has a worker actor. + return !!this.props.worker.workerActor; + } + + isActive() { + return this.props.worker.active; + } + + getServiceWorkerStatus() { + if (this.isActive() && this.isRunning()) { + return "running"; + } else if (this.isActive()) { + return "stopped"; + } + // We cannot get service worker registrations unless the registration is in + // ACTIVE state. Unable to know the actual state ("installing", "waiting"), we + // display a custom state "registering" for now. See Bug 1153292. + return "registering"; + } + + formatScope(scope) { + let [, remainder] = scope.split("://"); + return remainder || scope; + } + + formatSource(source) { + let parts = source.split("/"); + return parts[parts.length - 1]; + } + + render() { + let { worker } = this.props; + let status = this.getServiceWorkerStatus(); + + const unregisterButton = this.isActive() ? + button({ + onClick: this.unregister, + className: "devtools-button unregister-button", + "data-standalone": true + }, + Strings.GetStringFromName("unregister")) + : null; + + const debugLinkDisabled = this.isRunning() ? "" : "disabled"; + const debugLink = a({ + onClick: this.isRunning() ? this.debug : null, + title: this.isRunning() ? null : "Only running service workers can be debugged", + className: `${debugLinkDisabled} debug-link` + }, + Strings.GetStringFromName("debug")); + + const startLink = !this.isRunning() ? + a({ onClick: this.start, className: "start-link" }, + Strings.GetStringFromName("start")) + : null; + + return li({ className: "service-worker-container" }, + div( + { className: "service-worker-scope" }, + span({ title: worker.scope }, this.formatScope(worker.scope)), + unregisterButton), + div( + { className: "service-worker-source" }, + span({ className: "service-worker-meta-name" }, "Source"), + span({ title: worker.scope }, this.formatSource(worker.url)), + debugLink), + div( + { className: `service-worker-status service-worker-status-${status}` }, + span({ className: "service-worker-meta-name" }, "Status"), + Strings.GetStringFromName(status).toLowerCase(), + startLink) + ); + } +} + +module.exports = Worker;
new file mode 100644 --- /dev/null +++ b/devtools/client/application/src/components/WorkerList.css @@ -0,0 +1,12 @@ +/* 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/. */ + +.application-aboutdebugging-plug { + text-align: right; + padding: 5px 0; +} + +.application-workers-container { + flex-grow: 1; +}
new file mode 100644 --- /dev/null +++ b/devtools/client/application/src/components/WorkerList.js @@ -0,0 +1,51 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const PropTypes = require("devtools/client/shared/vendor/react-prop-types"); +const { createFactory, Component } = require("devtools/client/shared/vendor/react"); +const { a, div, h1, ul, li } = require("devtools/client/shared/vendor/react-dom-factories"); +const Worker = createFactory(require("./Worker")); + +/** + * This component handles the list of service workers displayed in the application panel + * and also displays a suggestion to use about debugging for debugging other service + * workers. + */ +class WorkerList extends Component { + static get propTypes() { + return { + client: PropTypes.object.isRequired, + workers: PropTypes.object.isRequired, + serviceContainer: PropTypes.object.isRequired, + }; + } + + render() { + const { workers, client, serviceContainer } = this.props; + const { openAboutDebugging } = serviceContainer; + + return [ + ul({ className: "application-workers-container" }, + li({}, + h1({ className: "application-title" }, "Service Workers") + ), + workers.map(worker => Worker({ + client, + debugDisabled: false, + worker, + })) + ), + div({ className: "application-aboutdebugging-plug" }, + "See about:debugging for Service Workers from other domains", + a({ onClick: () => openAboutDebugging() }, "Open about:debugging") + ) + ]; + } +} + +// Exports + +module.exports = WorkerList;
new file mode 100644 --- /dev/null +++ b/devtools/client/application/src/components/moz.build @@ -0,0 +1,12 @@ +# 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/. + +DevToolsModules( + 'App.css', + 'App.js', + 'Worker.css', + 'Worker.js', + 'WorkerList.css', + 'WorkerList.js', +)
new file mode 100644 --- /dev/null +++ b/devtools/client/application/src/constants.js @@ -0,0 +1,12 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const actionTypes = { + UPDATE_WORKERS: "UPDATE_WORKERS", +}; + +// flatten constants +module.exports = Object.assign({}, actionTypes);
new file mode 100644 --- /dev/null +++ b/devtools/client/application/src/create-store.js @@ -0,0 +1,22 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { createStore } = require("devtools/client/shared/vendor/redux"); + +// Reducers +const rootReducer = require("./reducers/index"); +const { WorkersState } = require("./reducers/workers-state"); + +function configureStore() { + // Prepare initial state. + const initialState = { + workers: new WorkersState(), + }; + + return createStore(rootReducer, initialState); +} + +exports.configureStore = configureStore;
new file mode 100644 --- /dev/null +++ b/devtools/client/application/src/moz.build @@ -0,0 +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/. + +DIRS += [ + 'actions', + 'components', + 'reducers', +] + +DevToolsModules( + 'constants.js', + 'create-store.js', +)
new file mode 100644 --- /dev/null +++ b/devtools/client/application/src/reducers/index.js @@ -0,0 +1,12 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { combineReducers } = require("devtools/client/shared/vendor/redux"); +const { workersReducer } = require("./workers-state"); + +module.exports = combineReducers({ + workers: workersReducer, +});
new file mode 100644 --- /dev/null +++ b/devtools/client/application/src/reducers/moz.build @@ -0,0 +1,8 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DevToolsModules( + 'index.js', + 'workers-state.js', +)
new file mode 100644 --- /dev/null +++ b/devtools/client/application/src/reducers/workers-state.js @@ -0,0 +1,33 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { + UPDATE_WORKERS, +} = require("../constants"); + +function WorkersState() { + return { + // Array of all service workers + list: [], + }; +} + +function workersReducer(state = WorkersState(), action) { + switch (action.type) { + case UPDATE_WORKERS: { + let { workers } = action; + return { list: workers }; + } + + default: + return state; + } +} + +module.exports = { + WorkersState, + workersReducer, +};
--- a/devtools/client/definitions.js +++ b/devtools/client/definitions.js @@ -20,16 +20,17 @@ loader.lazyGetter(this, "WebAudioEditorP loader.lazyGetter(this, "MemoryPanel", () => require("devtools/client/memory/panel").MemoryPanel); loader.lazyGetter(this, "PerformancePanel", () => require("devtools/client/performance/panel").PerformancePanel); loader.lazyGetter(this, "NewPerformancePanel", () => require("devtools/client/performance-new/panel").PerformancePanel); loader.lazyGetter(this, "NetMonitorPanel", () => require("devtools/client/netmonitor/panel").NetMonitorPanel); loader.lazyGetter(this, "StoragePanel", () => require("devtools/client/storage/panel").StoragePanel); loader.lazyGetter(this, "ScratchpadPanel", () => require("devtools/client/scratchpad/scratchpad-panel").ScratchpadPanel); loader.lazyGetter(this, "DomPanel", () => require("devtools/client/dom/dom-panel").DomPanel); loader.lazyGetter(this, "AccessibilityPanel", () => require("devtools/client/accessibility/accessibility-panel").AccessibilityPanel); +loader.lazyGetter(this, "ApplicationPanel", () => require("devtools/client/application/panel").ApplicationPanel); // Other dependencies loader.lazyRequireGetter(this, "CommandUtils", "devtools/client/shared/developer-toolbar", true); loader.lazyRequireGetter(this, "CommandState", "devtools/shared/gcli/command-state", true); loader.lazyRequireGetter(this, "ResponsiveUIManager", "devtools/client/responsive.html/manager", true); loader.lazyImporter(this, "ScratchpadManager", "resource://devtools/client/scratchpad/scratchpad-manager.jsm"); const {MultiLocalizationHelper} = require("devtools/shared/l10n"); @@ -439,32 +440,54 @@ Tools.accessibility = { return target.hasActor("accessibility"); }, build(iframeWindow, toolbox) { return new AccessibilityPanel(iframeWindow, toolbox); } }; +Tools.application = { + id: "application", + ordinal: 15, + visibilityswitch: "devtools.application.enabled", + icon: "chrome://devtools/skin/images/tool-application.svg", + url: "chrome://devtools/content/application/index.html", + label: "Application", + panelLabel: "Application", + tooltip: "Application", + inMenu: false, + hiddenInOptions: true, + + isTargetSupported: function(target) { + return target.isLocalTab; + }, + + build: function(iframeWindow, toolbox) { + return new ApplicationPanel(iframeWindow, toolbox); + } +}; + var defaultTools = [ Tools.options, Tools.webConsole, Tools.inspector, Tools.jsdebugger, Tools.styleEditor, Tools.shaderEditor, Tools.canvasDebugger, Tools.webAudioEditor, Tools.performance, Tools.netMonitor, Tools.storage, Tools.scratchpad, Tools.memory, Tools.dom, Tools.accessibility, + Tools.application, ]; exports.defaultTools = defaultTools; Tools.darkTheme = { id: "dark", label: l10n("options.darkTheme.label2"), ordinal: 1,
--- a/devtools/client/framework/devtools-browser.js +++ b/devtools/client/framework/devtools-browser.js @@ -384,16 +384,34 @@ var gDevToolsBrowser = exports.gDevTools } let msg = L10N.getStr("toolbox.noContentProcessForTab.message"); Services.prompt.alert(null, "", msg); return Promise.reject(msg); }, /** + * Open a window-hosted toolbox to debug the worker associated to the provided + * worker actor. + * + * @param {DebuggerClient} client + * @param {Object} workerActor + * worker actor form to debug + */ + openWorkerToolbox(client, workerActor) { + client.attachWorker(workerActor, (response, workerClient) => { + let workerTarget = TargetFactory.forWorker(workerClient); + gDevTools.showToolbox(workerTarget, null, Toolbox.HostType.WINDOW) + .then(toolbox => { + toolbox.once("destroy", () => workerClient.detach()); + }); + }); + }, + + /** * Install WebIDE widget */ // Used by itself installWebIDEWidget() { if (this.isWebIDEWidgetInstalled()) { return; }
--- a/devtools/client/jar.mn +++ b/devtools/client/jar.mn @@ -217,16 +217,17 @@ devtools.jar: skin/images/tool-storage.svg (themes/images/tool-storage.svg) skin/images/tool-profiler.svg (themes/images/tool-profiler.svg) skin/images/tool-network.svg (themes/images/tool-network.svg) skin/images/tool-scratchpad.svg (themes/images/tool-scratchpad.svg) skin/images/tool-webaudio.svg (themes/images/tool-webaudio.svg) skin/images/tool-memory.svg (themes/images/tool-memory.svg) skin/images/tool-dom.svg (themes/images/tool-dom.svg) skin/images/tool-accessibility.svg (themes/images/tool-accessibility.svg) + skin/images/tool-application.svg (themes/images/tool-application.svg) skin/images/close.svg (themes/images/close.svg) skin/images/clear.svg (themes/images/clear.svg) skin/images/vview-delete.png (themes/images/vview-delete.png) skin/images/vview-delete@2x.png (themes/images/vview-delete@2x.png) skin/images/vview-edit.png (themes/images/vview-edit.png) skin/images/vview-edit@2x.png (themes/images/vview-edit@2x.png) skin/images/vview-lock.png (themes/images/vview-lock.png) skin/images/vview-lock@2x.png (themes/images/vview-lock@2x.png) @@ -295,14 +296,18 @@ devtools.jar: content/netmonitor/src/assets/styles/StatisticsPanel.css (netmonitor/src/assets/styles/StatisticsPanel.css) content/netmonitor/src/assets/styles/StatusBar.css (netmonitor/src/assets/styles/StatusBar.css) content/netmonitor/src/assets/styles/Toolbar.css (netmonitor/src/assets/styles/Toolbar.css) content/netmonitor/src/assets/styles/variables.css (netmonitor/src/assets/styles/variables.css) content/netmonitor/src/assets/icons/play.svg (netmonitor/src/assets/icons/play.svg) content/netmonitor/index.html (netmonitor/index.html) content/netmonitor/initializer.js (netmonitor/initializer.js) + # Application panel + content/application/index.html (application/index.html) + content/application/initializer.js (application/initializer.js) + # Devtools-components skin/images/devtools-components/arrow.svg (themes/images/devtools-components/arrow.svg) # Devtools-reps skin/images/devtools-reps/jump-definition.svg (themes/images/devtools-reps/jump-definition.svg) skin/images/devtools-reps/open-inspector.svg (themes/images/devtools-reps/open-inspector.svg)
--- a/devtools/client/moz.build +++ b/devtools/client/moz.build @@ -5,16 +5,17 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. include('../templates.mozbuild') DIRS += [ 'aboutdebugging', 'accessibility', 'animationinspector', + 'application', 'canvasdebugger', 'commandline', 'debugger', 'dom', 'framework', 'inspector', 'jsonview', 'locales',
--- a/devtools/client/preferences/devtools-client.js +++ b/devtools/client/preferences/devtools-client.js @@ -159,16 +159,19 @@ pref("devtools.performance.ui.experiment pref("devtools.cache.disabled", false); // The default service workers UI setting pref("devtools.serviceWorkers.testing.enabled", false); // Enable the Network Monitor pref("devtools.netmonitor.enabled", true); +// Enable the Application panel +pref("devtools.application.enabled", false); + // The default Network Monitor UI settings pref("devtools.netmonitor.panes-network-details-width", 550); pref("devtools.netmonitor.panes-network-details-height", 450); pref("devtools.netmonitor.filters", "[\"all\"]"); pref("devtools.netmonitor.visibleColumns", "[\"status\",\"method\",\"file\",\"domain\",\"cause\",\"type\",\"transferred\",\"contentSize\",\"waterfall\"]" );
--- a/devtools/client/shared/components/reps/reps.css +++ b/devtools/client/shared/components/reps/reps.css @@ -397,8 +397,18 @@ html[dir="rtl"] .tree-node img.arrow { .object-inspector .object-delimiter { color: var(--theme-comment); } .object-inspector .tree-node img.arrow { display: inline-block; vertical-align: middle; } + +/* Focused styles */ +.tree.object-inspector .tree-node.focused * { + color: inherit; +} + +.tree-node.focused button.jump-definition, +.tree-node.focused button.open-inspector { + background-color: currentColor; +}
--- a/devtools/client/shared/components/reps/reps.js +++ b/devtools/client/shared/components/reps/reps.js @@ -1,18 +1,18 @@ (function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(require("devtools/client/shared/vendor/react-dom-factories"), require("devtools/client/shared/vendor/lodash"), require("devtools/client/shared/vendor/react-prop-types"), require("devtools/client/shared/vendor/react"), require("devtools/client/shared/vendor/react-redux"), require("devtools/client/shared/vendor/redux")); + module.exports = factory(require("devtools/client/shared/vendor/react-dom-factories"), require("devtools/client/shared/vendor/react-prop-types"), require("devtools/client/shared/vendor/react"), require("devtools/client/shared/vendor/react-redux"), require("devtools/client/shared/vendor/redux")); else if(typeof define === 'function' && define.amd) - define(["devtools/client/shared/vendor/react-dom-factories", "devtools/client/shared/vendor/lodash", "devtools/client/shared/vendor/react-prop-types", "devtools/client/shared/vendor/react", "devtools/client/shared/vendor/react-redux", "devtools/client/shared/vendor/redux"], factory); + define(["devtools/client/shared/vendor/react-dom-factories", "devtools/client/shared/vendor/react-prop-types", "devtools/client/shared/vendor/react", "devtools/client/shared/vendor/react-redux", "devtools/client/shared/vendor/redux"], factory); else { - var a = typeof exports === 'object' ? factory(require("devtools/client/shared/vendor/react-dom-factories"), require("devtools/client/shared/vendor/lodash"), require("devtools/client/shared/vendor/react-prop-types"), require("devtools/client/shared/vendor/react"), require("devtools/client/shared/vendor/react-redux"), require("devtools/client/shared/vendor/redux")) : factory(root["devtools/client/shared/vendor/react-dom-factories"], root["devtools/client/shared/vendor/lodash"], root["devtools/client/shared/vendor/react-prop-types"], root["devtools/client/shared/vendor/react"], root["devtools/client/shared/vendor/react-redux"], root["devtools/client/shared/vendor/redux"]); + var a = typeof exports === 'object' ? factory(require("devtools/client/shared/vendor/react-dom-factories"), require("devtools/client/shared/vendor/react-prop-types"), require("devtools/client/shared/vendor/react"), require("devtools/client/shared/vendor/react-redux"), require("devtools/client/shared/vendor/redux")) : factory(root["devtools/client/shared/vendor/react-dom-factories"], root["devtools/client/shared/vendor/react-prop-types"], root["devtools/client/shared/vendor/react"], root["devtools/client/shared/vendor/react-redux"], root["devtools/client/shared/vendor/redux"]); for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; } -})(typeof self !== 'undefined' ? self : this, function(__WEBPACK_EXTERNAL_MODULE_1__, __WEBPACK_EXTERNAL_MODULE_54__, __WEBPACK_EXTERNAL_MODULE_2__, __WEBPACK_EXTERNAL_MODULE_10__, __WEBPACK_EXTERNAL_MODULE_18__, __WEBPACK_EXTERNAL_MODULE_19__) { +})(typeof self !== 'undefined' ? self : this, function(__WEBPACK_EXTERNAL_MODULE_1__, __WEBPACK_EXTERNAL_MODULE_2__, __WEBPACK_EXTERNAL_MODULE_9__, __WEBPACK_EXTERNAL_MODULE_18__, __WEBPACK_EXTERNAL_MODULE_19__) { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache @@ -80,17 +80,17 @@ return /******/ (function(modules) { // "use strict"; /* 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/. */ // Dependencies -const validProtocols = /^(http|https|ftp|data|resource|chrome):/i; +const validProtocols = /(http|https|ftp|data|resource|chrome):/i; const tokenSplitRegex = /(\s|\'|\"|\\)+/; const ELLIPSIS = "\u2026"; const dom = __webpack_require__(1); const { span } = dom; /** * Returns true if the given object is a grip (see RDP protocol) */ @@ -427,22 +427,22 @@ function getGripType(object, noGrip) { * Determines whether a grip is a string containing a URL. * * @param string grip * The grip, which may contain a URL. * @return boolean * Whether the grip is a string containing a URL. */ function containsURL(grip) { - if (typeof grip !== "string") { + // An URL can't be shorter than 5 char (e.g. "ftp:"). + if (typeof grip !== "string" || grip.length < 5) { return false; } - let tokens = grip.split(tokenSplitRegex); - return tokens.some(isURL); + return validProtocols.test(grip); } /** * Determines whether a string token is a valid URL. * * @param string token * The token. * @return boolean @@ -562,17 +562,17 @@ const NaNRep = __webpack_require__(31); const Accessor = __webpack_require__(32); // DOM types (grips) const Attribute = __webpack_require__(33); const DateTime = __webpack_require__(34); const Document = __webpack_require__(35); const DocumentType = __webpack_require__(36); const Event = __webpack_require__(37); -const Func = __webpack_require__(12); +const Func = __webpack_require__(11); const PromiseRep = __webpack_require__(38); const RegExp = __webpack_require__(39); const StyleSheet = __webpack_require__(40); const CommentNode = __webpack_require__(41); const ElementNode = __webpack_require__(42); const TextNode = __webpack_require__(43); const ErrorRep = __webpack_require__(13); const Window = __webpack_require__(44); @@ -584,17 +584,17 @@ const GripMapEntry = __webpack_require__ const Grip = __webpack_require__(8); // List of all registered template. // XXX there should be a way for extensions to register a new // or modify an existing rep. let reps = [RegExp, StyleSheet, Event, DateTime, CommentNode, ElementNode, TextNode, Attribute, Func, PromiseRep, ArrayRep, Document, DocumentType, Window, ObjectWithText, ObjectWithURL, ErrorRep, GripArray, GripMap, GripMapEntry, Grip, Undefined, Null, StringRep, Number, SymbolRep, InfinityRep, NaNRep, Accessor]; /** - * Generic rep that is using for rendering native JS types or an object. + * Generic rep that is used for rendering native JS types or an object. * The right template used for rendering is picked automatically according * to the current value type. The value must be passed is as 'object' * property. */ const Rep = function (props) { let { object, defaultRep @@ -608,17 +608,17 @@ const Rep = function (props) { /** * Return a rep object that is responsible for rendering given * object. * * @param object {Object} Object to be rendered in the UI. This * can be generic JS object as well as a grip (handle to a remote * debuggee object). * - * @param defaultObject {React.Component} The default template + * @param defaultRep {React.Component} The default template * that should be used to render given object if none is found. * * @param noGrip {Boolean} If true, will only check reps not made for remote objects. */ function getRep(object, defaultRep = Obj, noGrip = false) { for (let i = 0; i < reps.length; i++) { let rep = reps[i]; try { @@ -708,17 +708,17 @@ const { a, span } = dom; /** * Renders a string. String value is enclosed within quotes. */ StringRep.propTypes = { useQuotes: PropTypes.bool, escapeWhitespace: PropTypes.bool, style: PropTypes.object, cropLimit: PropTypes.number.isRequired, - member: PropTypes.string, + member: PropTypes.object, object: PropTypes.object.isRequired, openLink: PropTypes.func, className: PropTypes.string }; function StringRep(props) { let { className, @@ -729,23 +729,29 @@ function StringRep(props) { escapeWhitespace = true, member, openLink } = props; let text = object; const isLong = isLongString(object); - const shouldCrop = (!member || !member.open) && cropLimit && text.length > cropLimit; + const isOpen = member && member.open; + const shouldCrop = !isOpen && cropLimit && text.length > cropLimit; if (isLong) { text = maybeCropLongString({ shouldCrop, cropLimit }, text); + + const { fullText } = object; + if (isOpen && fullText) { + text = fullText; + } } text = formatText({ useQuotes, escapeWhitespace }, text); const config = getElementConfig({ @@ -772,22 +778,21 @@ function StringRep(props) { function maybeCropLongString(opts, text) { const { shouldCrop, cropLimit } = opts; const { - fullText, initial, length } = text; - text = shouldCrop ? initial.substring(0, cropLimit) : fullText || initial; + text = shouldCrop ? initial.substring(0, cropLimit) : initial; if (text.length < length) { text += ELLIPSIS; } return text; } @@ -1502,70 +1507,36 @@ let Grip = { maxLengthMap }; // Exports from this module module.exports = Grip; /***/ }), /* 9 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* 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/. */ - -module.exports = { - ELEMENT_NODE: 1, - ATTRIBUTE_NODE: 2, - TEXT_NODE: 3, - CDATA_SECTION_NODE: 4, - ENTITY_REFERENCE_NODE: 5, - ENTITY_NODE: 6, - PROCESSING_INSTRUCTION_NODE: 7, - COMMENT_NODE: 8, - DOCUMENT_NODE: 9, - DOCUMENT_TYPE_NODE: 10, - DOCUMENT_FRAGMENT_NODE: 11, - NOTATION_NODE: 12, - - // DocumentPosition - DOCUMENT_POSITION_DISCONNECTED: 0x01, - DOCUMENT_POSITION_PRECEDING: 0x02, - DOCUMENT_POSITION_FOLLOWING: 0x04, - DOCUMENT_POSITION_CONTAINS: 0x08, - DOCUMENT_POSITION_CONTAINED_BY: 0x10, - DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: 0x20 -}; +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE_9__; /***/ }), /* 10 */ -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_10__; - -/***/ }), -/* 11 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* 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/. */ const client = __webpack_require__(20); const loadProperties = __webpack_require__(21); const node = __webpack_require__(22); const { nodeIsError, nodeIsPrimitive } = node; -const selection = __webpack_require__(55); +const selection = __webpack_require__(54); const { MODE } = __webpack_require__(3); const { REPS: { Rep, Grip } } = __webpack_require__(4); @@ -1595,17 +1566,17 @@ module.exports = { loadProperties, node, renderRep, selection, shouldRenderRootsInReps }; /***/ }), -/* 12 */ +/* 11 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* 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/. */ @@ -1767,16 +1738,50 @@ module.exports = { rep: wrapRender(FunctionRep), supportsObject, cleanFunctionName, // exported for testing purpose. getFunctionName }; /***/ }), +/* 12 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/* 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/. */ + +module.exports = { + ELEMENT_NODE: 1, + ATTRIBUTE_NODE: 2, + TEXT_NODE: 3, + CDATA_SECTION_NODE: 4, + ENTITY_REFERENCE_NODE: 5, + ENTITY_NODE: 6, + PROCESSING_INSTRUCTION_NODE: 7, + COMMENT_NODE: 8, + DOCUMENT_NODE: 9, + DOCUMENT_TYPE_NODE: 10, + DOCUMENT_FRAGMENT_NODE: 11, + NOTATION_NODE: 12, + + // DocumentPosition + DOCUMENT_POSITION_DISCONNECTED: 0x01, + DOCUMENT_POSITION_PRECEDING: 0x02, + DOCUMENT_POSITION_FOLLOWING: 0x04, + DOCUMENT_POSITION_CONTAINS: 0x08, + DOCUMENT_POSITION_CONTAINED_BY: 0x10, + DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: 0x20 +}; + +/***/ }), /* 13 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* 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 @@ -1785,17 +1790,17 @@ module.exports = { // ReactJS const PropTypes = __webpack_require__(2); // Utils const { getGripType, isGrip, wrapRender } = __webpack_require__(0); -const { cleanFunctionName } = __webpack_require__(12); +const { cleanFunctionName } = __webpack_require__(11); const { isLongString } = __webpack_require__(5); const { MODE } = __webpack_require__(3); const dom = __webpack_require__(1); const { span } = dom; const IGNORED_SOURCE_URLS = ["debugger eval code"]; /** @@ -2489,17 +2494,17 @@ function GripMapEntry(props) { suppressQuotes: false })); } function supportsObject(grip, noGrip = false) { if (noGrip === true) { return false; } - return grip && grip.type === "mapEntry" && grip.preview; + return grip && (grip.type === "mapEntry" || grip.type === "storageEntry") && grip.preview; } function createGripMapEntry(key, value) { return { type: "mapEntry", preview: { key, value @@ -2582,28 +2587,51 @@ async function enumSymbols(objectClient, async function getPrototype(objectClient) { if (typeof objectClient.getPrototype !== "function") { console.error("objectClient.getPrototype is not a function"); return Promise.resolve({}); } return objectClient.getPrototype(); } +async function getFullText(longStringClient, object) { + const { initial, length } = object; + + return new Promise((resolve, reject) => { + longStringClient.substring(initial.length, length, response => { + if (response.error) { + console.error("LongStringClient.substring", response.error + ": " + response.message); + reject({}); + return; + } + + resolve({ + fullText: initial + response.substring + }); + }); + }); +} + function iteratorSlice(iterator, start, end) { start = start || 0; const count = end ? end - start + 1 : iterator.count; + + if (count === 0) { + return Promise.resolve({}); + } return iterator.slice(start, count); } module.exports = { enumEntries, enumIndexedProperties, enumNonIndexedProperties, enumSymbols, - getPrototype + getPrototype, + getFullText }; /***/ }), /* 21 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -2612,36 +2640,38 @@ module.exports = { * 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/. */ const { enumEntries, enumIndexedProperties, enumNonIndexedProperties, getPrototype, - enumSymbols + enumSymbols, + getFullText } = __webpack_require__(20); const { getClosestGripNode, getClosestNonBucketNode, getValue, nodeHasAccessors, nodeHasAllEntriesInPreview, nodeHasProperties, nodeIsBucket, nodeIsDefaultProperties, nodeIsEntries, nodeIsMapEntry, nodeIsPrimitive, nodeIsProxy, - nodeNeedsNumericalBuckets + nodeNeedsNumericalBuckets, + nodeIsLongString } = __webpack_require__(22); -function loadItemProperties(item, createObjectClient, loadedProperties) { +function loadItemProperties(item, createObjectClient, createLongStringClient, loadedProperties) { const gripItem = getClosestGripNode(item); const value = getValue(gripItem); const [start, end] = item.meta ? [item.meta.startIndex, item.meta.endIndex] : []; let promises = []; let objectClient; const getObjectClient = () => objectClient || createObjectClient(value); @@ -2661,16 +2691,20 @@ function loadItemProperties(item, create if (shouldLoadItemPrototype(item, loadedProperties)) { promises.push(getPrototype(getObjectClient())); } if (shouldLoadItemSymbols(item, loadedProperties)) { promises.push(enumSymbols(getObjectClient(), start, end)); } + if (shouldLoadItemFullText(item, loadedProperties)) { + promises.push(getFullText(createLongStringClient(value), value)); + } + return Promise.all(promises).then(mergeResponses); } function mergeResponses(responses) { const data = {}; for (const response of responses) { if (response.hasOwnProperty("ownProperties")) { @@ -2679,16 +2713,20 @@ function mergeResponses(responses) { if (response.ownSymbols && response.ownSymbols.length > 0) { data.ownSymbols = response.ownSymbols; } if (response.prototype) { data.prototype = response.prototype; } + + if (response.fullText) { + data.fullText = response.fullText; + } } return data; } function shouldLoadItemIndexedProperties(item, loadedProperties = new Map()) { const gripItem = getClosestGripNode(item); const value = getValue(gripItem); @@ -2712,53 +2750,58 @@ function shouldLoadItemEntries(item, loa const value = getValue(gripItem); return value && nodeIsEntries(getClosestNonBucketNode(item)) && !nodeHasAllEntriesInPreview(gripItem) && !loadedProperties.has(item.path) && !nodeNeedsNumericalBuckets(item); } function shouldLoadItemPrototype(item, loadedProperties = new Map()) { const value = getValue(item); - return value && !loadedProperties.has(item.path) && !nodeIsBucket(item) && !nodeIsMapEntry(item) && !nodeIsEntries(item) && !nodeIsDefaultProperties(item) && !nodeHasAccessors(item) && !nodeIsPrimitive(item); + return value && !loadedProperties.has(item.path) && !nodeIsBucket(item) && !nodeIsMapEntry(item) && !nodeIsEntries(item) && !nodeIsDefaultProperties(item) && !nodeHasAccessors(item) && !nodeIsPrimitive(item) && !nodeIsLongString(item); } function shouldLoadItemSymbols(item, loadedProperties = new Map()) { const value = getValue(item); - return value && !loadedProperties.has(item.path) && !nodeIsBucket(item) && !nodeIsMapEntry(item) && !nodeIsEntries(item) && !nodeIsDefaultProperties(item) && !nodeHasAccessors(item) && !nodeIsPrimitive(item) && !nodeIsProxy(item); + return value && !loadedProperties.has(item.path) && !nodeIsBucket(item) && !nodeIsMapEntry(item) && !nodeIsEntries(item) && !nodeIsDefaultProperties(item) && !nodeHasAccessors(item) && !nodeIsPrimitive(item) && !nodeIsLongString(item) && !nodeIsProxy(item); +} + +function shouldLoadItemFullText(item, loadedProperties = new Map()) { + return !loadedProperties.has(item.path) && nodeIsLongString(item); } module.exports = { loadItemProperties, mergeResponses, shouldLoadItemEntries, shouldLoadItemIndexedProperties, shouldLoadItemNonIndexedProperties, shouldLoadItemPrototype, - shouldLoadItemSymbols + shouldLoadItemSymbols, + shouldLoadItemFullText }; /***/ }), /* 22 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* 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/. */ -const { get, has } = __webpack_require__(54); const { maybeEscapePropertyName } = __webpack_require__(0); const ArrayRep = __webpack_require__(6); const GripArrayRep = __webpack_require__(14); const GripMap = __webpack_require__(16); const GripMapEntryRep = __webpack_require__(17); const ErrorRep = __webpack_require__(13); +const { isLongString } = __webpack_require__(5); const MAX_NUMERICAL_PROPERTIES = 100; const NODE_TYPES = { BUCKET: Symbol("[n…m]"), DEFAULT_PROPERTIES: Symbol("<default properties>"), ENTRIES: Symbol("<entries>"), GET: Symbol("<get>"), @@ -2781,22 +2824,22 @@ if (typeof window === "object") { WINDOW_PROPERTIES = Object.getOwnPropertyNames(window); } function getType(item) { return item.type; } function getValue(item) { - if (has(item, "contents.value")) { - return get(item, "contents.value"); - } - - if (has(item, "contents.getterValue")) { - return get(item, "contents.getterValue", undefined); + if (item && item.contents && item.contents.hasOwnProperty("value")) { + return item.contents.value; + } + + if (item && item.contents && item.contents.hasOwnProperty("getterValue")) { + return item.contents.getterValue; } if (nodeHasAccessors(item)) { return item.contents; } return undefined; } @@ -2863,17 +2906,17 @@ function nodeIsMissingArguments(item) { return !nodeHasChildren(item) && value && value.missingArguments; } function nodeHasProperties(item) { return !nodeHasChildren(item) && nodeIsObject(item); } function nodeIsPrimitive(item) { - return !nodeHasChildren(item) && !nodeHasProperties(item) && !nodeIsEntries(item) && !nodeIsMapEntry(item) && !nodeHasAccessors(item) && !nodeIsBucket(item); + return !nodeHasChildren(item) && !nodeHasProperties(item) && !nodeIsEntries(item) && !nodeIsMapEntry(item) && !nodeHasAccessors(item) && !nodeIsBucket(item) && !nodeIsLongString(item); } function nodeIsDefaultProperties(item) { return getType(item) === NODE_TYPES.DEFAULT_PROPERTIES; } function isDefaultWindowProperty(name) { return WINDOW_PROPERTIES.includes(name); @@ -2921,33 +2964,42 @@ function nodeIsSetter(item) { function nodeIsBlock(item) { return getType(item) === NODE_TYPES.BLOCK; } function nodeIsError(item) { return ErrorRep.supportsObject(getValue(item)); } +function nodeIsLongString(item) { + return isLongString(getValue(item)); +} + +function nodeHasFullText(item) { + const value = getValue(item); + return nodeIsLongString(item) && value.hasOwnProperty("fullText"); +} + function nodeHasAccessors(item) { return !!getNodeGetter(item) || !!getNodeSetter(item); } function nodeSupportsNumericalBucketing(item) { // We exclude elements with entries since it's the <entries> node // itself that can have buckets. return nodeIsArrayLike(item) && !nodeHasEntries(item) || nodeIsEntries(item) || nodeIsBucket(item); } function nodeHasEntries(item) { const value = getValue(item); if (!value) { return false; } - return value.class === "Map" || value.class === "Set" || value.class === "WeakMap" || value.class === "WeakSet"; + return value.class === "Map" || value.class === "Set" || value.class === "WeakMap" || value.class === "WeakSet" || value.class === "Storage"; } function nodeHasAllEntriesInPreview(item) { const { preview } = getValue(item) || {}; if (!preview) { return false; } @@ -3081,21 +3133,21 @@ function makeNodesForMapEntry(item) { parent: item, name: "<value>", contents: { value }, type: NODE_TYPES.MAP_ENTRY_VALUE })]; } function getNodeGetter(item) { - return get(item, "contents.get", undefined); + return item && item.contents ? item.contents.get : undefined; } function getNodeSetter(item) { - return get(item, "contents.set", undefined); + return item && item.contents ? item.contents.set : undefined; } function makeNodesForAccessors(item) { const accessors = []; const getter = getNodeGetter(item); if (getter && getter.type !== "undefined") { accessors.push(createNode({ @@ -3255,16 +3307,28 @@ function makeNodesForProperties(objProps // Add the prototype if it exists and is not null if (prototype && prototype.type !== "null") { nodes.push(makeNodeForPrototype(objProps, parent)); } return nodes; } +function setNodeFullText(loadedProps, node) { + if (nodeHasFullText(node)) { + return node; + } + + if (nodeIsLongString(node)) { + node.contents.value.fullText = loadedProps.fullText; + } + + return node; +} + function makeNodeForPrototype(objProps, parent) { const { prototype } = objProps || {}; // Add the prototype if it exists and is not null if (prototype && prototype.type !== "null") { return createNode({ @@ -3360,19 +3424,23 @@ function getChildren(options) { if (nodeIsMapEntry(item)) { return addToCache(makeNodesForMapEntry(item)); } if (nodeIsProxy(item)) { return addToCache(makeNodesForProxyProperties(item)); } + if (nodeIsLongString(item) && hasLoadedProps) { + // Set longString object's fullText to fetched one. + return addToCache(setNodeFullText(loadedProps, item)); + } + if (nodeNeedsNumericalBuckets(item) && hasLoadedProps) { // Even if we have numerical buckets, we should have loaded non indexed properties, - // like length for example. const bucketNodes = makeNumericalBuckets(item); return addToCache(bucketNodes.concat(makeNodesForProperties(loadedProps, item))); } if (!nodeIsEntries(item) && !nodeIsBucket(item) && !nodeHasProperties(item)) { return []; } @@ -3458,16 +3526,18 @@ module.exports = { nodeHasChildren, nodeHasEntries, nodeHasProperties, nodeIsBlock, nodeIsBucket, nodeIsDefaultProperties, nodeIsEntries, nodeIsError, + nodeIsLongString, + nodeHasFullText, nodeIsFunction, nodeIsGetter, nodeIsMapEntry, nodeIsMissingArguments, nodeIsObject, nodeIsOptimizedOut, nodeIsPrimitive, nodeIsPromise, @@ -3494,17 +3564,17 @@ module.exports = { /* 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/. */ const { MODE } = __webpack_require__(3); const { REPS, getRep } = __webpack_require__(4); const ObjectInspector = __webpack_require__(47); -const ObjectInspectorUtils = __webpack_require__(11); +const ObjectInspectorUtils = __webpack_require__(10); const { parseURLEncodedText, parseURLParams, maybeEscapePropertyName, getGripPreviewItems } = __webpack_require__(0); @@ -4652,17 +4722,17 @@ module.exports = { const PropTypes = __webpack_require__(2); const { isGrip, cropString, cropMultipleLines, wrapRender } = __webpack_require__(0); const { MODE } = __webpack_require__(3); -const nodeConstants = __webpack_require__(9); +const nodeConstants = __webpack_require__(12); const dom = __webpack_require__(1); const { span } = dom; /** * Renders DOM comment node. */ CommentNode.propTypes = { object: PropTypes.object.isRequired, @@ -4719,92 +4789,118 @@ const PropTypes = __webpack_require__(2) // Utils const { isGrip, wrapRender } = __webpack_require__(0); const { rep: StringRep } = __webpack_require__(5); const { MODE } = __webpack_require__(3); -const nodeConstants = __webpack_require__(9); +const nodeConstants = __webpack_require__(12); const dom = __webpack_require__(1); const { span } = dom; /** * Renders DOM element node. */ ElementNode.propTypes = { object: PropTypes.object.isRequired, + inspectIconTitle: PropTypes.string, // @TODO Change this to Object.values once it's supported in Node's version of V8 mode: PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])), + onDOMNodeClick: PropTypes.func, onDOMNodeMouseOver: PropTypes.func, onDOMNodeMouseOut: PropTypes.func, onInspectIconClick: PropTypes.func }; function ElementNode(props) { let { object, + inspectIconTitle, mode, + onDOMNodeClick, onDOMNodeMouseOver, onDOMNodeMouseOut, onInspectIconClick } = props; let elements = getElements(object, mode); let isInTree = object.preview && object.preview.isConnected === true; let baseConfig = { "data-link-actor-id": object.actor, className: "objectBox objectBox-node" }; let inspectIcon; if (isInTree) { + if (onDOMNodeClick) { + Object.assign(baseConfig, { + onClick: _ => onDOMNodeClick(object) + }); + } + if (onDOMNodeMouseOver) { Object.assign(baseConfig, { onMouseOver: _ => onDOMNodeMouseOver(object) }); } if (onDOMNodeMouseOut) { Object.assign(baseConfig, { onMouseOut: onDOMNodeMouseOut }); } if (onInspectIconClick) { inspectIcon = dom.button({ className: "open-inspector", // TODO: Localize this with "openNodeInInspector" when Bug 1317038 lands - title: "Click to select the node in the inspector", - onClick: e => onInspectIconClick(object, e) + title: inspectIconTitle || "Click to select the node in the inspector", + onClick: e => { + if (onDOMNodeClick) { + e.stopPropagation(); + } + + onInspectIconClick(object, e); + } }); } } return span(baseConfig, ...elements, inspectIcon); } function getElements(grip, mode) { - let { attributes, nodeName } = grip.preview; + let { + attributes, + nodeName, + isAfterPseudoElement, + isBeforePseudoElement + } = grip.preview; const nodeNameElement = span({ className: "tag-name" }, nodeName); + if (isAfterPseudoElement || isBeforePseudoElement) { + return [span({ className: "attrName" }, `::${isAfterPseudoElement ? "after" : "before"}`)]; + } + if (mode === MODE.TINY) { let elements = [nodeNameElement]; if (attributes.id) { elements.push(span({ className: "attrName" }, `#${attributes.id}`)); } if (attributes.class) { elements.push(span({ className: "attrName" }, attributes.class.trim().split(/\s+/).map(cls => `.${cls}`).join(""))); } return elements; } + let attributeKeys = Object.keys(attributes); if (attributeKeys.includes("class")) { attributeKeys.splice(attributeKeys.indexOf("class"), 1); attributeKeys.unshift("class"); } if (attributeKeys.includes("id")) { attributeKeys.splice(attributeKeys.indexOf("id"), 1); attributeKeys.unshift("id"); @@ -5159,21 +5255,21 @@ module.exports = { "use strict"; /* 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/. */ -const { createElement, createFactory, PureComponent } = __webpack_require__(10); +const { createElement, createFactory, PureComponent } = __webpack_require__(9); const { Provider } = __webpack_require__(18); const ObjectInspector = createFactory(__webpack_require__(48)); -const createStore = __webpack_require__(57); -const Utils = __webpack_require__(11); +const createStore = __webpack_require__(56); +const Utils = __webpack_require__(10); const { renderRep, shouldRenderRootsInReps } = Utils; class OI extends PureComponent { constructor(props) { @@ -5213,30 +5309,30 @@ function _interopRequireDefault(obj) { r /* 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/. */ const { Component, createFactory -} = __webpack_require__(10); +} = __webpack_require__(9); const dom = __webpack_require__(1); const { connect } = __webpack_require__(18); const { bindActionCreators } = __webpack_require__(19); const Tree = createFactory(_devtoolsComponents2.default.Tree); __webpack_require__(52); const classnames = __webpack_require__(53); const { MODE } = __webpack_require__(3); -const Utils = __webpack_require__(11); +const Utils = __webpack_require__(10); const { getChildren, getClosestGripNode, getParent, getValue, nodeHasAccessors, nodeHasProperties, @@ -5248,17 +5344,19 @@ const { nodeIsMissingArguments, nodeIsOptimizedOut, nodeIsPrimitive, nodeIsPrototype, nodeIsSetter, nodeIsUninitializedBinding, nodeIsUnmappedBinding, nodeIsUnscopedBinding, - nodeIsWindow + nodeIsWindow, + nodeIsLongString, + nodeHasFullText } = Utils.node; // This implements a component that renders an interactive inspector // for looking at JavaScript objects. It expects descriptions of // objects from the protocol, and will dynamically fetch children // properties as objects are expanded. // // If you want to inspect a single object, pass the name and the @@ -5295,32 +5393,54 @@ class ObjectInspector extends Component self.setExpanded = this.setExpanded.bind(this); self.focusItem = this.focusItem.bind(this); self.getRoots = this.getRoots.bind(this); } shouldComponentUpdate(nextProps) { const { expandedPaths, + focusedItem, loadedProperties, roots } = this.props; if (roots !== nextProps.roots) { - // Since the roots changed, we assume the properties did as well. Thus we can clear - // the cachedNodes to avoid bugs and memory leaks. + // Since the roots changed, we assume the properties did as well, so we need to + // cleanup the component internal state. + + // We can clear the cachedNodes to avoid bugs and memory leaks. this.cachedNodes.clear(); + // The rootsChanged action will be handled in a middleware to release the actors + // of the old roots, as well as cleanup the state properties (expandedPaths, + // loadedProperties, …). + this.props.rootsChanged(nextProps); + // We don't render right away since the state is going to be changed by the + // rootsChanged action. The `state.forceUpdate` flag will be set to `true` so we + // can execute a new render cycle with the cleaned state. + return false; + } + + if (nextProps.forceUpdate === true) { return true; } // We should update if: // - there are new loaded properties // - OR the expanded paths number changed, and all of them have properties loaded // - OR the expanded paths number did not changed, but old and new sets differ - return loadedProperties.size !== nextProps.loadedProperties.size || expandedPaths.size !== nextProps.expandedPaths.size && [...nextProps.expandedPaths].every(path => nextProps.loadedProperties.has(path)) || expandedPaths.size === nextProps.expandedPaths.size && [...nextProps.expandedPaths].some(key => !expandedPaths.has(key)); + // - OR the focused node changed. + return loadedProperties.size !== nextProps.loadedProperties.size || expandedPaths.size !== nextProps.expandedPaths.size && [...nextProps.expandedPaths].every(path => nextProps.loadedProperties.has(path)) || expandedPaths.size === nextProps.expandedPaths.size && [...nextProps.expandedPaths].some(key => !expandedPaths.has(key)) || focusedItem !== nextProps.focusedItem; + } + + componentDidUpdate(prevProps) { + if (this.props.forceUpdate) { + // If the component was updated, we can then reset the forceUpdate flag. + this.props.forceUpdated(); + } } componentWillUnmount() { const { releaseActor } = this.props; if (typeof releaseActor !== "function") { return; } @@ -5353,49 +5473,55 @@ class ObjectInspector extends Component setExpanded(item, expand) { if (nodeIsPrimitive(item)) { return; } const { createObjectClient, + createLongStringClient, loadedProperties, nodeExpand, nodeCollapse, roots } = this.props; if (expand === true) { const gripItem = getClosestGripNode(item); const value = getValue(gripItem); const isRoot = value && roots.some(root => { const rootValue = getValue(root); return rootValue && rootValue.actor === value.actor; }); const actor = isRoot || !value ? null : value.actor; - nodeExpand(item, actor, loadedProperties, createObjectClient); + nodeExpand(item, actor, loadedProperties, createObjectClient, createLongStringClient); } else { nodeCollapse(item); } } focusItem(item) { const { + focusable = true, focusedItem, + nodeFocus, onFocus } = this.props; - if (focusedItem !== item && onFocus) { - onFocus(item); + if (focusable && focusedItem !== item) { + nodeFocus(item); + if (focusedItem !== item && onFocus) { + onFocus(item); + } } } getTreeItemLabelAndValue(item, depth, expanded) { - let label = item.name; + const label = item.name; const isPrimitive = nodeIsPrimitive(item); if (nodeIsOptimizedOut(item)) { return { label, value: dom.span({ className: "unavailable" }, "(optimized away)") }; } @@ -5442,28 +5568,34 @@ class ObjectInspector extends Component return { label: Utils.renderRep(item, { ...this.props, functionName: label }) }; } - if (nodeHasProperties(item) || nodeHasAccessors(item) || nodeIsMapEntry(item) || isPrimitive) { - let repsProp = { ...this.props }; + if (nodeHasProperties(item) || nodeHasAccessors(item) || nodeIsMapEntry(item) || nodeIsLongString(item) || isPrimitive) { + let repProps = { ...this.props }; if (depth > 0) { - repsProp.mode = this.props.mode === MODE.LONG ? MODE.SHORT : MODE.TINY; + repProps.mode = this.props.mode === MODE.LONG ? MODE.SHORT : MODE.TINY; } if (expanded) { - repsProp.mode = MODE.TINY; + repProps.mode = MODE.TINY; + } + + if (nodeIsLongString(item)) { + repProps.member = { + open: nodeHasFullText(item) && expanded + }; } return { label, - value: Utils.renderRep(item, repsProp) + value: Utils.renderRep(item, repProps) }; } return { label }; } @@ -5493,35 +5625,48 @@ class ObjectInspector extends Component setExpanded: this.setExpanded }); } : undefined }, label); } getTreeTopElementProps(item, depth, focused, expanded) { const { + onCmdCtrlClick, onDoubleClick, dimTopLevelWindow } = this.props; let parentElementProps = { className: classnames("node object-node", { focused, lessen: !expanded && (nodeIsDefaultProperties(item) || nodeIsPrototype(item) || dimTopLevelWindow === true && nodeIsWindow(item) && depth === 0), block: nodeIsBlock(item) }), onClick: e => { - e.stopPropagation(); - - // If the user selected text, bail out. - if (Utils.selection.documentHasSelection()) { + if (e.metaKey && onCmdCtrlClick) { + onCmdCtrlClick(item, { + depth, + event: e, + focused, + expanded + }); + e.stopPropagation(); return; } - this.setExpanded(item, !expanded); + // If this click happened because the user selected some text, bail out. + // Note that if the user selected some text before and then clicks here, + // the previously selected text will be first unselected, unless the user + // clicked on the arrow itself. Indeed because the arrow is an image, clicking on + // it does not remove any existing text selection. So we need to also check if + // teh arrow was clicked. + if (Utils.selection.documentHasSelection() && !(e.target && e.target.matches && e.target.matches(".arrow"))) { + e.stopPropagation(); + } } }; if (onDoubleClick) { parentElementProps.onDoubleClick = e => { e.stopPropagation(); onDoubleClick(item, { depth, @@ -5541,62 +5686,63 @@ class ObjectInspector extends Component return dom.div(this.getTreeTopElementProps(item, depth, focused, expanded), arrow, labelElement, delimiter, value); } render() { const { autoExpandAll = true, autoExpandDepth = 1, - disabledFocus, + focusable = true, disableWrap = false, expandedPaths, focusedItem, inline } = this.props; return Tree({ className: classnames({ inline, nowrap: disableWrap, "object-inspector": true }), autoExpandAll, autoExpandDepth, - disabledFocus, isExpanded: item => expandedPaths && expandedPaths.has(item.path), isExpandable: item => nodeIsPrimitive(item) === false, focused: focusedItem, getRoots: this.getRoots, getParent, getChildren: this.getItemChildren, getKey: this.getNodeKey, onExpand: item => this.setExpanded(item, true), onCollapse: item => this.setExpanded(item, false), - onFocus: this.focusItem, + onFocus: focusable ? this.focusItem : null, renderItem: this.renderTreeItem }); } } function mapStateToProps(state, props) { return { actors: state.actors, expandedPaths: state.expandedPaths, - focusedItem: state.focusedItem, - loadedProperties: state.loadedProperties + // If the root changes, we want to pass a possibly new focusedItem property + focusedItem: state.roots !== props.roots ? props.focusedItem : state.focusedItem, + loadedProperties: state.loadedProperties, + forceUpdate: state.forceUpdate }; } function mapDispatchToProps(dispatch) { - return bindActionCreators(__webpack_require__(56), dispatch); + return bindActionCreators(__webpack_require__(55), dispatch); } module.exports = connect(mapStateToProps, mapDispatchToProps)(ObjectInspector); /***/ }), /* 49 */ /***/ (function(module, exports, __webpack_require__) { @@ -5621,17 +5767,17 @@ module.exports = { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var _react = __webpack_require__(10); +var _react = __webpack_require__(9); var _react2 = _interopRequireDefault(_react); var _reactDomFactories = __webpack_require__(1); var _reactDomFactories2 = _interopRequireDefault(_reactDomFactories); var _propTypes = __webpack_require__(2); @@ -5955,16 +6101,19 @@ class Tree extends Component { // onExpand(item: Item) // onCollapse(item: Item) // // Example: // // onExpand: item => dispatchExpandActionToRedux(item) onExpand: _propTypes2.default.func, onCollapse: _propTypes2.default.func, + // Optional event handler called with the current focused node when the Enter key + // is pressed. Can be useful to allow further keyboard actions within the tree node. + onActivate: _propTypes2.default.func, isExpandable: _propTypes2.default.func, // Additional classes to add to the root element. className: _propTypes2.default.string, // style object to be applied to the root element. style: _propTypes2.default.object }; } @@ -5982,42 +6131,49 @@ class Tree extends Component { seen: new Set() }; this._onExpand = oncePerAnimationFrame(this._onExpand).bind(this); this._onCollapse = oncePerAnimationFrame(this._onCollapse).bind(this); this._focusPrevNode = oncePerAnimationFrame(this._focusPrevNode).bind(this); this._focusNextNode = oncePerAnimationFrame(this._focusNextNode).bind(this); this._focusParentNode = oncePerAnimationFrame(this._focusParentNode).bind(this); + this._focusFirstNode = oncePerAnimationFrame(this._focusFirstNode).bind(this); + this._focusLastNode = oncePerAnimationFrame(this._focusLastNode).bind(this); this._autoExpand = this._autoExpand.bind(this); this._preventArrowKeyScrolling = this._preventArrowKeyScrolling.bind(this); this._dfs = this._dfs.bind(this); this._dfsFromRoots = this._dfsFromRoots.bind(this); this._focus = this._focus.bind(this); this._scrollNodeIntoView = this._scrollNodeIntoView.bind(this); this._onBlur = this._onBlur.bind(this); this._onKeyDown = this._onKeyDown.bind(this); this._nodeIsExpandable = this._nodeIsExpandable.bind(this); + this._activateNode = oncePerAnimationFrame(this._activateNode).bind(this); } componentDidMount() { this._autoExpand(); if (this.props.focused) { this._scrollNodeIntoView(this.props.focused); + // Always keep the focus on the tree itself. + this.treeRef.focus(); } } componentWillReceiveProps(nextProps) { this._autoExpand(); } componentDidUpdate(prevProps, prevState) { if (prevProps.focused !== this.props.focused) { this._scrollNodeIntoView(this.props.focused); + // Always keep the focus on the tree itself. + this.treeRef.focus(); } } _autoExpand() { if (!this.props.autoExpandDepth) { return; } @@ -6147,18 +6303,21 @@ class Tree extends Component { * The item to be focused, or undefined to focus no item. * * @param {Object|undefined} options * An options object which can contain: * - dir: "up" or "down" to indicate if we should scroll the element to the * top or the bottom of the scrollable container when the element is * off canvas. */ - _focus(item, options) { - this._scrollNodeIntoView(item, options); + _focus(item, options = {}) { + const { preventAutoScroll } = options; + if (item && !preventAutoScroll) { + this._scrollNodeIntoView(item, options); + } if (this.props.onFocus) { this.props.onFocus(item); } } /** * Sets the passed in item to be the focused item. * @@ -6170,33 +6329,36 @@ class Tree extends Component { * - dir: "up" or "down" to indicate if we should scroll the element to the * top or the bottom of the scrollable container when the element is * off canvas. */ _scrollNodeIntoView(item, options = {}) { if (item !== undefined) { const treeElement = this.treeRef; const element = document.getElementById(this.props.getKey(item)); + if (element) { const { top, bottom } = element.getBoundingClientRect(); const closestScrolledParent = node => { if (node == null) { return null; } if (node.scrollHeight > node.clientHeight) { return node; } return closestScrolledParent(node.parentNode); }; const scrolledParent = closestScrolledParent(treeElement); - const isVisible = !scrolledParent || top >= 0 && bottom <= scrolledParent.clientHeight; + const scrolledParentRect = scrolledParent ? scrolledParent.getBoundingClientRect() : null; + const isVisible = !scrolledParent || top >= scrolledParentRect.top && bottom <= scrolledParentRect.bottom; if (!isVisible) { - let scrollToTop = !options.alignTo && top < 0 || options.alignTo === "top"; + const { alignTo } = options; + let scrollToTop = alignTo ? alignTo === "top" : !scrolledParentRect || top < scrolledParentRect.top; element.scrollIntoView(scrollToTop); } } } } /** * Sets the state to have no focused item. @@ -6240,16 +6402,28 @@ class Tree extends Component { return; case "ArrowRight": if (this._nodeIsExpandable(this.props.focused) && !this.props.isExpanded(this.props.focused)) { this._onExpand(this.props.focused); } else { this._focusNextNode(); } + return; + + case "Home": + this._focusFirstNode(); + return; + + case "End": + this._focusLastNode(); + return; + + case "Enter": + this._activateNode(); } } /** * Sets the previous node relative to the currently focused item, to focused. */ _focusPrevNode() { // Start a depth first search and keep going until we reach the currently @@ -6316,16 +6490,33 @@ class Tree extends Component { if (traversal[parentIndex].item === parent) { break; } } this._focus(parent, { alignTo: "top" }); } + _focusFirstNode() { + const traversal = this._dfsFromRoots(); + this._focus(traversal[0].item, { alignTo: "top" }); + } + + _focusLastNode() { + const traversal = this._dfsFromRoots(); + const lastIndex = traversal.length - 1; + this._focus(traversal[lastIndex].item, { alignTo: "bottom" }); + } + + _activateNode() { + if (this.props.onActivate) { + this.props.onActivate(this.props.focused); + } + } + _nodeIsExpandable(item) { return this.props.isExpandable ? this.props.isExpandable(item) : !!this.props.getChildren(item).length; } render() { const traversal = this._dfsFromRoots(); const { focused @@ -6342,17 +6533,19 @@ class Tree extends Component { depth, renderItem: this.props.renderItem, focused: focused === item, expanded: this.props.isExpanded(item), isExpandable: this._nodeIsExpandable(item), onExpand: this._onExpand, onCollapse: this._onCollapse, onClick: e => { - this._focus(item); + // Since the user just clicked the node, there's no need to check if it should + // be scrolled into view. + this._focus(item, { preventAutoScroll: true }); if (this.props.isExpanded(item)) { this.props.onCollapse(item); } else { this.props.onExpand(item, e.altKey); } } }); }); @@ -6464,84 +6657,64 @@ var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBP } else { window.classNames = classNames; } }()); /***/ }), /* 54 */ -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_54__; - -/***/ }), -/* 55 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* 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/. */ -const { ELEMENT_NODE } = __webpack_require__(9); - function documentHasSelection() { const selection = getSelection(); if (!selection) { return false; } - const { - anchorNode, - focusNode - } = selection; - - // When clicking the arrow, which is an inline svg element, the selection do have a type - // of "Range". We need to have an explicit case when the anchor and the focus node are - // the same and they have an arrow ancestor. - if (focusNode && focusNode === anchorNode && focusNode.nodeType == ELEMENT_NODE && focusNode.closest(".arrow")) { - return false; - } - return selection.type === "Range"; } module.exports = { documentHasSelection }; /***/ }), -/* 56 */ +/* 55 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const { loadItemProperties } = __webpack_require__(21); /* 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/. */ /** * This action is responsible for expanding a given node, * which also means that it will call the action responsible to fetch properties. */ -function nodeExpand(node, actor, loadedProperties, createObjectClient) { +function nodeExpand(node, actor, loadedProperties, createObjectClient, createLongStringClient) { return async ({ dispatch }) => { dispatch({ type: "NODE_EXPAND", data: { node } }); if (!loadedProperties.has(node.path)) { - dispatch(nodeLoadProperties(node, actor, loadedProperties, createObjectClient)); + dispatch(nodeLoadProperties(node, actor, loadedProperties, createObjectClient, createLongStringClient)); } }; } function nodeCollapse(node) { return { type: "NODE_COLLAPSE", data: { node } @@ -6553,79 +6726,130 @@ function nodeFocus(node) { type: "NODE_FOCUS", data: { node } }; } /* * This action checks if we need to fetch properties, entries, prototype and symbols * for a given node. If we do, it will call the appropriate ObjectClient functions. */ -function nodeLoadProperties(item, actor, loadedProperties, createObjectClient) { +function nodeLoadProperties(item, actor, loadedProperties, createObjectClient, createLongStringClient) { return async ({ dispatch }) => { try { - const properties = await loadItemProperties(item, createObjectClient, loadedProperties); + const properties = await loadItemProperties(item, createObjectClient, createLongStringClient, loadedProperties); dispatch(nodePropertiesLoaded(item, actor, properties)); } catch (e) { console.error(e); } }; } function nodePropertiesLoaded(node, actor, properties) { return { type: "NODE_PROPERTIES_LOADED", data: { node, actor, properties } }; } +/* + * This action is dispatched when the `roots` prop, provided by a consumer of the + * ObjectInspector (inspector, console, …), is modified. It will clean the internal + * state properties (expandedPaths, loadedProperties, …) and release the actors consumed + * with the previous roots. + * It takes a props argument which reflects what is passed by the upper-level consumer. + */ +function rootsChanged(props) { + return { + type: "ROOTS_CHANGED", + data: props + }; +} + +/* + * This action will reset the `forceUpdate` flag in the state. + */ +function forceUpdated() { + return { + type: "FORCE_UPDATED" + }; +} + module.exports = { + forceUpdated, nodeExpand, nodeCollapse, nodeFocus, nodeLoadProperties, - nodePropertiesLoaded + nodePropertiesLoaded, + rootsChanged }; /***/ }), -/* 57 */ +/* 56 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* 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/. */ -const { applyMiddleware, createStore } = __webpack_require__(19); -const { thunk } = __webpack_require__(58); -const { waitUntilService } = __webpack_require__(59); -const reducer = __webpack_require__(60); +const { applyMiddleware, createStore, compose } = __webpack_require__(19); +const { thunk } = __webpack_require__(57); +const { waitUntilService } = __webpack_require__(58); +const reducer = __webpack_require__(59); function createInitialState(overrides) { return { actors: new Set(), expandedPaths: new Set(), focusedItem: null, loadedProperties: new Map(), + forceUpdated: false, ...overrides }; } +function enableStateReinitializer(props) { + return next => (innerReducer, initialState, enhancer) => { + function reinitializerEnhancer(state, action) { + if (action.type !== "ROOTS_CHANGED") { + return innerReducer(state, action); + } + + if (props.releaseActor && initialState.actors) { + initialState.actors.forEach(props.releaseActor); + } + + return { + ...action.data, + actors: new Set(), + expandedPaths: new Set(), + loadedProperties: new Map(), + // Indicates to the component that we do want to render on the next render cycle. + forceUpdate: true + }; + } + return next(reinitializerEnhancer, initialState, enhancer); + }; +} + module.exports = props => { const middlewares = [thunk]; + if (props.injectWaitService) { middlewares.push(waitUntilService); } - return createStore(reducer, createInitialState(props), applyMiddleware(...middlewares)); + return createStore(reducer, createInitialState(props), compose(applyMiddleware(...middlewares), enableStateReinitializer(props))); }; /***/ }), -/* 58 */ +/* 57 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* 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/. */ @@ -6639,17 +6863,17 @@ module.exports = props => { function thunk({ dispatch, getState }) { return next => action => { return typeof action === "function" ? action({ dispatch, getState }) : next(action); }; } exports.thunk = thunk; /***/ }), -/* 59 */ +/* 58 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* 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/. */ @@ -6713,17 +6937,17 @@ function waitUntilService({ dispatch, ge } module.exports = { WAIT_UNTIL_TYPE, waitUntilService }; /***/ }), -/* 60 */ +/* 59 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; function reducer(state = {}, action) { const { type, @@ -6747,21 +6971,31 @@ function reducer(state = {}, action) { if (type === "NODE_PROPERTIES_LOADED") { return cloneState({ actors: data.actor ? new Set(state.actors || []).add(data.actor) : state.actors, loadedProperties: new Map(state.loadedProperties).set(data.node.path, action.data.properties) }); } if (type === "NODE_FOCUS") { + if (state.focusedItem === data.node) { + return state; + } + return cloneState({ focusedItem: data.node }); } + if (type === "FORCE_UPDATED") { + return cloneState({ + forceUpdate: false + }); + } + return state; } /* 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/. */ module.exports = reducer;
new file mode 100644 --- /dev/null +++ b/devtools/client/themes/images/tool-application.svg @@ -0,0 +1,16 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" stroke="context-fill #0b0b0b"> + <rect x="1.5" y="1.5" width="3" height="3" fill="transparent" stroke-width="1"/> + <rect x="6.5" y="1.5" width="3" height="3" fill="transparent" stroke-width="1"/> + <rect x="11.5" y="1.5" width="3" height="3" fill="transparent" stroke-width="1"/> + + <rect x="1.5" y="6.5" width="3" height="3" fill="transparent" stroke-width="1"/> + <rect x="6.5" y="6.5" width="3" height="3" fill="transparent" stroke-width="1"/> + <rect x="11.5" y="6.5" width="3" height="3" fill="transparent" stroke-width="1"/> + + <rect x="1.5" y="11.5" width="3" height="3" fill="transparent" stroke-width="1"/> + <rect x="6.5" y="11.5" width="3" height="3" fill="transparent" stroke-width="1"/> + <rect x="11.5" y="11.5" width="3" height="3" fill="transparent" stroke-width="1"/> +</svg> \ No newline at end of file
--- a/devtools/client/webconsole/utils/object-inspector.js +++ b/devtools/client/webconsole/utils/object-inspector.js @@ -43,17 +43,17 @@ function getObjectInspector(grip, servic : null; } const objectInspectorProps = { autoExpandDepth: 0, mode: MODE.LONG, // TODO: we disable focus since it's not currently working well in ObjectInspector. // Let's remove the property below when problem are fixed in OI. - disabledFocus: true, + focusable: false, roots: [{ path: (grip && grip.actor) || JSON.stringify(grip), contents: { value: grip } }], createObjectClient: object => new ObjectClient(serviceContainer.hudProxy.client, object),
new file mode 100644 --- /dev/null +++ b/devtools/server/actors/animation-type-longhand.js @@ -0,0 +1,347 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +// Types of animation types of longhand properties. +exports.ANIMATION_TYPE_FOR_LONGHANDS = [ + ["discrete", new Set([ + "align-content", + "align-items", + "align-self", + "-moz-appearance", + "backface-visibility", + "background-attachment", + "background-blend-mode", + "background-clip", + "background-image", + "background-origin", + "background-repeat", + "border-bottom-style", + "border-collapse", + "border-image-outset", + "border-image-repeat", + "border-image-slice", + "border-image-source", + "border-image-width", + "border-left-style", + "border-right-style", + "border-top-style", + "-moz-box-align", + "box-decoration-break", + "-moz-box-direction", + "-moz-box-ordinal-group", + "-moz-box-orient", + "-moz-box-pack", + "box-sizing", + "caption-side", + "clear", + "clip-rule", + "color-adjust", + "color-interpolation", + "color-interpolation-filters", + "column-fill", + "column-rule-style", + "column-span", + "contain", + "content", + "counter-increment", + "counter-reset", + "cursor", + "direction", + "dominant-baseline", + "empty-cells", + "fill-rule", + "flex-direction", + "flex-wrap", + "float", + "-moz-float-edge", + "font-family", + "font-feature-settings", + "font-kerning", + "font-language-override", + "font-style", + "font-synthesis", + "font-variant-alternates", + "font-variant-caps", + "font-variant-east-asian", + "font-variant-ligatures", + "font-variant-numeric", + "font-variant-position", + "-moz-force-broken-image-icon", + "grid-auto-columns", + "grid-auto-flow", + "grid-auto-rows", + "grid-column-end", + "grid-column-start", + "grid-row-end", + "grid-row-start", + "grid-template-areas", + "grid-template-columns", + "grid-template-rows", + "hyphens", + "image-orientation", + "image-rendering", + "ime-mode", + "initial-letter", + "isolation", + "justify-content", + "justify-items", + "justify-self", + "list-style-image", + "list-style-position", + "list-style-type", + "marker-end", + "marker-mid", + "marker-start", + "mask-clip", + "mask-composite", + "mask-image", + "mask-mode", + "mask-origin", + "mask-repeat", + "mask-type", + "mix-blend-mode", + "object-fit", + "-moz-orient", + "-moz-osx-font-smoothing", + "outline-style", + "overflow-clip-box-block", + "overflow-clip-box-inline", + "overflow-wrap", + "overflow-x", + "overflow-y", + "overscroll-behavior-x", + "overscroll-behavior-y", + "page-break-after", + "page-break-before", + "page-break-inside", + "paint-order", + "pointer-events", + "position", + "quotes", + "resize", + "ruby-align", + "ruby-position", + "scroll-behavior", + "scroll-snap-coordinate", + "scroll-snap-destination", + "scroll-snap-points-x", + "scroll-snap-points-y", + "scroll-snap-type-x", + "scroll-snap-type-y", + "shape-rendering", + "-moz-stack-sizing", + "stroke-linecap", + "stroke-linejoin", + "table-layout", + "text-align", + "text-align-last", + "text-anchor", + "text-combine-upright", + "text-decoration-line", + "text-decoration-style", + "text-emphasis-position", + "text-emphasis-style", + "text-justify", + "text-orientation", + "text-overflow", + "text-rendering", + "-moz-text-size-adjust", + "-webkit-text-stroke-width", + "text-transform", + "touch-action", + "transform-box", + "transform-style", + "unicode-bidi", + "-moz-user-focus", + "-moz-user-input", + "-moz-user-modify", + "-moz-user-select", + "vector-effect", + "visibility", + "white-space", + "will-change", + "-moz-window-dragging", + "word-break", + "writing-mode", + ])], + ["none", new Set([ + "animation-delay", + "animation-direction", + "animation-duration", + "animation-fill-mode", + "animation-iteration-count", + "animation-name", + "animation-play-state", + "animation-timing-function", + "-moz-binding", + "block-size", + "border-block-end-color", + "border-block-end-style", + "border-block-end-width", + "border-block-start-color", + "border-block-start-style", + "border-block-start-width", + "border-inline-end-color", + "border-inline-end-style", + "border-inline-end-width", + "border-inline-start-color", + "border-inline-start-style", + "border-inline-start-width", + "-moz-context-properties", + "-moz-control-character-visibility", + "display", + "font-optical-sizing", + "inline-size", + "margin-block-end", + "margin-block-start", + "margin-inline-end", + "margin-inline-start", + "-moz-math-display", + "max-block-size", + "max-inline-size", + "min-block-size", + "-moz-min-font-size-ratio", + "min-inline-size", + "offset-block-end", + "offset-block-start", + "offset-inline-end", + "offset-inline-start", + "padding-block-end", + "padding-block-start", + "padding-inline-end", + "padding-inline-start", + "rotate", + "scale", + "-moz-script-level", + "-moz-top-layer", + "transition-delay", + "transition-duration", + "transition-property", + "transition-timing-function", + "translate", + "-moz-window-shadow", + ])], + ["color", new Set([ + "background-color", + "border-bottom-color", + "border-left-color", + "border-right-color", + "border-top-color", + "caret-color", + "color", + "column-rule-color", + "flood-color", + "-moz-font-smoothing-background-color", + "lighting-color", + "outline-color", + "stop-color", + "text-decoration-color", + "text-emphasis-color", + "-webkit-text-fill-color", + "-webkit-text-stroke-color", + ])], + ["custom", new Set([ + "background-position-x", + "background-position-y", + "background-size", + "border-bottom-width", + "border-left-width", + "border-right-width", + "border-spacing", + "border-top-width", + "clip", + "clip-path", + "column-count", + "column-rule-width", + "filter", + "font-stretch", + "font-variation-settings", + "font-weight", + "-moz-image-region", + "mask-position-x", + "mask-position-y", + "mask-size", + "object-position", + "order", + "perspective-origin", + "shape-outside", + "stroke-dasharray", + "transform", + "transform-origin", + "-moz-window-transform", + "-moz-window-transform-origin", + ])], + ["coord", new Set([ + "border-bottom-left-radius", + "border-bottom-right-radius", + "border-top-left-radius", + "border-top-right-radius", + "bottom", + "column-gap", + "column-width", + "flex-basis", + "grid-column-gap", + "grid-row-gap", + "height", + "left", + "letter-spacing", + "line-height", + "margin-bottom", + "margin-left", + "margin-right", + "margin-top", + "max-height", + "max-width", + "min-height", + "min-width", + "-moz-outline-radius-bottomleft", + "-moz-outline-radius-bottomright", + "-moz-outline-radius-topleft", + "-moz-outline-radius-topright", + "padding-bottom", + "padding-left", + "padding-right", + "padding-top", + "perspective", + "right", + "stroke-dashoffset", + "stroke-width", + "-moz-tab-size", + "text-indent", + "top", + "vertical-align", + "width", + "word-spacing", + "z-index", + ])], + ["float", new Set([ + "-moz-box-flex", + "fill-opacity", + "flex-grow", + "flex-shrink", + "flood-opacity", + "font-size-adjust", + "opacity", + "shape-image-threshold", + "stop-opacity", + "stroke-miterlimit", + "stroke-opacity", + "-moz-window-opacity", + ])], + ["shadow", new Set([ + "box-shadow", + "text-shadow", + ])], + ["paintServer", new Set([ + "fill", + "stroke", + ])], + ["length", new Set([ + "font-size", + "outline-offset", + "outline-width", + ])], +];
--- a/devtools/server/actors/animation.js +++ b/devtools/server/actors/animation.js @@ -24,26 +24,37 @@ * - WebAnimation WebIDL files: * /dom/webidl/Animation*.webidl */ const {Cu, Ci} = require("chrome"); const protocol = require("devtools/shared/protocol"); const {Actor} = protocol; const {animationPlayerSpec, animationsSpec} = require("devtools/shared/specs/animation"); +const {ANIMATION_TYPE_FOR_LONGHANDS} = require("./animation-type-longhand"); // Types of animations. const ANIMATION_TYPES = { CSS_ANIMATION: "cssanimation", CSS_TRANSITION: "csstransition", SCRIPT_ANIMATION: "scriptanimation", UNKNOWN: "unknown" }; exports.ANIMATION_TYPES = ANIMATION_TYPES; +function getAnimationTypeForLonghand(property) { + for (let [type, props] of ANIMATION_TYPE_FOR_LONGHANDS) { + if (props.has(property)) { + return type; + } + } + throw new Error("Unknown longhand property name"); +} +exports.getAnimationTypeForLonghand = getAnimationTypeForLonghand; + /** * The AnimationPlayerActor provides information about a given animation: its * startTime, currentTime, current state, etc. * * Since the state of a player changes as the animation progresses it is often * useful to call getCurrentState at regular intervals to get the current state. * * This actor also allows playing, pausing and seeking the animation. @@ -510,17 +521,17 @@ var AnimationPlayerActor = protocol.Acto pseudo = target.type; target = target.parentElement; } const value = DOMWindowUtils.getUnanimatedComputedStyle(target, pseudo, property.name, DOMWindowUtils.FLUSH_NONE); - const animationType = DOMWindowUtils.getAnimationTypeForLonghand(property.name); + const animationType = getAnimationTypeForLonghand(property.name); underlyingValue = animationType === "float" ? parseFloat(value, 10) : value; } values.value = underlyingValue; }); } // Calculate the distance. for (let property of properties) { @@ -564,22 +575,19 @@ var AnimationPlayerActor = protocol.Acto }, /** * Get the animation types for a given list of CSS property names. * @param {Array} propertyNames - CSS property names (e.g. background-color) * @return {Object} Returns animation types (e.g. {"background-color": "rgb(0, 0, 0)"}. */ getAnimationTypes: function(propertyNames) { - const DOMWindowUtils = this.window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); const animationTypes = {}; for (let propertyName of propertyNames) { - animationTypes[propertyName] = - DOMWindowUtils.getAnimationTypeForLonghand(propertyName); + animationTypes[propertyName] = getAnimationTypeForLonghand(propertyName); } return animationTypes; }, /** * Returns the distance of between value1, value2. * @param {Object} target - dom element * @param {String} propertyName - e.g. transform
--- a/devtools/server/actors/moz.build +++ b/devtools/server/actors/moz.build @@ -16,16 +16,17 @@ DIRS += [ ] DevToolsModules( 'accessibility-parent.js', 'accessibility.js', 'actor-registry.js', 'addon.js', 'addons.js', + 'animation-type-longhand.js', 'animation.js', 'array-buffer.js', 'breakpoint.js', 'call-watcher.js', 'canvas.js', 'child-process.js', 'chrome.js', 'common.js',
--- a/devtools/server/tests/mochitest/chrome.ini +++ b/devtools/server/tests/mochitest/chrome.ini @@ -25,16 +25,17 @@ support-files = memory-helpers.js nonchrome_unsafeDereference.html small-image.gif setup-in-child.js setup-in-parent.js webconsole-helpers.js webextension-helpers.js [test_animation_actor-lifetime.html] +[test_animation-type-longhand.html] [test_connection-manager.html] [test_connectToFrame.html] [test_css-logic.html] [test_css-logic-media-queries.html] [test_css-logic-specificity.html] [test_css-properties.html] [test_Debugger.Source.prototype.introductionScript.html] [test_Debugger.Source.prototype.introductionType.html]
new file mode 100644 --- /dev/null +++ b/devtools/server/tests/mochitest/test_animation-type-longhand.html @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>Test animation-type-longhand</title> +<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> +<body> +<script> + "use strict"; + + // This test checks the content of animation type for longhands table that + // * every longhand property is included + // * nothing else is included + // * no property is mapped to more than one animation type + window.onload = function() { + const {require} = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {}); + const { ANIMATION_TYPE_FOR_LONGHANDS } = + require("devtools/server/actors/animation-type-longhand"); + const InspectorUtils = SpecialPowers.InspectorUtils; + + const all_longhands = InspectorUtils.getCSSPropertyNames({ + includeShorthands: false, + includeExperimentals: true, + }); + + let unseen_longhands = new Set(all_longhands); + let seen_longhands = new Set(); + for (let [, names] of ANIMATION_TYPE_FOR_LONGHANDS) { + for (let name of names) { + ok(!seen_longhands.has(name), + `${name} should have only one animation type`); + ok(unseen_longhands.has(name), + `${name} is an unseen longhand property`); + unseen_longhands.delete(name); + seen_longhands.add(name); + } + } + is(unseen_longhands.size, 0, + "All longhands should be mapped to some animation type"); + + SimpleTest.finish(); + }; +</script> +</body>
--- a/devtools/shared/client/root-client.js +++ b/devtools/shared/client/root-client.js @@ -86,16 +86,117 @@ RootClient.prototype = { * List the running processes. * * @param function onResponse * Called with the response packet. */ listProcesses: DebuggerClient.requester({ type: "listProcesses" }), /** + * Retrieve all service worker registrations as well as workers from the parent + * and child processes. Listing service workers involves merging information coming from + * registrations and workers, this method will combine this information to present a + * unified array of serviceWorkers. If you are only interested in other workers, use + * listWorkers. + * + * @return {Object} + * - {Array} service + * array of form-like objects for serviceworkers + * - {Array} shared + * Array of WorkerActor forms, containing shared workers. + * - {Array} other + * Array of WorkerActor forms, containing other workers. + */ + listAllWorkers: async function() { + let result = { + service: [], + shared: [], + other: [] + }; + + try { + let registrations = []; + let workers = []; + + // List service worker registrations + ({ registrations } = await this.listServiceWorkerRegistrations()); + + // List workers from the Parent process + ({ workers } = await this.listWorkers()); + + // And then from the Child processes + let { processes } = await this.listProcesses(); + for (let process of processes) { + // Ignore parent process + if (process.parent) { + continue; + } + let { form } = await this._client.getProcess(process.id); + let processActor = form.actor; + let response = await this._client.request({ + to: processActor, + type: "listWorkers" + }); + workers = workers.concat(response.workers); + } + + registrations.forEach(form => { + result.service.push({ + name: form.url, + url: form.url, + scope: form.scope, + fetch: form.fetch, + registrationActor: form.actor, + active: form.active + }); + }); + + workers.forEach(form => { + let worker = { + name: form.url, + url: form.url, + workerActor: form.actor + }; + switch (form.type) { + case Ci.nsIWorkerDebugger.TYPE_SERVICE: + let registration = result.service.find(r => r.scope === form.scope); + if (registration) { + // XXX: Race, sometimes a ServiceWorkerRegistrationInfo doesn't + // have a scriptSpec, but its associated WorkerDebugger does. + if (!registration.url) { + registration.name = registration.url = form.url; + } + registration.workerActor = form.actor; + } else { + worker.fetch = form.fetch; + + // If a service worker registration could not be found, this means we are in + // e10s, and registrations are not forwarded to other processes until they + // reach the activated state. Augment the worker as a registration worker to + // display it in aboutdebugging. + worker.scope = form.scope; + worker.active = false; + result.service.push(worker); + } + break; + case Ci.nsIWorkerDebugger.TYPE_SHARED: + result.shared.push(worker); + break; + default: + result.other.push(worker); + } + }); + } catch (e) { + // Something went wrong, maybe our client is disconnected? + } + + return result; + }, + + /** * Fetch the TabActor for the currently selected tab, or for a specific * tab given as first parameter. * * @param [optional] object filter * A dictionary object with following optional attributes: * - outerWindowID: used to match tabs in parent process * - tabId: used to match tabs in child processes * - tab: a reference to xul:tab element
--- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -2738,70 +2738,16 @@ nsDOMWindowUtils::ComputeAnimationDistan RefPtr<ComputedStyle> computedStyle = nsComputedDOMStyle::GetComputedStyle(element, nullptr); *aResult = v1.ComputeDistance(property, v2, computedStyle); return NS_OK; } NS_IMETHODIMP -nsDOMWindowUtils::GetAnimationTypeForLonghand(const nsAString& aProperty, - nsAString& aResult) -{ - nsCSSPropertyID propertyID = - nsCSSProps::LookupProperty(aProperty, CSSEnabledState::eForAllContent); - if (propertyID == eCSSProperty_UNKNOWN) { - return NS_ERROR_INVALID_ARG; - } - if (nsCSSProps::IsShorthand(propertyID)) { - // The given property should be a longhand. - return NS_ERROR_INVALID_ARG; - } - switch (nsCSSProps::kAnimTypeTable[propertyID]) { - case eStyleAnimType_Custom: - aResult.AssignLiteral("custom"); - break; - case eStyleAnimType_Coord: - case eStyleAnimType_Sides_Top: - case eStyleAnimType_Sides_Right: - case eStyleAnimType_Sides_Bottom: - case eStyleAnimType_Sides_Left: - case eStyleAnimType_Corner_TopLeft: - case eStyleAnimType_Corner_TopRight: - case eStyleAnimType_Corner_BottomRight: - case eStyleAnimType_Corner_BottomLeft: - aResult.AssignLiteral("coord"); - break; - case eStyleAnimType_nscoord: - aResult.AssignLiteral("length"); - break; - case eStyleAnimType_float: - aResult.AssignLiteral("float"); - break; - case eStyleAnimType_Color: - case eStyleAnimType_ComplexColor: - aResult.AssignLiteral("color"); - break; - case eStyleAnimType_PaintServer: - aResult.AssignLiteral("paintServer"); - break; - case eStyleAnimType_Shadow: - aResult.AssignLiteral("shadow"); - break; - case eStyleAnimType_Discrete: - aResult.AssignLiteral("discrete"); - break; - case eStyleAnimType_None: - aResult.AssignLiteral("none"); - break; - } - return NS_OK; -} - -NS_IMETHODIMP nsDOMWindowUtils::GetUnanimatedComputedStyle(nsIDOMElement* aElement, const nsAString& aPseudoElement, const nsAString& aProperty, int32_t aFlushType, nsAString& aResult) { nsCOMPtr<Element> element = do_QueryInterface(aElement); if (!element) {
--- a/dom/base/test/test_domwindowutils.html +++ b/dom/base/test/test_domwindowutils.html @@ -50,125 +50,28 @@ function test_sendMouseEventOptionals() SimpleTest.executeSoon(next); }, {once: true}); // Check explicit value for optional args utils.sendMouseEvent("mouseup", x, y, button, clickCount, modifiers, false, pressure, source, false); } -function test_getAnimationType() { - [ - { - propertyName: "align-content", - expectedType: "discrete" - }, - { - propertyName: "animation-delay", - expectedType: "none" - }, - { - propertyName: "background-color", - expectedType: "color" - }, - { - propertyName: "background-size", - expectedType: "custom" - }, - { - propertyName: "border-bottom-left-radius", - expectedType: "coord" - }, - { - propertyName: "border-bottom-right-radius", - expectedType: "coord" - }, - { - propertyName: "border-top-left-radius", - expectedType: "coord" - }, - { - propertyName: "border-top-right-radius", - expectedType: "coord" - }, - { - propertyName: "font-size", - expectedType: "length" - }, - { - propertyName: "margin-top", - expectedType: "coord" - }, - { - propertyName: "margin-right", - expectedType: "coord" - }, - { - propertyName: "margin-bottom", - expectedType: "coord" - }, - { - propertyName: "margin-left", - expectedType: "coord" - }, - { - propertyName: "opacity", - expectedType: "float" - }, - { - propertyName: "stroke", - expectedType: "paintServer" - }, - { - propertyName: "text-shadow", - expectedType: "shadow" - }, - { - propertyName: "transform", - expectedType: "custom" - }, - { - propertyName: "visibility", - expectedType: "discrete" - }, - { - propertyName: "width", - expectedType: "coord" - } - ].forEach(({ propertyName, expectedType }) => { - is(utils.getAnimationTypeForLonghand(propertyName), expectedType, - `Animation type should be ${ expectedType }`); - }); - - SimpleTest.doesThrow( - () => utils.getAnimationTypeForLonghand("background"), - "NS_ERROR_ILLEGAL_VALUE", - "background property should throw"); - - SimpleTest.doesThrow( - () => utils.getAnimationTypeForLonghand("invalid"), - "NS_ERROR_ILLEGAL_VALUE", - "Invalid property should throw"); - - next(); -} - function test_getUnanimatedComputedStyle() { SpecialPowers.pushPrefEnv( { set: [["dom.animations-api.core.enabled", true]] }, () => { window.open("file_domwindowutils_animation.html"); } ); } var tests = [ test_sendMouseEventDefaults, test_sendMouseEventOptionals, - test_getAnimationType, test_getUnanimatedComputedStyle ]; function next() { if (!tests.length) { SimpleTest.finish(); return; }
--- a/dom/chrome-webidl/InspectorUtils.webidl +++ b/dom/chrome-webidl/InspectorUtils.webidl @@ -83,16 +83,18 @@ namespace InspectorUtils { boolean hasPseudoClassLock(Element element, DOMString pseudoClass); void clearPseudoClassLocks(Element element); [Throws] void parseStyleSheet(CSSStyleSheet sheet, DOMString input); void scrollElementIntoView(Element element); }; dictionary PropertyNamesOptions { boolean includeAliases = false; + boolean includeShorthands = true; + boolean includeExperimentals = false; }; dictionary InspectorRGBATuple { /* * NOTE: This tuple is in the normal 0-255-sized RGB space but can be * fractional and may extend outside the 0-255 range. * * a is in the range 0 - 1.
--- a/dom/html/nsTextEditorState.cpp +++ b/dom/html/nsTextEditorState.cpp @@ -61,21 +61,21 @@ public: // another SetValue is already happening for this editor. If it is, // we must wait until we unwind to re-enable oninput events. , mOuterTransaction(aTextEditor->IsSuppressingDispatchingInputEvent()) { MOZ_ASSERT(aTextEditor); } ~ValueSetter() { - mTextEditor->SetSuppressDispatchingInputEvent(mOuterTransaction); + mTextEditor->SuppressDispatchingInputEvent(mOuterTransaction); } void Init() { - mTextEditor->SetSuppressDispatchingInputEvent(true); + mTextEditor->SuppressDispatchingInputEvent(true); } private: RefPtr<TextEditor> mTextEditor; bool mOuterTransaction; }; class RestoreSelectionState : public Runnable {
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -1430,23 +1430,16 @@ interface nsIDOMWindowUtils : nsISupport * property. */ double computeAnimationDistance(in nsIDOMElement element, in AString property, in AString value1, in AString value2); /** - * Returns the animation type of the specified property (e.g. 'coord'). - * - * @param aProperty A longhand CSS property (e.g. 'background-color'). - */ - AString getAnimationTypeForLonghand(in AString aProperty); - - /** * Returns the computed style for the specified property of given pseudo type * on the given element after removing styles from declarative animations. * @param aElement - A target element * @param aPseudoElement - A pseudo type (e.g. '::before' or null) * @param aProperty - A longhand CSS property (e.g. 'background-color') * @param aFlushType - FLUSH_NONE if any pending styles should not happen, * FLUSH_STYLE to flush pending styles. */
--- a/dom/interfaces/xul/nsIDOMXULButtonElement.idl +++ b/dom/interfaces/xul/nsIDOMXULButtonElement.idl @@ -1,28 +1,23 @@ /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsIDOMXULLabeledControlEl.idl" -[scriptable, uuid(d56f1f8f-fc4e-4650-9a85-25108bbd1980)] +[scriptable, uuid(6ed53cfb-9e59-424c-af8d-e74582381951)] interface nsIDOMXULButtonElement : nsIDOMXULLabeledControlElement { - const short CHECKSTATE_UNCHECKED = 0; - const short CHECKSTATE_CHECKED = 1; - const short CHECKSTATE_MIXED = 2; - attribute DOMString type; attribute DOMString dlgType; // For buttons of type="menu" only. attribute boolean open; // For buttons of type="checkbox" only. attribute boolean checked; - attribute long checkState; attribute boolean autoCheck; // For buttons of type="radio" only. attribute DOMString group; };
--- a/dom/interfaces/xul/nsIDOMXULCheckboxElement.idl +++ b/dom/interfaces/xul/nsIDOMXULCheckboxElement.idl @@ -1,18 +1,13 @@ /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsIDOMElement.idl" #include "nsIDOMXULLabeledControlEl.idl" -[scriptable, uuid(745518ad-3163-41f0-b358-c81fb5a587bc)] +[scriptable, uuid(674965d9-aff4-411d-a382-7cb32c0f25a1)] interface nsIDOMXULCheckboxElement : nsIDOMXULLabeledControlElement { - const short CHECKSTATE_UNCHECKED = 0; - const short CHECKSTATE_CHECKED = 1; - const short CHECKSTATE_MIXED = 2; - attribute boolean checked; - attribute long checkState; attribute boolean autoCheck; };
new file mode 100644 --- /dev/null +++ b/dom/media/AsyncLogger.h @@ -0,0 +1,269 @@ +/* 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/. */ + +/* Implementation of an asynchronous lock-free logging system. */ + +#ifndef mozilla_dom_AsyncLogger_h +#define mozilla_dom_AsyncLogger_h + +#include <atomic> +#include <thread> +#include "mozilla/Logging.h" +#include "mozilla/Attributes.h" +#include "mozilla/MathAlgorithms.h" +#include "mozilla/Sprintf.h" + +namespace mozilla { + +namespace detail { + + // This class implements a lock-free multiple producer single consumer queue of + // fixed size log messages, with the following characteristics: + // - Unbounded (uses a intrinsic linked list) + // - Allocates on Push. Push can be called on any thread. + // - Deallocates on Pop. Pop MUST always be called on the same thread for the + // life-time of the queue. + // + // In our scenario, the producer threads are real-time, they can't block. The + // consummer thread runs every now and then and empties the queue to a log + // file, on disk. + // + // Having fixed size messages and jemalloc is probably not the fastest, but + // allows having a simpler design, we count on the fact that jemalloc will get + // the memory from a thread-local source most of the time. +template<size_t MESSAGE_LENGTH> +class MPSCQueue +{ +public: + struct Message { + Message() + { + mNext.store(nullptr, std::memory_order_relaxed); + } + Message(const Message& aMessage) = delete; + void operator=(const Message& aMessage) = delete; + + char data[MESSAGE_LENGTH]; + std::atomic<Message*> mNext; + }; + // Creates a new MPSCQueue. Initially, the queue has a single sentinel node, + // pointed to by both mHead and mTail. + MPSCQueue() + // At construction, the initial message points to nullptr (it has no + // successor). It is a sentinel node, that does not contain meaningful + // data. + : mHead(new Message()) + , mTail(mHead.load(std::memory_order_relaxed)) + { } + + ~MPSCQueue() + { + Message dummy; + while (this->Pop(dummy.data)) {} + Message* front = mHead.load(std::memory_order_relaxed); + delete front; + } + + void + Push(MPSCQueue<MESSAGE_LENGTH>::Message* aMessage) + { + // The next two non-commented line are called A and B in this paragraph. + // Producer threads i, i-1, etc. are numbered in the order they reached + // A in time, thread i being the thread that has reached A first. + // Atomically, on line A the new `mHead` is set to be the node that was + // just allocated, with strong memory order. From now one, any thread + // that reaches A will see that the node just allocated is + // effectively the head of the list, and will make itself the new head + // of the list. + // In a bad case (when thread i executes A and then + // is not scheduled for a long time), it is possible that thread i-1 and + // subsequent threads create a seemingly disconnected set of nodes, but + // they all have the correct value for the next node to set as their + // mNext member on their respective stacks (in `prev`), and this is + // always correct. When the scheduler resumes, and line B is executed, + // the correct linkage is resumed. + // Before line B, since mNext for the node the was the last element of + // the queue still has an mNext of nullptr, Pop will not see the node + // added. + // For line A, it's critical to have strong ordering both ways (since + // it's going to possibly be read and write repeatidly by multiple + // threads) + // Line B can have weaker guarantees, it's only going to be written by a + // single thread, and we just need to ensure it's read properly by a + // single other one. + Message* prev = mHead.exchange(aMessage, std::memory_order_acq_rel); + prev->mNext.store(aMessage, std::memory_order_release); + } + + // Allocates a new node, copy aInput to the new memory location, and pushes + // it to the end of the list. + void + Push(const char aInput[MESSAGE_LENGTH]) + { + // Create a new message, and copy the messages passed on argument to the + // new memory location. We are not touching the queue right now. The + // successor for this new node is set to be nullptr. + Message* msg = new Message(); + strncpy(msg->data, aInput, MESSAGE_LENGTH); + + Push(msg); + } + + // Copy the content of the first message of the queue to aOutput, and + // frees the message. Returns true if there was a message, in which case + // `aOutput` contains a valid value. If the queue was empty, returns false, + // in which case `aOutput` is left untouched. + bool + Pop(char aOutput[MESSAGE_LENGTH]) + { + // Similarly, in this paragraph, the two following lines are called A + // and B, and threads are called thread i, i-1, etc. in order of + // execution of line A. + // On line A, the first element of the queue is acquired. It is simply a + // sentinel node. + // On line B, we acquire the node that has the data we want. If B is + // null, then only the sentinel node was present in the queue, we can + // safely return false. + // mTail can be loaded with relaxed ordering, since it's not written nor + // read by any other thread (this queue is single consumer). + // mNext can be written to by one of the producer, so it's necessary to + // ensure those writes are seen, hence the stricter ordering. + Message* tail = mTail.load(std::memory_order_relaxed); + Message* next = tail->mNext.load(std::memory_order_acquire); + + if (next == nullptr) { + return false; + } + + strncpy(aOutput, next->data, MESSAGE_LENGTH); + + // Simply shift the queue one node further, so that the sentinel node is + // now pointing to the correct most ancient node. It contains stale data, + // but this data will never be read again. + // It's only necessary to ensure the previous load on this thread is not + // reordered past this line, so release ordering is sufficient here. + mTail.store(next, std::memory_order_release); + + // This thread is now the only thing that points to `tail`, it can be + // safely deleted. + delete tail; + + return true; + } + +private: + // An atomic pointer to the most recent message in the queue. + std::atomic<Message*> mHead; + // An atomic pointer to a sentinel node, that points to the oldest message + // in the queue. + std::atomic<Message*> mTail; + + MPSCQueue(const MPSCQueue&) = delete; + void operator=(const MPSCQueue&) = delete; +public: + // The goal here is to make it easy on the allocator. We pack a pointer in the + // message struct, and we still want to do power of two allocations to + // minimize allocator slop. The allocation size are going to be constant, so + // the allocation is probably going to hit the thread local cache in jemalloc, + // making it cheap and, more importantly, lock-free enough. + static const size_t MESSAGE_PADDING = sizeof(Message::mNext); +private: + static_assert(IsPowerOfTwo(MESSAGE_LENGTH + MESSAGE_PADDING), + "MPSCQueue internal allocations must have a size that is a" + "power of two "); +}; +} // end namespace detail + +// This class implements a lock-free asynchronous logger, that outputs to +// MOZ_LOG. +// Any thread can use this logger without external synchronization and without +// being blocked. This log is suitable for use in real-time audio threads. +// Log formatting is best done externally, this class implements the output +// mechanism only. +// This class uses a thread internally, and must be started and stopped +// manually. +// If logging is disabled, all the calls are no-op. +class AsyncLogger +{ +public: + static const uint32_t MAX_MESSAGE_LENGTH = 512 - detail::MPSCQueue<sizeof(void*)>::MESSAGE_PADDING; + + // aLogModuleName is the name of the MOZ_LOG module. + explicit AsyncLogger(const char* aLogModuleName) + : mThread(nullptr) + , mLogModule(aLogModuleName) + , mRunning(false) + { } + + ~AsyncLogger() + { + if (Enabled()) { + Stop(); + } + } + + void Start() + { + MOZ_ASSERT(!mRunning, "Double calls to AsyncLogger::Start"); + if (Enabled()) { + mRunning = true; + Run(); + } + } + + void Stop() + { + if (Enabled()) { + if (mRunning) { + mRunning = false; + mThread->join(); + } + } else { + MOZ_ASSERT(!mRunning && !mThread); + } + } + + void Log(const char* format, ...) MOZ_FORMAT_PRINTF(2,3) + { + if (Enabled()) { + auto* msg = new detail::MPSCQueue<MAX_MESSAGE_LENGTH>::Message(); + va_list args; + va_start(args, format); + VsprintfLiteral(msg->data, format, args); + va_end(args); + mMessageQueue.Push(msg); + } + } + + bool Enabled() + { + return MOZ_LOG_TEST(mLogModule, mozilla::LogLevel::Verbose); + } + +private: + void Run() + { + MOZ_ASSERT(Enabled()); + mThread.reset(new std::thread([this]() { + while (mRunning) { + char message[MAX_MESSAGE_LENGTH]; + while (mMessageQueue.Pop(message) && mRunning) { + MOZ_LOG(mLogModule, mozilla::LogLevel::Verbose, ("%s", message)); + } + Sleep(); + } + })); + } + + void Sleep() { std::this_thread::sleep_for(std::chrono::milliseconds(10)); } + + std::unique_ptr<std::thread> mThread; + mozilla::LazyLogModule mLogModule; + detail::MPSCQueue<MAX_MESSAGE_LENGTH> mMessageQueue; + std::atomic<bool> mRunning; +}; + +} // end namespace mozilla + +#endif // mozilla_dom_AsyncLogger_h
--- a/dom/media/GraphDriver.cpp +++ b/dom/media/GraphDriver.cpp @@ -1,19 +1,21 @@ /* -*- Mode: C++; tab-width: 2; 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 <MediaStreamGraphImpl.h> #include "mozilla/dom/AudioContext.h" #include "mozilla/SharedThreadPool.h" #include "mozilla/ClearOnShutdown.h" #include "mozilla/Unused.h" #include "CubebUtils.h" +#include "Tracing.h" #ifdef MOZ_WEBRTC #include "webrtc/MediaEngineWebRTC.h" #endif #ifdef XP_MACOSX #include <sys/sysctl.h> #endif @@ -876,16 +878,19 @@ AudioCallbackDriver::AutoInCallback::Aut AudioCallbackDriver::AutoInCallback::~AutoInCallback() { mDriver->mInCallback = false; } long AudioCallbackDriver::DataCallback(const AudioDataValue* aInputBuffer, AudioDataValue* aOutputBuffer, long aFrames) { + TRACE_AUDIO_CALLBACK_BUDGET(aFrames, mSampleRate); + TRACE_AUDIO_CALLBACK(); + // Don't add the callback until we're inited and ready if (!mAddedMixer) { mGraphImpl->mMixer.AddCallback(this); mAddedMixer = true; } #ifdef DEBUG // DebugOnly<> doesn't work here... it forces an initialization that will cause
--- a/dom/media/MediaStreamGraph.cpp +++ b/dom/media/MediaStreamGraph.cpp @@ -27,25 +27,28 @@ #include "mozilla/media/MediaUtils.h" #include <algorithm> #include "GeckoProfiler.h" #include "VideoFrameContainer.h" #include "mozilla/AbstractThread.h" #include "mozilla/Unused.h" #include "mtransport/runnable_utils.h" #include "VideoUtils.h" +#include "Tracing.h" #include "webaudio/blink/DenormalDisabler.h" #include "webaudio/blink/HRTFDatabaseLoader.h" using namespace mozilla::layers; using namespace mozilla::dom; using namespace mozilla::gfx; using namespace mozilla::media; +mozilla::AsyncLogger gMSGTraceLogger("MSGTracing"); + namespace mozilla { LazyLogModule gMediaStreamGraphLog("MediaStreamGraph"); #ifdef LOG #undef LOG #endif // LOG #define LOG(type, msg) MOZ_LOG(gMediaStreamGraphLog, type, msg) @@ -63,16 +66,20 @@ enum SourceMediaStream::TrackCommands : static nsDataHashtable<nsUint32HashKey, MediaStreamGraphImpl*> gGraphs; MediaStreamGraphImpl::~MediaStreamGraphImpl() { MOZ_ASSERT(mStreams.IsEmpty() && mSuspendedStreams.IsEmpty(), "All streams should have been destroyed by messages from the main thread"); LOG(LogLevel::Debug, ("MediaStreamGraph %p destroyed", this)); LOG(LogLevel::Debug, ("MediaStreamGraphImpl::~MediaStreamGraphImpl")); + +#ifdef TRACING + gMSGTraceLogger.Stop(); +#endif } void MediaStreamGraphImpl::AddStreamGraphThread(MediaStream* aStream) { MOZ_ASSERT(OnGraphThreadOrNotRunning()); aStream->mTracksStartTime = mProcessedTime; @@ -1117,16 +1124,17 @@ MediaStreamGraphImpl::RunMessageAfterPro // Only one block is used for messages from the graph thread. MOZ_ASSERT(mFrontMessageQueue.Length() == 1); mFrontMessageQueue[0].mMessages.AppendElement(Move(aMessage)); } void MediaStreamGraphImpl::RunMessagesInQueue() { + TRACE_AUDIO_CALLBACK(); MOZ_ASSERT(OnGraphThread()); // Calculate independent action times for each batch of messages (each // batch corresponding to an event loop task). This isolates the performance // of different scripts to some extent. for (uint32_t i = 0; i < mFrontMessageQueue.Length(); ++i) { nsTArray<UniquePtr<ControlMessage>>& messages = mFrontMessageQueue[i].mMessages; for (uint32_t j = 0; j < messages.Length(); ++j) { @@ -1134,16 +1142,17 @@ MediaStreamGraphImpl::RunMessagesInQueue } } mFrontMessageQueue.Clear(); } void MediaStreamGraphImpl::UpdateGraph(GraphTime aEndBlockingDecisions) { + TRACE_AUDIO_CALLBACK(); MOZ_ASSERT(OnGraphThread()); MOZ_ASSERT(aEndBlockingDecisions >= mProcessedTime); // The next state computed time can be the same as the previous: it // means the driver would have been blocking indefinitly, but the graph has // been woken up right after having been to sleep. MOZ_ASSERT(aEndBlockingDecisions >= mStateComputedTime); UpdateStreamOrder(); @@ -1229,16 +1238,17 @@ MediaStreamGraphImpl::UpdateGraph(GraphT aEndBlockingDecisions == mStateComputedTime) { EnsureNextIteration(); } } void MediaStreamGraphImpl::Process() { + TRACE_AUDIO_CALLBACK(); MOZ_ASSERT(OnGraphThread()); // Play stream contents. bool allBlockedForever = true; // True when we've done ProcessInput for all processed streams. bool doneAllProducing = false; // This is the number of frame that are written to the AudioStreams, for // this cycle. StreamTime ticksPlayed = 0; @@ -1333,16 +1343,17 @@ MediaStreamGraphImpl::UpdateMainThreadSt SwapMessageQueues(); return true; } bool MediaStreamGraphImpl::OneIteration(GraphTime aStateEnd) { + TRACE_AUDIO_CALLBACK(); // Changes to LIFECYCLE_RUNNING occur before starting or reviving the graph // thread, and so the monitor need not be held to check mLifecycleState. // LIFECYCLE_THREAD_NOT_STARTED is possible when shutting down offline // graphs that have not started. MOZ_DIAGNOSTIC_ASSERT(mLifecycleState <= LIFECYCLE_RUNNING); MOZ_ASSERT(OnGraphThread()); WebCore::DenormalDisabler disabler; @@ -1539,16 +1550,17 @@ public: bool aSourceIsMSG) : Runnable("MediaStreamGraphStableStateRunnable") , mGraph(aGraph) , mSourceIsMSG(aSourceIsMSG) { } NS_IMETHOD Run() override { + TRACE(); if (mGraph) { mGraph->RunInStableState(mSourceIsMSG); } return NS_OK; } private: RefPtr<MediaStreamGraphImpl> mGraph; bool mSourceIsMSG; @@ -2760,16 +2772,17 @@ SourceMediaStream::SetPullEnabled(bool a GraphImpl()->AppendMessage(MakeUnique<Message>(this, aEnabled)); } bool SourceMediaStream::PullNewData( StreamTime aDesiredUpToTime, nsTArray<RefPtr<SourceMediaStream::NotifyPullPromise>>& aPromises) { + TRACE_AUDIO_CALLBACK(); MutexAutoLock lock(mMutex); if (!mPullEnabled || mFinished) { return false; } // Compute how much stream time we'll need assuming we don't block // the stream at all. StreamTime t = GraphTimeToStreamTime(aDesiredUpToTime); StreamTime current = mTracks.GetEnd(); @@ -3609,16 +3622,22 @@ MediaStreamGraphImpl::MediaStreamGraphIm { if (mRealtime) { if (aDriverRequested == AUDIO_THREAD_DRIVER) { AudioCallbackDriver* driver = new AudioCallbackDriver(this); mDriver = driver; } else { mDriver = new SystemClockDriver(this); } + +#ifdef TRACING + // This is a noop if the logger has not been enabled. + gMSGTraceLogger.Start(); + gMSGTraceLogger.Log("["); +#endif } else { mDriver = new OfflineClockDriver(this, MEDIA_GRAPH_TARGET_PERIOD_MS); } mLastMainThreadUpdate = TimeStamp::Now(); RegisterWeakAsyncMemoryReporter(this); }
--- a/dom/media/MediaStreamGraph.h +++ b/dom/media/MediaStreamGraph.h @@ -20,16 +20,23 @@ #include "nsIRunnable.h" #include "nsTArray.h" #include <speex/speex_resampler.h> class nsIRunnable; class nsIGlobalObject; class nsPIDOMWindowInner; +namespace mozilla { + class AsyncLogger; +}; + +extern mozilla::AsyncLogger gMSGTraceLogger; + + template <> class nsAutoRefTraits<SpeexResamplerState> : public nsPointerRefTraits<SpeexResamplerState> { public: static void Release(SpeexResamplerState* aState) { speex_resampler_destroy(aState); } }; namespace mozilla {
--- a/dom/media/MediaStreamGraphImpl.h +++ b/dom/media/MediaStreamGraphImpl.h @@ -18,16 +18,17 @@ #include "mozilla/UniquePtr.h" #include "mozilla/WeakPtr.h" #include "nsDataHashtable.h" #include "nsIMemoryReporter.h" #include "nsINamed.h" #include "nsIRunnable.h" #include "nsIThread.h" #include "nsITimer.h" +#include "AsyncLogger.h" namespace mozilla { namespace media { class ShutdownTicket; } template <typename T>
--- a/dom/media/PeerConnection.js +++ b/dom/media/PeerConnection.js @@ -2028,18 +2028,23 @@ class RTCRtpSender { } setTrack(track) { this._pc._replaceTrackNoRenegotiation(this._transceiverImpl, track); this.track = track; } getStats() { - return this._pc._async( - async () => this._pc._getStats(this.track)); + if (this.track) { + return this._pc._async( + async () => this._pc._getStats(this.track)); + } + return this._pc._win.Promise.resolve().then( + () => this._pc._win.RTCStatsReport._create(this._pc._win, new Map()) + ); } checkWasCreatedByPc(pc) { if (pc != this._pc.__DOM_IMPL__) { throw new this._pc._win.DOMException( "This sender was not created by this PeerConnection", "InvalidAccessError"); }
new file mode 100644 --- /dev/null +++ b/dom/media/Tracing.cpp @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 2; 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 "Tracing.h" + +#include <inttypes.h> +#include <cstdio> + +#include "AsyncLogger.h" +#include "mozilla/TimeStamp.h" + +using namespace mozilla; + +uint64_t +AutoTracer::NowInUs() +{ + static TimeStamp base = TimeStamp::Now(); + return (TimeStamp::Now() - base).ToMicroseconds(); +} + +void +AutoTracer::PrintEvent(const char* aName, + const char* aCategory, + const char* aComment, + TracingPhase aPhase, + uint64_t aTime, + uint64_t aPID, + uint64_t aThread) +{ + mLogger.Log("{\"name\": \"%s\", \"cat\": \"%s\", \"ph\": \"%c\"," + "\"ts\": %" PRIu64 ", \"pid\": %" PRIu64 ", \"tid\":" + " %" PRIu64 ", \"args\": { \"comment\": \"%s\"}},", + aName, aCategory, TRACING_PHASE_STRINGS[static_cast<int>(aPhase)], + aTime, aPID, aThread, aComment); +} + +void +AutoTracer::PrintBudget(const char* aName, + const char* aCategory, + const char* aComment, + uint64_t aDuration, + uint64_t aPID, + uint64_t aThread, + uint64_t aFrames) +{ + mLogger.Log("{\"name\": \"%s\", \"cat\": \"%s\", \"ph\": \"X\"," + "\"ts\": %" PRIu64 ", \"dur\": %" PRIu64 ", \"pid\": %" PRIu64 "," + "\"tid\": %" PRIu64 ", \"args\": { \"comment\": %" PRIu64 "}},", + aName, aCategory, NowInUs(), aDuration, aPID, aThread, aFrames); +} + +AutoTracer::AutoTracer(AsyncLogger& aLogger, + const char* aLocation, + uint64_t aPID, + uint64_t aTID, + EventType aEventType, + uint64_t aFrames, + uint64_t aSampleRate) + : mLogger(aLogger) + , mLocation(aLocation) + , mEventType(aEventType) + , mPID(aPID) + , mTID(aTID) +{ + MOZ_ASSERT(aEventType == EventType::BUDGET); + + if (aLogger.Enabled()) { + float durationUS = (static_cast<float>(aFrames) / aSampleRate) * 1e6; + PrintBudget(aLocation, "perf", mComment, durationUS, mPID, mTID, aFrames); + } +} + +AutoTracer::AutoTracer(AsyncLogger& aLogger, + const char* aLocation, + uint64_t aPID, + uint64_t aTID, + EventType aEventType, + const char* aComment) + : mLogger(aLogger) + , mLocation(aLocation) + , mComment(aComment) + , mEventType(aEventType) + , mPID(aPID) + , mTID(aTID) +{ + MOZ_ASSERT(aEventType == EventType::DURATION); + if (aLogger.Enabled()) { + PrintEvent(aLocation, "perf", mComment, TracingPhase::BEGIN, NowInUs(), aPID, aTID); + } +} + +AutoTracer::~AutoTracer() +{ + if (mEventType == EventType::DURATION) { + if (mLogger.Enabled()) { + PrintEvent(mLocation, "perf", mComment, TracingPhase::END, NowInUs(), mPID, mTID); + } + } +}
new file mode 100644 --- /dev/null +++ b/dom/media/Tracing.h @@ -0,0 +1,140 @@ +/* -*- Mode: C++; tab-width: 2; 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 TRACING_H +#define TRACING_H + +#include <cstdint> + +#include "AsyncLogger.h" + +#include <mozilla/Attributes.h> + +#if defined(_WIN32) +#include <process.h> +#define getpid() _getpid() +#else +#include <unistd.h> +#endif + +#if defined(_MSC_VER) +// MSVC +#define FUNCTION_SIGNATURE __FUNCSIG__ +#elif defined(__GNUC__) +// gcc, clang +#define FUNCTION_SIGNATURE __PRETTY_FUNCTION__ +#endif + +#ifdef TRACING + /* TRACE is for use in the real-time audio rendering thread. + * It would be better to always pass in the thread id. However, the thread an + * audio callback runs on can change when the underlying audio device change, + * and also it seems to be called from a thread pool in a round-robin fashion + * when audio remoting is activated, making the traces unreadable. + * The thread on which the AudioCallbackDriver::DataCallback is to always + * be thread 0, and the budget is set to always be thread 1. This allows + * displaying those elements in two separate lanes. + * The other thread have "normal" tid. Hashing allows being able to get a + * string representation that is unique and guaranteed to be portable. */ + #define TRACE_AUDIO_CALLBACK() \ + AutoTracer trace(gMSGTraceLogger, FUNCTION_SIGNATURE, getpid(), 0); + #define TRACE_AUDIO_CALLBACK_BUDGET(aFrames, aSampleRate) \ + AutoTracer budget(gMSGTraceLogger, "Real-time budget", getpid(), 1, \ + AutoTracer::EventType::BUDGET, aFrames, aSampleRate); + #define TRACE() \ + AutoTracer trace(gMSGTraceLogger, FUNCTION_SIGNATURE, getpid(), \ + std::hash<std::thread::id>{}(std::this_thread::get_id())); + #define TRACE_COMMENT(aComment) \ + AutoTracer trace(gMSGTraceLogger, FUNCTION_SIGNATURE, getpid(), \ + std::hash<std::thread::id>{}(std::this_thread::get_id()), \ + AutoTracer::EventType::DURATION, \ + aComment); +#else + #define TRACE_AUDIO_CALLBACK() + #define TRACE_AUDIO_CALLBACK_BUDGET(aFrames, aSampleRate) + #define TRACE() + #define TRACE_COMMENT(aComment) +#endif + +class MOZ_RAII AutoTracer +{ +public: + enum class EventType + { + DURATION, + BUDGET + }; + + AutoTracer(mozilla::AsyncLogger& aLogger, + const char* aLocation, + uint64_t aPID, + uint64_t aTID, + EventType aEventType = EventType::DURATION, + const char* aComment = nullptr); + AutoTracer(mozilla::AsyncLogger& aLogger, + const char* aLocation, + uint64_t aPID, + uint64_t aTID, + EventType aEventType, + uint64_t aSampleRate, + uint64_t aFrames); + ~AutoTracer(); +private: + uint64_t NowInUs(); + + enum class TracingPhase + { + BEGIN, + END, + COMPLETE + }; + + const char TRACING_PHASE_STRINGS[3] = { + 'B', + 'E', + 'X' + }; + + void PrintEvent(const char* aName, + const char* aCategory, + const char* aComment, + TracingPhase aPhase, + uint64_t aTime, + uint64_t aPID, + uint64_t aThread); + + void PrintBudget(const char* aName, + const char* aCategory, + const char* aComment, + uint64_t aDuration, + uint64_t aPID, + uint64_t aThread, + uint64_t aFrames); + + // The logger to use. It musdt have a lifetime longer than the block an + // instance of this class traces. + mozilla::AsyncLogger& mLogger; + // The location for this trace point, arbitrary string literal, often the + // name of the calling function, with a static lifetime. + const char* mLocation; + // A comment for this trace point, abitrary string literal with a static + // lifetime. + const char* mComment; + // The event type, for now either a budget or a duration. + const EventType mEventType; + // The process ID of the calling process. Traces are grouped by PID in the + // vizualizer. + const uint64_t mPID; + // The thread ID of the calling thread, will be displayed in a separate + // section in the trace visualizer. + const uint64_t mTID; +}; + +#if defined(_WIN32) +#undef getpid +#endif + +#endif /* TRACING_H */
--- a/dom/media/TrackUnionStream.cpp +++ b/dom/media/TrackUnionStream.cpp @@ -63,16 +63,17 @@ TrackUnionStream::TrackUnionStream() EndTrack(i); mTrackMap.RemoveElementAt(i); } } ProcessedMediaStream::RemoveInput(aPort); } void TrackUnionStream::ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) { + TRACE(); if (IsFinishedOnGraphThread()) { return; } AutoTArray<bool,8> mappedTracksFinished; AutoTArray<bool,8> mappedTracksWithMatchingInputTracks; for (uint32_t i = 0; i < mTrackMap.Length(); ++i) { mappedTracksFinished.AppendElement(true); mappedTracksWithMatchingInputTracks.AppendElement(false);
--- a/dom/media/moz.build +++ b/dom/media/moz.build @@ -84,16 +84,17 @@ XPIDL_SOURCES += [ 'nsIMediaManager.idl', ] XPIDL_MODULE = 'dom_media' EXPORTS += [ 'ADTSDecoder.h', 'ADTSDemuxer.h', + 'AsyncLogger.h', 'AudioBufferUtils.h', 'AudioChannelFormat.h', 'AudioCompactor.h', 'AudioConfig.h', 'AudioConverter.h', 'AudioMixer.h', 'AudioPacketizer.h', 'AudioSampleFormat.h', @@ -148,16 +149,17 @@ EXPORTS += [ 'QueueObject.h', 'SeekJob.h', 'SeekTarget.h', 'SelfRef.h', 'SharedBuffer.h', 'StreamTracks.h', 'ThreadPoolCOMListener.h', 'TimeUnits.h', + 'Tracing.h', 'TrackID.h', 'TrackUnionStream.h', 'VideoFrameContainer.h', 'VideoLimits.h', 'VideoSegment.h', 'VideoUtils.h', 'VorbisUtils.h', 'XiphExtradata.h', @@ -258,16 +260,17 @@ UNIFIED_SOURCES += [ 'ReaderProxy.cpp', 'SeekJob.cpp', 'StreamTracks.cpp', 'TextTrack.cpp', 'TextTrackCue.cpp', 'TextTrackCueList.cpp', 'TextTrackList.cpp', 'TextTrackRegion.cpp', + 'Tracing.cpp', 'TrackUnionStream.cpp', 'VideoFrameContainer.cpp', 'VideoPlaybackQuality.cpp', 'VideoSegment.cpp', 'VideoStreamTrack.cpp', 'VideoTrack.cpp', 'VideoTrackList.cpp', 'VideoUtils.cpp', @@ -321,16 +324,17 @@ LOCAL_INCLUDES += [ if CONFIG['MOZ_WEBRTC']: LOCAL_INCLUDES += [ '/media/webrtc/signaling/src/common', '/media/webrtc/trunk', ] DEFINES['MOZILLA_INTERNAL_API'] = True +DEFINES['TRACING'] = True if CONFIG['MOZ_ANDROID_HLS_SUPPORT']: DEFINES['MOZ_ANDROID_HLS_SUPPORT'] = True include('/ipc/chromium/chromium-config.mozbuild') # Suppress some GCC warnings being treated as errors: # - about attributes on forward declarations for types that are already
--- a/dom/media/tests/mochitest/mochitest.ini +++ b/dom/media/tests/mochitest/mochitest.ini @@ -332,15 +332,17 @@ skip-if = (android_version == '18') # an skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator) [test_selftest.html] # Bug 1227781: Crash with bogus TURN server. [test_peerConnection_bug1227781.html] [test_peerConnection_stats.html] skip-if = toolkit == 'android' # android(Bug 1189784, timeouts on 4.3 emulator, Bug 1373858) [test_peerConnection_sender_and_receiver_stats.html] skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator) +[test_peerConnection_trackless_sender_stats.html] +skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator) [test_peerConnection_verifyDescriptions.html] skip-if = (android_version == '18') [test_fingerprinting_resistance.html] [test_getUserMedia_nonDefaultRate.html] [test_peerConnection_nonDefaultRate.html] skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulator) [test_forceSampleRate.html]
--- a/dom/media/tests/mochitest/test_peerConnection_sender_and_receiver_stats.html +++ b/dom/media/tests/mochitest/test_peerConnection_sender_and_receiver_stats.html @@ -7,19 +7,19 @@ <pre id="test"> <script type="application/javascript"> createHTML({ bug: "1355220", title: "RTCRtpSender.getStats() and RTCRtpReceiver.getStats()", visible: true }); - var test; - var checkStats = (sndReport, rcvReport, mediaType) => { + ok(sndReport instanceof window.RTCStatsReport, "sender stats are a RTCStatsReport"); + ok(rcvReport instanceof window.RTCStatsReport, "receiver stats are a RTCStatsReport"); // Returns SSRCs and checks that the tracks are of the correct mediaType let getSsrcs = (report, kind) => { return [...report.values()] .filter(stat => stat.type.endsWith("bound-rtp")).map(stat =>{ is(stat.mediaType, kind, "mediaType of " + stat.id + " is expected type " + kind); return stat.ssrc; }).sort().join("|");
new file mode 100644 --- /dev/null +++ b/dom/media/tests/mochitest/test_peerConnection_trackless_sender_stats.html @@ -0,0 +1,56 @@ +<!DOCTYPE HTML> +<html> +<head> + <script type="application/javascript" src="pc.js"></script> +</head> +<body> +<pre id="test"> +<script type="application/javascript"> + createHTML({ + bug: "1452673", + title: "Trackless RTCRtpSender.getStats()", + visible: true + }); + + // Calling getstats() on a trackless RTCRtpSender should yield an empty + // stats report. When track stats are added in the future, the stats + // for the removed tracks should continue to appear. + + var test; + runNetworkTest(function (options) { + test = new PeerConnectionTest(options); + test.chain.removeAfter("PC_REMOTE_WAIT_FOR_MEDIA_FLOW"); + test.chain.append( + async function PC_LOCAL_AND_REMOTE_TRACKLESS_SENDER_STATS(test) { + return Promise.all([test.pcLocal.waitForSyncedRtcp(), + test.pcRemote.waitForSyncedRtcp()]) + .then(async () => { + let senders = test.pcLocal.getSenders(); + let receivers = test.pcRemote.getReceivers(); + is(senders.length, 2, "Have exactly two senders."); + is(receivers.length, 2, "Have exactly two receivers."); + for(let kind of ["audio", "video"]) { + is(senders.filter(s => s.track.kind == kind).length, 1, + "Exactly 1 sender of kind " + kind); + is(receivers.filter(r => r.track.kind == kind).length, 1, + "Exactly 1 receiver of kind " + kind); + } + // Remove tracks from senders + senders.forEach(async sender => { + await sender.replaceTrack(null); + is(sender.track, null, "Sender track removed"); + let stats = await sender.getStats(); + ok(stats instanceof window.RTCStatsReport, "Stats is instance of RTCStatsReport"); + // Number of stats in the report. This should be 0. + is(stats.size, 0, "Trackless sender stats report is empty"); + }); + }) + }); + test.setMediaConstraints([{audio: true}, {video: true}], []); + test.run(); + }); + +</script> +</pre> +</body> +</html> \ No newline at end of file
--- a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp +++ b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp @@ -12,16 +12,17 @@ #include "AudioConverter.h" #include "MediaManager.h" #include "MediaStreamGraphImpl.h" #include "MediaTrackConstraints.h" #include "mozilla/Assertions.h" #include "mozilla/ErrorNames.h" #include "mtransport/runnable_utils.h" #include "nsAutoPtr.h" +#include "Tracing.h" // scoped_ptr.h uses FF #ifdef FF #undef FF #endif #include "webrtc/modules/audio_device/opensl/single_rw_fifo.h" #include "webrtc/voice_engine/voice_engine_defines.h" #include "webrtc/modules/audio_processing/include/audio_processing.h" @@ -1178,16 +1179,17 @@ MediaEngineWebRTCMicrophoneSource::Inser // Note this can be called back after ::Shutdown() void MediaEngineWebRTCMicrophoneSource::NotifyInputData(MediaStreamGraph* aGraph, const AudioDataValue* aBuffer, size_t aFrames, TrackRate aRate, uint32_t aChannels) { + TRACE_AUDIO_CALLBACK(); // If some processing is necessary, packetize and insert in the WebRTC.org // code. Otherwise, directly insert the mic data in the MSG, bypassing all processing. if (PassThrough()) { InsertInGraph<AudioDataValue>(aBuffer, aFrames, aChannels); } else { PacketizeAndProcess(aGraph, aBuffer, aFrames, aRate, aChannels); } }
--- a/editor/libeditor/EditorBase.cpp +++ b/editor/libeditor/EditorBase.cpp @@ -5328,35 +5328,16 @@ EditorBase::OnFocus(EventTarget* aFocusE InitializeSelection(aFocusEventTarget); mSpellCheckerDictionaryUpdated = false; if (mInlineSpellChecker && CanEnableSpellCheck()) { mInlineSpellChecker->UpdateCurrentDictionary(); mSpellCheckerDictionaryUpdated = true; } } -NS_IMETHODIMP -EditorBase::GetSuppressDispatchingInputEvent(bool* aSuppressed) -{ - // NOTE: If you need to override this method, you need to make - // IsSuppressingDispatchingInputEvent() virtual. - if (NS_WARN_IF(aSuppressed)) { - return NS_ERROR_INVALID_ARG; - } - *aSuppressed = IsSuppressingDispatchingInputEvent(); - return NS_OK; -} - -NS_IMETHODIMP -EditorBase::SetSuppressDispatchingInputEvent(bool aSuppress) -{ - mDispatchInputEvent = !aSuppress; - return NS_OK; -} - int32_t EditorBase::GetIMESelectionStartOffsetIn(nsINode* aTextNode) { MOZ_ASSERT(aTextNode, "aTextNode must not be nullptr"); nsISelectionController* selectionController = GetSelectionController(); if (NS_WARN_IF(!selectionController)) { return -1;
--- a/editor/libeditor/EditorBase.h +++ b/editor/libeditor/EditorBase.h @@ -1440,16 +1440,25 @@ public: /** * IsInEditAction() return true while the instance is handling an edit action. * Otherwise, false. */ bool IsInEditAction() const { return mIsInEditAction; } /** + * SuppressDispatchingInputEvent() suppresses or unsuppresses dispatching + * "input" event. + */ + void SuppressDispatchingInputEvent(bool aSuppress) + { + mDispatchInputEvent = !aSuppress; + } + + /** * IsSuppressingDispatchingInputEvent() returns true if the editor stops * dispatching input event. Otherwise, false. */ bool IsSuppressingDispatchingInputEvent() const { return !mDispatchInputEvent; }
--- a/editor/nsIEditor.idl +++ b/editor/nsIEditor.idl @@ -513,19 +513,16 @@ interface nsIEditor : nsISupports void dumpContentTree(); /** Dumps a text representation of the content tree to standard out */ void debugDumpContent() ; /* Run unit tests. Noop in optimized builds */ void debugUnitTests(out long outNumTests, out long outNumTestsFailed); - /* Set true if you want to suppress dispatching input event. */ - attribute boolean suppressDispatchingInputEvent; - /** * forceCompositionEnd() force the composition end */ void forceCompositionEnd(); /** * whether this editor has active IME transaction */
--- a/gfx/layers/apz/public/APZSampler.h +++ b/gfx/layers/apz/public/APZSampler.h @@ -7,16 +7,17 @@ #ifndef mozilla_layers_APZSampler_h #define mozilla_layers_APZSampler_h #include <unordered_map> #include "base/platform_thread.h" // for PlatformThreadId #include "mozilla/layers/AsyncCompositionManager.h" // for AsyncTransform #include "mozilla/StaticMutex.h" +#include "mozilla/StaticPtr.h" #include "nsTArray.h" #include "Units.h" namespace mozilla { class TimeStamp; namespace wr { @@ -36,17 +37,18 @@ struct ScrollbarData; * This interface exposes APZ methods related to "sampling" (i.e. reading the * async transforms produced by APZ). These methods should all be called on * the sampler thread. */ class APZSampler { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(APZSampler) public: - explicit APZSampler(const RefPtr<APZCTreeManager>& aApz); + APZSampler(const RefPtr<APZCTreeManager>& aApz, + bool aIsUsingWebRender); void SetWebRenderWindowId(const wr::WindowId& aWindowId); /** * This function is invoked from rust on the render backend thread when it * is created. It effectively tells the APZSampler "the current thread is * the sampler thread for this window id" and allows APZSampler to remember * which thread it is. @@ -97,41 +99,38 @@ public: /** * Returns true if currently on the APZSampler's "sampler thread". */ bool IsSamplerThread() const; protected: virtual ~APZSampler(); - bool UsingWebRenderSamplerThread() const; static already_AddRefed<APZSampler> GetSampler(const wr::WrWindowId& aWindowId); private: RefPtr<APZCTreeManager> mApz; + bool mIsUsingWebRender; // Used to manage the mapping from a WR window id to APZSampler. These are only // used if WebRender is enabled. Both sWindowIdMap and mWindowId should only - // be used while holding the sWindowIdLock. + // be used while holding the sWindowIdLock. Note that we use a StaticAutoPtr + // wrapper on sWindowIdMap to avoid a static initializer for the unordered_map. + // This also avoids the initializer/memory allocation in cases where we're + // not using WebRender. static StaticMutex sWindowIdLock; - static std::unordered_map<uint64_t, APZSampler*> sWindowIdMap; + static StaticAutoPtr<std::unordered_map<uint64_t, APZSampler*>> sWindowIdMap; Maybe<wr::WrWindowId> mWindowId; + // Lock used to protected mSamplerThreadId + mutable Mutex mThreadIdLock; // If WebRender is enabled, this holds the thread id of the render backend // thread (which is the sampler thread) for the compositor associated with // this APZSampler instance. - // This is written to once during init and never cleared, and so reading it - // from multiple threads during normal operation (after initialization) - // without locking should be fine. Maybe<PlatformThreadId> mSamplerThreadId; -#ifdef DEBUG - // This flag is used to ensure that we don't ever try to do sampler-thread - // stuff before the updater thread has been properly initialized. - mutable bool mSamplerThreadQueried; -#endif Mutex mSampleTimeLock; // Can only be accessed or modified while holding mSampleTimeLock. TimeStamp mSampleTime; }; } // namespace layers } // namespace mozilla
--- a/gfx/layers/apz/public/APZUpdater.h +++ b/gfx/layers/apz/public/APZUpdater.h @@ -10,16 +10,17 @@ #include <deque> #include <unordered_map> #include "base/platform_thread.h" // for PlatformThreadId #include "LayersTypes.h" #include "mozilla/layers/APZTestData.h" #include "mozilla/layers/WebRenderScrollData.h" #include "mozilla/StaticMutex.h" +#include "mozilla/StaticPtr.h" #include "mozilla/webrender/WebRenderTypes.h" #include "nsThreadUtils.h" #include "Units.h" namespace mozilla { namespace wr { struct WrWindowId; @@ -38,17 +39,18 @@ class WebRenderScrollData; * response to IPC messages. The method implementations internally redispatch * themselves to the updater thread in the case where the compositor thread * is not the updater thread. */ class APZUpdater { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(APZUpdater) public: - explicit APZUpdater(const RefPtr<APZCTreeManager>& aApz); + APZUpdater(const RefPtr<APZCTreeManager>& aApz, + bool aIsUsingWebRender); bool HasTreeManager(const RefPtr<APZCTreeManager>& aApz); void SetWebRenderWindowId(const wr::WindowId& aWindowId); /** * This function is invoked from rust on the scene builder thread when it * is created. It effectively tells the APZUpdater "the current thread is * the updater thread for this window id" and allows APZUpdater to remember @@ -139,16 +141,17 @@ protected: bool UsingWebRenderUpdaterThread() const; static already_AddRefed<APZUpdater> GetUpdater(const wr::WrWindowId& aWindowId); void ProcessQueue(); private: RefPtr<APZCTreeManager> mApz; + bool mIsUsingWebRender; // Map from layers id to WebRenderScrollData. This can only be touched on // the updater thread. std::unordered_map<LayersId, WebRenderScrollData, LayersId::HashFn> mScrollData; // Stores epoch state for a particular layers id. This structure is only @@ -179,35 +182,32 @@ private: // Map from layers id to epoch state. // This data structure can only be touched on the updater thread. std::unordered_map<LayersId, EpochState, LayersId::HashFn> mEpochData; // Used to manage the mapping from a WR window id to APZUpdater. These are only // used if WebRender is enabled. Both sWindowIdMap and mWindowId should only - // be used while holding the sWindowIdLock. + // be used while holding the sWindowIdLock. Note that we use a StaticAutoPtr + // wrapper on sWindowIdMap to avoid a static initializer for the unordered_map. + // This also avoids the initializer/memory allocation in cases where we're + // not using WebRender. static StaticMutex sWindowIdLock; - static std::unordered_map<uint64_t, APZUpdater*> sWindowIdMap; + static StaticAutoPtr<std::unordered_map<uint64_t, APZUpdater*>> sWindowIdMap; Maybe<wr::WrWindowId> mWindowId; + // Lock used to protected mUpdaterThreadId; + mutable Mutex mThreadIdLock; // If WebRender and async scene building are enabled, this holds the thread id // of the scene builder thread (which is the updater thread) for the // compositor associated with this APZUpdater instance. It may be populated // even if async scene building is not enabled, but in that case we don't // care about the contents. - // This is written to once during init and never cleared, and so reading it - // from multiple threads during normal operation (after initialization) - // without locking should be fine. Maybe<PlatformThreadId> mUpdaterThreadId; -#ifdef DEBUG - // This flag is used to ensure that we don't ever try to do updater-thread - // stuff before the updater thread has been properly initialized. - mutable bool mUpdaterThreadQueried; -#endif // Helper struct that pairs each queued runnable with the layers id that it // is associated with. This allows us to easily implement the conceptual // separation of mUpdaterQueue into independent queues per layers id. struct QueuedTask { LayersId mLayersId; RefPtr<Runnable> mRunnable; };
--- a/gfx/layers/apz/src/APZSampler.cpp +++ b/gfx/layers/apz/src/APZSampler.cpp @@ -14,55 +14,58 @@ #include "mozilla/layers/SynchronousTask.h" #include "TreeTraversal.h" #include "mozilla/webrender/WebRenderAPI.h" namespace mozilla { namespace layers { StaticMutex APZSampler::sWindowIdLock; -std::unordered_map<uint64_t, APZSampler*> APZSampler::sWindowIdMap; +StaticAutoPtr<std::unordered_map<uint64_t, APZSampler*>> APZSampler::sWindowIdMap; -APZSampler::APZSampler(const RefPtr<APZCTreeManager>& aApz) +APZSampler::APZSampler(const RefPtr<APZCTreeManager>& aApz, + bool aIsUsingWebRender) : mApz(aApz) -#ifdef DEBUG - , mSamplerThreadQueried(false) -#endif + , mIsUsingWebRender(aIsUsingWebRender) + , mThreadIdLock("APZSampler::mThreadIdLock") , mSampleTimeLock("APZSampler::mSampleTimeLock") { MOZ_ASSERT(aApz); mApz->SetSampler(this); } APZSampler::~APZSampler() { mApz->SetSampler(nullptr); StaticMutexAutoLock lock(sWindowIdLock); if (mWindowId) { - sWindowIdMap.erase(wr::AsUint64(*mWindowId)); + MOZ_ASSERT(sWindowIdMap); + sWindowIdMap->erase(wr::AsUint64(*mWindowId)); } } void APZSampler::SetWebRenderWindowId(const wr::WindowId& aWindowId) { StaticMutexAutoLock lock(sWindowIdLock); MOZ_ASSERT(!mWindowId); mWindowId = Some(aWindowId); - sWindowIdMap[wr::AsUint64(aWindowId)] = this; + if (!sWindowIdMap) { + sWindowIdMap = new std::unordered_map<uint64_t, APZSampler*>(); + } + (*sWindowIdMap)[wr::AsUint64(aWindowId)] = this; } /*static*/ void APZSampler::SetSamplerThread(const wr::WrWindowId& aWindowId) { if (RefPtr<APZSampler> sampler = GetSampler(aWindowId)) { - // Ensure nobody tried to use the updater thread before this point. - MOZ_ASSERT(!sampler->mSamplerThreadQueried); + MutexAutoLock lock(sampler->mThreadIdLock); sampler->mSamplerThreadId = Some(PlatformThread::CurrentId()); } } /*static*/ void APZSampler::SampleForWebRender(const wr::WrWindowId& aWindowId, wr::Transaction* aTransaction) { @@ -209,47 +212,37 @@ APZSampler::AssertOnSamplerThread() cons if (APZThreadUtils::GetThreadAssertionsEnabled()) { MOZ_ASSERT(IsSamplerThread()); } } bool APZSampler::IsSamplerThread() const { - if (UsingWebRenderSamplerThread()) { - return PlatformThread::CurrentId() == *mSamplerThreadId; + if (mIsUsingWebRender) { + // If the sampler thread id isn't set yet then we cannot be running on the + // sampler thread (because we will have the thread id before we run any + // other C++ code on it, and this function is only ever invoked from C++ + // code), so return false in that scenario. + MutexAutoLock lock(mThreadIdLock); + return mSamplerThreadId && PlatformThread::CurrentId() == *mSamplerThreadId; } return CompositorThreadHolder::IsInCompositorThread(); } -bool -APZSampler::UsingWebRenderSamplerThread() const -{ - // If mSamplerThreadId is not set at the point that this is called, then - // that means that either (a) WebRender is not enabled for the compositor - // to which this APZSampler is attached or (b) we are attempting to do - // something sampler-related before WebRender is up and running. In case - // (a) falling back to the compositor thread is correct, and in case (b) - // we should stop doing the sampler-related thing so early. We catch this - // case by setting the mSamplerThreadQueried flag and asserting on WR - // initialization. -#ifdef DEBUG - mSamplerThreadQueried = true; -#endif - return mSamplerThreadId.isSome(); -} - /*static*/ already_AddRefed<APZSampler> APZSampler::GetSampler(const wr::WrWindowId& aWindowId) { RefPtr<APZSampler> sampler; StaticMutexAutoLock lock(sWindowIdLock); - auto it = sWindowIdMap.find(wr::AsUint64(aWindowId)); - if (it != sWindowIdMap.end()) { - sampler = it->second; + if (sWindowIdMap) { + auto it = sWindowIdMap->find(wr::AsUint64(aWindowId)); + if (it != sWindowIdMap->end()) { + sampler = it->second; + } } return sampler.forget(); } } // namespace layers } // namespace mozilla void
--- a/gfx/layers/apz/src/APZUpdater.cpp +++ b/gfx/layers/apz/src/APZUpdater.cpp @@ -14,62 +14,65 @@ #include "mozilla/layers/SynchronousTask.h" #include "mozilla/layers/WebRenderScrollDataWrapper.h" #include "mozilla/webrender/WebRenderAPI.h" namespace mozilla { namespace layers { StaticMutex APZUpdater::sWindowIdLock; -std::unordered_map<uint64_t, APZUpdater*> APZUpdater::sWindowIdMap; +StaticAutoPtr<std::unordered_map<uint64_t, APZUpdater*>> APZUpdater::sWindowIdMap; -APZUpdater::APZUpdater(const RefPtr<APZCTreeManager>& aApz) +APZUpdater::APZUpdater(const RefPtr<APZCTreeManager>& aApz, + bool aIsUsingWebRender) : mApz(aApz) -#ifdef DEBUG - , mUpdaterThreadQueried(false) -#endif + , mIsUsingWebRender(aIsUsingWebRender) + , mThreadIdLock("APZUpdater::ThreadIdLock") , mQueueLock("APZUpdater::QueueLock") { MOZ_ASSERT(aApz); mApz->SetUpdater(this); } APZUpdater::~APZUpdater() { mApz->SetUpdater(nullptr); StaticMutexAutoLock lock(sWindowIdLock); if (mWindowId) { + MOZ_ASSERT(sWindowIdMap); // Ensure that ClearTree was called and the task got run - MOZ_ASSERT(sWindowIdMap.find(wr::AsUint64(*mWindowId)) == sWindowIdMap.end()); + MOZ_ASSERT(sWindowIdMap->find(wr::AsUint64(*mWindowId)) == sWindowIdMap->end()); } } bool APZUpdater::HasTreeManager(const RefPtr<APZCTreeManager>& aApz) { return aApz.get() == mApz.get(); } void APZUpdater::SetWebRenderWindowId(const wr::WindowId& aWindowId) { StaticMutexAutoLock lock(sWindowIdLock); MOZ_ASSERT(!mWindowId); mWindowId = Some(aWindowId); - sWindowIdMap[wr::AsUint64(aWindowId)] = this; + if (!sWindowIdMap) { + sWindowIdMap = new std::unordered_map<uint64_t, APZUpdater*>(); + } + (*sWindowIdMap)[wr::AsUint64(aWindowId)] = this; } /*static*/ void APZUpdater::SetUpdaterThread(const wr::WrWindowId& aWindowId) { if (RefPtr<APZUpdater> updater = GetUpdater(aWindowId)) { - // Ensure nobody tried to use the updater thread before this point. - MOZ_ASSERT(!updater->mUpdaterThreadQueried); + MutexAutoLock lock(updater->mThreadIdLock); updater->mUpdaterThreadId = Some(PlatformThread::CurrentId()); } } /*static*/ void APZUpdater::PrepareForSceneSwap(const wr::WrWindowId& aWindowId) { if (RefPtr<APZUpdater> updater = GetUpdater(aWindowId)) { @@ -142,17 +145,18 @@ APZUpdater::ClearTree(LayersId aRootLaye self->mApz->ClearTree(); // Once ClearTree is called on the APZCTreeManager, we are in a shutdown // phase. After this point it's ok if WebRender cannot get a hold of the // updater via the window id, and it's a good point to remove the mapping // and avoid leaving a dangling pointer to this object. StaticMutexAutoLock lock(sWindowIdLock); if (self->mWindowId) { - sWindowIdMap.erase(wr::AsUint64(*(self->mWindowId))); + MOZ_ASSERT(sWindowIdMap); + sWindowIdMap->erase(wr::AsUint64(*(self->mWindowId))); } } )); } void APZUpdater::UpdateFocusState(LayersId aRootLayerTreeId, LayersId aOriginatingLayersId, @@ -329,16 +333,23 @@ APZUpdater::AssertOnUpdaterThread() cons } } void APZUpdater::RunOnUpdaterThread(LayersId aLayersId, already_AddRefed<Runnable> aTask) { RefPtr<Runnable> task = aTask; + // In the scenario where UsingWebRenderUpdaterThread() is true, this function + // might get called early (before mUpdaterThreadId is set). In that case + // IsUpdaterThread() will return false and we'll queue the task onto + // mUpdaterQueue. This is fine; the task is still guaranteed to run (barring + // catastrophic failure) because the WakeSceneBuilder call will still trigger + // the callback to run tasks. + if (IsUpdaterThread()) { task->Run(); return; } if (UsingWebRenderUpdaterThread()) { // If the updater thread is a WebRender thread, and we're not on it // right now, save the task in the queue. We will run tasks from the queue @@ -370,17 +381,22 @@ APZUpdater::RunOnUpdaterThread(LayersId NS_WARNING("Dropping task posted to updater thread"); } } bool APZUpdater::IsUpdaterThread() const { if (UsingWebRenderUpdaterThread()) { - return PlatformThread::CurrentId() == *mUpdaterThreadId; + // If the updater thread id isn't set yet then we cannot be running on the + // updater thread (because we will have the thread id before we run any + // C++ code on it, and this function is only ever invoked from C++ code), + // so return false in that scenario. + MutexAutoLock lock(mThreadIdLock); + return mUpdaterThreadId && PlatformThread::CurrentId() == *mUpdaterThreadId; } return CompositorThreadHolder::IsInCompositorThread(); } void APZUpdater::RunOnControllerThread(LayersId aLayersId, already_AddRefed<Runnable> aTask) { MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); @@ -389,41 +405,29 @@ APZUpdater::RunOnControllerThread(Layers "APZUpdater::RunOnControllerThread", &APZThreadUtils::RunOnControllerThread, Move(aTask))); } bool APZUpdater::UsingWebRenderUpdaterThread() const { - if (!gfxPrefs::WebRenderAsyncSceneBuild()) { - return false; - } - // If mUpdaterThreadId is not set at the point that this is called, then - // that means that either (a) WebRender is not enabled for the compositor - // to which this APZUpdater is attached or (b) we are attempting to do - // something updater-related before WebRender is up and running. In case - // (a) falling back to the compositor thread is correct, and in case (b) - // we should stop doing the updater-related thing so early. We catch this - // case by setting the mUpdaterThreadQueried flag and asserting on WR - // initialization. -#ifdef DEBUG - mUpdaterThreadQueried = true; -#endif - return mUpdaterThreadId.isSome(); + return (mIsUsingWebRender && gfxPrefs::WebRenderAsyncSceneBuild()); } /*static*/ already_AddRefed<APZUpdater> APZUpdater::GetUpdater(const wr::WrWindowId& aWindowId) { RefPtr<APZUpdater> updater; StaticMutexAutoLock lock(sWindowIdLock); - auto it = sWindowIdMap.find(wr::AsUint64(aWindowId)); - if (it != sWindowIdMap.end()) { - updater = it->second; + if (sWindowIdMap) { + auto it = sWindowIdMap->find(wr::AsUint64(aWindowId)); + if (it != sWindowIdMap->end()) { + updater = it->second; + } } return updater.forget(); } void APZUpdater::ProcessQueue() { { // scope lock to check for emptiness
--- a/gfx/layers/apz/test/gtest/APZCBasicTester.h +++ b/gfx/layers/apz/test/gtest/APZCBasicTester.h @@ -26,18 +26,18 @@ public: protected: virtual void SetUp() { gfxPrefs::GetSingleton(); APZThreadUtils::SetThreadAssertionsEnabled(false); APZThreadUtils::SetControllerThread(MessageLoop::current()); tm = new TestAPZCTreeManager(mcc); - updater = new APZUpdater(tm); - sampler = new APZSampler(tm); + updater = new APZUpdater(tm, false); + sampler = new APZSampler(tm, false); apzc = new TestAsyncPanZoomController(LayersId{0}, mcc, tm, mGestureBehavior); apzc->SetFrameMetrics(TestFrameMetrics()); apzc->GetScrollMetadata().SetIsLayersIdRoot(true); } /** * Get the APZC's scroll range in CSS pixels. */
--- a/gfx/layers/apz/test/gtest/APZCTreeManagerTester.h +++ b/gfx/layers/apz/test/gtest/APZCTreeManagerTester.h @@ -22,18 +22,18 @@ class APZCTreeManagerTester : public APZ protected: virtual void SetUp() { gfxPrefs::GetSingleton(); gfxPlatform::GetPlatform(); APZThreadUtils::SetThreadAssertionsEnabled(false); APZThreadUtils::SetControllerThread(MessageLoop::current()); manager = new TestAPZCTreeManager(mcc); - updater = new APZUpdater(manager); - sampler = new APZSampler(manager); + updater = new APZUpdater(manager, false); + sampler = new APZSampler(manager, false); } virtual void TearDown() { while (mcc->RunThroughDelayedTasks()); manager->ClearTree(); manager->ClearContentController(); }
--- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -753,17 +753,18 @@ MoveScrollbarForLayerMargin(Layer* aRoot const ScreenMargin& aFixedLayerMargins) { // See bug 1223928 comment 9 - once we can detect the RCD with just the // isRootContent flag on the metrics, we can probably move this code into // ApplyAsyncTransformToScrollbar rather than having it as a separate // adjustment on the layer tree. Layer* scrollbar = BreadthFirstSearch<ReverseIterator>(aRoot, [aRootScrollId](Layer* aNode) { - return (aNode->GetScrollbarData().mDirection.isSome() && + return (aNode->GetScrollbarData().IsThumb() && + aNode->GetScrollbarData().mDirection.isSome() && *aNode->GetScrollbarData().mDirection == ScrollDirection::eHorizontal && aNode->GetScrollbarData().mTargetViewId == aRootScrollId); }); if (scrollbar) { // Shift the horizontal scrollbar down into the new space exposed by the // dynamic toolbar hiding. Technically we should also scale the vertical // scrollbar a bit to expand into the new space but it's not as noticeable // and it would add a lot more complexity, so we're going with the "it's not
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CompositorBridgeParent.cpp @@ -380,18 +380,18 @@ CompositorBridgeParent::Initialize() MOZ_ASSERT(CompositorThread(), "The compositor thread must be Initialized before instanciating a CompositorBridgeParent."); if (mOptions.UseAPZ()) { MOZ_ASSERT(!mApzcTreeManager); MOZ_ASSERT(!mApzSampler); MOZ_ASSERT(!mApzUpdater); mApzcTreeManager = new APZCTreeManager(mRootLayerTreeID); - mApzSampler = new APZSampler(mApzcTreeManager); - mApzUpdater = new APZUpdater(mApzcTreeManager); + mApzSampler = new APZSampler(mApzcTreeManager, mOptions.UseWebRender()); + mApzUpdater = new APZUpdater(mApzcTreeManager, mOptions.UseWebRender()); } mCompositorBridgeID = 0; // FIXME: This holds on the the fact that right now the only thing that // can destroy this instance is initialized on the compositor thread after // this task has been processed. MOZ_ASSERT(CompositorLoop()); CompositorLoop()->PostTask(NewRunnableFunction("AddCompositorRunnable",
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp @@ -130,17 +130,17 @@ CrossProcessCompositorBridgeParent::Allo // If the widget has shutdown its compositor, we may not have had a chance yet // to unmap our layers id, and we could get here without a parent compositor. // In this case return an empty APZCTM. if (!state.mParent) { // Note: we immediately call ClearTree since otherwise the APZCTM will // retain a reference to itself, through the checkerboard observer. LayersId dummyId{0}; RefPtr<APZCTreeManager> temp = new APZCTreeManager(dummyId); - RefPtr<APZUpdater> tempUpdater = new APZUpdater(temp); + RefPtr<APZUpdater> tempUpdater = new APZUpdater(temp, false); tempUpdater->ClearTree(dummyId); return new APZCTreeManagerParent(aLayersId, temp, tempUpdater); } state.mParent->AllocateAPZCTreeManagerParent(lock, aLayersId, state); return state.mApzcTreeManagerParent; } bool
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -1160,24 +1160,28 @@ void WebRenderBridgeParent::ActorDestroy(ActorDestroyReason aWhy) { Destroy(); } void WebRenderBridgeParent::AdvanceAnimations() { - TimeStamp animTime = mCompositorScheduler->GetLastComposeTime(); + Maybe<TimeStamp> testingTimeStamp; if (CompositorBridgeParent* cbp = GetRootCompositorBridgeParent()) { - animTime = cbp->GetTestingTimeStamp().valueOr(animTime); + testingTimeStamp = cbp->GetTestingTimeStamp(); } - AnimationHelper::SampleAnimations(mAnimStorage, - !mPreviousFrameTimeStamp.IsNull() ? - mPreviousFrameTimeStamp : animTime); + TimeStamp animTime = testingTimeStamp.valueOr( + !mPreviousFrameTimeStamp.IsNull() + ? mPreviousFrameTimeStamp + : mCompositorScheduler->GetLastComposeTime()); + + + AnimationHelper::SampleAnimations(mAnimStorage, animTime); // Reset the previous time stamp if we don't already have any running // animations to avoid using the time which is far behind for newly // started animations. mPreviousFrameTimeStamp = mAnimStorage->AnimatedValueCount() ? animTime : TimeStamp(); }
--- a/intl/locale/langGroups.properties +++ b/intl/locale/langGroups.properties @@ -16,31 +16,35 @@ # (arc)/Avestan script.) #ae=ar ab=x-cyrillic ach=x-western af=x-western alg=x-cans am=x-ethi +an=x-western ar=ar as=x-beng +ast=x-western ay=x-western +az=x-western be=x-cyrillic bg=x-cyrillic bn=x-beng bo=x-tibt br=x-western bs=x-western ca=x-western cak=x-western ce=x-western ch=x-western co=x-western cr=x-cans +crh=x-western cs=x-western csb=x-western #cu=x-cyrillic cv=x-cyrillic cy=x-western da=x-western de=x-western dsb=x-western @@ -98,19 +102,22 @@ kw=x-western #ky=x-cyrillic la=x-western lb=x-western lij=x-western ln=x-western lt=x-western ltg=x-western lv=x-western +mai=x-devanagari +meh=x-western mg=x-western mh=x-western mi=x-western +mix=x-western mk=x-cyrillic ml=x-mlym # Mongolian script is also used for Mongolian mn=x-cyrillic mr=x-devanagari ms=x-western mt=x-western na=x-western @@ -172,16 +179,17 @@ tl=x-western tlh=x-western tn=x-western to=x-western tr=x-western ts=x-western tt=x-western uk=x-cyrillic ur=ar +uz=x-western ve=x-western vi=x-western vo=x-western wa=x-western wo=x-western xh=x-western yi=he yo=x-western
--- a/intl/locale/language.properties +++ b/intl/locale/language.properties @@ -43,16 +43,17 @@ bo.accept = true br.accept = true bs.accept = true ca.accept = true cak.accept = true ce.accept = true ch.accept = true co.accept = true cr.accept = true +crh.accept = true cs.accept = true csb.accept = true cu.accept = true cv.accept = true cy.accept = true da.accept = true de.accept = true de-at.accept = true @@ -171,19 +172,22 @@ lg.accept = true li.accept = true lij.accept = true ln.accept = true lo.accept = true lt.accept = true ltg.accept = true lu.accept = true lv.accept = true +mai.accept = true +meh.accept = true mg.accept = true mh.accept = true mi.accept = true +mix.accept = true mk.accept = true mk-mk.accept = true ml.accept = true mn.accept = true mr.accept = true ms.accept = true mt.accept = true my.accept = true @@ -226,16 +230,17 @@ sa.accept = true sc.accept = true sd.accept = true sg.accept = true si.accept = true sk.accept = true sl.accept = true sm.accept = true so.accept = true +son.accept = true son-ml.accept = true sq.accept = true sr.accept = true ss.accept = true st.accept = true su.accept = true sv.accept = true sv-fi.accept = true
--- a/layout/base/RestyleManager.cpp +++ b/layout/base/RestyleManager.cpp @@ -3517,24 +3517,30 @@ RestyleManager::DoReparentComputedStyleF // updated as a child). And given how this method ends up getting called, if // we reach here for a table frame, we are already in the middle of // reparenting the table wrapper frame. So no need to // UpdateStyleOfOwnedAnonBoxes() here. ReparentFrameDescendants(aFrame, providerChild, aStyleSet); // We do not need to do the equivalent of UpdateFramePseudoElementStyles, - // because those are hadled by our descendant walk. + // because those are handled by our descendant walk. } void RestyleManager::ReparentFrameDescendants(nsIFrame* aFrame, nsIFrame* aProviderChild, ServoStyleSet& aStyleSet) { + if (aFrame->GetContent()->IsElement() && + !aFrame->GetContent()->AsElement()->HasServoData()) { + // We're getting into a display: none subtree, avoid reparenting into stuff + // that is going to go away anyway in seconds. + return; + } nsIFrame::ChildListIterator lists(aFrame); for (; !lists.IsDone(); lists.Next()) { for (nsIFrame* child : lists.CurrentList()) { // only do frames that are in flow if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW) && child != aProviderChild) { DoReparentComputedStyleForFirstLine(child, aStyleSet); }
--- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -11363,17 +11363,23 @@ nsIFrame::GetCompositorHitTestInfo(nsDis MOZ_ASSERT((result & CompositorHitTestInfo::eTouchActionMask) == CompositorHitTestInfo::eTouchActionMask); } } nsDisplayOwnLayerFlags flags = aBuilder->GetCurrentScrollbarFlags(); if (flags != nsDisplayOwnLayerFlags::eNone) { if (GetContent()->IsXULElement(nsGkAtoms::thumb)) { - result |= CompositorHitTestInfo::eScrollbarThumb; + bool thumbGetsLayer = aBuilder->GetCurrentScrollbarTarget() != + layers::FrameMetrics::NULL_SCROLL_ID; + if (thumbGetsLayer) { + result |= CompositorHitTestInfo::eScrollbarThumb; + } else { + result |= CompositorHitTestInfo::eDispatchToContent; + } } // The only flags that get set in nsDisplayListBuilder::mCurrentScrollbarFlags // are the scrollbar direction flags if (flags == nsDisplayOwnLayerFlags::eVerticalScrollbar) { result |= CompositorHitTestInfo::eScrollbarVertical; } else { MOZ_ASSERT(flags == nsDisplayOwnLayerFlags::eHorizontalScrollbar); }
--- a/layout/inspector/InspectorUtils.cpp +++ b/layout/inspector/InspectorUtils.cpp @@ -363,44 +363,47 @@ InspectorUtils::IsInheritedProperty(Glob return Servo_Property_IsInherited(&propName); } /* static */ void InspectorUtils::GetCSSPropertyNames(GlobalObject& aGlobalObject, const PropertyNamesOptions& aOptions, nsTArray<nsString>& aResult) { -#define DO_PROP(_prop) \ - PR_BEGIN_MACRO \ - nsCSSPropertyID cssProp = nsCSSPropertyID(_prop); \ - if (nsCSSProps::IsEnabled(cssProp, CSSEnabledState::eForAllContent)) { \ - nsDependentCString name(kCSSRawProperties[_prop]); \ - aResult.AppendElement(NS_ConvertASCIItoUTF16(name)); \ - } \ - PR_END_MACRO + CSSEnabledState enabledState = aOptions.mIncludeExperimentals + ? CSSEnabledState::eIgnoreEnabledState + : CSSEnabledState::eForAllContent; + + auto appendProperty = [enabledState, &aResult](uint32_t prop) { + nsCSSPropertyID cssProp = nsCSSPropertyID(prop); + if (nsCSSProps::IsEnabled(cssProp, enabledState)) { + nsDependentCString name(kCSSRawProperties[prop]); + aResult.AppendElement(NS_ConvertASCIItoUTF16(name)); + } + }; uint32_t prop = 0; for ( ; prop < eCSSProperty_COUNT_no_shorthands; ++prop) { if (nsCSSProps::PropertyParseType(nsCSSPropertyID(prop)) != CSS_PROPERTY_PARSE_INACCESSIBLE) { - DO_PROP(prop); + appendProperty(prop); } } - for ( ; prop < eCSSProperty_COUNT; ++prop) { - DO_PROP(prop); + if (aOptions.mIncludeShorthands) { + for ( ; prop < eCSSProperty_COUNT; ++prop) { + appendProperty(prop); + } } if (aOptions.mIncludeAliases) { for (prop = eCSSProperty_COUNT; prop < eCSSProperty_COUNT_with_aliases; ++prop) { - DO_PROP(prop); + appendProperty(prop); } } - -#undef DO_PROP } static void InsertNoDuplicates(nsTArray<nsString>& aArray, const nsAString& aString) { size_t i = aArray.IndexOfFirstElementGt(aString); if (i > 0 && aArray[i-1].Equals(aString)) { return;
--- a/layout/style/ServoCSSPropList.mako.py +++ b/layout/style/ServoCSSPropList.mako.py @@ -32,16 +32,20 @@ def flags(prop): if prop.explicitly_enabled_in_chrome(): result.append("CSS_PROPERTY_ENABLED_IN_UA_SHEETS_AND_CHROME") elif prop.explicitly_enabled_in_ua_sheets(): result.append("CSS_PROPERTY_ENABLED_IN_UA_SHEETS") if is_internal(prop): result.append("CSS_PROPERTY_INTERNAL") if prop.enabled_in == "": result.append("CSS_PROPERTY_PARSE_INACCESSIBLE") + if "GETCS_NEEDS_LAYOUT_FLUSH" in prop.flags: + result.append("CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH") + if "CAN_ANIMATE_ON_COMPOSITOR" in prop.flags: + result.append("CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR") return ", ".join('"{}"'.format(flag) for flag in result) def pref(prop): if prop.gecko_pref: return '"' + prop.gecko_pref + '"' return '""' %>
new file mode 100644 --- /dev/null +++ b/layout/style/crashtests/1455108.html @@ -0,0 +1,17 @@ +<!doctype html> +<style> + div::first-line { + color: yellow: + } + .foo span { + display: none; + } + .foo::first-line { + color: red; + } +</style> +<div><span>Yo, I'm a first-line<span> really</span></span> +<script> + document.body.offsetTop; + document.querySelector('div').classList.add('foo'); +</script>
--- a/layout/style/crashtests/crashtests.list +++ b/layout/style/crashtests/crashtests.list @@ -268,8 +268,9 @@ test-pref(dom.animations-api.core.enable pref(dom.webcomponents.shadowdom.enabled,true) load 1419554.html load 1426312.html load 1439793.html load 1409183.html pref(dom.webcomponents.shadowdom.enabled,true) load 1445682.html load 1450691.html pref(dom.webcomponents.shadowdom.enabled,true) load 1453206.html load 1454140.html +load 1455108.html
--- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -90,25 +90,25 @@ // A caller who wants all the properties can define the |CSS_PROP| // macro. #ifdef CSS_PROP #define USED_CSS_PROP // We still need this extra level so that CSS_PROP_DOMPROP_PREFIXED has // a chance to be expanded. -#define CSS_PROP_(name_, id_, method_, flags_, pref_, parsevariant_, kwtable_, animtype_) CSS_PROP(name_, id_, method_, flags_, pref_, parsevariant_, kwtable_, animtype_) +#define CSS_PROP_(name_, id_, method_, flags_, pref_, parsevariant_, kwtable_) CSS_PROP(name_, id_, method_, flags_, pref_, parsevariant_, kwtable_) #else /* !defined(CSS_PROP) */ // An includer who does not define CSS_PROP can define any or all of the // per-struct macros that are equivalent to it, and the rest will be // ignored. -#define CSS_PROP_(name_, id_, method_, flags_, pref_, parsevariant_, kwtable_, animtype_) /* nothing */ +#define CSS_PROP_(name_, id_, method_, flags_, pref_, parsevariant_, kwtable_) /* nothing */ #endif /* !defined(CSS_PROP) */ /*************************************************************************/ // For notes XXX bug 3935 below, the names being parsed do not correspond // to the constants used internally. It would be nice to bring the // constants into line sometime. @@ -142,264 +142,235 @@ CSS_PROP_( align-content, align_content, AlignContent, CSS_PROPERTY_PARSE_FUNCTION, "", VARIANT_HK, - kAutoCompletionAlignJustifyContent, - eStyleAnimType_Discrete) + kAutoCompletionAlignJustifyContent) CSS_PROP_( align-items, align_items, AlignItems, CSS_PROPERTY_PARSE_FUNCTION, "", VARIANT_HK, - kAutoCompletionAlignItems, - eStyleAnimType_Discrete) + kAutoCompletionAlignItems) CSS_PROP_( align-self, align_self, AlignSelf, CSS_PROPERTY_PARSE_FUNCTION, "", VARIANT_HK, - kAutoCompletionAlignJustifySelf, - eStyleAnimType_Discrete) + kAutoCompletionAlignJustifySelf) CSS_PROP_SHORTHAND( all, all, All, CSS_PROPERTY_PARSE_FUNCTION, "layout.css.all-shorthand.enabled") CSS_PROP_SHORTHAND( animation, animation, Animation, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( animation-delay, animation_delay, AnimationDelay, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "", VARIANT_TIME, // used by list parsing - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( animation-direction, animation_direction, AnimationDirection, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "", VARIANT_KEYWORD, // used by list parsing - kAnimationDirectionKTable, - eStyleAnimType_None) + kAnimationDirectionKTable) CSS_PROP_( animation-duration, animation_duration, AnimationDuration, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "", VARIANT_TIME | VARIANT_NONNEGATIVE_DIMENSION, // used by list parsing - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( animation-fill-mode, animation_fill_mode, AnimationFillMode, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "", VARIANT_KEYWORD, // used by list parsing - kAnimationFillModeKTable, - eStyleAnimType_None) + kAnimationFillModeKTable) CSS_PROP_( animation-iteration-count, animation_iteration_count, AnimationIterationCount, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "", VARIANT_KEYWORD | VARIANT_NUMBER, // used by list parsing - kAnimationIterationCountKTable, - eStyleAnimType_None) + kAnimationIterationCountKTable) CSS_PROP_( animation-name, animation_name, AnimationName, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "", // FIXME: The spec should say something about 'inherit' and 'initial' // not being allowed. VARIANT_NONE | VARIANT_IDENTIFIER_NO_INHERIT | VARIANT_STRING, // used by list parsing - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( animation-play-state, animation_play_state, AnimationPlayState, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "", VARIANT_KEYWORD, // used by list parsing - kAnimationPlayStateKTable, - eStyleAnimType_None) + kAnimationPlayStateKTable) CSS_PROP_( animation-timing-function, animation_timing_function, AnimationTimingFunction, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "", VARIANT_KEYWORD | VARIANT_TIMING_FUNCTION, // used by list parsing - kTransitionTimingFunctionKTable, - eStyleAnimType_None) + kTransitionTimingFunctionKTable) CSS_PROP_( -moz-appearance, _moz_appearance, CSS_PROP_DOMPROP_PREFIXED(Appearance), 0, "", VARIANT_HK, - kAppearanceKTable, - eStyleAnimType_Discrete) + kAppearanceKTable) CSS_PROP_( backface-visibility, backface_visibility, BackfaceVisibility, 0, "", VARIANT_HK, - kBackfaceVisibilityKTable, - eStyleAnimType_Discrete) + kBackfaceVisibilityKTable) CSS_PROP_SHORTHAND( background, background, Background, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( background-attachment, background_attachment, BackgroundAttachment, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "", VARIANT_KEYWORD, // used by list parsing - kImageLayerAttachmentKTable, - eStyleAnimType_Discrete) + kImageLayerAttachmentKTable) CSS_PROP_( background-blend-mode, background_blend_mode, BackgroundBlendMode, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "layout.css.background-blend-mode.enabled", VARIANT_KEYWORD, // used by list parsing - kBlendModeKTable, - eStyleAnimType_Discrete) + kBlendModeKTable) CSS_PROP_( background-clip, background_clip, BackgroundClip, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "", VARIANT_KEYWORD, // used by list parsing - kBackgroundClipKTable, - eStyleAnimType_Discrete) + kBackgroundClipKTable) CSS_PROP_( background-color, background_color, BackgroundColor, 0, "", VARIANT_HC, - nullptr, - eStyleAnimType_ComplexColor) + nullptr) CSS_PROP_( background-image, background_image, BackgroundImage, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "", VARIANT_IMAGE, // used by list parsing - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_( background-origin, background_origin, BackgroundOrigin, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "", VARIANT_KEYWORD, // used by list parsing - kBackgroundOriginKTable, - eStyleAnimType_Discrete) + kBackgroundOriginKTable) CSS_PROP_SHORTHAND( background-position, background_position, BackgroundPosition, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( background-position-x, background_position_x, BackgroundPositionX, - CSS_PROPERTY_PARSE_FUNCTION | - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + CSS_PROPERTY_PARSE_FUNCTION, "", 0, - kImageLayerPositionKTable, - eStyleAnimType_Custom) + kImageLayerPositionKTable) CSS_PROP_( background-position-y, background_position_y, BackgroundPositionY, - CSS_PROPERTY_PARSE_FUNCTION | - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + CSS_PROPERTY_PARSE_FUNCTION, "", 0, - kImageLayerPositionKTable, - eStyleAnimType_Custom) + kImageLayerPositionKTable) CSS_PROP_( background-repeat, background_repeat, BackgroundRepeat, - CSS_PROPERTY_PARSE_FUNCTION | - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + CSS_PROPERTY_PARSE_FUNCTION, "", VARIANT_KEYWORD, // used by list parsing - kImageLayerRepeatKTable, - eStyleAnimType_Discrete) + kImageLayerRepeatKTable) CSS_PROP_( background-size, background_size, BackgroundSize, - CSS_PROPERTY_PARSE_FUNCTION | - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + CSS_PROPERTY_PARSE_FUNCTION, "", 0, - kImageLayerSizeKTable, - eStyleAnimType_Custom) + kImageLayerSizeKTable) CSS_PROP_( -moz-binding, _moz_binding, CSS_PROP_DOMPROP_PREFIXED(Binding), 0, "", VARIANT_HUO, - nullptr, - eStyleAnimType_None) // XXX bug 3935 + nullptr) // XXX bug 3935 CSS_PROP_( block-size, block_size, BlockSize, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_AHLP | VARIANT_CALC, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_SHORTHAND( border, border, Border, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_SHORTHAND( border-block-end, @@ -409,129 +380,117 @@ CSS_PROP_SHORTHAND( "") CSS_PROP_( border-block-end-color, border_block_end_color, BorderBlockEndColor, 0, "", VARIANT_HC, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( border-block-end-style, border_block_end_style, BorderBlockEndStyle, 0, "", VARIANT_HK, - kBorderStyleKTable, - eStyleAnimType_None) + kBorderStyleKTable) CSS_PROP_( border-block-end-width, border_block_end_width, BorderBlockEndWidth, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_HKL | VARIANT_CALC, - kBorderWidthKTable, - eStyleAnimType_None) + kBorderWidthKTable) CSS_PROP_SHORTHAND( border-block-start, border_block_start, BorderBlockStart, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( border-block-start-color, border_block_start_color, BorderBlockStartColor, 0, "", VARIANT_HC, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( border-block-start-style, border_block_start_style, BorderBlockStartStyle, 0, "", VARIANT_HK, - kBorderStyleKTable, - eStyleAnimType_None) + kBorderStyleKTable) CSS_PROP_( border-block-start-width, border_block_start_width, BorderBlockStartWidth, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_HKL | VARIANT_CALC, - kBorderWidthKTable, - eStyleAnimType_None) + kBorderWidthKTable) CSS_PROP_SHORTHAND( border-bottom, border_bottom, BorderBottom, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( border-bottom-color, border_bottom_color, BorderBottomColor, 0, "", VARIANT_HC, - nullptr, - eStyleAnimType_ComplexColor) + nullptr) CSS_PROP_( border-bottom-left-radius, border_bottom_left_radius, BorderBottomLeftRadius, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Corner_BottomLeft) + nullptr) CSS_PROP_( border-bottom-right-radius, border_bottom_right_radius, BorderBottomRightRadius, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Corner_BottomRight) + nullptr) CSS_PROP_( border-bottom-style, border_bottom_style, BorderBottomStyle, 0, "", VARIANT_HK, - kBorderStyleKTable, - eStyleAnimType_Discrete) // on/off will need reflow + kBorderStyleKTable) // on/off will need reflow CSS_PROP_( border-bottom-width, border_bottom_width, BorderBottomWidth, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_HKL | VARIANT_CALC, - kBorderWidthKTable, - eStyleAnimType_Custom) + kBorderWidthKTable) CSS_PROP_( border-collapse, border_collapse, BorderCollapse, 0, "", VARIANT_HK, - kBorderCollapseKTable, - eStyleAnimType_Discrete) + kBorderCollapseKTable) CSS_PROP_SHORTHAND( border-color, border_color, BorderColor, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_SHORTHAND( border-image, @@ -541,153 +500,139 @@ CSS_PROP_SHORTHAND( "") CSS_PROP_( border-image-outset, border_image_outset, BorderImageOutset, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_( border-image-repeat, border_image_repeat, BorderImageRepeat, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - kBorderImageRepeatKTable, - eStyleAnimType_Discrete) + kBorderImageRepeatKTable) CSS_PROP_( border-image-slice, border_image_slice, BorderImageSlice, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - kBorderImageSliceKTable, - eStyleAnimType_Discrete) + kBorderImageSliceKTable) CSS_PROP_( border-image-source, border_image_source, BorderImageSource, 0, "", VARIANT_IMAGE | VARIANT_INHERIT, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_( border-image-width, border_image_width, BorderImageWidth, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_SHORTHAND( border-inline-end, border_inline_end, BorderInlineEnd, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( border-inline-end-color, border_inline_end_color, BorderInlineEndColor, 0, "", VARIANT_HC, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( border-inline-end-style, border_inline_end_style, BorderInlineEndStyle, 0, "", VARIANT_HK, - kBorderStyleKTable, - eStyleAnimType_None) + kBorderStyleKTable) CSS_PROP_( border-inline-end-width, border_inline_end_width, BorderInlineEndWidth, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_HKL | VARIANT_CALC, - kBorderWidthKTable, - eStyleAnimType_None) + kBorderWidthKTable) CSS_PROP_SHORTHAND( border-inline-start, border_inline_start, BorderInlineStart, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( border-inline-start-color, border_inline_start_color, BorderInlineStartColor, 0, "", VARIANT_HC, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( border-inline-start-style, border_inline_start_style, BorderInlineStartStyle, 0, "", VARIANT_HK, - kBorderStyleKTable, - eStyleAnimType_None) + kBorderStyleKTable) CSS_PROP_( border-inline-start-width, border_inline_start_width, BorderInlineStartWidth, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_HKL | VARIANT_CALC, - kBorderWidthKTable, - eStyleAnimType_None) + kBorderWidthKTable) CSS_PROP_SHORTHAND( border-left, border_left, BorderLeft, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( border-left-color, border_left_color, BorderLeftColor, 0, "", VARIANT_HC, - nullptr, - eStyleAnimType_ComplexColor) + nullptr) CSS_PROP_( border-left-style, border_left_style, BorderLeftStyle, 0, "", VARIANT_HK, - kBorderStyleKTable, - eStyleAnimType_Discrete) + kBorderStyleKTable) CSS_PROP_( border-left-width, border_left_width, BorderLeftWidth, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_HKL | VARIANT_CALC, - kBorderWidthKTable, - eStyleAnimType_Custom) + kBorderWidthKTable) CSS_PROP_SHORTHAND( border-radius, border_radius, BorderRadius, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_SHORTHAND( border-right, @@ -697,45 +642,41 @@ CSS_PROP_SHORTHAND( "") CSS_PROP_( border-right-color, border_right_color, BorderRightColor, 0, "", VARIANT_HC, - nullptr, - eStyleAnimType_ComplexColor) + nullptr) CSS_PROP_( border-right-style, border_right_style, BorderRightStyle, 0, "", VARIANT_HK, - kBorderStyleKTable, - eStyleAnimType_Discrete) + kBorderStyleKTable) CSS_PROP_( border-right-width, border_right_width, BorderRightWidth, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_HKL | VARIANT_CALC, - kBorderWidthKTable, - eStyleAnimType_Custom) + kBorderWidthKTable) CSS_PROP_( border-spacing, border_spacing, BorderSpacing, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Custom) + nullptr) CSS_PROP_SHORTHAND( border-style, border_style, BorderStyle, CSS_PROPERTY_PARSE_FUNCTION, "") // on/off will need reflow CSS_PROP_SHORTHAND( border-top, @@ -745,771 +686,688 @@ CSS_PROP_SHORTHAND( "") CSS_PROP_( border-top-color, border_top_color, BorderTopColor, 0, "", VARIANT_HC, - nullptr, - eStyleAnimType_ComplexColor) + nullptr) CSS_PROP_( border-top-left-radius, border_top_left_radius, BorderTopLeftRadius, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Corner_TopLeft) + nullptr) CSS_PROP_( border-top-right-radius, border_top_right_radius, BorderTopRightRadius, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Corner_TopRight) + nullptr) CSS_PROP_( border-top-style, border_top_style, BorderTopStyle, 0, "", VARIANT_HK, - kBorderStyleKTable, - eStyleAnimType_Discrete) // on/off will need reflow + kBorderStyleKTable) // on/off will need reflow CSS_PROP_( border-top-width, border_top_width, BorderTopWidth, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_HKL | VARIANT_CALC, - kBorderWidthKTable, - eStyleAnimType_Custom) + kBorderWidthKTable) CSS_PROP_SHORTHAND( border-width, border_width, BorderWidth, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( bottom, bottom, Bottom, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_AHLP | VARIANT_CALC, - nullptr, - eStyleAnimType_Sides_Bottom) + nullptr) CSS_PROP_( -moz-box-align, _moz_box_align, CSS_PROP_DOMPROP_PREFIXED(BoxAlign), 0, "", VARIANT_HK, - kBoxAlignKTable, - eStyleAnimType_Discrete) // XXX bug 3935 + kBoxAlignKTable) // XXX bug 3935 CSS_PROP_( box-decoration-break, box_decoration_break, BoxDecorationBreak, 0, "layout.css.box-decoration-break.enabled", VARIANT_HK, - kBoxDecorationBreakKTable, - eStyleAnimType_Discrete) + kBoxDecorationBreakKTable) CSS_PROP_( -moz-box-direction, _moz_box_direction, CSS_PROP_DOMPROP_PREFIXED(BoxDirection), 0, "", VARIANT_HK, - kBoxDirectionKTable, - eStyleAnimType_Discrete) // XXX bug 3935 + kBoxDirectionKTable) // XXX bug 3935 CSS_PROP_( -moz-box-flex, _moz_box_flex, CSS_PROP_DOMPROP_PREFIXED(BoxFlex), 0, "", VARIANT_HN, - nullptr, - eStyleAnimType_float) // XXX bug 3935 + nullptr) // XXX bug 3935 CSS_PROP_( -moz-box-ordinal-group, _moz_box_ordinal_group, CSS_PROP_DOMPROP_PREFIXED(BoxOrdinalGroup), 0, "", VARIANT_HI, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_( -moz-box-orient, _moz_box_orient, CSS_PROP_DOMPROP_PREFIXED(BoxOrient), 0, "", VARIANT_HK, - kBoxOrientKTable, - eStyleAnimType_Discrete) // XXX bug 3935 + kBoxOrientKTable) // XXX bug 3935 CSS_PROP_( -moz-box-pack, _moz_box_pack, CSS_PROP_DOMPROP_PREFIXED(BoxPack), 0, "", VARIANT_HK, - kBoxPackKTable, - eStyleAnimType_Discrete) // XXX bug 3935 + kBoxPackKTable) // XXX bug 3935 CSS_PROP_( box-shadow, box_shadow, BoxShadow, - CSS_PROPERTY_PARSE_FUNCTION | - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + CSS_PROPERTY_PARSE_FUNCTION, // NOTE: some components must be nonnegative "", VARIANT_COLOR | VARIANT_LENGTH | VARIANT_CALC | VARIANT_INHERIT | VARIANT_NONE, - kBoxShadowTypeKTable, - eStyleAnimType_Shadow) + kBoxShadowTypeKTable) CSS_PROP_( box-sizing, box_sizing, BoxSizing, 0, "", VARIANT_HK, - kBoxSizingKTable, - eStyleAnimType_Discrete) + kBoxSizingKTable) CSS_PROP_( caption-side, caption_side, CaptionSide, 0, "", VARIANT_HK, - kCaptionSideKTable, - eStyleAnimType_Discrete) + kCaptionSideKTable) CSS_PROP_( caret-color, caret_color, CaretColor, 0, "", VARIANT_AUTO | VARIANT_HC, - nullptr, - eStyleAnimType_ComplexColor) + nullptr) CSS_PROP_( clear, clear, Clear, 0, "", VARIANT_HK, - kClearKTable, - eStyleAnimType_Discrete) + kClearKTable) CSS_PROP_( clip, clip, Clip, CSS_PROPERTY_PARSE_FUNCTION, "", VARIANT_AH, - nullptr, - eStyleAnimType_Custom) + nullptr) CSS_PROP_( clip-path, clip_path, ClipPath, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "", VARIANT_HUO, - nullptr, - eStyleAnimType_Custom) + nullptr) CSS_PROP_( clip-rule, clip_rule, ClipRule, 0, "", VARIANT_HK, - kFillRuleKTable, - eStyleAnimType_Discrete) + kFillRuleKTable) CSS_PROP_( color, color, Color, 0, "", VARIANT_HC, - nullptr, - eStyleAnimType_Color) + nullptr) CSS_PROP_( color-adjust, color_adjust, ColorAdjust, 0, "layout.css.color-adjust.enabled", VARIANT_HK, - kColorAdjustKTable, - eStyleAnimType_Discrete) + kColorAdjustKTable) CSS_PROP_( color-interpolation, color_interpolation, ColorInterpolation, 0, "", VARIANT_HK, - kColorInterpolationKTable, - eStyleAnimType_Discrete) + kColorInterpolationKTable) CSS_PROP_( color-interpolation-filters, color_interpolation_filters, ColorInterpolationFilters, 0, "", VARIANT_HK, - kColorInterpolationKTable, - eStyleAnimType_Discrete) + kColorInterpolationKTable) CSS_PROP_( column-count, column_count, ColumnCount, 0, "", VARIANT_AHI, - nullptr, - eStyleAnimType_Custom) + nullptr) CSS_PROP_( column-fill, column_fill, ColumnFill, 0, "", VARIANT_HK, - kColumnFillKTable, - eStyleAnimType_Discrete) + kColumnFillKTable) CSS_PROP_( column-gap, column_gap, ColumnGap, 0, "", VARIANT_HLP | VARIANT_NORMAL | VARIANT_CALC, - nullptr, - eStyleAnimType_Coord) + nullptr) CSS_PROP_SHORTHAND( column-rule, column_rule, ColumnRule, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( column-rule-color, column_rule_color, ColumnRuleColor, 0, "", VARIANT_HC, - nullptr, - eStyleAnimType_ComplexColor) + nullptr) CSS_PROP_( column-rule-style, column_rule_style, ColumnRuleStyle, 0, "", VARIANT_HK, - kBorderStyleKTable, - eStyleAnimType_Discrete) + kBorderStyleKTable) CSS_PROP_( column-rule-width, column_rule_width, ColumnRuleWidth, 0, "", VARIANT_HKL | VARIANT_CALC, - kBorderWidthKTable, - eStyleAnimType_Custom) + kBorderWidthKTable) CSS_PROP_( column-span, column_span, ColumnSpan, 0, "layout.css.column-span.enabled", VARIANT_HK, - kColumnSpanKTable, - eStyleAnimType_Discrete) + kColumnSpanKTable) CSS_PROP_( column-width, column_width, ColumnWidth, 0, "", VARIANT_AHL | VARIANT_CALC, - nullptr, - eStyleAnimType_Coord) + nullptr) CSS_PROP_SHORTHAND( columns, columns, Columns, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( contain, contain, Contain, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "layout.css.contain.enabled", // Does not affect parsing, but is needed for tab completion in devtools: VARIANT_HK | VARIANT_NONE, - kContainKTable, - eStyleAnimType_Discrete) + kContainKTable) CSS_PROP_( content, content, Content, CSS_PROPERTY_PARSE_FUNCTION, "", VARIANT_HMK | VARIANT_NONE | VARIANT_URL | VARIANT_COUNTER | VARIANT_ATTR, - kContentKTable, - eStyleAnimType_Discrete) + kContentKTable) #ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL CSS_PROP_( // Only intended to be used internally by Mozilla, so prefixed. -moz-context-properties, _moz_context_properties, CSS_PROP_DOMPROP_PREFIXED(ContextProperties), CSS_PROPERTY_PARSE_FUNCTION | - CSS_PROPERTY_VALUE_LIST_USES_COMMAS | CSS_PROPERTY_INTERNAL, "", 0, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( -moz-control-character-visibility, _moz_control_character_visibility, CSS_PROP_DOMPROP_PREFIXED(ControlCharacterVisibility), CSS_PROPERTY_INTERNAL, "", VARIANT_HK, - kControlCharacterVisibilityKTable, - eStyleAnimType_None) + kControlCharacterVisibilityKTable) #endif // CSS_PROP_LIST_EXCLUDE_INTERNAL CSS_PROP_( counter-increment, counter_increment, CounterIncrement, CSS_PROPERTY_PARSE_FUNCTION, "", VARIANT_INHERIT | VARIANT_NONE, - nullptr, - eStyleAnimType_Discrete) // XXX bug 137285 + nullptr) // XXX bug 137285 CSS_PROP_( counter-reset, counter_reset, CounterReset, CSS_PROPERTY_PARSE_FUNCTION, "", VARIANT_INHERIT | VARIANT_NONE, - nullptr, - eStyleAnimType_Discrete) // XXX bug 137285 + nullptr) // XXX bug 137285 CSS_PROP_( cursor, cursor, Cursor, - CSS_PROPERTY_PARSE_FUNCTION | - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + CSS_PROPERTY_PARSE_FUNCTION, "", 0, - kCursorKTable, - eStyleAnimType_Discrete) + kCursorKTable) #ifndef CSS_PROP_LIST_ONLY_COMPONENTS_OF_ALL_SHORTHAND CSS_PROP_( direction, direction, Direction, 0, "", VARIANT_HK, - kDirectionKTable, - eStyleAnimType_Discrete) + kDirectionKTable) #endif // !defined(CSS_PROP_LIST_ONLY_COMPONENTS_OF_ALL_SHORTHAND) CSS_PROP_( display, display, Display, 0, "", VARIANT_HK, - kDisplayKTable, - eStyleAnimType_None) + kDisplayKTable) CSS_PROP_( dominant-baseline, dominant_baseline, DominantBaseline, 0, "", VARIANT_HK, - kDominantBaselineKTable, - eStyleAnimType_Discrete) + kDominantBaselineKTable) CSS_PROP_( empty-cells, empty_cells, EmptyCells, 0, "", VARIANT_HK, - kEmptyCellsKTable, - eStyleAnimType_Discrete) + kEmptyCellsKTable) CSS_PROP_( fill, fill, Fill, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - kContextPatternKTable, - eStyleAnimType_PaintServer) + kContextPatternKTable) CSS_PROP_( fill-opacity, fill_opacity, FillOpacity, 0, "", VARIANT_HN | VARIANT_KEYWORD, - kContextOpacityKTable, - eStyleAnimType_float) + kContextOpacityKTable) CSS_PROP_( fill-rule, fill_rule, FillRule, 0, "", VARIANT_HK, - kFillRuleKTable, - eStyleAnimType_Discrete) + kFillRuleKTable) CSS_PROP_( filter, filter, Filter, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Custom) + nullptr) CSS_PROP_SHORTHAND( flex, flex, Flex, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( flex-basis, flex_basis, FlexBasis, 0, "", // NOTE: The parsing implementation for the 'flex' shorthand property has // its own code to parse each subproperty. It does not depend on the // longhand parsing defined here. VARIANT_AHKLP | VARIANT_CALC, - kFlexBasisKTable, - eStyleAnimType_Coord) + kFlexBasisKTable) CSS_PROP_( flex-direction, flex_direction, FlexDirection, 0, "", VARIANT_HK, - kFlexDirectionKTable, - eStyleAnimType_Discrete) + kFlexDirectionKTable) CSS_PROP_SHORTHAND( flex-flow, flex_flow, FlexFlow, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( flex-grow, flex_grow, FlexGrow, 0, "", // NOTE: The parsing implementation for the 'flex' shorthand property has // its own code to parse each subproperty. It does not depend on the // longhand parsing defined here. VARIANT_HN, - nullptr, - eStyleAnimType_float) + nullptr) CSS_PROP_( flex-shrink, flex_shrink, FlexShrink, 0, "", // NOTE: The parsing implementation for the 'flex' shorthand property has // its own code to parse each subproperty. It does not depend on the // longhand parsing defined here. VARIANT_HN, - nullptr, - eStyleAnimType_float) + nullptr) CSS_PROP_( flex-wrap, flex_wrap, FlexWrap, 0, "", VARIANT_HK, - kFlexWrapKTable, - eStyleAnimType_Discrete) + kFlexWrapKTable) CSS_PROP_( float, float, CSS_PROP_PUBLIC_OR_PRIVATE(CssFloat, Float), 0, "", VARIANT_HK, - kFloatKTable, - eStyleAnimType_Discrete) + kFloatKTable) CSS_PROP_( -moz-float-edge, _moz_float_edge, CSS_PROP_DOMPROP_PREFIXED(FloatEdge), 0, "", VARIANT_HK, - kFloatEdgeKTable, - eStyleAnimType_Discrete) // XXX bug 3935 + kFloatEdgeKTable) // XXX bug 3935 CSS_PROP_( flood-color, flood_color, FloodColor, 0, "", VARIANT_HC, - nullptr, - eStyleAnimType_Color) + nullptr) CSS_PROP_( flood-opacity, flood_opacity, FloodOpacity, 0, "", VARIANT_HN, - nullptr, - eStyleAnimType_float) + nullptr) CSS_PROP_SHORTHAND( font, font, Font, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( font-family, font_family, FontFamily, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_( font-feature-settings, font_feature_settings, FontFeatureSettings, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_( font-kerning, font_kerning, FontKerning, 0, "", VARIANT_HK, - kFontKerningKTable, - eStyleAnimType_Discrete) + kFontKerningKTable) CSS_PROP_( font-language-override, font_language_override, FontLanguageOverride, 0, "", VARIANT_NORMAL | VARIANT_INHERIT | VARIANT_STRING, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_( font-optical-sizing, font_optical_sizing, FontOpticalSizing, 0, "layout.css.font-variations.enabled", VARIANT_HK, - kFontOpticalSizingKTable, - eStyleAnimType_None) + kFontOpticalSizingKTable) CSS_PROP_( font-size, font_size, FontSize, 0, "", VARIANT_HKLP | VARIANT_SYSFONT | VARIANT_CALC, - kFontSizeKTable, - // Note that mSize is the correct place for *reading* the computed value, - // but setting it requires setting mFont.size as well. - eStyleAnimType_nscoord) + kFontSizeKTable) CSS_PROP_( font-size-adjust, font_size_adjust, FontSizeAdjust, 0, "", VARIANT_HON | VARIANT_SYSFONT, - nullptr, - eStyleAnimType_float) + nullptr) #ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL CSS_PROP_( -moz-font-smoothing-background-color, _moz_font_smoothing_background_color, CSS_PROP_DOMPROP_PREFIXED(FontSmoothingBackgroundColor), CSS_PROPERTY_INTERNAL | CSS_PROPERTY_ENABLED_IN_UA_SHEETS_AND_CHROME, "", VARIANT_HC, - nullptr, - eStyleAnimType_Color) + nullptr) #endif // CSS_PROP_LIST_EXCLUDE_INTERNAL CSS_PROP_( font-stretch, font_stretch, FontStretch, 0, "", VARIANT_HK | VARIANT_SYSFONT, - kFontStretchKTable, - eStyleAnimType_Custom) + kFontStretchKTable) CSS_PROP_( font-style, font_style, FontStyle, 0, "", VARIANT_HK | VARIANT_SYSFONT, - kFontStyleKTable, - eStyleAnimType_Discrete) + kFontStyleKTable) CSS_PROP_( font-synthesis, font_synthesis, FontSynthesis, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "", 0, - kFontSynthesisKTable, - eStyleAnimType_Discrete) + kFontSynthesisKTable) CSS_PROP_SHORTHAND( font-variant, font_variant, FontVariant, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( font-variant-alternates, font_variant_alternates, FontVariantAlternates, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "", 0, - kFontVariantAlternatesKTable, - eStyleAnimType_Discrete) + kFontVariantAlternatesKTable) CSS_PROP_( font-variant-caps, font_variant_caps, FontVariantCaps, 0, "", VARIANT_HMK, - kFontVariantCapsKTable, - eStyleAnimType_Discrete) + kFontVariantCapsKTable) CSS_PROP_( font-variant-east-asian, font_variant_east_asian, FontVariantEastAsian, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "", 0, - kFontVariantEastAsianKTable, - eStyleAnimType_Discrete) + kFontVariantEastAsianKTable) CSS_PROP_( font-variant-ligatures, font_variant_ligatures, FontVariantLigatures, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "", 0, - kFontVariantLigaturesKTable, - eStyleAnimType_Discrete) + kFontVariantLigaturesKTable) CSS_PROP_( font-variant-numeric, font_variant_numeric, FontVariantNumeric, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "", 0, - kFontVariantNumericKTable, - eStyleAnimType_Discrete) + kFontVariantNumericKTable) CSS_PROP_( font-variant-position, font_variant_position, FontVariantPosition, 0, "", VARIANT_HMK, - kFontVariantPositionKTable, - eStyleAnimType_Discrete) + kFontVariantPositionKTable) CSS_PROP_( font-variation-settings, font_variation_settings, FontVariationSettings, - CSS_PROPERTY_VALUE_PARSER_FUNCTION | - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + CSS_PROPERTY_VALUE_PARSER_FUNCTION, "layout.css.font-variations.enabled", 0, - nullptr, - eStyleAnimType_Custom) + nullptr) CSS_PROP_( font-weight, font_weight, FontWeight, CSS_PROPERTY_VALUE_PARSER_FUNCTION, // NOTE: This property has range restrictions on interpolation! "", 0, - kFontWeightKTable, - eStyleAnimType_Custom) + kFontWeightKTable) CSS_PROP_( -moz-force-broken-image-icon, _moz_force_broken_image_icon, CSS_PROP_DOMPROP_PREFIXED(ForceBrokenImageIcon), 0, "", VARIANT_HI, - nullptr, - eStyleAnimType_Discrete) // bug 58646 + nullptr) // bug 58646 CSS_PROP_SHORTHAND( grid, grid, Grid, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_SHORTHAND( grid-area, @@ -1519,69 +1377,63 @@ CSS_PROP_SHORTHAND( "") CSS_PROP_( grid-auto-columns, grid_auto_columns, GridAutoColumns, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - kGridTrackBreadthKTable, - eStyleAnimType_Discrete) + kGridTrackBreadthKTable) CSS_PROP_( grid-auto-flow, grid_auto_flow, GridAutoFlow, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - kGridAutoFlowKTable, - eStyleAnimType_Discrete) + kGridAutoFlowKTable) CSS_PROP_( grid-auto-rows, grid_auto_rows, GridAutoRows, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - kGridTrackBreadthKTable, - eStyleAnimType_Discrete) + kGridTrackBreadthKTable) CSS_PROP_SHORTHAND( grid-column, grid_column, GridColumn, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( grid-column-end, grid_column_end, GridColumnEnd, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_( grid-column-gap, grid_column_gap, GridColumnGap, 0, "", VARIANT_HLP | VARIANT_CALC, - nullptr, - eStyleAnimType_Coord) + nullptr) CSS_PROP_( grid-column-start, grid_column_start, GridColumnStart, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_SHORTHAND( grid-gap, grid_gap, GridGap, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_SHORTHAND( grid-row, @@ -1591,771 +1443,690 @@ CSS_PROP_SHORTHAND( "") CSS_PROP_( grid-row-end, grid_row_end, GridRowEnd, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_( grid-row-gap, grid_row_gap, GridRowGap, 0, "", VARIANT_HLP | VARIANT_CALC, - nullptr, - eStyleAnimType_Coord) + nullptr) CSS_PROP_( grid-row-start, grid_row_start, GridRowStart, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_SHORTHAND( grid-template, grid_template, GridTemplate, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( grid-template-areas, grid_template_areas, GridTemplateAreas, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_( grid-template-columns, grid_template_columns, GridTemplateColumns, CSS_PROPERTY_PARSE_FUNCTION | CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", 0, - kGridTrackBreadthKTable, - eStyleAnimType_Discrete) + kGridTrackBreadthKTable) CSS_PROP_( grid-template-rows, grid_template_rows, GridTemplateRows, CSS_PROPERTY_PARSE_FUNCTION | CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", 0, - kGridTrackBreadthKTable, - eStyleAnimType_Discrete) + kGridTrackBreadthKTable) CSS_PROP_( height, height, Height, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_AHKLP | VARIANT_CALC, - kWidthKTable, - eStyleAnimType_Coord) + kWidthKTable) CSS_PROP_( hyphens, hyphens, Hyphens, 0, "", VARIANT_HK, - kHyphensKTable, - eStyleAnimType_Discrete) + kHyphensKTable) CSS_PROP_( image-orientation, image_orientation, ImageOrientation, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "layout.css.image-orientation.enabled", 0, - kImageOrientationKTable, - eStyleAnimType_Discrete) + kImageOrientationKTable) CSS_PROP_( -moz-image-region, _moz_image_region, CSS_PROP_DOMPROP_PREFIXED(ImageRegion), CSS_PROPERTY_PARSE_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Custom) + nullptr) CSS_PROP_( image-rendering, image_rendering, ImageRendering, 0, "", VARIANT_HK, - kImageRenderingKTable, - eStyleAnimType_Discrete) + kImageRenderingKTable) CSS_PROP_( ime-mode, ime_mode, ImeMode, 0, "", VARIANT_HK, - kIMEModeKTable, - eStyleAnimType_Discrete) + kIMEModeKTable) CSS_PROP_( initial-letter, initial_letter, InitialLetter, CSS_PROPERTY_PARSE_FUNCTION, "layout.css.initial-letter.enabled", 0, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_( inline-size, inline_size, InlineSize, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_AHKLP | VARIANT_CALC, - kWidthKTable, - eStyleAnimType_None) + kWidthKTable) CSS_PROP_( isolation, isolation, Isolation, 0, "layout.css.isolation.enabled", VARIANT_HK, - kIsolationKTable, - eStyleAnimType_Discrete) + kIsolationKTable) CSS_PROP_( justify-content, justify_content, JustifyContent, CSS_PROPERTY_PARSE_FUNCTION, "", VARIANT_HK, - kAutoCompletionAlignJustifyContent, - eStyleAnimType_Discrete) + kAutoCompletionAlignJustifyContent) CSS_PROP_( justify-items, justify_items, JustifyItems, CSS_PROPERTY_PARSE_FUNCTION, "", VARIANT_HK, // for auto-completion we use same values as justify-self: - kAutoCompletionAlignJustifySelf, - eStyleAnimType_Discrete) + kAutoCompletionAlignJustifySelf) CSS_PROP_( justify-self, justify_self, JustifySelf, CSS_PROPERTY_PARSE_FUNCTION, "", VARIANT_HK, - kAutoCompletionAlignJustifySelf, - eStyleAnimType_Discrete) + kAutoCompletionAlignJustifySelf) #ifndef CSS_PROP_LIST_ONLY_COMPONENTS_OF_ALL_SHORTHAND #ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL CSS_PROP_( -x-lang, _x_lang, Lang, CSS_PROPERTY_INTERNAL | CSS_PROPERTY_PARSE_INACCESSIBLE, "", 0, - nullptr, - eStyleAnimType_None) + nullptr) #endif // CSS_PROP_LIST_EXCLUDE_INTERNAL #endif // CSS_PROP_LIST_ONLY_COMPONENTS_OF_ALL_SHORTHAND CSS_PROP_( left, left, Left, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_AHLP | VARIANT_CALC, - nullptr, - eStyleAnimType_Sides_Left) + nullptr) CSS_PROP_( letter-spacing, letter_spacing, LetterSpacing, 0, "", VARIANT_HL | VARIANT_NORMAL | VARIANT_CALC, - nullptr, - eStyleAnimType_Coord) + nullptr) CSS_PROP_( lighting-color, lighting_color, LightingColor, 0, "", VARIANT_HC, - nullptr, - eStyleAnimType_Color) + nullptr) CSS_PROP_( line-height, line_height, LineHeight, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_HLPN | VARIANT_KEYWORD | VARIANT_NORMAL | VARIANT_SYSFONT | VARIANT_CALC, - kLineHeightKTable, - eStyleAnimType_Coord) + kLineHeightKTable) CSS_PROP_SHORTHAND( list-style, list_style, ListStyle, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( list-style-image, list_style_image, ListStyleImage, 0, "", VARIANT_HUO, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_( list-style-position, list_style_position, ListStylePosition, 0, "", VARIANT_HK, - kListStylePositionKTable, - eStyleAnimType_Discrete) + kListStylePositionKTable) CSS_PROP_( list-style-type, list_style_type, ListStyleType, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_SHORTHAND( margin, margin, Margin, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( margin-block-end, margin_block_end, MarginBlockEnd, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_AHLP | VARIANT_CALC, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( margin-block-start, margin_block_start, MarginBlockStart, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_AHLP | VARIANT_CALC, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( margin-bottom, margin_bottom, MarginBottom, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_AHLP | VARIANT_CALC, - nullptr, - eStyleAnimType_Sides_Bottom) + nullptr) CSS_PROP_( margin-inline-end, margin_inline_end, MarginInlineEnd, - 0, + CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_AHLP | VARIANT_CALC, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( margin-inline-start, margin_inline_start, MarginInlineStart, - 0, + CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_AHLP | VARIANT_CALC, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( margin-left, margin_left, MarginLeft, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_AHLP | VARIANT_CALC, - nullptr, - eStyleAnimType_Sides_Left) + nullptr) CSS_PROP_( margin-right, margin_right, MarginRight, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_AHLP | VARIANT_CALC, - nullptr, - eStyleAnimType_Sides_Right) + nullptr) CSS_PROP_( margin-top, margin_top, MarginTop, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_AHLP | VARIANT_CALC, - nullptr, - eStyleAnimType_Sides_Top) + nullptr) CSS_PROP_SHORTHAND( marker, marker, Marker, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( marker-end, marker_end, MarkerEnd, 0, "", VARIANT_HUO, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_( marker-mid, marker_mid, MarkerMid, 0, "", VARIANT_HUO, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_( marker-start, marker_start, MarkerStart, 0, "", VARIANT_HUO, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_SHORTHAND( mask, mask, Mask, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( mask-clip, mask_clip, MaskClip, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "", VARIANT_KEYWORD, // used by list parsing - kMaskClipKTable, - eStyleAnimType_Discrete) + kMaskClipKTable) CSS_PROP_( mask-composite, mask_composite, MaskComposite, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "", VARIANT_KEYWORD, // used by list parsing - kImageLayerCompositeKTable, - eStyleAnimType_Discrete) + kImageLayerCompositeKTable) CSS_PROP_( mask-image, mask_image, MaskImage, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "", VARIANT_IMAGE, // used by list parsing - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_( mask-mode, mask_mode, MaskMode, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "", VARIANT_KEYWORD, // used by list parsing - kImageLayerModeKTable, - eStyleAnimType_Discrete) + kImageLayerModeKTable) CSS_PROP_( mask-origin, mask_origin, MaskOrigin, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "", VARIANT_KEYWORD, // used by list parsing - kMaskOriginKTable, - eStyleAnimType_Discrete) + kMaskOriginKTable) CSS_PROP_SHORTHAND( mask-position, mask_position, MaskPosition, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( mask-position-x, mask_position_x, MaskPositionX, - CSS_PROPERTY_PARSE_FUNCTION | - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + CSS_PROPERTY_PARSE_FUNCTION, "", 0, - kImageLayerPositionKTable, - eStyleAnimType_Custom) + kImageLayerPositionKTable) CSS_PROP_( mask-position-y, mask_position_y, MaskPositionY, - CSS_PROPERTY_PARSE_FUNCTION | - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + CSS_PROPERTY_PARSE_FUNCTION, "", 0, - kImageLayerPositionKTable, - eStyleAnimType_Custom) + kImageLayerPositionKTable) CSS_PROP_( mask-repeat, mask_repeat, MaskRepeat, - CSS_PROPERTY_PARSE_FUNCTION | - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + CSS_PROPERTY_PARSE_FUNCTION, "", VARIANT_KEYWORD, // used by list parsing - kImageLayerRepeatKTable, - eStyleAnimType_Discrete) + kImageLayerRepeatKTable) CSS_PROP_( mask-size, mask_size, MaskSize, - CSS_PROPERTY_PARSE_FUNCTION | - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + CSS_PROPERTY_PARSE_FUNCTION, "", 0, - kImageLayerSizeKTable, - eStyleAnimType_Custom) + kImageLayerSizeKTable) CSS_PROP_( mask-type, mask_type, MaskType, 0, "", VARIANT_HK, - kMaskTypeKTable, - eStyleAnimType_Discrete) + kMaskTypeKTable) #ifndef CSS_PROP_LIST_ONLY_COMPONENTS_OF_ALL_SHORTHAND #ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL CSS_PROP_( -moz-math-display, _moz_math_display, MathDisplay, CSS_PROPERTY_INTERNAL | CSS_PROPERTY_ENABLED_IN_UA_SHEETS, "", VARIANT_HK, - kMathDisplayKTable, - eStyleAnimType_None) + kMathDisplayKTable) CSS_PROP_( -moz-math-variant, _moz_math_variant, MathVariant, CSS_PROPERTY_INTERNAL | CSS_PROPERTY_PARSE_INACCESSIBLE, "", VARIANT_HK, - kMathVariantKTable, - eStyleAnimType_None) + kMathVariantKTable) #endif // CSS_PROP_LIST_EXCLUDE_INTERNAL #endif // CSS_PROP_LIST_ONLY_COMPONENTS_OF_ALL_SHORTHAND CSS_PROP_( max-block-size, max_block_size, MaxBlockSize, - CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, + 0, "", VARIANT_HLPO | VARIANT_CALC, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( max-height, max_height, MaxHeight, 0, "", VARIANT_HKLPO | VARIANT_CALC, - kWidthKTable, - eStyleAnimType_Coord) + kWidthKTable) CSS_PROP_( max-inline-size, max_inline_size, MaxInlineSize, - CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, + 0, "", VARIANT_HKLPO | VARIANT_CALC, - kWidthKTable, - eStyleAnimType_None) + kWidthKTable) CSS_PROP_( max-width, max_width, MaxWidth, 0, "", VARIANT_HKLPO | VARIANT_CALC, - kWidthKTable, - eStyleAnimType_Coord) + kWidthKTable) CSS_PROP_( min-block-size, min_block_size, MinBlockSize, - CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, + 0, "", VARIANT_AHLP | VARIANT_CALC, - nullptr, - eStyleAnimType_None) + nullptr) #ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL CSS_PROP_( -moz-min-font-size-ratio, _moz_min_font_size_ratio, CSS_PROP_DOMPROP_PREFIXED(MinFontSizeRatio), CSS_PROPERTY_INTERNAL | CSS_PROPERTY_ENABLED_IN_UA_SHEETS, "", VARIANT_INHERIT | VARIANT_PERCENT, - nullptr, - eStyleAnimType_None) + nullptr) #endif // CSS_PROP_LIST_EXCLUDE_INTERNAL CSS_PROP_( min-height, min_height, MinHeight, 0, "", VARIANT_AHKLP | VARIANT_CALC, - kWidthKTable, - eStyleAnimType_Coord) + kWidthKTable) CSS_PROP_( min-inline-size, min_inline_size, MinInlineSize, - CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, + 0, "", VARIANT_AHKLP | VARIANT_CALC, - kWidthKTable, - eStyleAnimType_None) + kWidthKTable) CSS_PROP_( min-width, min_width, MinWidth, 0, "", VARIANT_AHKLP | VARIANT_CALC, - kWidthKTable, - eStyleAnimType_Coord) + kWidthKTable) CSS_PROP_( mix-blend-mode, mix_blend_mode, MixBlendMode, 0, "layout.css.mix-blend-mode.enabled", VARIANT_HK, - kBlendModeKTable, - eStyleAnimType_Discrete) + kBlendModeKTable) CSS_PROP_( object-fit, object_fit, ObjectFit, 0, "", VARIANT_HK, - kObjectFitKTable, - eStyleAnimType_Discrete) + kObjectFitKTable) CSS_PROP_( object-position, object_position, ObjectPosition, CSS_PROPERTY_PARSE_FUNCTION, "", VARIANT_CALC, - kImageLayerPositionKTable, - eStyleAnimType_Custom) + kImageLayerPositionKTable) CSS_PROP_( offset-block-end, offset_block_end, OffsetBlockEnd, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_AHLP | VARIANT_CALC, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( offset-block-start, offset_block_start, OffsetBlockStart, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_AHLP | VARIANT_CALC, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( offset-inline-end, offset_inline_end, OffsetInlineEnd, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_AHLP | VARIANT_CALC, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( offset-inline-start, offset_inline_start, OffsetInlineStart, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_AHLP | VARIANT_CALC, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( opacity, opacity, Opacity, CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR, "", VARIANT_HN, - nullptr, - eStyleAnimType_float) + nullptr) CSS_PROP_( order, order, Order, 0, "", VARIANT_HI, - nullptr, - eStyleAnimType_Custom) // <integer> + nullptr) // <integer> CSS_PROP_( -moz-orient, _moz_orient, CSS_PROP_DOMPROP_PREFIXED(Orient), 0, "", VARIANT_HK, - kOrientKTable, - eStyleAnimType_Discrete) + kOrientKTable) CSS_PROP_( -moz-osx-font-smoothing, _moz_osx_font_smoothing, CSS_PROP_DOMPROP_PREFIXED(OsxFontSmoothing), 0, "layout.css.osx-font-smoothing.enabled", VARIANT_HK, - kFontSmoothingKTable, - eStyleAnimType_Discrete) + kFontSmoothingKTable) CSS_PROP_SHORTHAND( outline, outline, Outline, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( outline-color, outline_color, OutlineColor, 0, "", VARIANT_HC, - nullptr, - eStyleAnimType_ComplexColor) + nullptr) CSS_PROP_( outline-offset, outline_offset, OutlineOffset, 0, "", VARIANT_HL | VARIANT_CALC, - nullptr, - eStyleAnimType_nscoord) + nullptr) CSS_PROP_SHORTHAND( -moz-outline-radius, _moz_outline_radius, CSS_PROP_DOMPROP_PREFIXED(OutlineRadius), CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( -moz-outline-radius-bottomleft, _moz_outline_radius_bottomleft, CSS_PROP_DOMPROP_PREFIXED(OutlineRadiusBottomleft), CSS_PROPERTY_PARSE_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Corner_BottomLeft) + nullptr) CSS_PROP_( -moz-outline-radius-bottomright, _moz_outline_radius_bottomright, CSS_PROP_DOMPROP_PREFIXED(OutlineRadiusBottomright), CSS_PROPERTY_PARSE_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Corner_BottomRight) + nullptr) CSS_PROP_( -moz-outline-radius-topleft, _moz_outline_radius_topleft, CSS_PROP_DOMPROP_PREFIXED(OutlineRadiusTopleft), CSS_PROPERTY_PARSE_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Corner_TopLeft) + nullptr) CSS_PROP_( -moz-outline-radius-topright, _moz_outline_radius_topright, CSS_PROP_DOMPROP_PREFIXED(OutlineRadiusTopright), CSS_PROPERTY_PARSE_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Corner_TopRight) + nullptr) CSS_PROP_( outline-style, outline_style, OutlineStyle, 0, "", VARIANT_HK, - kOutlineStyleKTable, - eStyleAnimType_Discrete) + kOutlineStyleKTable) CSS_PROP_( outline-width, outline_width, OutlineWidth, 0, "", VARIANT_HKL | VARIANT_CALC, - kBorderWidthKTable, - eStyleAnimType_nscoord) + kBorderWidthKTable) CSS_PROP_SHORTHAND( overflow, overflow, Overflow, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_SHORTHAND( overflow-clip-box, @@ -2366,212 +2137,191 @@ CSS_PROP_SHORTHAND( "layout.css.overflow-clip-box.enabled") CSS_PROP_( overflow-clip-box-block, overflow_clip_box_block, OverflowClipBoxBlock, CSS_PROPERTY_ENABLED_IN_UA_SHEETS, "layout.css.overflow-clip-box.enabled", VARIANT_HK, - kOverflowClipBoxKTable, - eStyleAnimType_Discrete) + kOverflowClipBoxKTable) CSS_PROP_( overflow-clip-box-inline, overflow_clip_box_inline, OverflowClipBoxInline, CSS_PROPERTY_ENABLED_IN_UA_SHEETS, "layout.css.overflow-clip-box.enabled", VARIANT_HK, - kOverflowClipBoxKTable, - eStyleAnimType_Discrete) + kOverflowClipBoxKTable) CSS_PROP_( overflow-wrap, overflow_wrap, OverflowWrap, 0, "", VARIANT_HK, - kOverflowWrapKTable, - eStyleAnimType_Discrete) + kOverflowWrapKTable) CSS_PROP_( overflow-x, overflow_x, OverflowX, 0, "", VARIANT_HK, - kOverflowSubKTable, - eStyleAnimType_Discrete) + kOverflowSubKTable) CSS_PROP_( overflow-y, overflow_y, OverflowY, 0, "", VARIANT_HK, - kOverflowSubKTable, - eStyleAnimType_Discrete) + kOverflowSubKTable) CSS_PROP_SHORTHAND( overscroll-behavior, overscroll_behavior, OverscrollBehavior, CSS_PROPERTY_PARSE_FUNCTION, "layout.css.overscroll-behavior.enabled") CSS_PROP_( overscroll-behavior-x, overscroll_behavior_x, OverscrollBehaviorX, 0, "layout.css.overscroll-behavior.enabled", VARIANT_HK, - kOverscrollBehaviorKTable, - eStyleAnimType_Discrete) + kOverscrollBehaviorKTable) CSS_PROP_( overscroll-behavior-y, overscroll_behavior_y, OverscrollBehaviorY, 0, "layout.css.overscroll-behavior.enabled", VARIANT_HK, - kOverscrollBehaviorKTable, - eStyleAnimType_Discrete) + kOverscrollBehaviorKTable) CSS_PROP_SHORTHAND( padding, padding, Padding, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( padding-block-end, padding_block_end, PaddingBlockEnd, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_HLP | VARIANT_CALC, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( padding-block-start, padding_block_start, PaddingBlockStart, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_HLP | VARIANT_CALC, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( padding-bottom, padding_bottom, PaddingBottom, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_HLP | VARIANT_CALC, - nullptr, - eStyleAnimType_Sides_Bottom) + nullptr) CSS_PROP_( padding-inline-end, padding_inline_end, PaddingInlineEnd, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_HLP | VARIANT_CALC, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( padding-inline-start, padding_inline_start, PaddingInlineStart, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_HLP | VARIANT_CALC, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( padding-left, padding_left, PaddingLeft, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_HLP | VARIANT_CALC, - nullptr, - eStyleAnimType_Sides_Left) + nullptr) CSS_PROP_( padding-right, padding_right, PaddingRight, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_HLP | VARIANT_CALC, - nullptr, - eStyleAnimType_Sides_Right) + nullptr) CSS_PROP_( padding-top, padding_top, PaddingTop, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_HLP | VARIANT_CALC, - nullptr, - eStyleAnimType_Sides_Top) + nullptr) CSS_PROP_( page-break-after, page_break_after, PageBreakAfter, 0, "", VARIANT_HK, - kPageBreakKTable, - eStyleAnimType_Discrete) // temp fix for bug 24000 + kPageBreakKTable) // temp fix for bug 24000 CSS_PROP_( page-break-before, page_break_before, PageBreakBefore, 0, "", VARIANT_HK, - kPageBreakKTable, - eStyleAnimType_Discrete) // temp fix for bug 24000 + kPageBreakKTable) // temp fix for bug 24000 CSS_PROP_( page-break-inside, page_break_inside, PageBreakInside, 0, "", VARIANT_HK, - kPageBreakInsideKTable, - eStyleAnimType_Discrete) + kPageBreakInsideKTable) CSS_PROP_( paint-order, paint_order, PaintOrder, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_( perspective, perspective, Perspective, 0, "", VARIANT_NONE | VARIANT_INHERIT | VARIANT_LENGTH | VARIANT_NONNEGATIVE_DIMENSION, - nullptr, - eStyleAnimType_Coord) + nullptr) CSS_PROP_( perspective-origin, perspective_origin, PerspectiveOrigin, CSS_PROPERTY_PARSE_FUNCTION | CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_CALC, - kImageLayerPositionKTable, - eStyleAnimType_Custom) + kImageLayerPositionKTable) CSS_PROP_SHORTHAND( place-content, place_content, PlaceContent, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_SHORTHAND( place-items, @@ -2587,902 +2337,805 @@ CSS_PROP_SHORTHAND( "") CSS_PROP_( pointer-events, pointer_events, PointerEvents, 0, "", VARIANT_HK, - kPointerEventsKTable, - eStyleAnimType_Discrete) + kPointerEventsKTable) CSS_PROP_( position, position, Position, 0, "", VARIANT_HK, - kPositionKTable, - eStyleAnimType_Discrete) + kPositionKTable) CSS_PROP_( quotes, quotes, Quotes, CSS_PROPERTY_PARSE_FUNCTION, "", VARIANT_HOS, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_( resize, resize, Resize, 0, "", VARIANT_HK, - kResizeKTable, - eStyleAnimType_Discrete) + kResizeKTable) CSS_PROP_( right, right, Right, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_AHLP | VARIANT_CALC, - nullptr, - eStyleAnimType_Sides_Right) + nullptr) CSS_PROP_( rotate, rotate, Rotate, - CSS_PROPERTY_PARSE_FUNCTION | - CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, + CSS_PROPERTY_PARSE_FUNCTION, "layout.css.individual-transform.enabled", 0, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( ruby-align, ruby_align, RubyAlign, 0, "", VARIANT_HK, - kRubyAlignKTable, - eStyleAnimType_Discrete) + kRubyAlignKTable) CSS_PROP_( ruby-position, ruby_position, RubyPosition, 0, "", VARIANT_HK, - kRubyPositionKTable, - eStyleAnimType_Discrete) + kRubyPositionKTable) CSS_PROP_( scale, scale, Scale, - CSS_PROPERTY_PARSE_FUNCTION | - CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, + CSS_PROPERTY_PARSE_FUNCTION, "layout.css.individual-transform.enabled", 0, - nullptr, - eStyleAnimType_None) + nullptr) #ifndef CSS_PROP_LIST_ONLY_COMPONENTS_OF_ALL_SHORTHAND #ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL CSS_PROP_( -moz-script-level, _moz_script_level, ScriptLevel, // We only allow 'script-level' when unsafe rules are enabled, because // otherwise it could interfere with rulenode optimizations if used in // a non-MathML-enabled document. CSS_PROPERTY_INTERNAL | CSS_PROPERTY_ENABLED_IN_UA_SHEETS, "", // script-level can take Auto, Integer and Number values, but only Auto // ("increment if parent is not in displaystyle") and Integer // ("relative") values can be specified in a style sheet. VARIANT_AHI, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( -moz-script-min-size, _moz_script_min_size, ScriptMinSize, CSS_PROPERTY_INTERNAL | CSS_PROPERTY_PARSE_INACCESSIBLE, "", 0, - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( -moz-script-size-multiplier, _moz_script_size_multiplier, ScriptSizeMultiplier, CSS_PROPERTY_INTERNAL | CSS_PROPERTY_PARSE_INACCESSIBLE, "", 0, - nullptr, - eStyleAnimType_None) + nullptr) #endif // CSS_PROP_LIST_EXCLUDE_INTERNAL #endif // CSS_PROP_LIST_ONLY_COMPONENTS_OF_ALL_SHORTHAND CSS_PROP_( scroll-behavior, scroll_behavior, ScrollBehavior, 0, "layout.css.scroll-behavior.property-enabled", VARIANT_HK, - kScrollBehaviorKTable, - eStyleAnimType_Discrete) + kScrollBehaviorKTable) CSS_PROP_( scroll-snap-coordinate, scroll_snap_coordinate, ScrollSnapCoordinate, - CSS_PROPERTY_VALUE_PARSER_FUNCTION | - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + CSS_PROPERTY_VALUE_PARSER_FUNCTION, "layout.css.scroll-snap.enabled", 0, - kImageLayerPositionKTable, - eStyleAnimType_Discrete) + kImageLayerPositionKTable) CSS_PROP_( scroll-snap-destination, scroll_snap_destination, ScrollSnapDestination, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "layout.css.scroll-snap.enabled", 0, - kImageLayerPositionKTable, - eStyleAnimType_Discrete) + kImageLayerPositionKTable) CSS_PROP_( scroll-snap-points-x, scroll_snap_points_x, ScrollSnapPointsX, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "layout.css.scroll-snap.enabled", 0, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_( scroll-snap-points-y, scroll_snap_points_y, ScrollSnapPointsY, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "layout.css.scroll-snap.enabled", 0, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_SHORTHAND( scroll-snap-type, scroll_snap_type, ScrollSnapType, CSS_PROPERTY_PARSE_FUNCTION, "layout.css.scroll-snap.enabled") CSS_PROP_( scroll-snap-type-x, scroll_snap_type_x, ScrollSnapTypeX, 0, "layout.css.scroll-snap.enabled", VARIANT_HK, - kScrollSnapTypeKTable, - eStyleAnimType_Discrete) + kScrollSnapTypeKTable) CSS_PROP_( scroll-snap-type-y, scroll_snap_type_y, ScrollSnapTypeY, 0, "layout.css.scroll-snap.enabled", VARIANT_HK, - kScrollSnapTypeKTable, - eStyleAnimType_Discrete) + kScrollSnapTypeKTable) CSS_PROP_( shape-image-threshold, shape_image_threshold, ShapeImageThreshold, 0, "layout.css.shape-outside.enabled", VARIANT_HN, - nullptr, - eStyleAnimType_float) + nullptr) CSS_PROP_( shape-outside, shape_outside, ShapeOutside, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "layout.css.shape-outside.enabled", 0, - nullptr, - eStyleAnimType_Custom) + nullptr) CSS_PROP_( shape-rendering, shape_rendering, ShapeRendering, 0, "", VARIANT_HK, - kShapeRenderingKTable, - eStyleAnimType_Discrete) + kShapeRenderingKTable) #ifndef CSS_PROP_LIST_ONLY_COMPONENTS_OF_ALL_SHORTHAND #ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL CSS_PROP_( -x-span, _x_span, Span, CSS_PROPERTY_INTERNAL | CSS_PROPERTY_PARSE_INACCESSIBLE, "", 0, - nullptr, - eStyleAnimType_None) + nullptr) #endif // CSS_PROP_LIST_EXCLUDE_INTERNAL #endif // CSS_PROP_LIST_ONLY_COMPONENTS_OF_ALL_SHORTHAND CSS_PROP_( -moz-stack-sizing, _moz_stack_sizing, CSS_PROP_DOMPROP_PREFIXED(StackSizing), 0, "", VARIANT_HK, - kStackSizingKTable, - eStyleAnimType_Discrete) + kStackSizingKTable) CSS_PROP_( stop-color, stop_color, StopColor, 0, "", VARIANT_HC, - nullptr, - eStyleAnimType_Color) + nullptr) CSS_PROP_( stop-opacity, stop_opacity, StopOpacity, 0, "", VARIANT_HN, - nullptr, - eStyleAnimType_float) + nullptr) CSS_PROP_( stroke, stroke, Stroke, CSS_PROPERTY_PARSE_FUNCTION, "", 0, - kContextPatternKTable, - eStyleAnimType_PaintServer) + kContextPatternKTable) CSS_PROP_( stroke-dasharray, stroke_dasharray, StrokeDasharray, - CSS_PROPERTY_PARSE_FUNCTION | - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + CSS_PROPERTY_PARSE_FUNCTION, // NOTE: Internal values have range restrictions. "", 0, - kStrokeContextValueKTable, - eStyleAnimType_Custom) + kStrokeContextValueKTable) CSS_PROP_( stroke-dashoffset, stroke_dashoffset, StrokeDashoffset, 0, "", VARIANT_HLPN | VARIANT_OPENTYPE_SVG_KEYWORD, - kStrokeContextValueKTable, - eStyleAnimType_Coord) + kStrokeContextValueKTable) CSS_PROP_( stroke-linecap, stroke_linecap, StrokeLinecap, 0, "", VARIANT_HK, - kStrokeLinecapKTable, - eStyleAnimType_Discrete) + kStrokeLinecapKTable) CSS_PROP_( stroke-linejoin, stroke_linejoin, StrokeLinejoin, 0, "", VARIANT_HK, - kStrokeLinejoinKTable, - eStyleAnimType_Discrete) + kStrokeLinejoinKTable) CSS_PROP_( stroke-miterlimit, stroke_miterlimit, StrokeMiterlimit, 0, "", VARIANT_HN, - nullptr, - eStyleAnimType_float) + nullptr) CSS_PROP_( stroke-opacity, stroke_opacity, StrokeOpacity, 0, "", VARIANT_HN | VARIANT_KEYWORD, - kContextOpacityKTable, - eStyleAnimType_float) + kContextOpacityKTable) CSS_PROP_( stroke-width, stroke_width, StrokeWidth, 0, "", VARIANT_HLPN | VARIANT_OPENTYPE_SVG_KEYWORD, - kStrokeContextValueKTable, - eStyleAnimType_Coord) + kStrokeContextValueKTable) CSS_PROP_( -moz-tab-size, _moz_tab_size, CSS_PROP_DOMPROP_PREFIXED(TabSize), 0, "", VARIANT_INHERIT | VARIANT_LNCALC, - nullptr, - eStyleAnimType_Coord) + nullptr) CSS_PROP_( table-layout, table_layout, TableLayout, 0, "", VARIANT_HK, - kTableLayoutKTable, - eStyleAnimType_Discrete) + kTableLayoutKTable) CSS_PROP_( text-align, text_align, TextAlign, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "", // When we support aligning on a string, we can parse text-align // as a string.... VARIANT_HK /* | VARIANT_STRING */, - kTextAlignKTable, - eStyleAnimType_Discrete) + kTextAlignKTable) CSS_PROP_( text-align-last, text_align_last, TextAlignLast, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "", VARIANT_HK, - kTextAlignLastKTable, - eStyleAnimType_Discrete) + kTextAlignLastKTable) CSS_PROP_( text-anchor, text_anchor, TextAnchor, 0, "", VARIANT_HK, - kTextAnchorKTable, - eStyleAnimType_Discrete) + kTextAnchorKTable) CSS_PROP_( text-combine-upright, text_combine_upright, TextCombineUpright, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "layout.css.text-combine-upright.enabled", 0, - kTextCombineUprightKTable, - eStyleAnimType_Discrete) + kTextCombineUprightKTable) CSS_PROP_SHORTHAND( text-decoration, text_decoration, TextDecoration, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( text-decoration-color, text_decoration_color, TextDecorationColor, 0, "", VARIANT_HC, - nullptr, - eStyleAnimType_ComplexColor) + nullptr) CSS_PROP_( text-decoration-line, text_decoration_line, TextDecorationLine, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "", 0, - kTextDecorationLineKTable, - eStyleAnimType_Discrete) + kTextDecorationLineKTable) CSS_PROP_( text-decoration-style, text_decoration_style, TextDecorationStyle, 0, "", VARIANT_HK, - kTextDecorationStyleKTable, - eStyleAnimType_Discrete) + kTextDecorationStyleKTable) CSS_PROP_SHORTHAND( text-emphasis, text_emphasis, TextEmphasis, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( text-emphasis-color, text_emphasis_color, TextEmphasisColor, 0, "", VARIANT_HC, - nullptr, - eStyleAnimType_ComplexColor) + nullptr) CSS_PROP_( text-emphasis-position, text_emphasis_position, TextEmphasisPosition, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "", 0, - kTextEmphasisPositionKTable, - eStyleAnimType_Discrete) + kTextEmphasisPositionKTable) CSS_PROP_( text-emphasis-style, text_emphasis_style, TextEmphasisStyle, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_( -webkit-text-fill-color, _webkit_text_fill_color, WebkitTextFillColor, 0, "layout.css.prefixes.webkit", VARIANT_HC, - nullptr, - eStyleAnimType_ComplexColor) + nullptr) CSS_PROP_( text-indent, text_indent, TextIndent, 0, "", VARIANT_HLP | VARIANT_CALC, - nullptr, - eStyleAnimType_Coord) + nullptr) CSS_PROP_( text-justify, text_justify, TextJustify, 0, "layout.css.text-justify.enabled", VARIANT_HK, - kTextJustifyKTable, - eStyleAnimType_Discrete) + kTextJustifyKTable) CSS_PROP_( text-orientation, text_orientation, TextOrientation, 0, "", VARIANT_HK, - kTextOrientationKTable, - eStyleAnimType_Discrete) + kTextOrientationKTable) CSS_PROP_( text-overflow, text_overflow, TextOverflow, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "", 0, - kTextOverflowKTable, - eStyleAnimType_Discrete) + kTextOverflowKTable) CSS_PROP_( text-rendering, text_rendering, TextRendering, 0, "", VARIANT_HK, - kTextRenderingKTable, - eStyleAnimType_Discrete) + kTextRenderingKTable) CSS_PROP_( text-shadow, text_shadow, TextShadow, - CSS_PROPERTY_PARSE_FUNCTION | - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + CSS_PROPERTY_PARSE_FUNCTION, // NOTE: some components must be nonnegative "", VARIANT_COLOR | VARIANT_LENGTH | VARIANT_CALC | VARIANT_INHERIT | VARIANT_NONE, - nullptr, - eStyleAnimType_Shadow) + nullptr) CSS_PROP_( -moz-text-size-adjust, _moz_text_size_adjust, CSS_PROP_DOMPROP_PREFIXED(TextSizeAdjust), 0, "", VARIANT_HK, - kTextSizeAdjustKTable, - eStyleAnimType_Discrete) + kTextSizeAdjustKTable) CSS_PROP_SHORTHAND( -webkit-text-stroke, _webkit_text_stroke, WebkitTextStroke, CSS_PROPERTY_PARSE_FUNCTION, "layout.css.prefixes.webkit") CSS_PROP_( -webkit-text-stroke-color, _webkit_text_stroke_color, WebkitTextStrokeColor, 0, "layout.css.prefixes.webkit", VARIANT_HC, - nullptr, - eStyleAnimType_ComplexColor) + nullptr) CSS_PROP_( -webkit-text-stroke-width, _webkit_text_stroke_width, WebkitTextStrokeWidth, 0, "layout.css.prefixes.webkit", VARIANT_HKL | VARIANT_CALC, - kBorderWidthKTable, - eStyleAnimType_Discrete) + kBorderWidthKTable) CSS_PROP_( text-transform, text_transform, TextTransform, 0, "", VARIANT_HK, - kTextTransformKTable, - eStyleAnimType_Discrete) + kTextTransformKTable) #ifndef CSS_PROP_LIST_ONLY_COMPONENTS_OF_ALL_SHORTHAND #ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL CSS_PROP_( -x-text-zoom, _x_text_zoom, TextZoom, CSS_PROPERTY_INTERNAL | CSS_PROPERTY_PARSE_INACCESSIBLE, "", 0, - nullptr, - eStyleAnimType_None) + nullptr) #endif // CSS_PROP_LIST_EXCLUDE_INTERNAL #endif // CSS_PROP_LIST_ONLY_COMPONENTS_OF_ALL_SHORTHAND CSS_PROP_( top, top, Top, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_AHLP | VARIANT_CALC, - nullptr, - eStyleAnimType_Sides_Top) + nullptr) #ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL CSS_PROP_( -moz-top-layer, _moz_top_layer, CSS_PROP_DOMPROP_PREFIXED(TopLayer), CSS_PROPERTY_INTERNAL | CSS_PROPERTY_ENABLED_IN_UA_SHEETS, "", VARIANT_HK, - kTopLayerKTable, - eStyleAnimType_None) + kTopLayerKTable) #endif // CSS_PROP_LIST_EXCLUDE_INTERNAL CSS_PROP_( touch-action, touch_action, TouchAction, CSS_PROPERTY_VALUE_PARSER_FUNCTION, "layout.css.touch_action.enabled", VARIANT_HK, - kTouchActionKTable, - eStyleAnimType_Discrete) + kTouchActionKTable) CSS_PROP_( transform, transform, Transform, CSS_PROPERTY_PARSE_FUNCTION | CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH | CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR, "", 0, - nullptr, - eStyleAnimType_Custom) + nullptr) CSS_PROP_( transform-box, transform_box, TransformBox, 0, "svg.transform-box.enabled", VARIANT_HK, - kTransformBoxKTable, - eStyleAnimType_Discrete) + kTransformBoxKTable) CSS_PROP_( transform-origin, transform_origin, TransformOrigin, CSS_PROPERTY_PARSE_FUNCTION | CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", 0, - kImageLayerPositionKTable, - eStyleAnimType_Custom) + kImageLayerPositionKTable) CSS_PROP_( transform-style, transform_style, TransformStyle, 0, "", VARIANT_HK, - kTransformStyleKTable, - eStyleAnimType_Discrete) + kTransformStyleKTable) CSS_PROP_SHORTHAND( transition, transition, Transition, CSS_PROPERTY_PARSE_FUNCTION, "") CSS_PROP_( transition-delay, transition_delay, TransitionDelay, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "", VARIANT_TIME, // used by list parsing - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( transition-duration, transition_duration, TransitionDuration, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "", VARIANT_TIME | VARIANT_NONNEGATIVE_DIMENSION, // used by list parsing - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( transition-property, transition_property, TransitionProperty, - CSS_PROPERTY_PARSE_FUNCTION | - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + CSS_PROPERTY_PARSE_FUNCTION, "", VARIANT_IDENTIFIER | VARIANT_NONE | VARIANT_ALL, // used only in shorthand - nullptr, - eStyleAnimType_None) + nullptr) CSS_PROP_( transition-timing-function, transition_timing_function, TransitionTimingFunction, - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + 0, "", VARIANT_KEYWORD | VARIANT_TIMING_FUNCTION, // used by list parsing - kTransitionTimingFunctionKTable, - eStyleAnimType_None) + kTransitionTimingFunctionKTable) CSS_PROP_( translate, translate, Translate, CSS_PROPERTY_PARSE_FUNCTION | CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "layout.css.individual-transform.enabled", 0, - nullptr, - eStyleAnimType_None) + nullptr) #ifndef CSS_PROP_LIST_ONLY_COMPONENTS_OF_ALL_SHORTHAND CSS_PROP_( unicode-bidi, unicode_bidi, UnicodeBidi, 0, "", VARIANT_HK, - kUnicodeBidiKTable, - eStyleAnimType_Discrete) + kUnicodeBidiKTable) #endif // CSS_PROP_LIST_ONLY_COMPONENTS_OF_ALL_SHORTHAND CSS_PROP_( -moz-user-focus, _moz_user_focus, CSS_PROP_DOMPROP_PREFIXED(UserFocus), 0, "", VARIANT_HK, - kUserFocusKTable, - eStyleAnimType_Discrete) // XXX bug 3935 + kUserFocusKTable) // XXX bug 3935 CSS_PROP_( -moz-user-input, _moz_user_input, CSS_PROP_DOMPROP_PREFIXED(UserInput), 0, "", VARIANT_HK, - kUserInputKTable, - eStyleAnimType_Discrete) // XXX ??? // XXX bug 3935 + kUserInputKTable) // XXX ??? // XXX bug 3935 CSS_PROP_( -moz-user-modify, _moz_user_modify, CSS_PROP_DOMPROP_PREFIXED(UserModify), 0, "", VARIANT_HK, - kUserModifyKTable, - eStyleAnimType_Discrete) // XXX bug 3935 + kUserModifyKTable) // XXX bug 3935 CSS_PROP_( -moz-user-select, _moz_user_select, CSS_PROP_DOMPROP_PREFIXED(UserSelect), 0, "", VARIANT_HK, - kUserSelectKTable, - eStyleAnimType_Discrete) // XXX bug 3935 + kUserSelectKTable) // XXX bug 3935 CSS_PROP_( vector-effect, vector_effect, VectorEffect, 0, "", VARIANT_HK, - kVectorEffectKTable, - eStyleAnimType_Discrete) + kVectorEffectKTable) // NOTE: vertical-align is only supposed to apply to :first-letter when // 'float' is 'none', but we don't worry about that since it has no // effect otherwise CSS_PROP_( vertical-align, vertical_align, VerticalAlign, 0, "", VARIANT_HKLP | VARIANT_CALC, - kVerticalAlignKTable, - eStyleAnimType_Coord) + kVerticalAlignKTable) CSS_PROP_( visibility, visibility, Visibility, 0, "", VARIANT_HK, - kVisibilityKTable, - eStyleAnimType_Discrete) // reflow for collapse + kVisibilityKTable) // reflow for collapse CSS_PROP_( white-space, white_space, WhiteSpace, 0, "", VARIANT_HK, - kWhitespaceKTable, - eStyleAnimType_Discrete) + kWhitespaceKTable) CSS_PROP_( width, width, Width, CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", VARIANT_AHKLP | VARIANT_CALC, - kWidthKTable, - eStyleAnimType_Coord) + kWidthKTable) CSS_PROP_( will-change, will_change, WillChange, - CSS_PROPERTY_PARSE_FUNCTION | - CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + CSS_PROPERTY_PARSE_FUNCTION, "", 0, - nullptr, - eStyleAnimType_Discrete) + nullptr) CSS_PROP_( -moz-window-dragging, _moz_window_dragging, CSS_PROP_DOMPROP_PREFIXED(WindowDragging), 0, "", VARIANT_HK, - kWindowDraggingKTable, - eStyleAnimType_Discrete) + kWindowDraggingKTable) #ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL CSS_PROP_( -moz-window-opacity, _moz_window_opacity, CSS_PROP_DOMPROP_PREFIXED(WindowOpacity), - CSS_PROPERTY_INTERNAL | 0, + CSS_PROPERTY_INTERNAL, "", VARIANT_HN, - nullptr, - eStyleAnimType_float) + nullptr) CSS_PROP_( -moz-window-shadow, _moz_window_shadow, CSS_PROP_DOMPROP_PREFIXED(WindowShadow), CSS_PROPERTY_INTERNAL | CSS_PROPERTY_ENABLED_IN_UA_SHEETS_AND_CHROME, "", VARIANT_HK, - kWindowShadowKTable, - eStyleAnimType_None) + kWindowShadowKTable) CSS_PROP_( -moz-window-transform, _moz_window_transform, CSS_PROP_DOMPROP_PREFIXED(WindowTransform), CSS_PROPERTY_INTERNAL | CSS_PROPERTY_PARSE_FUNCTION | CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", 0, - nullptr, - eStyleAnimType_Custom) + nullptr) CSS_PROP_( -moz-window-transform-origin, _moz_window_transform_origin, CSS_PROP_DOMPROP_PREFIXED(WindowTransformOrigin), CSS_PROPERTY_INTERNAL | CSS_PROPERTY_PARSE_FUNCTION | CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", 0, - kImageLayerPositionKTable, - eStyleAnimType_Custom) + kImageLayerPositionKTable) #endif // CSS_PROP_LIST_EXCLUDE_INTERNAL CSS_PROP_( word-break, word_break, WordBreak, 0, "", VARIANT_HK, - kWordBreakKTable, - eStyleAnimType_Discrete) + kWordBreakKTable) CSS_PROP_( word-spacing, word_spacing, WordSpacing, 0, "", VARIANT_HLP | VARIANT_NORMAL | VARIANT_CALC, - nullptr, - eStyleAnimType_Coord) + nullptr) CSS_PROP_( writing-mode, writing_mode, WritingMode, 0, "", VARIANT_HK, - kWritingModeKTable, - eStyleAnimType_Discrete) + kWritingModeKTable) CSS_PROP_( z-index, z_index, ZIndex, 0, "", VARIANT_AHI, - nullptr, - eStyleAnimType_Coord) + nullptr) #undef CSS_PROP_ #ifdef DEFINED_CSS_PROP_SHORTHAND #undef CSS_PROP_SHORTHAND #undef DEFINED_CSS_PROP_SHORTHAND #endif
--- a/layout/style/nsCSSProps.cpp +++ b/layout/style/nsCSSProps.cpp @@ -180,30 +180,31 @@ CheckServoCSSPropList() #include "mozilla/ServoCSSPropList.h" #undef CSS_PROP_ALIAS #undef CSS_PROP_SHORTHAND #undef CSS_PROP_LONGHAND }; const uint32_t kServoFlags = CSS_PROPERTY_ENABLED_MASK | CSS_PROPERTY_INTERNAL | - CSS_PROPERTY_PARSE_INACCESSIBLE; + CSS_PROPERTY_PARSE_INACCESSIBLE | CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH | + CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR; bool mismatch = false; for (size_t i = 0; i < eCSSProperty_COUNT_with_aliases; i++) { auto& geckoData = sGeckoProps[i]; auto& servoData = sServoProps[i]; const char* name = nsCSSProps::GetStringValue(geckoData.mID).get(); if (geckoData.mID != servoData.mID) { printf_stderr("Order mismatches: gecko: %s, servo: %s\n", name, nsCSSProps::GetStringValue(servoData.mID).get()); mismatch = true; continue; } if ((geckoData.mFlags & kServoFlags) != servoData.mFlags) { - printf_stderr("Enabled flags of %s mismatch\n", name); + printf_stderr("Flags of %s mismatch\n", name); mismatch = true; } if (strcmp(geckoData.mPref, servoData.mPref) != 0) { printf_stderr("Pref of %s mismatches\n", name); mismatch = true; } } @@ -2298,17 +2299,17 @@ nsCSSProps::ValueToKeyword(int32_t aValu } else { return nsCSSKeywords::GetStringValue(keyword); } } /* static */ const KTableEntry* const nsCSSProps::kKeywordTableTable[eCSSProperty_COUNT_no_shorthands] = { #define CSS_PROP(name_, id_, method_, flags_, pref_, parsevariant_, \ - kwtable_, ...) kwtable_, + kwtable_) kwtable_, #include "nsCSSPropList.h" #undef CSS_PROP }; const nsCString& nsCSSProps::LookupPropertyValue(nsCSSPropertyID aProp, int32_t aValue) { MOZ_ASSERT(aProp >= 0 && aProp < eCSSProperty_COUNT, @@ -2341,25 +2342,16 @@ bool nsCSSProps::GetColorName(int32_t aP nsCSSKeywords::AddRefTable(); aStr = nsCSSKeywords::GetStringValue(keyword); nsCSSKeywords::ReleaseTable(); rv = true; } return rv; } -const nsStyleAnimType -nsCSSProps::kAnimTypeTable[eCSSProperty_COUNT_no_shorthands] = { -#define CSS_PROP(name_, id_, method_, flags_, pref_, \ - parsevariant_, kwtable_, animtype_) \ - animtype_, -#include "nsCSSPropList.h" -#undef CSS_PROP -}; - const uint32_t nsCSSProps::kFlagsTable[eCSSProperty_COUNT] = { #define CSS_PROP(name_, id_, method_, flags_, ...) flags_, #include "nsCSSPropList.h" #undef CSS_PROP #define CSS_PROP_SHORTHAND(name_, id_, method_, flags_, pref_) flags_, #include "nsCSSPropList.h" #undef CSS_PROP_SHORTHAND };
--- a/layout/style/nsCSSProps.h +++ b/layout/style/nsCSSProps.h @@ -119,18 +119,16 @@ #define VARIANT_LPCALC (VARIANT_LCALC | VARIANT_PERCENT) #define VARIANT_LNCALC (VARIANT_LCALC | VARIANT_NUMBER) #define VARIANT_LPNCALC (VARIANT_LNCALC | VARIANT_PERCENT) #define VARIANT_IMAGE (VARIANT_URL | VARIANT_NONE | VARIANT_GRADIENT | \ VARIANT_IMAGE_RECT | VARIANT_ELEMENT) // Flags for the kFlagsTable bitfield (flags_ in nsCSSPropList.h) -#define CSS_PROPERTY_VALUE_LIST_USES_COMMAS (1<<1) /* otherwise spaces */ - // Define what mechanism the CSS parser uses for parsing the property. // See CSSParserImpl::ParseProperty(nsCSSPropertyID). Don't use 0 so that // we can verify that every property sets one of the values. #define CSS_PROPERTY_PARSE_PROPERTY_MASK (7<<9) #define CSS_PROPERTY_PARSE_INACCESSIBLE (1<<9) #define CSS_PROPERTY_PARSE_FUNCTION (2<<9) // See CSSParserImpl::ParseSingleValueProperty and comment above @@ -171,66 +169,16 @@ static_assert((CSS_PROPERTY_PARSE_PROPER // This property can be animated on the compositor. #define CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR (1<<27) // This property is an internal property that is not represented // in the DOM. Properties with this flag must be defined in an #ifndef // CSS_PROP_LIST_EXCLUDE_INTERNAL section of nsCSSPropList.h. #define CSS_PROPERTY_INTERNAL (1<<28) -/** - * Types of animatable values. - */ -enum nsStyleAnimType { - // requires a custom implementation in - // StyleAnimationValue::ExtractComputedValue - eStyleAnimType_Custom, - - // nsStyleCoord with animatable values - eStyleAnimType_Coord, - - // same as Coord, except for one side of an nsStyleSides - // listed in the same order as the NS_STYLE_* constants - eStyleAnimType_Sides_Top, - eStyleAnimType_Sides_Right, - eStyleAnimType_Sides_Bottom, - eStyleAnimType_Sides_Left, - - // similar, but for the *pair* of coord members of an nsStyleCorners - // for the relevant corner - eStyleAnimType_Corner_TopLeft, - eStyleAnimType_Corner_TopRight, - eStyleAnimType_Corner_BottomRight, - eStyleAnimType_Corner_BottomLeft, - - // nscoord values - eStyleAnimType_nscoord, - - // float values - eStyleAnimType_float, - - // nscolor values - eStyleAnimType_Color, - - // StyleComplexColor values - eStyleAnimType_ComplexColor, - - // nsStyleSVGPaint values - eStyleAnimType_PaintServer, - - // RefPtr<nsCSSShadowArray> values - eStyleAnimType_Shadow, - - // discrete values - eStyleAnimType_Discrete, - - // property not animatable - eStyleAnimType_None -}; - class nsCSSProps { public: typedef mozilla::CSSEnabledState EnabledState; struct KTableEntry { // KTableEntry objects can be initialized either with an int16_t value // or a value of an enumeration type that can fit within an int16_t. @@ -335,17 +283,16 @@ public: static const nsCString& ValueToKeyword(T aValue, const KTableEntry aTable[]) { static_assert(mozilla::EnumTypeFitsWithin<T, int16_t>::value, "aValue must be an enum that fits within KTableEntry::mValue"); return ValueToKeyword(static_cast<int16_t>(aValue), aTable); } static const KTableEntry* const kKeywordTableTable[eCSSProperty_COUNT_no_shorthands]; - static const nsStyleAnimType kAnimTypeTable[eCSSProperty_COUNT_no_shorthands]; private: static const uint32_t kFlagsTable[eCSSProperty_COUNT]; public: static inline bool PropHasFlags(nsCSSPropertyID aProperty, uint32_t aFlags) { MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT,
--- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp @@ -45,16 +45,17 @@ #include "nsThreadUtils.h" #include "nspr.h" #include "runnable_utils.h" #include "srtp.h" #include "transportflow.h" #include "transportlayer.h" #include "transportlayerdtls.h" #include "transportlayerice.h" +#include "Tracing.h" #include "webrtc/base/bind.h" #include "webrtc/base/keep_ref_until_done.h" #include "webrtc/common_types.h" #include "webrtc/common_video/include/i420_buffer_pool.h" #include "webrtc/common_video/include/video_frame_buffer.h" #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" @@ -1926,22 +1927,23 @@ MediaPipelineTransmit::PipelineListener: LOGTAG, "MediaPipeline::NotifyRealtimeTrackData() listener=%p, offset=%" PRId64 ", duration=%" PRId64, this, aOffset, aMedia.GetDuration()); if (aMedia.GetType() == MediaSegment::VIDEO) { + TRACE_COMMENT("Video"); // We have to call the upstream NotifyRealtimeTrackData and // MediaStreamVideoSink will route them to SetCurrentFrames. MediaStreamVideoSink::NotifyRealtimeTrackData(aGraph, aOffset, aMedia); return; } - + TRACE_COMMENT("Audio"); NewData(aMedia, aGraph->GraphRate()); } void MediaPipelineTransmit::PipelineListener::NotifyQueuedChanges( MediaStreamGraph* aGraph, StreamTime aOffset, const MediaSegment& aQueuedMedia) @@ -2017,16 +2019,17 @@ MediaPipelineTransmit::PipelineListener: const AudioSegment* audio = static_cast<const AudioSegment*>(&aMedia); for (AudioSegment::ConstChunkIterator iter(*audio); !iter.IsEnded(); iter.Next()) { mAudioProcessing->QueueAudioChunk(aRate, *iter, mEnabled); } } else { const VideoSegment* video = static_cast<const VideoSegment*>(&aMedia); + for (VideoSegment::ConstChunkIterator iter(*video); !iter.IsEnded(); iter.Next()) { mConverter->QueueVideoChunk(*iter, !mEnabled); } } } void @@ -2229,16 +2232,17 @@ private: ~PipelineListener() { NS_ReleaseOnMainThreadSystemGroup("MediaPipeline::mConduit", mConduit.forget()); } void NotifyPullImpl(StreamTime aDesiredTime) { + TRACE(); uint32_t samplesPer10ms = mRate / 100; // mSource's rate is not necessarily the same as the graph rate, since there // are sample-rate constraints on the inbound audio: only 16, 32, 44.1 and // 48kHz are supported. The audio frames we get here is going to be // resampled when inserted into the graph. TrackTicks desired = mSource->TimeToTicksRoundUp(mRate, aDesiredTime); TrackTicks framesNeeded = desired - mPlayedTicks;
--- a/netwerk/base/nsStandardURL.cpp +++ b/netwerk/base/nsStandardURL.cpp @@ -1794,16 +1794,24 @@ nsStandardURL::SetUsername(const nsACStr nsresult nsStandardURL::SetPassword(const nsACString &input) { ENSURE_MUTABLE(); const nsPromiseFlatCString &password = PromiseFlatCString(input); + auto clearedPassword = MakeScopeExit([&password, this]() { + // Check that if this method is called with the empty string then the + // password is definitely cleared when exiting this method. + if (password.IsEmpty()) { + MOZ_DIAGNOSTIC_ASSERT(this->Password().IsEmpty()); + } + }); + LOG(("nsStandardURL::SetPassword [password=%s]\n", password.get())); if (mURLType == URLTYPE_NO_AUTHORITY) { if (password.IsEmpty()) return NS_OK; NS_WARNING("cannot set password on no-auth url"); return NS_ERROR_UNEXPECTED; }
--- a/python/mozbuild/mozbuild/virtualenv.py +++ b/python/mozbuild/mozbuild/virtualenv.py @@ -483,17 +483,17 @@ class VirtualenvManager(object): args = [ 'install', '--use-wheel', package, ] return self._run_pip(args) - def install_pip_requirements(self, path, require_hashes=True): + def install_pip_requirements(self, path, require_hashes=True, quiet=False): """Install a pip requirements.txt file. The supplied path is a text file containing pip requirement specifiers. If require_hashes is True, each specifier must contain the expected hash of the downloaded package. See: https://pip.pypa.io/en/stable/reference/pip_install/#hash-checking-mode @@ -506,16 +506,19 @@ class VirtualenvManager(object): 'install', '--requirement', path, ] if require_hashes: args.append('--require-hashes') + if quiet: + args.append('--quiet') + return self._run_pip(args) def _run_pip(self, args): # It's tempting to call pip natively via pip.main(). However, # the current Python interpreter may not be the virtualenv python. # This will confuse pip and cause the package to attempt to install # against the executing interpreter. By creating a new process, we # force the virtualenv's interpreter to be used and all is well.
--- a/services/sync/tps/extensions/tps/resource/auth/fxaccounts.jsm +++ b/services/sync/tps/extensions/tps/resource/auth/fxaccounts.jsm @@ -173,17 +173,19 @@ var Authentication = { try { // Required here since we don't go through the real login page await FxAccountsConfig.ensureConfigured(); let client = new FxAccountsClient(); let credentials = await client.signIn(account.username, account.password, true); await fxAccounts.setSignedInUser(credentials); - await this._completeVerification(account.username); + if (!credentials.verified) { + await this._completeVerification(account.username); + } if (Weave.Status.login !== Weave.LOGIN_SUCCEEDED) { Logger.logInfo("Logging into Weave."); await Weave.Service.login(); } return true; } catch (error) { throw new Error("signIn() failed with: " + error.message);
--- a/services/sync/tps/extensions/tps/resource/modules/bookmarks.jsm +++ b/services/sync/tps/extensions/tps/resource/modules/bookmarks.jsm @@ -75,16 +75,17 @@ function PlacesItem(props) { PlacesItem.prototype = { // an array of possible root folders for places items _bookmarkFolders: { "places": PlacesUtils.bookmarks.rootGuid, "menu": PlacesUtils.bookmarks.menuGuid, "tags": PlacesUtils.bookmarks.tagsGuid, "unfiled": PlacesUtils.bookmarks.unfiledGuid, "toolbar": PlacesUtils.bookmarks.toolbarGuid, + "mobile": PlacesUtils.bookmarks.mobileGuid, }, _typeMap: new Map([ [PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER, PlacesUtils.bookmarks.TYPE_FOLDER], [PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR, PlacesUtils.bookmarks.TYPE_SEPARATOR], [PlacesUtils.TYPE_X_MOZ_PLACE, PlacesUtils.bookmarks.TYPE_BOOKMARK], ]),
--- a/servo/components/style/properties/longhand/border.mako.rs +++ b/servo/components/style/properties/longhand/border.mako.rs @@ -38,27 +38,29 @@ alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-style"), spec=maybe_logical_spec(side, "style"), flags="APPLIES_TO_FIRST_LETTER", animation_value_type="discrete" if not is_logical else "none", logical=is_logical, needs_context=False, )} - ${helpers.predefined_type("border-%s-width" % side_name, - "BorderSideWidth", - "::values::computed::NonNegativeLength::new(3.)", - computed_type="::values::computed::NonNegativeLength", - alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-width"), - spec=maybe_logical_spec(side, "width"), - animation_value_type="NonNegativeLength", - logical=is_logical, - flags="APPLIES_TO_FIRST_LETTER", - allow_quirks=not is_logical, - servo_restyle_damage = "reflow rebuild_and_reflow_inline")} + ${helpers.predefined_type( + "border-%s-width" % side_name, + "BorderSideWidth", + "::values::computed::NonNegativeLength::new(3.)", + computed_type="::values::computed::NonNegativeLength", + alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-width"), + spec=maybe_logical_spec(side, "width"), + animation_value_type="NonNegativeLength", + logical=is_logical, + flags="APPLIES_TO_FIRST_LETTER GETCS_NEEDS_LAYOUT_FLUSH", + allow_quirks=not is_logical, + servo_restyle_damage="reflow rebuild_and_reflow_inline" + )} % endfor ${helpers.gecko_keyword_conversion(Keyword('border-style', "none solid double dotted dashed hidden groove ridge inset outset"), type="::values::specified::BorderStyle")} // FIXME(#4126): when gfx supports painting it, make this Size2D<LengthOrPercentage> % for corner in ["top-left", "top-right", "bottom-right", "bottom-left"]:
--- a/servo/components/style/properties/longhand/box.mako.rs +++ b/servo/components/style/properties/longhand/box.mako.rs @@ -398,24 +398,28 @@ gecko_pref="layout.css.scroll-snap.enabled", spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-destination)", animation_value_type="discrete", allow_empty="NotInitial" )} <% transform_extra_prefixes = "moz:layout.css.prefixes.transforms webkit" %> -${helpers.predefined_type("transform", "Transform", - "generics::transform::Transform::none()", - extra_prefixes=transform_extra_prefixes, - animation_value_type="ComputedValue", - gecko_ffi_name="mSpecifiedTransform", - flags="CREATES_STACKING_CONTEXT FIXPOS_CB", - spec="https://drafts.csswg.org/css-transforms/#propdef-transform", - servo_restyle_damage = "reflow_out_of_flow")} +${helpers.predefined_type( + "transform", + "Transform", + "generics::transform::Transform::none()", + extra_prefixes=transform_extra_prefixes, + animation_value_type="ComputedValue", + gecko_ffi_name="mSpecifiedTransform", + flags="CREATES_STACKING_CONTEXT FIXPOS_CB \ + GETCS_NEEDS_LAYOUT_FLUSH CAN_ANIMATE_ON_COMPOSITOR", + spec="https://drafts.csswg.org/css-transforms/#propdef-transform", + servo_restyle_damage="reflow_out_of_flow" +)} ${helpers.predefined_type("rotate", "Rotate", "generics::transform::Rotate::None", animation_value_type="ComputedValue", boxed=True, flags="CREATES_STACKING_CONTEXT FIXPOS_CB", gecko_pref="layout.css.individual-transform.enabled", spec="https://drafts.csswg.org/css-transforms-2/#individual-transforms", @@ -425,24 +429,27 @@ "generics::transform::Scale::None", animation_value_type="ComputedValue", boxed=True, flags="CREATES_STACKING_CONTEXT FIXPOS_CB", gecko_pref="layout.css.individual-transform.enabled", spec="https://drafts.csswg.org/css-transforms-2/#individual-transforms", servo_restyle_damage = "reflow_out_of_flow")} -${helpers.predefined_type("translate", "Translate", - "generics::transform::Translate::None", - animation_value_type="ComputedValue", - boxed=True, - flags="CREATES_STACKING_CONTEXT FIXPOS_CB", - gecko_pref="layout.css.individual-transform.enabled", - spec="https://drafts.csswg.org/css-transforms-2/#individual-transforms", - servo_restyle_damage = "reflow_out_of_flow")} +${helpers.predefined_type( + "translate", + "Translate", + "generics::transform::Translate::None", + animation_value_type="ComputedValue", + boxed=True, + flags="CREATES_STACKING_CONTEXT FIXPOS_CB GETCS_NEEDS_LAYOUT_FLUSH", + gecko_pref="layout.css.individual-transform.enabled", + spec="https://drafts.csswg.org/css-transforms-2/#individual-transforms", + servo_restyle_damage="reflow_out_of_flow" +)} // CSSOM View Module // https://www.w3.org/TR/cssom-view-1/ ${helpers.single_keyword("scroll-behavior", "auto smooth", gecko_pref="layout.css.scroll-behavior.property-enabled", products="gecko", spec="https://drafts.csswg.org/cssom-view/#propdef-scroll-behavior", @@ -524,24 +531,27 @@ gecko_ffi_name="mChildPerspective", spec="https://drafts.csswg.org/css-transforms/#perspective", extra_prefixes=transform_extra_prefixes, flags="CREATES_STACKING_CONTEXT FIXPOS_CB", animation_value_type="AnimatedPerspective", servo_restyle_damage = "reflow_out_of_flow", )} -${helpers.predefined_type("perspective-origin", - "position::Position", - "computed::position::Position::center()", - boxed=True, - extra_prefixes=transform_extra_prefixes, - spec="https://drafts.csswg.org/css-transforms-2/#perspective-origin-property", - animation_value_type="ComputedValue", - servo_restyle_damage = "reflow_out_of_flow")} +${helpers.predefined_type( + "perspective-origin", + "position::Position", + "computed::position::Position::center()", + boxed=True, + extra_prefixes=transform_extra_prefixes, + spec="https://drafts.csswg.org/css-transforms-2/#perspective-origin-property", + flags="GETCS_NEEDS_LAYOUT_FLUSH", + animation_value_type="ComputedValue", + servo_restyle_damage="reflow_out_of_flow" +)} ${helpers.single_keyword("backface-visibility", "visible hidden", spec="https://drafts.csswg.org/css-transforms/#backface-visibility-property", extra_prefixes=transform_extra_prefixes, animation_value_type="discrete")} ${helpers.single_keyword("transform-box", @@ -560,25 +570,28 @@ spec="https://drafts.csswg.org/css-transforms-2/#transform-style-property", needs_context=False, extra_prefixes=transform_extra_prefixes, flags="CREATES_STACKING_CONTEXT FIXPOS_CB", animation_value_type="discrete", servo_restyle_damage = "reflow_out_of_flow", )} -${helpers.predefined_type("transform-origin", - "TransformOrigin", - "computed::TransformOrigin::initial_value()", - animation_value_type="ComputedValue", - extra_prefixes=transform_extra_prefixes, - gecko_ffi_name="mTransformOrigin", - boxed=True, - spec="https://drafts.csswg.org/css-transforms/#transform-origin-property", - servo_restyle_damage = "reflow_out_of_flow")} +${helpers.predefined_type( + "transform-origin", + "TransformOrigin", + "computed::TransformOrigin::initial_value()", + animation_value_type="ComputedValue", + extra_prefixes=transform_extra_prefixes, + gecko_ffi_name="mTransformOrigin", + boxed=True, + flags="GETCS_NEEDS_LAYOUT_FLUSH", + spec="https://drafts.csswg.org/css-transforms/#transform-origin-property", + servo_restyle_damage="reflow_out_of_flow" +)} ${helpers.predefined_type("contain", "Contain", "specified::Contain::empty()", animation_value_type="discrete", products="gecko", flags="FIXPOS_CB", gecko_pref="layout.css.contain.enabled",
--- a/servo/components/style/properties/longhand/effects.mako.rs +++ b/servo/components/style/properties/longhand/effects.mako.rs @@ -2,23 +2,26 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ <%namespace name="helpers" file="/helpers.mako.rs" /> // Box-shadow, etc. <% data.new_style_struct("Effects", inherited=False) %> -${helpers.predefined_type("opacity", - "Opacity", - "1.0", - animation_value_type="ComputedValue", - flags="CREATES_STACKING_CONTEXT APPLIES_TO_PLACEHOLDER", - spec="https://drafts.csswg.org/css-color/#opacity", - servo_restyle_damage = "reflow_out_of_flow")} +${helpers.predefined_type( + "opacity", + "Opacity", + "1.0", + animation_value_type="ComputedValue", + flags="CREATES_STACKING_CONTEXT APPLIES_TO_PLACEHOLDER \ + CAN_ANIMATE_ON_COMPOSITOR", + spec="https://drafts.csswg.org/css-color/#opacity", + servo_restyle_damage = "reflow_out_of_flow" +)} ${helpers.predefined_type( "box-shadow", "BoxShadow", None, vector=True, animation_value_type="AnimatedBoxShadowList", extra_prefixes="webkit",
--- a/servo/components/style/properties/longhand/inherited_text.mako.rs +++ b/servo/components/style/properties/longhand/inherited_text.mako.rs @@ -1,23 +1,26 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ <%namespace name="helpers" file="/helpers.mako.rs" /> <% from data import Keyword %> <% data.new_style_struct("InheritedText", inherited=True, gecko_name="Text") %> -${helpers.predefined_type("line-height", - "LineHeight", - "computed::LineHeight::normal()", - animation_value_type="LineHeight", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", - spec="https://drafts.csswg.org/css2/visudet.html#propdef-line-height", - servo_restyle_damage = "reflow")} +${helpers.predefined_type( + "line-height", + "LineHeight", + "computed::LineHeight::normal()", + animation_value_type="LineHeight", + flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE \ + APPLIES_TO_PLACEHOLDER GETCS_NEEDS_LAYOUT_FLUSH", + spec="https://drafts.csswg.org/css2/visudet.html#propdef-line-height", + servo_restyle_damage="reflow" +)} // CSS Text Module Level 3 // TODO(pcwalton): `full-width` ${helpers.single_keyword("text-transform", "none capitalize uppercase lowercase", extra_gecko_values="full-width", animation_value_type="discrete",
--- a/servo/components/style/properties/longhand/margin.mako.rs +++ b/servo/components/style/properties/longhand/margin.mako.rs @@ -7,17 +7,22 @@ <% data.new_style_struct("Margin", inherited=False) %> % for side in ALL_SIDES: <% spec = "https://drafts.csswg.org/css-box/#propdef-margin-%s" % side[0] if side[1]: spec = "https://drafts.csswg.org/css-logical-props/#propdef-margin-%s" % side[1] %> - ${helpers.predefined_type("margin-%s" % side[0], "LengthOrPercentageOrAuto", - "computed::LengthOrPercentageOrAuto::Length(computed::Length::new(0.))", - alias=maybe_moz_logical_alias(product, side, "-moz-margin-%s"), - allow_quirks=not side[1], - animation_value_type="ComputedValue", logical = side[1], spec = spec, - flags="APPLIES_TO_FIRST_LETTER", - allowed_in_page_rule=True, - servo_restyle_damage = "reflow")} + ${helpers.predefined_type( + "margin-%s" % side[0], + "LengthOrPercentageOrAuto", + "computed::LengthOrPercentageOrAuto::Length(computed::Length::new(0.))", + alias=maybe_moz_logical_alias(product, side, "-moz-margin-%s"), + allow_quirks=not side[1], + animation_value_type="ComputedValue", + logical=side[1], + spec=spec, + flags="APPLIES_TO_FIRST_LETTER GETCS_NEEDS_LAYOUT_FLUSH", + allowed_in_page_rule=True, + servo_restyle_damage="reflow" + )} % endfor
--- a/servo/components/style/properties/longhand/padding.mako.rs +++ b/servo/components/style/properties/longhand/padding.mako.rs @@ -9,18 +9,21 @@ // APPLIES_TO_PLACEHOLDER so we can set it in UA stylesheets. But we use a // !important value there, so pages can't set it. % for side in ALL_SIDES: <% spec = "https://drafts.csswg.org/css-box/#propdef-padding-%s" % side[0] if side[1]: spec = "https://drafts.csswg.org/css-logical-props/#propdef-padding-%s" % side[1] %> - ${helpers.predefined_type("padding-%s" % side[0], "NonNegativeLengthOrPercentage", - "computed::NonNegativeLengthOrPercentage::zero()", - alias=maybe_moz_logical_alias(product, side, "-moz-padding-%s"), - animation_value_type="NonNegativeLengthOrPercentage", - logical = side[1], - spec = spec, - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_PLACEHOLDER", - allow_quirks=not side[1], - servo_restyle_damage = "reflow rebuild_and_reflow_inline")} + ${helpers.predefined_type( + "padding-%s" % side[0], + "NonNegativeLengthOrPercentage", + "computed::NonNegativeLengthOrPercentage::zero()", + alias=maybe_moz_logical_alias(product, side, "-moz-padding-%s"), + animation_value_type="NonNegativeLengthOrPercentage", + logical=side[1], + spec=spec, + flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_PLACEHOLDER GETCS_NEEDS_LAYOUT_FLUSH", + allow_quirks=not side[1], + servo_restyle_damage="reflow rebuild_and_reflow_inline" + )} % endfor
--- a/servo/components/style/properties/longhand/position.mako.rs +++ b/servo/components/style/properties/longhand/position.mako.rs @@ -5,28 +5,38 @@ <%! from data import to_rust_ident %> <%namespace name="helpers" file="/helpers.mako.rs" /> <% from data import ALL_SIZES, PHYSICAL_SIDES, LOGICAL_SIDES %> <% data.new_style_struct("Position", inherited=False) %> // "top" / "left" / "bottom" / "right" % for side in PHYSICAL_SIDES: - ${helpers.predefined_type(side, "LengthOrPercentageOrAuto", - "computed::LengthOrPercentageOrAuto::Auto", - spec="https://www.w3.org/TR/CSS2/visuren.html#propdef-%s" % side, - animation_value_type="ComputedValue", - allow_quirks=True, servo_restyle_damage = "reflow_out_of_flow")} + ${helpers.predefined_type( + side, + "LengthOrPercentageOrAuto", + "computed::LengthOrPercentageOrAuto::Auto", + spec="https://www.w3.org/TR/CSS2/visuren.html#propdef-%s" % side, + flags="GETCS_NEEDS_LAYOUT_FLUSH", + animation_value_type="ComputedValue", + allow_quirks=True, + servo_restyle_damage="reflow_out_of_flow" + )} % endfor // offset-* logical properties, map to "top" / "left" / "bottom" / "right" % for side in LOGICAL_SIDES: - ${helpers.predefined_type("offset-%s" % side, "LengthOrPercentageOrAuto", - "computed::LengthOrPercentageOrAuto::Auto", - spec="https://drafts.csswg.org/css-logical-props/#propdef-offset-%s" % side, - animation_value_type="ComputedValue", logical=True)} + ${helpers.predefined_type( + "offset-%s" % side, + "LengthOrPercentageOrAuto", + "computed::LengthOrPercentageOrAuto::Auto", + spec="https://drafts.csswg.org/css-logical-props/#propdef-offset-%s" % side, + flags="GETCS_NEEDS_LAYOUT_FLUSH", + animation_value_type="ComputedValue", + logical=True, + )} % endfor #[cfg(feature = "gecko")] macro_rules! impl_align_conversions { ($name: path) => { impl From<u8> for $name { fn from(bits: u8) -> $name { $name(::values::specified::align::AlignFlags::from_bits(bits) @@ -208,17 +218,18 @@ macro_rules! impl_align_conversions { size, "MozLength", "computed::MozLength::auto()", parse_function, logical=logical, allow_quirks=not logical, spec=spec % size, animation_value_type="MozLength", - servo_restyle_damage = "reflow" + flags="GETCS_NEEDS_LAYOUT_FLUSH", + servo_restyle_damage="reflow" )} // min-width, min-height, min-block-size, min-inline-size, ${helpers.predefined_type( "min-%s" % size, "MozLength", "computed::MozLength::auto()", parse_function, logical=logical, @@ -313,23 +324,26 @@ macro_rules! impl_align_conversions { ${helpers.predefined_type("grid-auto-%ss" % kind, "TrackSize", "Default::default()", animation_value_type="discrete", spec="https://drafts.csswg.org/css-grid/#propdef-grid-auto-%ss" % kind, products="gecko", boxed=True)} - ${helpers.predefined_type("grid-template-%ss" % kind, - "GridTemplateComponent", - "specified::GenericGridTemplateComponent::None", - products="gecko", - spec="https://drafts.csswg.org/css-grid/#propdef-grid-template-%ss" % kind, - boxed=True, - animation_value_type="discrete")} + ${helpers.predefined_type( + "grid-template-%ss" % kind, + "GridTemplateComponent", + "specified::GenericGridTemplateComponent::None", + products="gecko", + spec="https://drafts.csswg.org/css-grid/#propdef-grid-template-%ss" % kind, + boxed=True, + flags="GETCS_NEEDS_LAYOUT_FLUSH", + animation_value_type="discrete" + )} % endfor ${helpers.predefined_type("grid-auto-flow", "GridAutoFlow", initial_value="computed::GridAutoFlow::row()", products="gecko", animation_value_type="discrete",
--- a/servo/components/style/properties/longhand/ui.mako.rs +++ b/servo/components/style/properties/longhand/ui.mako.rs @@ -43,31 +43,39 @@ // TODO(bug 1419695) This should be hidden from content. ${helpers.predefined_type("-moz-window-opacity", "Opacity", "1.0", products="gecko", gecko_ffi_name="mWindowOpacity", animation_value_type="ComputedValue", spec="None (Nonstandard internal property)")} // TODO(bug 1419695) This should be hidden from content. -${helpers.predefined_type("-moz-window-transform", "Transform", - "generics::transform::Transform::none()", - products="gecko", gecko_ffi_name="mSpecifiedWindowTransform", - animation_value_type="ComputedValue", - spec="None (Nonstandard internal property)")} +${helpers.predefined_type( + "-moz-window-transform", + "Transform", + "generics::transform::Transform::none()", + products="gecko", + gecko_ffi_name="mSpecifiedWindowTransform", + flags="GETCS_NEEDS_LAYOUT_FLUSH", + animation_value_type="ComputedValue", + spec="None (Nonstandard internal property)" +)} // TODO(bug 1419695) This should be hidden from content. -${helpers.predefined_type("-moz-window-transform-origin", - "TransformOrigin", - "computed::TransformOrigin::initial_value()", - animation_value_type="ComputedValue", - gecko_ffi_name="mWindowTransformOrigin", - products="gecko", - boxed=True, - spec="None (Nonstandard internal property)")} +${helpers.predefined_type( + "-moz-window-transform-origin", + "TransformOrigin", + "computed::TransformOrigin::initial_value()", + animation_value_type="ComputedValue", + gecko_ffi_name="mWindowTransformOrigin", + products="gecko", + boxed=True, + flags="GETCS_NEEDS_LAYOUT_FLUSH", + spec="None (Nonstandard internal property)" +)} // TODO(emilio): Probably also should be hidden from content. ${helpers.predefined_type("-moz-force-broken-image-icon", "MozForceBrokenImageIcon", "computed::MozForceBrokenImageIcon::false_value()", animation_value_type="discrete", products="gecko", spec="None (Nonstandard Firefox-only property)")}
--- a/servo/components/style/properties/properties.mako.rs +++ b/servo/components/style/properties/properties.mako.rs @@ -776,16 +776,25 @@ bitflags! { /// absolutely positioned elements. const ABSPOS_CB = 1 << 2; /// This longhand property applies to ::first-letter. const APPLIES_TO_FIRST_LETTER = 1 << 3; /// This longhand property applies to ::first-line. const APPLIES_TO_FIRST_LINE = 1 << 4; /// This longhand property applies to ::placeholder. const APPLIES_TO_PLACEHOLDER = 1 << 5; + + /* The following flags are currently not used in Rust code, they + * only need to be listed in corresponding properties so that + * they can be checked in the C++ side via ServoCSSPropList.h. */ + /// This property's getComputedStyle implementation requires layout + /// to be flushed. + const GETCS_NEEDS_LAYOUT_FLUSH = 0; + /// This property can be animated on the compositor. + const CAN_ANIMATE_ON_COMPOSITOR = 0; } } /// An identifier for a given longhand property. #[derive(Clone, Copy, Eq, Hash, MallocSizeOf, PartialEq)] #[repr(u16)] pub enum LonghandId { % for i, property in enumerate(data.longhands):
--- a/taskcluster/ci/source-test/doc.yml +++ b/taskcluster/ci/source-test/doc.yml @@ -13,17 +13,17 @@ generate: artifacts: - type: file name: public/docs.tar.gz path: /builds/worker/checkouts/gecko/docs-out/main.tar.gz run: using: run-task command: > cd /builds/worker/checkouts/gecko && - ./mach doc --outdir docs-out --no-open --archive + ./mach doc --outdir docs-out --no-open --no-serve --archive sparse-profile: sphinx-docs optimization: skip-unless-schedules: [docs] upload: description: Generate and upload the Sphinx documentation platform: lint/opt treeherder: @@ -33,14 +33,14 @@ upload: run-on-projects: [mozilla-central] worker-type: aws-provisioner-v1/gecko-t-linux-xlarge worker: docker-image: {in-tree: "lint"} max-run-time: 1800 taskcluster-proxy: true run: using: run-task - command: cd /builds/worker/checkouts/gecko && ./mach doc --upload --no-open + command: cd /builds/worker/checkouts/gecko && ./mach doc --upload --no-open --no-serve sparse-profile: sphinx-docs scopes: - secrets:get:project/releng/gecko/build/level-{level}/gecko-docs-upload optimization: skip-unless-schedules: [docs]
--- a/testing/mozharness/configs/merge_day/release_to_esr.py +++ b/testing/mozharness/configs/merge_day/release_to_esr.py @@ -1,15 +1,12 @@ import os ABS_WORK_DIR = os.path.join(os.getcwd(), "build") -NEW_ESR_REPO = "https://hg.mozilla.org/releases/mozilla-esr59" -# ESR-specific branding (logo) lives in the old repo: -OLD_ESR_REPO = "https://hg.mozilla.org/releases/mozilla-esr52" -OLD_ESR_CHANGESET = "df0931ac8b02" +NEW_ESR_REPO = "https://hg.mozilla.org/releases/mozilla-esr60" config = { "log_name": "relese_to_esr", "version_files": [ {"file": "browser/config/version.txt", "suffix": ""}, {"file": "browser/config/version_display.txt", "suffix": ""}, {"file": "config/milestone.txt", "suffix": ""}, ], @@ -39,15 +36,11 @@ config = { "tools_repo_url": "https://hg.mozilla.org/build/tools", "tools_repo_branch": "default", "from_repo_url": "https://hg.mozilla.org/releases/mozilla-release", "to_repo_url": NEW_ESR_REPO, "base_tag": "FIREFOX_ESR_%(major_version)s_BASE", "migration_behavior": "release_to_esr", "require_remove_locales": False, - "graft_patches": [ - {"repo": OLD_ESR_REPO, - "changeset": OLD_ESR_CHANGESET}, - ], "requires_head_merge": False, "pull_all_branches": False, }
--- a/testing/mozharness/scripts/merge_day/gecko_migration.py +++ b/testing/mozharness/scripts/merge_day/gecko_migration.py @@ -396,49 +396,24 @@ class GeckoMigration(MercurialScript, Ba os.path.join(dirs['abs_to_dir'], "browser/locales/shipped-locales"), self.config['remove_locales'] ) self.touch_clobber_file(dirs['abs_to_dir']) def release_to_esr(self, *args, **kwargs): """ mozilla-release -> mozilla-esrNN behavior. """ dirs = self.query_abs_dirs() - for to_graft in self.config.get("graft_patches", []): - self.graft(repo=to_graft["repo"], changeset=to_graft["changeset"], - cwd=dirs['abs_to_dir']) self.apply_replacements() self.touch_clobber_file(dirs['abs_to_dir']) def apply_replacements(self): dirs = self.query_abs_dirs() for f, from_, to in self.config["replacements"]: self.replace(os.path.join(dirs['abs_to_dir'], f), from_, to) - def graft(self, repo, changeset, cwd): - """Graft a Mercurial changeset from a remote repository.""" - hg = self.query_exe("hg", return_type="list") - self.info("Pulling %s from %s" % (changeset, repo)) - pull_cmd = hg + ["pull", "-r", changeset, repo] - status = self.run_command( - pull_cmd, - cwd=cwd, - error_list=HgErrorList, - ) - if status != 0: - self.fatal("Cannot pull %s from %s properly" % (changeset, repo)) - cmd = hg + ["graft&