Merge mozilla-central to autoland. a=merge
authorDaniel Varga <dvarga@mozilla.com>
Sat, 20 Oct 2018 13:14:31 +0300
changeset 500740 5d4fb7fef7d0383e4244bdd221ec61018bff1662
parent 500737 a2df0d50925f188b41fdc60328b058b4afb53a41 (current diff)
parent 500739 f88ebf2720c875520d2de1cf4104a3b550c73ad8 (diff)
child 500743 380375ad1dbd2402b5d131dd5cc8bed9d78ba072
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone64.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
Merge mozilla-central to autoland. a=merge
browser/themes/shared/icons/performance.svg
testing/talos/talos/tests/tart/addon/bootstrap.js
testing/talos/talos/tests/tart/addon/chrome.manifest
testing/talos/talos/tests/tart/addon/content/blank.icon.html
testing/talos/talos/tests/tart/addon/content/tart.ico
testing/talos/talos/tests/tart/addon/install.rdf
testing/web-platform/meta/html/semantics/text-level-semantics/the-wbr-element/wbr-element.html.ini
testing/web-platform/meta/infrastructure/assumptions/ahem.html.ini
toolkit/themes/shared/icons/performance.svg
--- a/browser/base/content/test/static/browser_all_files_referenced.js
+++ b/browser/base/content/test/static/browser_all_files_referenced.js
@@ -161,19 +161,19 @@ var whitelist = [
   {file: "chrome://global/content/test-ipc.xul"},
   // Bug 1356036
   {file: "resource://gre/modules/PerformanceWatcher-content.js"},
   {file: "resource://gre/modules/PerformanceWatcher.jsm"},
   // Bug 1378173 (warning: still used by devtools)
   {file: "resource://gre/modules/Promise.jsm"},
   // Still used by WebIDE, which is going away but not entirely gone.
   {file: "resource://gre/modules/ZipUtils.jsm"},
-  // Bug 1463225 (on Mac this is only used by a test)
+  // Bug 1463225 (on Mac and Windows this is only used by a test)
   {file: "chrome://global/content/bindings/toolbar.xml",
-   platforms: ["macosx"]},
+   platforms: ["macosx", "win"]},
   // Bug 1483277 (temporarily unreferenced)
   {file: "chrome://browser/content/browser.xhtml"},
   // Bug 1494170
   // (The references to these files are dynamically generated, so the test can't
   // find the references)
   {file: "chrome://devtools/skin/images/aboutdebugging-firefox-aurora.svg",
    isFromDevTools: true},
   {file: "chrome://devtools/skin/images/aboutdebugging-firefox-beta.svg",
--- a/browser/components/aboutconfig/content/aboutconfig.html
+++ b/browser/components/aboutconfig/content/aboutconfig.html
@@ -3,18 +3,19 @@
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <!DOCTYPE HTML>
 <html>
   <head>
     <meta charset="utf-8">
     <link rel="stylesheet" media="screen, projection" type="text/css"
           href="chrome://global/skin/in-content/common.css"/>
-    <link rel="stylesheet" type="text/css" 
+    <link rel="stylesheet" type="text/css"
           href="chrome://browser/content/aboutconfig/aboutconfig.css"/>
-    <script type="application/javascript" 
+    <link rel="localization" href="browser/aboutConfig.ftl">
+    <script type="application/javascript"
             src="chrome://browser/content/aboutconfig/aboutconfig.js"></script>
-    <title>about:config</title>
+    <title data-l10n-id="about-config-title"></title>
   </head>
 
   <body>
   </body>
  </html>
new file mode 100644
--- /dev/null
+++ b/browser/components/aboutconfig/content/aboutconfig.notftl
@@ -0,0 +1,5 @@
+# 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/.
+
+about-config-title = about:config
--- a/browser/components/aboutconfig/jar.mn
+++ b/browser/components/aboutconfig/jar.mn
@@ -1,8 +1,12 @@
+#filter substitution
 # 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/.
 
 browser.jar:
-   content/browser/aboutconfig/aboutconfig.css          (content/aboutconfig.css)
-   content/browser/aboutconfig/aboutconfig.html         (content/aboutconfig.html)
-   content/browser/aboutconfig/aboutconfig.js           (content/aboutconfig.js)
+  content/browser/aboutconfig/aboutconfig.css     (content/aboutconfig.css)
+  content/browser/aboutconfig/aboutconfig.html    (content/aboutconfig.html)
+  content/browser/aboutconfig/aboutconfig.js      (content/aboutconfig.js)
+
+[localization] @AB_CD@.jar:
+  browser/aboutConfig.ftl                         (content/aboutconfig.notftl)
--- a/browser/components/aboutconfig/test/browser/browser_basic.js
+++ b/browser/components/aboutconfig/test/browser/browser_basic.js
@@ -2,13 +2,14 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 add_task(async function test_load_title() {
   await BrowserTestUtils.withNewTab({
     gBrowser,
     url: "chrome://browser/content/aboutconfig/aboutconfig.html",
   }, browser => {
     info("about:config loaded");
-    return ContentTask.spawn(browser, null, () => {
+    return ContentTask.spawn(browser, null, async () => {
+      await content.document.l10n.ready;
       Assert.equal(content.document.title, "about:config");
     });
   });
 });
--- a/browser/themes/shared/jar.inc.mn
+++ b/browser/themes/shared/jar.inc.mn
@@ -159,17 +159,16 @@
   skin/classic/browser/link.svg                       (../shared/icons/link.svg)
   skin/classic/browser/mail.svg                       (../shared/icons/mail.svg)
   skin/classic/browser/menu.svg                       (../shared/icons/menu.svg)
   skin/classic/browser/menu-badged.svg                (../shared/icons/menu-badged.svg)
   skin/classic/browser/new-tab.svg                    (../shared/icons/new-tab.svg)
   skin/classic/browser/new-window.svg                 (../shared/icons/new-window.svg)
   skin/classic/browser/open.svg                       (../shared/icons/open.svg)
   skin/classic/browser/page-action.svg                (../shared/icons/page-action.svg)
-  skin/classic/browser/performance.svg                (../shared/icons/performance.svg)
   skin/classic/browser/print.svg                      (../shared/icons/print.svg)
   skin/classic/browser/private-browsing.svg           (../shared/icons/private-browsing.svg)
   skin/classic/browser/privateBrowsing.svg            (../shared/icons/privateBrowsing.svg)
   skin/classic/browser/restore-session.svg            (../shared/icons/restore-session.svg)
   skin/classic/browser/quit.svg                       (../shared/icons/quit.svg)
   skin/classic/browser/reload.svg                     (../shared/icons/reload.svg)
   skin/classic/browser/reload-to-stop.svg             (../shared/icons/reload-to-stop.svg)
   skin/classic/browser/save.svg                       (../shared/icons/save.svg)
--- a/browser/themes/shared/menupanel.inc.css
+++ b/browser/themes/shared/menupanel.inc.css
@@ -29,17 +29,17 @@
 }
 
 #appMenu-find-button,
 #panelMenu_searchBookmarks {
   list-style-image: url(chrome://browser/skin/search-glass.svg);
 }
 
 #appMenu-taskmanager-button {
-  list-style-image: url("chrome://browser/skin/performance.svg");
+  list-style-image: url(chrome://global/skin/icons/performance.svg);
 }
 
 #appMenu-help-button {
   list-style-image: url(chrome://global/skin/icons/help.svg);
 }
 
 #appMenu-cut-button {
   list-style-image: url(chrome://browser/skin/edit-cut.svg);
--- a/devtools/client/shared/css-angle.js
+++ b/devtools/client/shared/css-angle.js
@@ -1,25 +1,24 @@
 /* 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, "CSS_ANGLEUNIT",
-  "devtools/shared/css/properties-db", true);
-
 const SPECIALVALUES = new Set([
   "initial",
   "inherit",
   "unset",
 ]);
 
 const {getCSSLexer} = require("devtools/shared/css/lexer");
 
+loader.lazyRequireGetter(this, "CSS_ANGLEUNIT", "devtools/shared/css/constants", true);
+
 /**
  * This module is used to convert between various angle units.
  *
  * Usage:
  *   let {angleUtils} = require("devtools/client/shared/css-angle");
  *   let angle = new angleUtils.CssAngle("180deg");
  *
  *   angle.authored === "180deg"
--- a/devtools/client/shared/output-parser.js
+++ b/devtools/client/shared/output-parser.js
@@ -6,31 +6,39 @@
 
 const Services = require("Services");
 const {angleUtils} = require("devtools/client/shared/css-angle");
 const {colorUtils} = require("devtools/shared/css/color");
 const {getCSSLexer} = require("devtools/shared/css/lexer");
 const EventEmitter = require("devtools/shared/event-emitter");
 const {appendText} = require("devtools/client/inspector/shared/utils");
 
-loader.lazyRequireGetter(this, "ANGLE_TAKING_FUNCTIONS",
-  "devtools/shared/css/properties-db", true);
-loader.lazyRequireGetter(this, "BASIC_SHAPE_FUNCTIONS",
-  "devtools/shared/css/properties-db", true);
-loader.lazyRequireGetter(this, "BEZIER_KEYWORDS",
-  "devtools/shared/css/properties-db", true);
-loader.lazyRequireGetter(this, "COLOR_TAKING_FUNCTIONS",
-  "devtools/shared/css/properties-db", true);
-loader.lazyRequireGetter(this, "CSS_TYPES",
-  "devtools/shared/css/properties-db", true);
+loader.lazyRequireGetter(this, "CSS_TYPES", "devtools/shared/css/constants", true);
 
 const STYLE_INSPECTOR_PROPERTIES = "devtools/shared/locales/styleinspector.properties";
 const {LocalizationHelper} = require("devtools/shared/l10n");
 const STYLE_INSPECTOR_L10N = new LocalizationHelper(STYLE_INSPECTOR_PROPERTIES);
 
+// Functions that accept an angle argument.
+const ANGLE_TAKING_FUNCTIONS = ["linear-gradient", "-moz-linear-gradient",
+                                "repeating-linear-gradient",
+                                "-moz-repeating-linear-gradient", "rotate", "rotateX",
+                                "rotateY", "rotateZ", "rotate3d", "skew", "skewX",
+                                "skewY", "hue-rotate"];
+// All cubic-bezier CSS timing-function names.
+const BEZIER_KEYWORDS = ["linear", "ease-in-out", "ease-in", "ease-out", "ease"];
+// Functions that accept a color argument.
+const COLOR_TAKING_FUNCTIONS = ["linear-gradient", "-moz-linear-gradient",
+                                "repeating-linear-gradient",
+                                "-moz-repeating-linear-gradient", "radial-gradient",
+                                "-moz-radial-gradient", "repeating-radial-gradient",
+                                "-moz-repeating-radial-gradient", "drop-shadow"];
+// Functions that accept a shape argument.
+const BASIC_SHAPE_FUNCTIONS = ["polygon", "circle", "ellipse", "inset"];
+
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 
 const FLEXBOX_HIGHLIGHTER_ENABLED_PREF = "devtools.inspector.flexboxHighlighter.enabled";
 const CSS_SHAPES_ENABLED_PREF = "devtools.inspector.shapesHighlighter.enabled";
 const CSS_SHAPE_OUTSIDE_ENABLED_PREF = "layout.css.shape-outside.enabled";
 
 /**
  * This module is used to process text for output by developer tools. This means
--- a/devtools/client/webreplay/menu.js
+++ b/devtools/client/webreplay/menu.js
@@ -16,63 +16,68 @@ function l10n(key) {
 
 const ChromeUtils = require("ChromeUtils");
 ChromeUtils.defineModuleGetter(this, "Services",
                                "resource://gre/modules/Services.jsm");
 
 function RecordNewTab() {
   const { gBrowser } = Services.wm.getMostRecentWindow("navigator:browser");
   gBrowser.selectedTab = gBrowser.addWebTab("about:blank", { recordExecution: "*" });
+  Services.telemetry.scalarAdd("devtools.webreplay.new_recording", 1);
 }
 
 function ReloadAndRecordTab() {
   const { gBrowser } = Services.wm.getMostRecentWindow("navigator:browser");
   const url = gBrowser.currentURI.spec;
   gBrowser.updateBrowserRemoteness(gBrowser.selectedBrowser, true,
                                    { recordExecution: "*", newFrameloader: true });
   gBrowser.loadURI(url, {
     triggeringPrincipal: gBrowser.selectedBrowser.contentPrincipal,
   });
+  Services.telemetry.scalarAdd("devtools.webreplay.reload_recording", 1);
 }
 
 function ReloadAndStopRecordingTab() {
   const { gBrowser } = Services.wm.getMostRecentWindow("navigator:browser");
   const url = gBrowser.currentURI.spec;
   gBrowser.updateBrowserRemoteness(gBrowser.selectedBrowser, true,
                                    { newFrameloader: true });
   gBrowser.loadURI(url, {
     triggeringPrincipal: gBrowser.selectedBrowser.contentPrincipal,
   });
+  Services.telemetry.scalarAdd("devtools.webreplay.stop_recording", 1);
 }
 
 function SaveRecording() {
   const { gBrowser } = Services.wm.getMostRecentWindow("navigator:browser");
   const fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
   const window = gBrowser.ownerGlobal;
   fp.init(window, null, Ci.nsIFilePicker.modeSave);
   fp.open(rv => {
     if (rv == Ci.nsIFilePicker.returnOK || rv == Ci.nsIFilePicker.returnReplace) {
       const tabParent = gBrowser.selectedTab.linkedBrowser.frameLoader.tabParent;
       if (!tabParent || !tabParent.saveRecording(fp.file.path)) {
         window.alert("Current tab is not recording");
       }
     }
   });
+  Services.telemetry.scalarAdd("devtools.webreplay.save_recording", 1);
 }
 
 function ReplayNewTab() {
   const { gBrowser } = Services.wm.getMostRecentWindow("navigator:browser");
   const fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
   const window = gBrowser.ownerGlobal;
   fp.init(window, null, Ci.nsIFilePicker.modeOpen);
   fp.open(rv => {
     if (rv == Ci.nsIFilePicker.returnOK || rv == Ci.nsIFilePicker.returnReplace) {
       gBrowser.selectedTab = gBrowser.addWebTab(null, { replayExecution: fp.file.path });
     }
   });
+  Services.telemetry.scalarAdd("devtools.webreplay.load_recording", 1);
 }
 
 const menuItems = [
   { id: "devtoolsRecordNewTab", command: RecordNewTab },
   { id: "devtoolsReloadAndRecordTab", command: ReloadAndRecordTab },
   { id: "devtoolsSaveRecording", command: SaveRecording },
   { id: "devtoolsReplayNewTab", command: ReplayNewTab },
 ];
--- a/devtools/server/actors/css-properties.js
+++ b/devtools/server/actors/css-properties.js
@@ -1,23 +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";
 
-loader.lazyRequireGetter(this, "CSS_TYPES",
-  "devtools/shared/css/properties-db", true);
-
 const protocol = require("devtools/shared/protocol");
 const { ActorClassWithSpec, Actor } = protocol;
 const { cssPropertiesSpec } = require("devtools/shared/specs/css-properties");
 const { cssColors } = require("devtools/shared/css/color-db");
 const InspectorUtils = require("InspectorUtils");
 
+loader.lazyRequireGetter(this, "CSS_TYPES", "devtools/shared/css/constants", true);
+
 exports.CssPropertiesActor = ActorClassWithSpec(cssPropertiesSpec, {
   typeName: "cssProperties",
 
   initialize(conn) {
     Actor.prototype.initialize.call(this, conn);
   },
 
   destroy() {
--- a/devtools/shared/css/color.js
+++ b/devtools/shared/css/color.js
@@ -3,18 +3,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const Services = require("Services");
 const {getCSSLexer} = require("devtools/shared/css/lexer");
 const {cssColors} = require("devtools/shared/css/color-db");
 
+loader.lazyRequireGetter(this, "CSS_ANGLEUNIT", "devtools/shared/css/constants", true);
 loader.lazyRequireGetter(this, "getAngleValueInDegrees", "devtools/shared/css/parsing-utils", true);
-loader.lazyRequireGetter(this, "CSS_ANGLEUNIT", "devtools/shared/css/properties-db", true);
 
 const COLOR_UNIT_PREF = "devtools.defaultColorUnit";
 
 const SPECIALVALUES = new Set([
   "currentcolor",
   "initial",
   "inherit",
   "transparent",
new file mode 100644
--- /dev/null
+++ b/devtools/shared/css/constants.js
@@ -0,0 +1,27 @@
+/* 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";
+
+/**
+ * All CSS <angle> types that properties can support.
+ */
+exports.CSS_ANGLEUNIT = {
+  "deg": "deg",
+  "rad": "rad",
+  "grad": "grad",
+  "turn": "turn"
+};
+
+/**
+ * All CSS types that properties can support. This list can be manually edited.
+ *
+ * The existing numbers are for backward compatibility so that newer versions
+ * are still able to debug an old version correctly.
+ */
+exports.CSS_TYPES = {
+  "COLOR": 2,
+  "GRADIENT": 4,
+  "TIMING_FUNCTION": 10,
+};
--- a/devtools/shared/css/moz.build
+++ b/devtools/shared/css/moz.build
@@ -6,12 +6,13 @@
 
 DIRS += [
     'generated',
 ]
 
 DevToolsModules(
     'color-db.js',
     'color.js',
+    'constants.js',
     'lexer.js',
     'parsing-utils.js',
     'properties-db.js',
 )
--- a/devtools/shared/css/parsing-utils.js
+++ b/devtools/shared/css/parsing-utils.js
@@ -9,22 +9,21 @@
 // parseDeclarations - parse a CSS rule into declarations
 // RuleRewriter - rewrite CSS rule text
 // parsePseudoClassesAndAttributes - parse selector and extract
 //     pseudo-classes
 // parseSingleValue - parse a single CSS property value
 
 "use strict";
 
-loader.lazyRequireGetter(this, "CSS_ANGLEUNIT",
-  "devtools/shared/css/properties-db", true);
-
 const promise = require("promise");
 const {getCSSLexer} = require("devtools/shared/css/lexer");
 
+loader.lazyRequireGetter(this, "CSS_ANGLEUNIT", "devtools/shared/css/constants", true);
+
 const SELECTOR_ATTRIBUTE = exports.SELECTOR_ATTRIBUTE = 1;
 const SELECTOR_ELEMENT = exports.SELECTOR_ELEMENT = 2;
 const SELECTOR_PSEUDO_CLASS = exports.SELECTOR_PSEUDO_CLASS = 3;
 
 // Used to test whether a newline appears anywhere in some text.
 const NEWLINE_RX = /[\r\n]/;
 // Used to test whether a bit of text starts an empty comment, either
 // an "ordinary" /* ... */ comment, or a "heuristic bypass" comment
--- a/devtools/shared/css/properties-db.js
+++ b/devtools/shared/css/properties-db.js
@@ -21,63 +21,16 @@ try {
                 `being run, then it needs to be fixed.`, error);
   db = {
     CSS_PROPERTIES: {},
     PSEUDO_ELEMENTS: [],
   };
 }
 
 /**
- * All CSS types that properties can support. This list can be manually edited.
- *
- * The existing numbers are for backward compatibility so that newer versions
- * are still able to debug an old version correctly.
- */
-exports.CSS_TYPES = {
-  "COLOR": 2,
-  "GRADIENT": 4,
-  "TIMING_FUNCTION": 10,
-};
-
-/**
- * All CSS <angle> types that properties can support. This list can be manually edited.
- */
-exports.CSS_ANGLEUNIT = {
-  "deg": "deg",
-  "rad": "rad",
-  "grad": "grad",
-  "turn": "turn",
-};
-
-/**
- * All cubic-bezier CSS timing-function names. This list can be manually edited.
- */
-exports.BEZIER_KEYWORDS = ["linear", "ease-in-out", "ease-in", "ease-out", "ease"];
-
-/**
- * Functions that accept a color argument. This list can be manually edited.
- */
-exports.COLOR_TAKING_FUNCTIONS = ["linear-gradient", "-moz-linear-gradient",
-                                  "repeating-linear-gradient",
-                                  "-moz-repeating-linear-gradient", "radial-gradient",
-                                  "-moz-radial-gradient", "repeating-radial-gradient",
-                                  "-moz-repeating-radial-gradient", "drop-shadow"];
-
-/**
- * Functions that accept an angle argument. This list can be manually edited.
- */
-exports.ANGLE_TAKING_FUNCTIONS = ["linear-gradient", "-moz-linear-gradient",
-                                  "repeating-linear-gradient",
-                                  "-moz-repeating-linear-gradient", "rotate", "rotateX",
-                                  "rotateY", "rotateZ", "rotate3d", "skew", "skewX",
-                                  "skewY", "hue-rotate"];
-
-exports.BASIC_SHAPE_FUNCTIONS = ["polygon", "circle", "ellipse", "inset"];
-
-/**
  * The list of all CSS Pseudo Elements.
  *
  * This list can be updated with `mach devtools-css-db`.
  */
 exports.PSEUDO_ELEMENTS = db.PSEUDO_ELEMENTS;
 
 /**
  * A list of CSS Properties and their various characteristics. This is used on the
--- a/devtools/shared/fronts/css-properties.js
+++ b/devtools/shared/fronts/css-properties.js
@@ -153,17 +153,17 @@ CssProperties.prototype = {
    */
   isInherited(property) {
     return (this.properties[property] && this.properties[property].isInherited) ||
             isCssVariable(property);
   },
 
   /**
    * Checks if the property supports the given CSS type.
-   * CSS types should come from devtools/shared/css/properties-db.js' CSS_TYPES.
+   * CSS types should come from devtools/shared/css/constants.js' CSS_TYPES.
    *
    * @param {String} property The property to be checked.
    * @param {Number} type One of the type values from CSS_TYPES.
    * @return {Boolean}
    */
   supportsType(property, type) {
     return this.properties[property] && this.properties[property].supports.includes(type);
   },
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1726,38 +1726,24 @@ namespace {
 
 void
 DelayedDeleteSubprocess(GeckoChildProcessHost* aSubprocess)
 {
   RefPtr<DeleteTask<GeckoChildProcessHost>> task = new DeleteTask<GeckoChildProcessHost>(aSubprocess);
   XRE_GetIOMessageLoop()->PostTask(task.forget());
 }
 
-// This runnable only exists to delegate ownership of the
-// ContentParent to this runnable, until it's deleted by the event
-// system.
-struct DelayedDeleteContentParentTask : public Runnable
-{
-  explicit DelayedDeleteContentParentTask(ContentParent* aObj)
-    : Runnable("dom::DelayedDeleteContentParentTask")
-    , mKungFuDeathGrip(aObj)
-  {
-  }
-
-  // No-op
-  NS_IMETHOD Run() override { return NS_OK; }
-
-  RefPtr<ContentParent> mKungFuDeathGrip;
-};
-
 } // namespace
 
 void
 ContentParent::ActorDestroy(ActorDestroyReason why)
 {
+  RefPtr<ContentParent> kungFuDeathGrip(mSelfRef.forget());
+  MOZ_RELEASE_ASSERT(kungFuDeathGrip);
+
   if (mForceKillTimer) {
     mForceKillTimer->Cancel();
     mForceKillTimer = nullptr;
   }
 
   // Signal shutdown completion regardless of error state, so we can
   // finish waiting in the xpcom-shutdown/profile-before-change observer.
   mIPCOpen = false;
@@ -1778,17 +1764,16 @@ ContentParent::ActorDestroy(ActorDestroy
     // ShutDownProcess below to perform other necessary clean up.
     mCalledClose = true;
   }
 
   // Make sure we always clean up.
   ShutDownProcess(why == NormalShutdown ? CLOSE_CHANNEL
                                         : CLOSE_CHANNEL_WITH_ERROR);
 
-  RefPtr<ContentParent> kungFuDeathGrip(this);
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     size_t length = ArrayLength(sObserverTopics);
     for (size_t i = 0; i < length; ++i) {
       obs->RemoveObserver(static_cast<nsIObserver*>(this),
                           sObserverTopics[i]);
     }
   }
@@ -1865,17 +1850,19 @@ ContentParent::ActorDestroy(ActorDestroy
 
   // IPDL rules require actors to live on past ActorDestroy, but it
   // may be that the kungFuDeathGrip above is the last reference to
   // |this|.  If so, when we go out of scope here, we're deleted and
   // all hell breaks loose.
   //
   // This runnable ensures that a reference to |this| lives on at
   // least until after the current task finishes running.
-  NS_DispatchToCurrentThread(new DelayedDeleteContentParentTask(this));
+  NS_DispatchToCurrentThread(
+    NS_NewRunnableFunction("DelayedReleaseContentParent",
+                           [kungFuDeathGrip] { }));
 
   ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
   nsTArray<ContentParentId> childIDArray =
     cpm->GetAllChildProcessById(this->ChildID());
 
   // Destroy any processes created by this ContentParent
   for(uint32_t i = 0; i < childIDArray.Length(); i++) {
     ContentParent* cp = cpm->GetContentProcessById(childIDArray[i]);
@@ -2240,16 +2227,19 @@ ContentParent::LaunchSubprocess(ProcessP
 #else
   if (!mSubprocess->LaunchAndWaitForProcessHandle(extraArgs)) {
 #endif
     NS_ERROR("failed to launch child in the parent");
     MarkAsDead();
     return false;
   }
 
+  // See also ActorDestroy.
+  mSelfRef = this;
+
 #ifdef ASYNC_CONTENTPROC_LAUNCH
   OpenWithAsyncPid(mSubprocess->GetChannel());
 #else
   base::ProcessId procId =
     base::GetProcId(mSubprocess->GetChildProcessHandle());
   Open(mSubprocess->GetChannel(), procId);
 #ifdef MOZ_CODE_COVERAGE
   Unused << SendShareCodeCoverageMutex(
@@ -2286,16 +2276,17 @@ ContentParent::LaunchSubprocess(ProcessP
 }
 
 ContentParent::ContentParent(ContentParent* aOpener,
                              const nsAString& aRemoteType,
                              RecordReplayState aRecordReplayState,
                              const nsAString& aRecordingFile,
                              int32_t aJSPluginID)
   : nsIContentParent()
+  , mSelfRef(nullptr)
   , mSubprocess(nullptr)
   , mLaunchTS(TimeStamp::Now())
   , mActivateTS(TimeStamp::Now())
   , mOpener(aOpener)
   , mRemoteType(aRemoteType)
   , mChildID(gContentChildID++)
   , mGeolocationWatchID(-1)
   , mJSPluginID(aJSPluginID)
@@ -3340,21 +3331,16 @@ ContentParent::KillHard(const char* aRea
   // process handle becomes invalid on the first call, causing a second call
   // to crash our process - more details in bug 890840.
   if (mCalledKillHard) {
     return;
   }
   mCalledKillHard = true;
   mForceKillTimer = nullptr;
 
-  MessageChannel* channel = GetIPCChannel();
-  if (channel) {
-    channel->SetInKillHardShutdown();
-  }
-
   // We're about to kill the child process associated with this content.
   // Something has gone wrong to get us here, so we generate a minidump
   // of the parent and child for submission to the crash server.
   if (mCrashReporter) {
     // GeneratePairedMinidump creates two minidumps for us - the main
     // one is for the content process we're about to kill, and the other
     // one is for the main browser process. That second one is the extra
     // minidump tagging along, so we have to tell the crash reporter that
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -1275,16 +1275,18 @@ public:
 
   nsresult SaveRecording(nsIFile* aFile, bool* aRetval);
 
   bool IsRecordingOrReplaying() const {
     return mRecordReplayState != eNotRecordingOrReplaying;
   }
 
 private:
+  // Released in ActorDestroy; deliberately not exposed to the CC.
+  RefPtr<ContentParent> mSelfRef;
 
   // If you add strong pointers to cycle collected objects here, be sure to
   // release these objects in ShutDownProcess.  See the comment there for more
   // details.
 
   ContentProcessHost* mSubprocess;
   const TimeStamp mLaunchTS; // used to calculate time to start content process
   TimeStamp mActivateTS;
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -629,17 +629,16 @@ MessageChannel::MessageChannel(const cha
     mSawInterruptOutMsg(false),
     mIsWaitingForIncoming(false),
     mAbortOnError(false),
     mNotifiedChannelDone(false),
     mFlags(REQUIRE_DEFAULT),
     mPeerPidSet(false),
     mPeerPid(-1),
     mIsPostponingSends(false),
-    mInKillHardShutdown(false),
     mBuildIDsConfirmedMatch(false)
 {
     MOZ_COUNT_CTOR(ipc::MessageChannel);
 
 #ifdef OS_WIN
     mTopFrame = nullptr;
     mIsSyncWaitingOnNonMainThread = false;
 #endif
@@ -793,20 +792,17 @@ MessageChannel::Clear()
     // Also don't clear mListener.  If we clear it, then sending a message
     // through this channel after it's Clear()'ed can cause this process to
     // crash.
     //
     // In practice, mListener owns the channel, so the channel gets deleted
     // before mListener.  But just to be safe, mListener is a weak pointer.
 
 #if !defined(ANDROID)
-    // KillHard shutdowns can occur with the channel in connected state. We are
-    // already collecting crash dump data about KillHard shutdowns and we
-    // shouldn't intentionally crash here.
-    if (!Unsound_IsClosed() && !mInKillHardShutdown) {
+    if (!Unsound_IsClosed()) {
         CrashReporter::AnnotateCrashReport(
           CrashReporter::Annotation::IPCFatalErrorProtocol, nsDependentCString(mName));
         switch (mChannelState) {
             case ChannelOpening:
                 MOZ_CRASH("MessageChannel destroyed without being closed " \
                           "(mChannelState == ChannelOpening).");
                 break;
             case ChannelConnected:
--- a/ipc/glue/MessageChannel.h
+++ b/ipc/glue/MessageChannel.h
@@ -326,20 +326,16 @@ private:
 
     static bool IsPumpingMessages() {
         return sIsPumpingMessages;
     }
     static void SetIsPumpingMessages(bool aIsPumping) {
         sIsPumpingMessages = aIsPumping;
     }
 
-    void SetInKillHardShutdown() {
-        mInKillHardShutdown = true;
-    }
-
 #ifdef OS_WIN
     struct MOZ_STACK_CLASS SyncStackFrame
     {
         SyncStackFrame(MessageChannel* channel, bool interrupt);
         ~SyncStackFrame();
 
         bool mInterrupt;
         bool mSpinNestedEvents;
@@ -859,18 +855,16 @@ private:
     bool mPeerPidSet;
     int32_t mPeerPid;
 
     // Channels can enter messages are not sent immediately; instead, they are
     // held in a queue until another thread deems it is safe to send them.
     bool mIsPostponingSends;
     std::vector<UniquePtr<Message>> mPostponedSends;
 
-    bool mInKillHardShutdown;
-
     bool mBuildIDsConfirmedMatch;
 };
 
 void
 CancelCPOWs();
 
 } // namespace ipc
 } // namespace mozilla
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -4345,41 +4345,65 @@ PromiseObject::dependentPromises(JSConte
 
     RootedValue reactionsVal(cx, reactions());
 
     // If no reactions are pending, we don't have list and are done.
     if (reactionsVal.isNullOrUndefined()) {
         return true;
     }
 
-    RootedNativeObject reactions(cx, &reactionsVal.toObject().as<NativeObject>());
-
-    // If only a single reaction is pending, it's stored directly.
-    if (reactions->is<PromiseReactionRecord>()) {
+    RootedObject reactionsObj(cx, &reactionsVal.toObject());
+
+    // If only a single reaction exists, it's stored directly instead of in a
+    // list. In that case, `reactionsObj` might be a wrapper, which we can
+    // always safely unwrap.
+    if (IsProxy(reactionsObj)) {
+        reactionsObj = UncheckedUnwrap(reactionsObj);
+        if (JS_IsDeadWrapper(reactionsObj)) {
+            JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
+            return false;
+        }
+        MOZ_RELEASE_ASSERT(reactionsObj->is<PromiseReactionRecord>());
+    }
+
+    if (reactionsObj->is<PromiseReactionRecord>()) {
         // Not all reactions have a Promise on them.
-        RootedObject promiseObj(cx, reactions->as<PromiseReactionRecord>().promise());
+        RootedObject promiseObj(cx, reactionsObj->as<PromiseReactionRecord>().promise());
         if (!promiseObj) {
             return true;
         }
 
         if (!values.growBy(1)) {
             return false;
         }
 
         values[0].setObject(*promiseObj);
         return true;
     }
 
+    MOZ_RELEASE_ASSERT(reactionsObj->is<NativeObject>());
+    HandleNativeObject reactions = reactionsObj.as<NativeObject>();
+
     uint32_t len = reactions->getDenseInitializedLength();
     MOZ_ASSERT(len >= 2);
 
     uint32_t valuesIndex = 0;
+    Rooted<PromiseReactionRecord*> reaction(cx);
     for (uint32_t i = 0; i < len; i++) {
-        const Value& element = reactions->getDenseElement(i);
-        PromiseReactionRecord* reaction = &element.toObject().as<PromiseReactionRecord>();
+        JSObject* element = &reactions->getDenseElement(i).toObject();
+        if (IsProxy(element)) {
+            element = UncheckedUnwrap(element);
+            if (JS_IsDeadWrapper(element)) {
+                JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
+                return false;
+            }
+        }
+
+        MOZ_RELEASE_ASSERT(element->is<PromiseReactionRecord>());
+        reaction = &element->as<PromiseReactionRecord>();
 
         // Not all reactions have a Promise on them.
         RootedObject promiseObj(cx, reaction->promise());
         if (!promiseObj) {
             continue;
         }
         if (!values.growBy(1)) {
             return false;
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Object-promiseDependentPromises-realms.js
@@ -0,0 +1,17 @@
+// Bug 1475669 - Cross-compartment dependent promises.
+
+// Create a promise in realm 1.
+let g1 = newGlobal();
+let p1 = new g1.Promise((_resolve, _reject) => {});
+
+// Add a dependent promise in realm 2.
+let g2 = newGlobal();
+let p2 = g2.Promise.prototype.then.call(p1, g2.eval(`value => {}`));
+
+// Use debugger to find p2 from p1.
+let dbg = new Debugger;
+let g1w = dbg.addDebuggee(g1);
+let g2w = dbg.addDebuggee(g2);
+let dependents = g1w.makeDebuggeeValue(p1).promiseDependentPromises;
+assertEq(dependents.length, 1);
+assertEq(dependents[0], g2w.makeDebuggeeValue(p2));
--- a/testing/awsy/awsy/process_perf_data.py
+++ b/testing/awsy/awsy/process_perf_data.py
@@ -77,20 +77,30 @@ def create_suite(name, node, data_path, 
     :param checkpoints: Which checkpoints to include.
     """
     suite = {
         'name': name,
         'subtests': [],
         'lowerIsBetter': True,
         'units': 'bytes'
     }
+
+    extra_opts = []
+    # The stylo attributes override each other.
     if 'STYLO_FORCE_ENABLED' in os.environ and os.environ['STYLO_FORCE_ENABLED']:
-        suite['extraOptions'] = ["stylo"]
+        extra_opts = ["stylo"]
     if 'STYLO_THREADS' in os.environ and os.environ['STYLO_THREADS'] == '1':
-        suite['extraOptions'] = ["stylo-sequential"]
+        extra_opts = ["stylo-sequential"]
+
+    if 'DMD' in os.environ and os.environ['DMD']:
+        extra_opts.append("dmd")
+
+    if extra_opts:
+        suite['extraOptions'] = extra_opts
+
     update_checkpoint_paths(glob.glob(os.path.join(data_path, "memory-report*")), checkpoints)
 
     total = 0
     for checkpoint in checkpoints:
         memory_report_path = os.path.join(data_path, checkpoint['path'])
 
         name_filter = checkpoint.get('name_filter', None)
         if checkpoint.get('median'):
deleted file mode 100644
--- a/testing/web-platform/meta/html/semantics/text-level-semantics/the-wbr-element/wbr-element.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[wbr-element.html]
-  expected:
-    if not debug and not webrender and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-    if debug and not webrender and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/infrastructure/assumptions/ahem.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[ahem.html]
-  expected:
-    if not debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-    if debug and not webrender and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
--- a/testing/web-platform/meta/webvtt/rendering/cues-with-video/processing-model/too_many_cues.html.ini
+++ b/testing/web-platform/meta/webvtt/rendering/cues-with-video/processing-model/too_many_cues.html.ini
@@ -1,5 +1,3 @@
 [too_many_cues.html]
   expected:
-    if debug and not webrender and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): PASS
-    if not debug and not webrender and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): PASS
     FAIL
--- a/toolkit/components/aboutperformance/content/aboutPerformance.xhtml
+++ b/toolkit/components/aboutperformance/content/aboutPerformance.xhtml
@@ -2,18 +2,18 @@
 
 <!-- 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/. -->
 
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <title data-l10n-id="about-performance-title"/>
-    <link rel="icon" type="image/png" id="favicon"
-          href="chrome://branding/content/icon32.png"/>
+    <link rel="icon" type="image/svg+xml" id="favicon"
+          href="chrome://global/skin/icons/performance.svg"/>
     <link rel="stylesheet" href="chrome://global/skin/in-content/common.css"
           type="text/css"/>
     <link rel="localization" href="toolkit/about/aboutPerformance.ftl"/>
     <script type="text/javascript" src="chrome://global/content/aboutPerformance.js"></script>
     <style>
       @import url("chrome://global/skin/in-content/common.css");
 
       html {
--- a/toolkit/components/telemetry/Scalars.yaml
+++ b/toolkit/components/telemetry/Scalars.yaml
@@ -1485,16 +1485,77 @@ devtools.toolbox:
     keyed: true
     notification_emails:
       - dev-developer-tools@lists.mozilla.org
       - daisuke@mozilla.com
     release_channel_collection: opt-out
     record_in_processes:
       - 'main'
 
+devtools.webreplay:
+  new_recording:
+    bug_numbers:
+     - 1495910
+    description: >
+      Number of times a blank recording tab was created.
+    expires: never
+    kind: uint
+    notification_emails:
+     - bhackett@mozilla.com
+    record_in_processes:
+     - 'main'
+
+  reload_recording:
+    bug_numbers:
+     - 1495910
+    description: >
+      Number of times a non-recording tab was reloaded to create a recording tab.
+    expires: never
+    kind: uint
+    notification_emails:
+     - bhackett@mozilla.com
+    record_in_processes:
+     - 'main'
+
+  stop_recording:
+    bug_numbers:
+     - 1495910
+    description: >
+      Number of times a recording tab was reloaded to create a non-recording tab.
+    expires: never
+    kind: uint
+    notification_emails:
+     - bhackett@mozilla.com
+    record_in_processes:
+     - 'main'
+
+  save_recording:
+    bug_numbers:
+     - 1495910
+    description: >
+      Number of times a recording was saved.
+    expires: never
+    kind: uint
+    notification_emails:
+     - bhackett@mozilla.com
+    record_in_processes:
+     - 'main'
+
+  load_recording:
+    bug_numbers:
+     - 1495910
+    description: >
+      Number of times a recording was loaded.
+    expires: never
+    kind: uint
+    notification_emails:
+     - bhackett@mozilla.com
+    record_in_processes:
+     - 'main'
+
 navigator.storage:
   estimate_count:
     bug_numbers:
       - 1359708
     description: >
       Number of times navigator.storage.estimate has been used.
     expires: "60"
     kind: uint
--- a/toolkit/content/widgets/toolbar.xml
+++ b/toolkit/content/widgets/toolbar.xml
@@ -4,111 +4,16 @@
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 
 <bindings id="toolbarBindings"
           xmlns="http://www.mozilla.org/xbl"
           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
           xmlns:xbl="http://www.mozilla.org/xbl">
 
-  <binding id="toolbar-menubar-autohide">
-    <implementation>
-      <constructor>
-        this._setInactive();
-      </constructor>
-      <destructor>
-        this._setActive();
-      </destructor>
-
-      <field name="_inactiveTimeout">null</field>
-
-      <field name="_contextMenuListener"><![CDATA[({
-        toolbar: this,
-        contextMenu: null,
-
-        get active() {
-          return !!this.contextMenu;
-        },
-
-        init(event) {
-          var node = event.target;
-          while (node != this.toolbar) {
-            if (node.localName == "menupopup")
-              return;
-            node = node.parentNode;
-          }
-
-          var contextMenuId = this.toolbar.getAttribute("context");
-          if (!contextMenuId)
-            return;
-
-          this.contextMenu = document.getElementById(contextMenuId);
-          if (!this.contextMenu)
-            return;
-
-          this.contextMenu.addEventListener("popupshown", this);
-          this.contextMenu.addEventListener("popuphiding", this);
-          this.toolbar.addEventListener("mousemove", this);
-        },
-        handleEvent(event) {
-          switch (event.type) {
-            case "popupshown":
-              this.toolbar.removeEventListener("mousemove", this);
-              break;
-            case "popuphiding":
-            case "mousemove":
-              this.toolbar._setInactiveAsync();
-              this.toolbar.removeEventListener("mousemove", this);
-              this.contextMenu.removeEventListener("popuphiding", this);
-              this.contextMenu.removeEventListener("popupshown", this);
-              this.contextMenu = null;
-              break;
-          }
-        },
-      })]]></field>
-
-      <method name="_setInactive">
-        <body><![CDATA[
-          this.setAttribute("inactive", "true");
-        ]]></body>
-      </method>
-
-      <method name="_setInactiveAsync">
-        <body><![CDATA[
-          this._inactiveTimeout = setTimeout(function(self) {
-            if (self.getAttribute("autohide") == "true") {
-              self._inactiveTimeout = null;
-              self._setInactive();
-            }
-          }, 0, this);
-        ]]></body>
-      </method>
-
-      <method name="_setActive">
-        <body><![CDATA[
-          if (this._inactiveTimeout) {
-            clearTimeout(this._inactiveTimeout);
-            this._inactiveTimeout = null;
-          }
-          this.removeAttribute("inactive");
-        ]]></body>
-      </method>
-    </implementation>
-
-    <handlers>
-      <handler event="DOMMenuBarActive"     action="this._setActive();"/>
-      <handler event="popupshowing"         action="this._setActive();"/>
-      <handler event="mousedown" button="2" action="this._contextMenuListener.init(event);"/>
-      <handler event="DOMMenuBarInactive"><![CDATA[
-        if (!this._contextMenuListener.active)
-          this._setInactiveAsync();
-      ]]></handler>
-    </handlers>
-  </binding>
-
   <binding id="toolbar-drag">
     <implementation>
       <field name="_dragBindingAlive">true</field>
       <constructor><![CDATA[
         if (!this._draggableStarted) {
           this._draggableStarted = true;
           try {
             let tmp = {};
--- a/toolkit/content/xul.css
+++ b/toolkit/content/xul.css
@@ -279,17 +279,16 @@ toolbar[customizing="true"][hidden="true
 
 %ifdef XP_MACOSX
 toolbar[type="menubar"] {
   min-height: 0 !important;
   border: 0 !important;
 }
 %else
 toolbar[type="menubar"][autohide="true"] {
-  -moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbar-menubar-autohide");
   overflow: hidden;
 }
 
 toolbar[type="menubar"][autohide="true"][inactive="true"]:not([customizing="true"]) {
   min-height: 0 !important;
   height: 0 !important;
   -moz-appearance: none !important;
   border-style: none !important;
rename from browser/themes/shared/icons/performance.svg
rename to toolkit/themes/shared/icons/performance.svg
--- a/toolkit/themes/shared/jar.inc.mn
+++ b/toolkit/themes/shared/jar.inc.mn
@@ -34,16 +34,17 @@ toolkit.jar:
   skin/classic/global/icons/close.svg                      (../../shared/icons/close.svg)
   skin/classic/global/icons/error.svg                      (../../shared/icons/error.svg)
   skin/classic/global/icons/find-previous-arrow.svg        (../../shared/icons/find-previous-arrow.svg)
   skin/classic/global/icons/find-next-arrow.svg            (../../shared/icons/find-next-arrow.svg)
   skin/classic/global/icons/help.svg                       (../../shared/icons/help.svg)
   skin/classic/global/icons/info.svg                       (../../shared/incontent-icons/info.svg)
   skin/classic/global/icons/loading.png                    (../../shared/icons/loading.png)
   skin/classic/global/icons/loading@2x.png                 (../../shared/icons/loading@2x.png)
+  skin/classic/global/icons/performance.svg                (../../shared/icons/performance.svg)
   skin/classic/global/icons/resizer.svg                    (../../shared/icons/resizer.svg)
   skin/classic/global/icons/shortcut.svg                   (../../shared/icons/shortcut.svg)
   skin/classic/global/icons/spinner-arrow-down.svg         (../../shared/icons/spinner-arrow-down.svg)
   skin/classic/global/icons/spinner-arrow-up.svg           (../../shared/icons/spinner-arrow-up.svg)
   skin/classic/global/icons/twisty-collapsed.svg           (../../shared/icons/twisty-collapsed.svg)
   skin/classic/global/icons/twisty-collapsed-rtl.svg       (../../shared/icons/twisty-collapsed-rtl.svg)
   skin/classic/global/icons/twisty-expanded.svg            (../../shared/icons/twisty-expanded.svg)
   skin/classic/global/icons/arrow-dropdown-12.svg          (../../shared/icons/arrow-dropdown-12.svg)