Merge autoland to m-c, a=merge
authorPhil Ringnalda <philringnalda@gmail.com>
Sat, 10 Dec 2016 08:23:52 -0800
changeset 325580 5cc901aa30a2f8ce528082f8b5a4f06c34fef363
parent 325492 97c0626d8789b7bcaaa04e4661bf36f58f3fb82b (current diff)
parent 325579 14617919dacee1191582e731509fd55d06b11d27 (diff)
child 325624 c51e7406d7b2e2246a1ece0d8989282ca752039f
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersmerge
milestone53.0a1
Merge autoland to m-c, a=merge MozReview-Commit-ID: L49FlCjxKhb
toolkit/modules/secondscreen/PresentationApp.jsm
--- a/.eslintignore
+++ b/.eslintignore
@@ -91,20 +91,23 @@ devtools/client/projecteditor/**
 devtools/client/promisedebugger/**
 devtools/client/responsivedesign/**
 devtools/client/scratchpad/**
 devtools/client/shadereditor/**
 devtools/client/shared/*.jsm
 devtools/client/shared/webgl-utils.js
 devtools/client/shared/widgets/*.jsm
 devtools/client/webaudioeditor/**
-devtools/client/webconsole/**
-!devtools/client/webconsole/panel.js
-!devtools/client/webconsole/jsterm.js
-!devtools/client/webconsole/console-commands.js
+devtools/client/webconsole/net/**
+devtools/client/webconsole/test/**
+devtools/client/webconsole/console-output.js
+devtools/client/webconsole/hudservice.js
+devtools/client/webconsole/utils.js
+devtools/client/webconsole/webconsole-connection-proxy.js
+devtools/client/webconsole/webconsole.js
 devtools/client/webide/**
 !devtools/client/webide/components/webideCli.js
 devtools/server/*.js
 devtools/server/*.jsm
 !devtools/server/child.js
 !devtools/server/css-logic.js
 !devtools/server/main.js
 !devtools/server/websocket-server.js
--- a/browser/components/extensions/ext-windows.js
+++ b/browser/components/extensions/ext-windows.js
@@ -55,16 +55,19 @@ extensions.registerSchemaAPI("windows", 
         return () => {
           AllWindowEvents.removeListener("focus", listener);
           AllWindowEvents.removeListener("blur", listener);
         };
       }).api(),
 
       get: function(windowId, getInfo) {
         let window = WindowManager.getWindow(windowId, context);
+        if (!window) {
+          return Promise.reject({message: `Invalid window ID: ${windowId}`});
+        }
         return Promise.resolve(WindowManager.convert(extension, window, getInfo));
       },
 
       getCurrent: function(getInfo) {
         let window = currentWindow(context);
         return Promise.resolve(WindowManager.convert(extension, window, getInfo));
       },
 
--- a/browser/components/extensions/test/browser/browser_ext_windows.js
+++ b/browser/components/extensions/test/browser/browser_ext_windows.js
@@ -1,13 +1,13 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
-add_task(function* () {
+add_task(function* testWindowGetAll() {
   let raisedWin = Services.ww.openWindow(
     null, Services.prefs.getCharPref("browser.chromeURL"), "_blank",
     "chrome,dialog=no,all,alwaysRaised", null);
 
   yield TestUtils.topicObserved("browser-delayed-startup-finished",
                                 subject => subject == raisedWin);
 
   let extension = ExtensionTestUtils.loadExtension({
@@ -26,8 +26,25 @@ add_task(function* () {
   });
 
   yield extension.startup();
   yield extension.awaitFinish("alwaysOnTop");
   yield extension.unload();
 
   yield BrowserTestUtils.closeWindow(raisedWin);
 });
+
+add_task(function* testInvalidWindowId() {
+  let extension = ExtensionTestUtils.loadExtension({
+    async background() {
+      await browser.test.assertRejects(
+        // Assuming that this windowId does not exist.
+        browser.windows.get(123456789),
+        /Invalid window/,
+        "Should receive invalid window");
+      browser.test.notifyPass("windows.get.invalid");
+    },
+  });
+
+  yield extension.startup();
+  yield extension.awaitFinish("windows.get.invalid");
+  yield extension.unload();
+});
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/new-console-output/.eslintrc.js
@@ -0,0 +1,5 @@
+"use strict";
+
+module.exports = {
+  "env": { "browser": true }
+};
--- a/devtools/client/webconsole/new-console-output/components/console-output.js
+++ b/devtools/client/webconsole/new-console-output/components/console-output.js
@@ -4,17 +4,16 @@
 "use strict";
 
 const {
   createClass,
   createFactory,
   DOM: dom,
   PropTypes
 } = require("devtools/client/shared/vendor/react");
-const ReactDOM = require("devtools/client/shared/vendor/react-dom");
 const { connect } = require("devtools/client/shared/vendor/react-redux");
 
 const {
   getAllMessages,
   getAllMessagesUiById,
   getAllMessagesTableDataById,
   getAllGroupsById,
 } = require("devtools/client/webconsole/new-console-output/selectors/messages");
--- a/devtools/client/webconsole/new-console-output/components/message.js
+++ b/devtools/client/webconsole/new-console-output/components/message.js
@@ -58,17 +58,18 @@ const Message = createClass({
   componentDidMount() {
     if (this.messageNode) {
       if (this.props.scrollToMessage) {
         this.messageNode.scrollIntoView();
       }
       // Event used in tests. Some message types don't pass it in because existing tests
       // did not emit for them.
       if (this.props.serviceContainer) {
-        this.props.serviceContainer.emitNewMessage(this.messageNode, this.props.messageId);
+        this.props.serviceContainer.emitNewMessage(
+          this.messageNode, this.props.messageId);
       }
     }
   },
 
   onLearnMoreClick: function () {
     let {exceptionDocURL} = this.props;
     this.props.serviceContainer.openLink(exceptionDocURL);
   },
--- a/devtools/client/webconsole/new-console-output/main.js
+++ b/devtools/client/webconsole/new-console-output/main.js
@@ -3,21 +3,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
  /* global BrowserLoader */
 
 "use strict";
 
 var { utils: Cu } = Components;
 
-const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
 const { BrowserLoader } = Cu.import("resource://devtools/client/shared/browser-loader.js", {});
 
 // Initialize module loader and load all modules of the new inline
 // preview feature. The entire code-base doesn't need any extra
 // privileges and runs entirely in content scope.
 const NewConsoleOutputWrapper = BrowserLoader({
   baseURI: "resource://devtools/client/webconsole/new-console-output/",
   window}).require("./new-console-output-wrapper");
 
 this.NewConsoleOutput = function (parentNode, jsterm, toolbox, owner, serviceContainer) {
-  return new NewConsoleOutputWrapper(parentNode, jsterm, toolbox, owner, serviceContainer);
+  return new NewConsoleOutputWrapper(
+    parentNode, jsterm, toolbox, owner, serviceContainer);
 };
--- a/devtools/client/webconsole/new-console-output/test/chrome/head.js
+++ b/devtools/client/webconsole/new-console-output/test/chrome/head.js
@@ -1,16 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
+/* exported Task, browserRequire */
 
 "use strict";
 
 var { utils: Cu } = Components;
 
 var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
-var { Assert } = require("resource://testing-common/Assert.jsm");
 var { BrowserLoader } = Cu.import("resource://devtools/client/shared/browser-loader.js", {});
 var { Task } = require("devtools/shared/task");
 
 var { require: browserRequire } = BrowserLoader({
   baseURI: "resource://devtools/client/webconsole/",
   window
 });
--- a/devtools/client/webconsole/new-console-output/test/chrome/test_render_perf.html
+++ b/devtools/client/webconsole/new-console-output/test/chrome/test_render_perf.html
@@ -8,16 +8,18 @@
   <!-- Any copyright is dedicated to the Public Domain.
      - http://creativecommons.org/publicdomain/zero/1.0/ -->
 </head>
 <body>
 <p>Test for render perf</p>
 <div id="output"></div>
 
 <script type="text/javascript;version=1.8">
+"use strict";
+
 const testPackets = [];
 const numMessages = 1000;
 for (let id = 0; id < numMessages; id++) {
   let message = "Odd text";
   if (id % 2 === 0) {
     message = "Even text";
   }
   testPackets.push({
@@ -52,19 +54,22 @@ function timeit(cb) {
     let start = performance.now();
     cb();
     let elapsed = performance.now() - start;
     resolve(elapsed / 1000);
   });
 }
 
 window.onload = Task.async(function* () {
-  const { configureStore } = browserRequire("devtools/client/webconsole/new-console-output/store");
-  const { filterTextSet, filtersClear } = browserRequire("devtools/client/webconsole/new-console-output/actions/index");
-  const NewConsoleOutputWrapper = browserRequire("devtools/client/webconsole/new-console-output/new-console-output-wrapper");
+  const { configureStore } = browserRequire(
+    "devtools/client/webconsole/new-console-output/store");
+  const { filterTextSet, filtersClear } = browserRequire(
+    "devtools/client/webconsole/new-console-output/actions/index");
+  const NewConsoleOutputWrapper = browserRequire(
+    "devtools/client/webconsole/new-console-output/new-console-output-wrapper");
   const wrapper = new NewConsoleOutputWrapper(document.querySelector("#output"), {});
 
   const store = configureStore();
 
   let time = yield timeit(() => {
     testPackets.forEach((message) => {
       wrapper.dispatchMessageAdd(message);
     });
--- a/devtools/client/webconsole/new-console-output/test/components/console-api-call.test.js
+++ b/devtools/client/webconsole/new-console-output/test/components/console-api-call.test.js
@@ -29,17 +29,19 @@ const tempfilePath = "http://example.com
 describe("ConsoleAPICall component:", () => {
   describe("console.log", () => {
     it("renders string grips", () => {
       const message = stubPreparedMessages.get("console.log('foobar', 'test')");
       const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
 
       expect(wrapper.find(".message-body").text()).toBe("foobar test");
       expect(wrapper.find(".objectBox-string").length).toBe(2);
-      expect(wrapper.find("div.message.cm-s-mozilla span span.message-flex-body span.message-body.devtools-monospace").length).toBe(1);
+      let selector = "div.message.cm-s-mozilla span span.message-flex-body " +
+        "span.message-body.devtools-monospace";
+      expect(wrapper.find(selector).length).toBe(1);
 
       // There should be the location
       const locationLink = wrapper.find(`.message-location`);
       expect(locationLink.length).toBe(1);
       expect(locationLink.text()).toBe("test-tempfile.js:1:27");
     });
 
     it("renders string grips with custom style", () => {
@@ -70,17 +72,19 @@ describe("ConsoleAPICall component:", ()
       const message =
         stubPreparedMessages.get("console.log('foobar', 'test')")
         .set("repeat", 107);
       const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
 
       expect(wrapper.find(".message-repeats").text()).toBe("107");
       expect(wrapper.find(".message-repeats").prop("title")).toBe("107 repeats");
 
-      expect(wrapper.find("span > span.message-flex-body > span.message-body.devtools-monospace + span.message-repeats").length).toBe(1);
+      let selector = "span > span.message-flex-body > " +
+        "span.message-body.devtools-monospace + span.message-repeats";
+      expect(wrapper.find(selector).length).toBe(1);
     });
 
     it("has the expected indent", () => {
       const message = stubPreparedMessages.get("console.log('foobar', 'test')");
 
       const indent = 10;
       let wrapper = render(ConsoleApiCall({ message, serviceContainer, indent }));
       expect(wrapper.find(".indent").prop("style").width)
@@ -106,20 +110,22 @@ describe("ConsoleAPICall component:", ()
       const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
 
       expect(wrapper.find(".message-body").text()).toBe("bar: 1");
     });
   });
 
   describe("console.assert", () => {
     it("renders", () => {
-      const message = stubPreparedMessages.get("console.assert(false, {message: 'foobar'})");
+      const message = stubPreparedMessages.get(
+        "console.assert(false, {message: 'foobar'})");
       const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
 
-      expect(wrapper.find(".message-body").text()).toBe("Assertion failed: Object { message: \"foobar\" }");
+      expect(wrapper.find(".message-body").text())
+        .toBe("Assertion failed: Object { message: \"foobar\" }");
     });
   });
 
   describe("console.time", () => {
     it("does not show anything", () => {
       const message = stubPreparedMessages.get("console.time('bar')");
       const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
 
@@ -140,29 +146,36 @@ describe("ConsoleAPICall component:", ()
   describe("console.trace", () => {
     it("renders", () => {
       const message = stubPreparedMessages.get("console.trace()");
       const wrapper = render(ConsoleApiCall({ message, serviceContainer, open: true }));
       const filepath = `${tempfilePath}`;
 
       expect(wrapper.find(".message-body").text()).toBe("console.trace()");
 
-      const frameLinks = wrapper.find(`.stack-trace span.frame-link[data-url='${filepath}']`);
+      const frameLinks = wrapper.find(
+        `.stack-trace span.frame-link[data-url='${filepath}']`);
       expect(frameLinks.length).toBe(3);
 
-      expect(frameLinks.eq(0).find(".frame-link-function-display-name").text()).toBe("testStacktraceFiltering");
-      expect(frameLinks.eq(0).find(".frame-link-filename").text()).toBe(filepath);
+      expect(frameLinks.eq(0).find(".frame-link-function-display-name").text())
+        .toBe("testStacktraceFiltering");
+      expect(frameLinks.eq(0).find(".frame-link-filename").text())
+        .toBe(filepath);
 
-      expect(frameLinks.eq(1).find(".frame-link-function-display-name").text()).toBe("foo");
-      expect(frameLinks.eq(1).find(".frame-link-filename").text()).toBe(filepath);
+      expect(frameLinks.eq(1).find(".frame-link-function-display-name").text())
+        .toBe("foo");
+      expect(frameLinks.eq(1).find(".frame-link-filename").text())
+        .toBe(filepath);
 
-      expect(frameLinks.eq(2).find(".frame-link-function-display-name").text()).toBe("triggerPacket");
-      expect(frameLinks.eq(2).find(".frame-link-filename").text()).toBe(filepath);
+      expect(frameLinks.eq(2).find(".frame-link-function-display-name").text())
+        .toBe("triggerPacket");
+      expect(frameLinks.eq(2).find(".frame-link-filename").text())
+        .toBe(filepath);
 
-      //it should not be collapsible.
+      // it should not be collapsible.
       expect(wrapper.find(`.theme-twisty`).length).toBe(0);
     });
   });
 
   describe("console.group", () => {
     it("renders", () => {
       const message = stubPreparedMessages.get("console.group('bar')");
       const wrapper = render(ConsoleApiCall({ message, serviceContainer, open: true }));
--- a/devtools/client/webconsole/new-console-output/test/components/filter-bar.test.js
+++ b/devtools/client/webconsole/new-console-output/test/components/filter-bar.test.js
@@ -35,17 +35,18 @@ describe("FilterBar component:", () => {
     expect(toolbar.children().eq(0).attr("title")).toBe("Clear output");
 
     // Filter bar toggle
     expect(toolbar.children().eq(1).attr("class"))
       .toBe("devtools-button devtools-filter-icon");
     expect(toolbar.children().eq(1).attr("title")).toBe("Toggle filter bar");
 
     // Text filter
-    expect(toolbar.children().eq(2).attr("class")).toBe("devtools-plaininput text-filter");
+    expect(toolbar.children().eq(2).attr("class"))
+      .toBe("devtools-plaininput text-filter");
     expect(toolbar.children().eq(2).attr("placeholder")).toBe("Filter output");
     expect(toolbar.children().eq(2).attr("type")).toBe("search");
     expect(toolbar.children().eq(2).attr("value")).toBe("");
   });
 
   it("displays filter bar when button is clicked", () => {
     const store = setupStore([]);
 
@@ -66,17 +67,18 @@ describe("FilterBar component:", () => {
     const debugButton = FilterButton(Object.assign({}, buttonProps,
       { label: "Debug", filterKey: MESSAGE_LEVEL.DEBUG }));
     const infoButton = FilterButton(Object.assign({}, buttonProps,
       { label: "Info", filterKey: MESSAGE_LEVEL.INFO }));
     const warnButton = FilterButton(Object.assign({}, buttonProps,
       { label: "Warnings", filterKey: MESSAGE_LEVEL.WARN }));
     const errorButton = FilterButton(Object.assign({}, buttonProps,
       { label: "Errors", filterKey: MESSAGE_LEVEL.ERROR }));
-    expect(wrapper.contains([errorButton, warnButton, logButton, infoButton, debugButton])).toBe(true);
+    let buttons = [errorButton, warnButton, logButton, infoButton, debugButton];
+    expect(wrapper.contains(buttons)).toBe(true);
   });
 
   it("fires MESSAGES_CLEAR action when clear button is clicked", () => {
     const store = setupStore([]);
     store.dispatch = sinon.spy();
 
     const wrapper = mount(Provider({store}, FilterBar({ serviceContainer })));
     wrapper.find(".devtools-clear-icon").simulate("click");
--- a/devtools/client/webconsole/new-console-output/test/components/network-event-message.test.js
+++ b/devtools/client/webconsole/new-console-output/test/components/network-event-message.test.js
@@ -27,17 +27,19 @@ describe("NetworkEventMessage component:
       const L10n = require("devtools/client/webconsole/new-console-output/test/fixtures/L10n");
       const { timestampString } = new L10n();
 
       expect(wrapper.find(".timestamp").text()).toBe(timestampString(message.timeStamp));
       expect(wrapper.find(".message-body .method").text()).toBe("GET");
       expect(wrapper.find(".message-body .xhr").length).toBe(0);
       expect(wrapper.find(".message-body .url").length).toBe(1);
       expect(wrapper.find(".message-body .url").text()).toBe(EXPECTED_URL);
-      expect(wrapper.find("div.message.cm-s-mozilla span.message-body.devtools-monospace").length).toBe(1);
+      expect(wrapper
+        .find("div.message.cm-s-mozilla span.message-body.devtools-monospace").length
+      ).toBe(1);
     });
 
     it("has the expected indent", () => {
       const message = stubPreparedMessages.get("GET request");
 
       const indent = 10;
       let wrapper = render(NetworkEventMessage({ message, serviceContainer, indent}));
       expect(wrapper.find(".indent").prop("style").width)
@@ -52,26 +54,28 @@ describe("NetworkEventMessage component:
     it("renders as expected", () => {
       const message = stubPreparedMessages.get("XHR GET request");
       const wrapper = render(NetworkEventMessage({ message, serviceContainer }));
 
       expect(wrapper.find(".message-body .method").text()).toBe("GET");
       expect(wrapper.find(".message-body .xhr").length).toBe(1);
       expect(wrapper.find(".message-body .xhr").text()).toBe("XHR");
       expect(wrapper.find(".message-body .url").text()).toBe(EXPECTED_URL);
-      expect(wrapper.find("div.message.cm-s-mozilla span.message-body.devtools-monospace").length).toBe(1);
+      let selector = "div.message.cm-s-mozilla span.message-body.devtools-monospace";
+      expect(wrapper.find(selector).length).toBe(1);
     });
   });
 
   describe("XHR POST request", () => {
     it("renders as expected", () => {
       const message = stubPreparedMessages.get("XHR POST request");
       const wrapper = render(NetworkEventMessage({ message, serviceContainer }));
 
       expect(wrapper.find(".message-body .method").text()).toBe("POST");
       expect(wrapper.find(".message-body .xhr").length).toBe(1);
       expect(wrapper.find(".message-body .xhr").text()).toBe("XHR");
       expect(wrapper.find(".message-body .url").length).toBe(1);
       expect(wrapper.find(".message-body .url").text()).toBe(EXPECTED_URL);
-      expect(wrapper.find("div.message.cm-s-mozilla span.message-body.devtools-monospace").length).toBe(1);
+      let selector = "div.message.cm-s-mozilla span.message-body.devtools-monospace";
+      expect(wrapper.find(selector).length);
     });
   });
 });
--- a/devtools/client/webconsole/new-console-output/test/fixtures/Services.js
+++ b/devtools/client/webconsole/new-console-output/test/fixtures/Services.js
@@ -7,16 +7,17 @@ const { PREFS } = require("devtools/clie
 
 module.exports = {
   prefs: {
     getIntPref: pref => {
       switch (pref) {
         case "devtools.hud.loglimit":
           return 1000;
       }
+      return null;
     },
     getBoolPref: pref => {
       const falsey = [
         PREFS.FILTER.NET,
         PREFS.FILTER.NETXHR,
         PREFS.UI.FILTER_BAR,
       ];
       return !falsey.includes(pref);
--- a/devtools/client/webconsole/new-console-output/test/fixtures/serviceContainer.js
+++ b/devtools/client/webconsole/new-console-output/test/fixtures/serviceContainer.js
@@ -8,10 +8,11 @@ module.exports = {
   emitNewMessage: () => {},
   hudProxyClient: {},
   onViewSourceInDebugger: () => {},
   openNetworkPanel: () => {},
   sourceMapService: {
     subscribe: () => {},
   },
   openLink: () => {},
+  // eslint-disable-next-line react/display-name
   createElement: tagName => document.createElement(tagName)
 };
--- a/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/browser_webconsole_update_stubs_console_api.js
+++ b/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/browser_webconsole_update_stubs_console_api.js
@@ -1,56 +1,58 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
-requestLongerTimeout(2)
+requestLongerTimeout(2);
 
-Cu.import("resource://gre/modules/osfile.jsm");
+Cu.import("resource://gre/modules/osfile.jsm", {});
 const { consoleApi: snippets } = require("devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/stub-snippets.js");
 
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html";
 
 let stubs = {
   preparedMessages: [],
   packets: [],
 };
 
 add_task(function* () {
-  for (var [key, {keys, code}] of snippets) {
+  for (let [key, {keys, code}] of snippets) {
     yield OS.File.writeAtomic(TEMP_FILE_PATH, `function triggerPacket() {${code}}`);
 
     let toolbox = yield openNewTabAndToolbox(TEST_URI, "webconsole");
     let {ui} = toolbox.getCurrentPanel().hud;
 
     ok(ui.jsterm, "jsterm exists");
     ok(ui.newConsoleOutput, "newConsoleOutput exists");
 
     let received = new Promise(resolve => {
       let i = 0;
       let listener = (type, res) => {
         stubs.packets.push(formatPacket(keys[i], res));
         stubs.preparedMessages.push(formatStub(keys[i], res));
-        if(++i === keys.length ){
+        if (++i === keys.length) {
           toolbox.target.client.removeListener("consoleAPICall", listener);
           resolve();
         }
       };
       toolbox.target.client.addListener("consoleAPICall", listener);
     });
 
-    yield ContentTask.spawn(gBrowser.selectedBrowser, key, function(key) {
-      var script = content.document.createElement("script");
-      script.src = "test-tempfile.js?key=" + encodeURIComponent(key);
-      script.onload = function() { content.wrappedJSObject.triggerPacket(); }
+    yield ContentTask.spawn(gBrowser.selectedBrowser, key, function (subKey) {
+      let script = content.document.createElement("script");
+      script.src = "test-tempfile.js?key=" + encodeURIComponent(subKey);
+      script.onload = function () {
+        content.wrappedJSObject.triggerPacket();
+      };
       content.document.body.appendChild(script);
     });
 
     yield received;
 
     yield closeTabAndToolbox();
   }
   let filePath = OS.Path.join(`${BASE_PATH}/stubs`, "consoleApi.js");
-  OS.File.writeAtomic(filePath, formatFile(stubs));
+  OS.File.writeAtomic(filePath, formatFile(stubs, "ConsoleMessage"));
   OS.File.writeAtomic(TEMP_FILE_PATH, "");
 });
--- a/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/browser_webconsole_update_stubs_css_message.js
+++ b/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/browser_webconsole_update_stubs_css_message.js
@@ -1,14 +1,14 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-Cu.import("resource://gre/modules/osfile.jsm");
+Cu.import("resource://gre/modules/osfile.jsm", {});
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-css-message.html";
 
 const { cssMessage: snippets} = require("devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/stub-snippets.js");
 
 let stubs = {
   preparedMessages: [],
   packets: [],
 };
@@ -38,11 +38,11 @@ add_task(function* () {
       stylesheet.href = "test-tempfile.css?key=" + encodeURIComponent(snippetKey);
       content.document.body.appendChild(stylesheet);
     });
 
     yield received;
   }
 
   let filePath = OS.Path.join(`${BASE_PATH}/stubs`, "cssMessage.js");
-  OS.File.writeAtomic(filePath, formatFile(stubs));
+  OS.File.writeAtomic(filePath, formatFile(stubs, "ConsoleMessage"));
   OS.File.writeAtomic(TEMP_CSS_FILE_PATH, "");
 });
--- a/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/browser_webconsole_update_stubs_evaluation_result.js
+++ b/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/browser_webconsole_update_stubs_evaluation_result.js
@@ -1,32 +1,32 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-Cu.import("resource://gre/modules/osfile.jsm");
+Cu.import("resource://gre/modules/osfile.jsm", {});
 const TEST_URI = "data:text/html;charset=utf-8,stub generation";
 
 const { evaluationResult: snippets} = require("devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/stub-snippets.js");
 
 let stubs = {
   preparedMessages: [],
   packets: [],
 };
 
 add_task(function* () {
   let toolbox = yield openNewTabAndToolbox(TEST_URI, "webconsole");
   ok(true, "make the test not fail");
 
-  for (var [code,key] of snippets) {
+  for (let [code, key] of snippets) {
     const packet = yield new Promise(resolve => {
       toolbox.target.activeConsole.evaluateJS(code, resolve);
     });
     stubs.packets.push(formatPacket(key, packet));
     stubs.preparedMessages.push(formatStub(key, packet));
   }
 
   let filePath = OS.Path.join(`${BASE_PATH}/stubs`, "evaluationResult.js");
-  OS.File.writeAtomic(filePath, formatFile(stubs));
+  OS.File.writeAtomic(filePath, formatFile(stubs, "ConsoleMessage"));
 });
--- a/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/browser_webconsole_update_stubs_network_event.js
+++ b/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/browser_webconsole_update_stubs_network_event.js
@@ -1,47 +1,47 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-Cu.import("resource://gre/modules/osfile.jsm");
+Cu.import("resource://gre/modules/osfile.jsm", {});
 const TARGET = "networkEvent";
 const { [TARGET]: snippets } = require("devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/stub-snippets.js");
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-network-event.html";
 
 let stubs = {
   preparedMessages: [],
   packets: [],
 };
 
 add_task(function* () {
-  for (var [key, {keys, code}] of snippets) {
+  for (let {keys, code} of snippets.values()) {
     OS.File.writeAtomic(TEMP_FILE_PATH, `function triggerPacket() {${code}}`);
     let toolbox = yield openNewTabAndToolbox(TEST_URI, "webconsole");
     let {ui} = toolbox.getCurrentPanel().hud;
 
     ok(ui.jsterm, "jsterm exists");
     ok(ui.newConsoleOutput, "newConsoleOutput exists");
 
     let received = new Promise(resolve => {
       let i = 0;
       toolbox.target.client.addListener(TARGET, (type, res) => {
         stubs.packets.push(formatPacket(keys[i], res));
         stubs.preparedMessages.push(formatNetworkStub(keys[i], res));
-        if(++i === keys.length ){
+        if (++i === keys.length) {
           resolve();
         }
       });
     });
 
-    yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
+    yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function () {
       content.wrappedJSObject.triggerPacket();
     });
 
     yield received;
   }
   let filePath = OS.Path.join(`${BASE_PATH}/stubs/${TARGET}.js`);
-  OS.File.writeAtomic(filePath, formatFile(stubs));
+  OS.File.writeAtomic(filePath, formatFile(stubs, "NetworkEventMessage"));
   OS.File.writeAtomic(TEMP_FILE_PATH, "");
 });
--- a/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/browser_webconsole_update_stubs_page_error.js
+++ b/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/browser_webconsole_update_stubs_page_error.js
@@ -1,48 +1,48 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-Cu.import("resource://gre/modules/osfile.jsm");
+Cu.import("resource://gre/modules/osfile.jsm", {});
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html";
 
 const { pageError: snippets} = require("devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/stub-snippets.js");
 
 let stubs = {
   preparedMessages: [],
   packets: [],
 };
 
 add_task(function* () {
   let toolbox = yield openNewTabAndToolbox(TEST_URI, "webconsole");
   ok(true, "make the test not fail");
 
-  for (var [key,code] of snippets) {
+  for (let [key, code] of snippets) {
     OS.File.writeAtomic(TEMP_FILE_PATH, `${code}`);
     let received = new Promise(resolve => {
       toolbox.target.client.addListener("pageError", function onPacket(e, packet) {
         toolbox.target.client.removeListener("pageError", onPacket);
         info("Received page error:" + e + " " + JSON.stringify(packet, null, "\t"));
 
         let message = prepareMessage(packet, {getNextId: () => 1});
         stubs.packets.push(formatPacket(message.messageText, packet));
         stubs.preparedMessages.push(formatStub(message.messageText, packet));
         resolve();
       });
     });
 
-    yield ContentTask.spawn(gBrowser.selectedBrowser, key, function(key) {
-      var script = content.document.createElement("script");
-      script.src = "test-tempfile.js?key=" + encodeURIComponent(key);
+    yield ContentTask.spawn(gBrowser.selectedBrowser, key, function (subKey) {
+      let script = content.document.createElement("script");
+      script.src = "test-tempfile.js?key=" + encodeURIComponent(subKey);
       content.document.body.appendChild(script);
     });
 
     yield received;
   }
 
   let filePath = OS.Path.join(`${BASE_PATH}/stubs`, "pageError.js");
-  OS.File.writeAtomic(filePath, formatFile(stubs));
+  OS.File.writeAtomic(filePath, formatFile(stubs, "ConsoleMessage"));
   OS.File.writeAtomic(TEMP_FILE_PATH, "");
 });
--- a/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/head.js
+++ b/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/head.js
@@ -1,55 +1,56 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
-/* import-globals-from ../../../../framework/test/shared-head.js */
-
+/* import-globals-from ../../../../../framework/test/shared-head.js */
+/* exported TEMP_FILE_PATH, TEMP_CSS_FILE_PATH, formatPacket, formatStub,
+            formatNetworkStub, formatFile */
 "use strict";
 
 // shared-head.js handles imports, constants, and utility functions
 // Load the shared-head file first.
 Services.scriptloader.loadSubScript(
   "chrome://mochitests/content/browser/devtools/client/framework/test/shared-head.js",
   this);
 
 Services.prefs.setBoolPref("devtools.webconsole.new-frontend-enabled", true);
 registerCleanupFunction(() => {
   Services.prefs.clearUserPref("devtools.webconsole.new-frontend-enabled");
 });
 
 const { prepareMessage } = require("devtools/client/webconsole/new-console-output/utils/messages");
 const { stubPackets } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs/index.js");
 
-const BASE_PATH = "../../../../devtools/client/webconsole/new-console-output/test/fixtures";
+const BASE_PATH =
+  "../../../../devtools/client/webconsole/new-console-output/test/fixtures";
 const TEMP_FILE_PATH = OS.Path.join(`${BASE_PATH}/stub-generators`, "test-tempfile.js");
 const TEMP_CSS_FILE_PATH = OS.Path.join(`${BASE_PATH}/stub-generators`,
                                         "test-tempfile.css");
 
 let cachedPackets = {};
 
 function getCleanedPacket(key, packet) {
-  if(Object.keys(cachedPackets).includes(key)) {
+  if (Object.keys(cachedPackets).includes(key)) {
     return cachedPackets[key];
   }
 
   // Strip escaped characters.
   let safeKey = key
     .replace(/\\n/g, "\n")
     .replace(/\\r/g, "\r")
     .replace(/\\\"/g, `\"`)
     .replace(/\\\'/g, `\'`);
 
   // If the stub already exist, we want to ignore irrelevant properties
   // (actor, timeStamp, timer, ...) that might changed and "pollute"
   // the diff resulting from this stub generation.
   let res;
   if (stubPackets.has(safeKey)) {
-
     let existingPacket = stubPackets.get(safeKey);
     res = Object.assign({}, packet, {
       from: existingPacket.from
     });
 
     // Clean root timestamp.
     if (res.timestamp) {
       res.timestamp = existingPacket.timestamp;
@@ -79,28 +80,28 @@ function getCleanedPacket(key, packet) {
         });
       }
     }
 
     if (res.result) {
       // Clean actor ids on evaluation result messages.
       res.result.actor = existingPacket.result.actor;
       if (res.result.preview) {
-        if(res.result.preview.timestamp) {
+        if (res.result.preview.timestamp) {
           // Clean timestamp there too.
           res.result.preview.timestamp = existingPacket.result.preview.timestamp;
         }
       }
     }
 
     if (res.exception) {
       // Clean actor ids on exception messages.
       res.exception.actor = existingPacket.exception.actor;
       if (res.exception.preview) {
-        if(res.exception.preview.timestamp) {
+        if (res.exception.preview.timestamp) {
           // Clean timestamp there too.
           res.exception.preview.timestamp = existingPacket.exception.preview.timestamp;
         }
       }
     }
 
     if (res.eventActor) {
       // Clean actor ids, timeStamp and startedDateTime on network messages.
@@ -108,40 +109,36 @@ function getCleanedPacket(key, packet) {
       res.eventActor.startedDateTime = existingPacket.eventActor.startedDateTime;
       res.eventActor.timeStamp = existingPacket.eventActor.timeStamp;
     }
 
     if (res.pageError) {
       // Clean timeStamp on pageError messages.
       res.pageError.timeStamp = existingPacket.pageError.timeStamp;
     }
-
   } else {
     res = packet;
   }
 
   cachedPackets[key] = res;
   return res;
 }
 
 function formatPacket(key, packet) {
-  return `
-stubPackets.set("${key}", ${JSON.stringify(getCleanedPacket(key, packet), null, "\t")});
-`;
+  let stringifiedPacket = JSON.stringify(getCleanedPacket(key, packet), null, 2);
+  return `stubPackets.set("${key}", ${stringifiedPacket});`;
 }
 
 function formatStub(key, packet) {
   let prepared = prepareMessage(
     getCleanedPacket(key, packet),
     {getNextId: () => "1"}
   );
-
-  return `
-stubPreparedMessages.set("${key}", new ConsoleMessage(${JSON.stringify(prepared, null, "\t")}));
-`;
+  let stringifiedMessage = JSON.stringify(prepared, null, 2);
+  return `stubPreparedMessages.set("${key}", new ConsoleMessage(${stringifiedMessage}));`;
 }
 
 function formatNetworkStub(key, packet) {
   let actor = packet.eventActor;
   let networkInfo = {
     _type: "NetworkEvent",
     timeStamp: actor.timeStamp,
     node: null,
@@ -159,36 +156,39 @@ function formatNetworkStub(key, packet) 
     timings: {},
     // track the list of network event updates
     updates: [],
     private: actor.private,
     fromCache: actor.fromCache,
     fromServiceWorker: actor.fromServiceWorker
   };
   let prepared = prepareMessage(networkInfo, {getNextId: () => "1"});
-  return `
-stubPreparedMessages.set("${key}", new NetworkEventMessage(${JSON.stringify(prepared, null, "\t")}));
-`;
+  let stringifiedMessage = JSON.stringify(prepared, null, 2);
+  return `stubPreparedMessages.set("${key}", ` +
+    `new NetworkEventMessage(${stringifiedMessage}));`;
 }
 
-function formatFile(stubs) {
+function formatFile(stubs, type) {
   return `/* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */
+/* eslint-disable max-len */
 
 "use strict";
 
 /*
  * THIS FILE IS AUTOGENERATED. DO NOT MODIFY BY HAND. RUN TESTS IN FIXTURES/ TO UPDATE.
  */
 
-const { ConsoleMessage, NetworkEventMessage } = require("devtools/client/webconsole/new-console-output/types");
+const { ${type} } =
+  require("devtools/client/webconsole/new-console-output/types");
 
 let stubPreparedMessages = new Map();
 let stubPackets = new Map();
+${stubs.preparedMessages.join("\n\n")}
 
-${stubs.preparedMessages.join("")}
-${stubs.packets.join("")}
+${stubs.packets.join("\n\n")}
 
 module.exports = {
   stubPreparedMessages,
   stubPackets,
-}`;
+};
+`;
 }
--- a/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/stub-snippets.js
+++ b/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/stub-snippets.js
@@ -1,17 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-var {DebuggerServer} = require("devtools/server/main");
-var longString = (new Array(DebuggerServer.LONG_STRING_LENGTH + 4)).join("a");
-var initialString = longString.substring(0, DebuggerServer.LONG_STRING_INITIAL_LENGTH);
-
 // Console API
 
 const consoleApiCommands = [
   "console.log('foobar', 'test')",
   "console.log(undefined)",
   "console.warn('danger, will robinson!')",
   "console.log(NaN)",
   "console.log(null)",
--- a/devtools/client/webconsole/new-console-output/test/fixtures/stubs/consoleApi.js
+++ b/devtools/client/webconsole/new-console-output/test/fixtures/stubs/consoleApi.js
@@ -1,1506 +1,1312 @@
 /* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */
+/* eslint-disable max-len */
 
 "use strict";
 
 /*
  * THIS FILE IS AUTOGENERATED. DO NOT MODIFY BY HAND. RUN TESTS IN FIXTURES/ TO UPDATE.
  */
 
-const { ConsoleMessage, NetworkEventMessage } = require("devtools/client/webconsole/new-console-output/types");
+const { ConsoleMessage } =
+  require("devtools/client/webconsole/new-console-output/types");
 
 let stubPreparedMessages = new Map();
 let stubPackets = new Map();
-
-
 stubPreparedMessages.set("console.log('foobar', 'test')", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159894798,
-	"type": "log",
-	"level": "log",
-	"messageText": null,
-	"parameters": [
-		"foobar",
-		"test"
-	],
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159894798,\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"foobar\",\"test\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27foobar%27%2C%20%27test%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27foobar%27%2C%20%27test%27)",
-		"line": 1,
-		"column": 27
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159894798,
+  "type": "log",
+  "level": "log",
+  "messageText": null,
+  "parameters": [
+    "foobar",
+    "test"
+  ],
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159894798,\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"foobar\",\"test\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27foobar%27%2C%20%27test%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27foobar%27%2C%20%27test%27)",
+    "line": 1,
+    "column": 27
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.log(undefined)", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159896036,
-	"type": "log",
-	"level": "log",
-	"messageText": null,
-	"parameters": [
-		{
-			"type": "undefined"
-		}
-	],
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159896036,\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"undefined\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(undefined)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(undefined)",
-		"line": 1,
-		"column": 27
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159896036,
+  "type": "log",
+  "level": "log",
+  "messageText": null,
+  "parameters": [
+    {
+      "type": "undefined"
+    }
+  ],
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159896036,\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"undefined\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(undefined)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(undefined)",
+    "line": 1,
+    "column": 27
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.warn('danger, will robinson!')", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159897333,
-	"type": "warn",
-	"level": "warn",
-	"messageText": null,
-	"parameters": [
-		"danger, will robinson!"
-	],
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159897333,\"type\":\"warn\",\"level\":\"warn\",\"messageText\":null,\"parameters\":[\"danger, will robinson!\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.warn(%27danger%2C%20will%20robinson!%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.warn(%27danger%2C%20will%20robinson!%27)",
-		"line": 1,
-		"column": 27
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159897333,
+  "type": "warn",
+  "level": "warn",
+  "messageText": null,
+  "parameters": [
+    "danger, will robinson!"
+  ],
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159897333,\"type\":\"warn\",\"level\":\"warn\",\"messageText\":null,\"parameters\":[\"danger, will robinson!\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.warn(%27danger%2C%20will%20robinson!%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.warn(%27danger%2C%20will%20robinson!%27)",
+    "line": 1,
+    "column": 27
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.log(NaN)", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159898667,
-	"type": "log",
-	"level": "log",
-	"messageText": null,
-	"parameters": [
-		{
-			"type": "NaN"
-		}
-	],
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159898667,\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"NaN\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(NaN)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(NaN)",
-		"line": 1,
-		"column": 27
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159898667,
+  "type": "log",
+  "level": "log",
+  "messageText": null,
+  "parameters": [
+    {
+      "type": "NaN"
+    }
+  ],
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159898667,\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"NaN\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(NaN)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(NaN)",
+    "line": 1,
+    "column": 27
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.log(null)", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159900151,
-	"type": "log",
-	"level": "log",
-	"messageText": null,
-	"parameters": [
-		{
-			"type": "null"
-		}
-	],
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159900151,\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"null\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(null)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(null)",
-		"line": 1,
-		"column": 27
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159900151,
+  "type": "log",
+  "level": "log",
+  "messageText": null,
+  "parameters": [
+    {
+      "type": "null"
+    }
+  ],
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159900151,\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"null\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(null)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(null)",
+    "line": 1,
+    "column": 27
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.log('鼬')", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159901470,
-	"type": "log",
-	"level": "log",
-	"messageText": null,
-	"parameters": [
-		"鼬"
-	],
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159901470,\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"鼬\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%E9%BC%AC%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%E9%BC%AC%27)",
-		"line": 1,
-		"column": 27
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159901470,
+  "type": "log",
+  "level": "log",
+  "messageText": null,
+  "parameters": [
+    "鼬"
+  ],
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159901470,\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"鼬\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%E9%BC%AC%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%E9%BC%AC%27)",
+    "line": 1,
+    "column": 27
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.clear()", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159902721,
-	"type": "clear",
-	"level": "log",
-	"messageText": null,
-	"parameters": [
-		"Console was cleared."
-	],
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159902721,\"type\":\"clear\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"Console was cleared.\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.clear()\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.clear()",
-		"line": 1,
-		"column": 27
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159902721,
+  "type": "clear",
+  "level": "log",
+  "messageText": null,
+  "parameters": [
+    "Console was cleared."
+  ],
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159902721,\"type\":\"clear\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"Console was cleared.\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.clear()\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.clear()",
+    "line": 1,
+    "column": 27
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.count('bar')", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159903982,
-	"type": "log",
-	"level": "debug",
-	"messageText": "bar: 1",
-	"parameters": null,
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159903982,\"type\":\"log\",\"level\":\"debug\",\"messageText\":\"bar: 1\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.count(%27bar%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.count(%27bar%27)",
-		"line": 1,
-		"column": 27
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159903982,
+  "type": "log",
+  "level": "debug",
+  "messageText": "bar: 1",
+  "parameters": null,
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159903982,\"type\":\"log\",\"level\":\"debug\",\"messageText\":\"bar: 1\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.count(%27bar%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.count(%27bar%27)",
+    "line": 1,
+    "column": 27
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.assert(false, {message: 'foobar'})", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159905182,
-	"type": "assert",
-	"level": "error",
-	"messageText": null,
-	"parameters": [
-		{
-			"type": "object",
-			"actor": "server1.conn8.child1/obj31",
-			"class": "Object",
-			"extensible": true,
-			"frozen": false,
-			"sealed": false,
-			"ownPropertyLength": 1,
-			"preview": {
-				"kind": "Object",
-				"ownProperties": {
-					"message": {
-						"configurable": true,
-						"enumerable": true,
-						"writable": true,
-						"value": "foobar"
-					}
-				},
-				"ownPropertiesLength": 1,
-				"safeGetterValues": {}
-			}
-		}
-	],
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159905182,\"type\":\"assert\",\"level\":\"error\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn8.child1/obj31\",\"class\":\"Object\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":1,\"preview\":{\"kind\":\"Object\",\"ownProperties\":{\"message\":{\"configurable\":true,\"enumerable\":true,\"writable\":true,\"value\":\"foobar\"}},\"ownPropertiesLength\":1,\"safeGetterValues\":{}}}],\"repeatId\":null,\"stacktrace\":[{\"columnNumber\":27,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)\",\"functionName\":\"triggerPacket\",\"language\":2,\"lineNumber\":1}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": [
-		{
-			"columnNumber": 27,
-			"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)",
-			"functionName": "triggerPacket",
-			"language": 2,
-			"lineNumber": 1
-		}
-	],
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)",
-		"line": 1,
-		"column": 27
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159905182,
+  "type": "assert",
+  "level": "error",
+  "messageText": null,
+  "parameters": [
+    {
+      "type": "object",
+      "actor": "server1.conn8.child1/obj31",
+      "class": "Object",
+      "extensible": true,
+      "frozen": false,
+      "sealed": false,
+      "ownPropertyLength": 1,
+      "preview": {
+        "kind": "Object",
+        "ownProperties": {
+          "message": {
+            "configurable": true,
+            "enumerable": true,
+            "writable": true,
+            "value": "foobar"
+          }
+        },
+        "ownPropertiesLength": 1,
+        "safeGetterValues": {}
+      }
+    }
+  ],
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159905182,\"type\":\"assert\",\"level\":\"error\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn8.child1/obj31\",\"class\":\"Object\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":1,\"preview\":{\"kind\":\"Object\",\"ownProperties\":{\"message\":{\"configurable\":true,\"enumerable\":true,\"writable\":true,\"value\":\"foobar\"}},\"ownPropertiesLength\":1,\"safeGetterValues\":{}}}],\"repeatId\":null,\"stacktrace\":[{\"columnNumber\":27,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)\",\"functionName\":\"triggerPacket\",\"language\":2,\"lineNumber\":1}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": [
+    {
+      "columnNumber": 27,
+      "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)",
+      "functionName": "triggerPacket",
+      "language": 2,
+      "lineNumber": 1
+    }
+  ],
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)",
+    "line": 1,
+    "column": 27
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.log('hello \nfrom \rthe \"string world!')", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159906444,
-	"type": "log",
-	"level": "log",
-	"messageText": null,
-	"parameters": [
-		"hello \nfrom \rthe \"string world!"
-	],
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159906444,\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"hello \\nfrom \\rthe \\\"string world!\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27hello%20%5Cnfrom%20%5Crthe%20%5C%22string%20world!%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27hello%20%5Cnfrom%20%5Crthe%20%5C%22string%20world!%27)",
-		"line": 1,
-		"column": 27
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159906444,
+  "type": "log",
+  "level": "log",
+  "messageText": null,
+  "parameters": [
+    "hello \nfrom \rthe \"string world!"
+  ],
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159906444,\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"hello \\nfrom \\rthe \\\"string world!\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27hello%20%5Cnfrom%20%5Crthe%20%5C%22string%20world!%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27hello%20%5Cnfrom%20%5Crthe%20%5C%22string%20world!%27)",
+    "line": 1,
+    "column": 27
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.log('úṇĩçödê țĕșť')", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159907704,
-	"type": "log",
-	"level": "log",
-	"messageText": null,
-	"parameters": [
-		"úṇĩçödê țĕșť"
-	],
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159907704,\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"úṇĩçödê țĕșť\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%C3%BA%E1%B9%87%C4%A9%C3%A7%C3%B6d%C3%AA%20%C8%9B%C4%95%C8%99%C5%A5%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%C3%BA%E1%B9%87%C4%A9%C3%A7%C3%B6d%C3%AA%20%C8%9B%C4%95%C8%99%C5%A5%27)",
-		"line": 1,
-		"column": 27
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159907704,
+  "type": "log",
+  "level": "log",
+  "messageText": null,
+  "parameters": [
+    "úṇĩçödê țĕșť"
+  ],
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159907704,\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"úṇĩçödê țĕșť\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%C3%BA%E1%B9%87%C4%A9%C3%A7%C3%B6d%C3%AA%20%C8%9B%C4%95%C8%99%C5%A5%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%C3%BA%E1%B9%87%C4%A9%C3%A7%C3%B6d%C3%AA%20%C8%9B%C4%95%C8%99%C5%A5%27)",
+    "line": 1,
+    "column": 27
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.dirxml(window)", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159908948,
-	"type": "log",
-	"level": "log",
-	"messageText": null,
-	"parameters": [
-		{
-			"type": "object",
-			"actor": "server1.conn11.child1/obj31",
-			"class": "Window",
-			"extensible": true,
-			"frozen": false,
-			"sealed": false,
-			"ownPropertyLength": 812,
-			"preview": {
-				"kind": "ObjectWithURL",
-				"url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html"
-			}
-		}
-	],
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159908948,\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn11.child1/obj31\",\"class\":\"Window\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":812,\"preview\":{\"kind\":\"ObjectWithURL\",\"url\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html\"}}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.dirxml(window)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.dirxml(window)",
-		"line": 1,
-		"column": 27
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159908948,
+  "type": "log",
+  "level": "log",
+  "messageText": null,
+  "parameters": [
+    {
+      "type": "object",
+      "actor": "server1.conn11.child1/obj31",
+      "class": "Window",
+      "extensible": true,
+      "frozen": false,
+      "sealed": false,
+      "ownPropertyLength": 811,
+      "preview": {
+        "kind": "ObjectWithURL",
+        "url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html"
+      }
+    }
+  ],
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159908948,\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn11.child1/obj31\",\"class\":\"Window\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":811,\"preview\":{\"kind\":\"ObjectWithURL\",\"url\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html\"}}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.dirxml(window)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.dirxml(window)",
+    "line": 1,
+    "column": 27
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.trace()", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159910198,
-	"type": "trace",
-	"level": "log",
-	"messageText": null,
-	"parameters": [],
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159910198,\"type\":\"trace\",\"level\":\"log\",\"messageText\":null,\"parameters\":[],\"repeatId\":null,\"stacktrace\":[{\"columnNumber\":3,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"testStacktraceFiltering\",\"language\":2,\"lineNumber\":3},{\"columnNumber\":3,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"foo\",\"language\":2,\"lineNumber\":6},{\"columnNumber\":1,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"triggerPacket\",\"language\":2,\"lineNumber\":9}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"line\":3,\"column\":3},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": [
-		{
-			"columnNumber": 3,
-			"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()",
-			"functionName": "testStacktraceFiltering",
-			"language": 2,
-			"lineNumber": 3
-		},
-		{
-			"columnNumber": 3,
-			"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()",
-			"functionName": "foo",
-			"language": 2,
-			"lineNumber": 6
-		},
-		{
-			"columnNumber": 1,
-			"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()",
-			"functionName": "triggerPacket",
-			"language": 2,
-			"lineNumber": 9
-		}
-	],
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()",
-		"line": 3,
-		"column": 3
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159910198,
+  "type": "trace",
+  "level": "log",
+  "messageText": null,
+  "parameters": [],
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159910198,\"type\":\"trace\",\"level\":\"log\",\"messageText\":null,\"parameters\":[],\"repeatId\":null,\"stacktrace\":[{\"columnNumber\":3,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"testStacktraceFiltering\",\"language\":2,\"lineNumber\":3},{\"columnNumber\":3,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"foo\",\"language\":2,\"lineNumber\":6},{\"columnNumber\":1,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"triggerPacket\",\"language\":2,\"lineNumber\":9}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"line\":3,\"column\":3},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": [
+    {
+      "columnNumber": 3,
+      "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()",
+      "functionName": "testStacktraceFiltering",
+      "language": 2,
+      "lineNumber": 3
+    },
+    {
+      "columnNumber": 3,
+      "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()",
+      "functionName": "foo",
+      "language": 2,
+      "lineNumber": 6
+    },
+    {
+      "columnNumber": 1,
+      "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()",
+      "functionName": "triggerPacket",
+      "language": 2,
+      "lineNumber": 9
+    }
+  ],
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()",
+    "line": 3,
+    "column": 3
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.time('bar')", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159911476,
-	"type": "nullMessage",
-	"level": "log",
-	"messageText": null,
-	"parameters": null,
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159911476,\"type\":\"nullMessage\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)",
-		"line": 2,
-		"column": 1
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159911476,
+  "type": "nullMessage",
+  "level": "log",
+  "messageText": null,
+  "parameters": null,
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159911476,\"type\":\"nullMessage\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)",
+    "line": 2,
+    "column": 1
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.timeEnd('bar')", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159911478,
-	"type": "timeEnd",
-	"level": "log",
-	"messageText": "bar: 1.36ms",
-	"parameters": null,
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159911478,\"type\":\"timeEnd\",\"level\":\"log\",\"messageText\":\"bar: 1.36ms\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)",
-		"line": 3,
-		"column": 1
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159911478,
+  "type": "timeEnd",
+  "level": "log",
+  "messageText": "bar: 1.36ms",
+  "parameters": null,
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159911478,\"type\":\"timeEnd\",\"level\":\"log\",\"messageText\":\"bar: 1.36ms\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)",
+    "line": 3,
+    "column": 1
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.table('bar')", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159912655,
-	"type": "log",
-	"level": "log",
-	"messageText": null,
-	"parameters": [
-		"bar"
-	],
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159912655,\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"bar\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%27bar%27)",
-		"line": 2,
-		"column": 1
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159912655,
+  "type": "log",
+  "level": "log",
+  "messageText": null,
+  "parameters": [
+    "bar"
+  ],
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159912655,\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"bar\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%27bar%27)",
+    "line": 2,
+    "column": 1
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.table(['a', 'b', 'c'])", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159913807,
-	"type": "table",
-	"level": "log",
-	"messageText": null,
-	"parameters": [
-		{
-			"type": "object",
-			"actor": "server1.conn15.child1/obj31",
-			"class": "Array",
-			"extensible": true,
-			"frozen": false,
-			"sealed": false,
-			"ownPropertyLength": 4,
-			"preview": {
-				"kind": "ArrayLike",
-				"length": 3,
-				"items": [
-					"a",
-					"b",
-					"c"
-				]
-			}
-		}
-	],
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159913807,\"type\":\"table\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn15.child1/obj31\",\"class\":\"Array\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":4,\"preview\":{\"kind\":\"ArrayLike\",\"length\":3,\"items\":[\"a\",\"b\",\"c\"]}}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%5B%27a%27%2C%20%27b%27%2C%20%27c%27%5D)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%5B%27a%27%2C%20%27b%27%2C%20%27c%27%5D)",
-		"line": 2,
-		"column": 1
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159913807,
+  "type": "table",
+  "level": "log",
+  "messageText": null,
+  "parameters": [
+    {
+      "type": "object",
+      "actor": "server1.conn15.child1/obj31",
+      "class": "Array",
+      "extensible": true,
+      "frozen": false,
+      "sealed": false,
+      "ownPropertyLength": 4,
+      "preview": {
+        "kind": "ArrayLike",
+        "length": 3,
+        "items": [
+          "a",
+          "b",
+          "c"
+        ]
+      }
+    }
+  ],
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159913807,\"type\":\"table\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn15.child1/obj31\",\"class\":\"Array\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":4,\"preview\":{\"kind\":\"ArrayLike\",\"length\":3,\"items\":[\"a\",\"b\",\"c\"]}}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%5B%27a%27%2C%20%27b%27%2C%20%27c%27%5D)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%5B%27a%27%2C%20%27b%27%2C%20%27c%27%5D)",
+    "line": 2,
+    "column": 1
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.group('bar')", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159914984,
-	"type": "startGroup",
-	"level": "log",
-	"messageText": "bar",
-	"parameters": null,
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159914984,\"type\":\"startGroup\",\"level\":\"log\",\"messageText\":\"bar\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)",
-		"line": 2,
-		"column": 1
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159914984,
+  "type": "startGroup",
+  "level": "log",
+  "messageText": "bar",
+  "parameters": null,
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159914984,\"type\":\"startGroup\",\"level\":\"log\",\"messageText\":\"bar\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)",
+    "line": 2,
+    "column": 1
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.groupEnd('bar')", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159914987,
-	"type": "endGroup",
-	"level": "log",
-	"messageText": null,
-	"parameters": null,
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159914987,\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)",
-		"line": 3,
-		"column": 1
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159914987,
+  "type": "endGroup",
+  "level": "log",
+  "messageText": null,
+  "parameters": null,
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159914987,\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)",
+    "line": 3,
+    "column": 1
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.groupCollapsed('foo')", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159916153,
-	"type": "startGroupCollapsed",
-	"level": "log",
-	"messageText": "foo",
-	"parameters": null,
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159916153,\"type\":\"startGroupCollapsed\",\"level\":\"log\",\"messageText\":\"foo\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)",
-		"line": 2,
-		"column": 1
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159916153,
+  "type": "startGroupCollapsed",
+  "level": "log",
+  "messageText": "foo",
+  "parameters": null,
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159916153,\"type\":\"startGroupCollapsed\",\"level\":\"log\",\"messageText\":\"foo\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)",
+    "line": 2,
+    "column": 1
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.groupEnd('foo')", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159916155,
-	"type": "endGroup",
-	"level": "log",
-	"messageText": null,
-	"parameters": null,
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159916155,\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)",
-		"line": 3,
-		"column": 1
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159916155,
+  "type": "endGroup",
+  "level": "log",
+  "messageText": null,
+  "parameters": null,
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159916155,\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)",
+    "line": 3,
+    "column": 1
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.group()", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159917524,
-	"type": "startGroup",
-	"level": "log",
-	"messageText": "<no group label>",
-	"parameters": null,
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159917524,\"type\":\"startGroup\",\"level\":\"log\",\"messageText\":\"<no group label>\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()",
-		"line": 2,
-		"column": 1
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159917524,
+  "type": "startGroup",
+  "level": "log",
+  "messageText": "<no group label>",
+  "parameters": null,
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159917524,\"type\":\"startGroup\",\"level\":\"log\",\"messageText\":\"<no group label>\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()",
+    "line": 2,
+    "column": 1
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.groupEnd()", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159917526,
-	"type": "endGroup",
-	"level": "log",
-	"messageText": null,
-	"parameters": null,
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159917526,\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()",
-		"line": 3,
-		"column": 1
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": []
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159917526,
+  "type": "endGroup",
+  "level": "log",
+  "messageText": null,
+  "parameters": null,
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159917526,\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()",
+    "line": 3,
+    "column": 1
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": []
 }));
 
 stubPreparedMessages.set("console.log(%cfoobar)", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "console-api",
-	"timeStamp": 1479159919144,
-	"type": "log",
-	"level": "log",
-	"messageText": null,
-	"parameters": [
-		"foo",
-		"bar"
-	],
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159919144,\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"foo\",\"bar\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%25cfoobar)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[\"color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px\",\"color:red;background:url('http://example.com/test')\"]}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%25cfoobar)",
-		"line": 2,
-		"column": 1
-	},
-	"groupId": null,
-	"exceptionDocURL": null,
-	"userProvidedStyles": [
-		"color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px",
-		"color:red;background:url('http://example.com/test')"
-	]
+  "id": "1",
+  "allowRepeating": true,
+  "source": "console-api",
+  "timeStamp": 1479159919144,
+  "type": "log",
+  "level": "log",
+  "messageText": null,
+  "parameters": [
+    "foo",
+    "bar"
+  ],
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"timeStamp\":1479159919144,\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"foo\",\"bar\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%25cfoobar)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[\"color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px\",\"color:red;background:url('http://example.com/test')\"]}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%25cfoobar)",
+    "line": 2,
+    "column": 1
+  },
+  "groupId": null,
+  "exceptionDocURL": null,
+  "userProvidedStyles": [
+    "color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px",
+    "color:red;background:url('http://example.com/test')"
+  ]
 }));
 
-
 stubPackets.set("console.log('foobar', 'test')", {
-	"from": "server1.conn0.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [
-			"foobar",
-			"test"
-		],
-		"columnNumber": 27,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27foobar%27%2C%20%27test%27)",
-		"functionName": "triggerPacket",
-		"groupName": "",
-		"level": "log",
-		"lineNumber": 1,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"styles": [],
-		"timeStamp": 1479159894798,
-		"timer": null,
-		"workerType": "none",
-		"category": "webdev"
-	}
+  "from": "server1.conn0.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [
+      "foobar",
+      "test"
+    ],
+    "columnNumber": 27,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27foobar%27%2C%20%27test%27)",
+    "functionName": "triggerPacket",
+    "groupName": "",
+    "level": "log",
+    "lineNumber": 1,
+    "private": false,
+    "styles": [],
+    "timeStamp": 1479159894798,
+    "timer": null,
+    "workerType": "none",
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.log(undefined)", {
-	"from": "server1.conn1.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [
-			{
-				"type": "undefined"
-			}
-		],
-		"columnNumber": 27,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(undefined)",
-		"functionName": "triggerPacket",
-		"groupName": "",
-		"level": "log",
-		"lineNumber": 1,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"styles": [],
-		"timeStamp": 1479159896036,
-		"timer": null,
-		"workerType": "none",
-		"category": "webdev"
-	}
+  "from": "server1.conn1.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [
+      {
+        "type": "undefined"
+      }
+    ],
+    "columnNumber": 27,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(undefined)",
+    "functionName": "triggerPacket",
+    "groupName": "",
+    "level": "log",
+    "lineNumber": 1,
+    "private": false,
+    "styles": [],
+    "timeStamp": 1479159896036,
+    "timer": null,
+    "workerType": "none",
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.warn('danger, will robinson!')", {
-	"from": "server1.conn2.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [
-			"danger, will robinson!"
-		],
-		"columnNumber": 27,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.warn(%27danger%2C%20will%20robinson!%27)",
-		"functionName": "triggerPacket",
-		"groupName": "",
-		"level": "warn",
-		"lineNumber": 1,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"styles": [],
-		"timeStamp": 1479159897333,
-		"timer": null,
-		"workerType": "none",
-		"category": "webdev"
-	}
+  "from": "server1.conn2.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [
+      "danger, will robinson!"
+    ],
+    "columnNumber": 27,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.warn(%27danger%2C%20will%20robinson!%27)",
+    "functionName": "triggerPacket",
+    "groupName": "",
+    "level": "warn",
+    "lineNumber": 1,
+    "private": false,
+    "styles": [],
+    "timeStamp": 1479159897333,
+    "timer": null,
+    "workerType": "none",
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.log(NaN)", {
-	"from": "server1.conn3.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [
-			{
-				"type": "NaN"
-			}
-		],
-		"columnNumber": 27,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(NaN)",
-		"functionName": "triggerPacket",
-		"groupName": "",
-		"level": "log",
-		"lineNumber": 1,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"styles": [],
-		"timeStamp": 1479159898667,
-		"timer": null,
-		"workerType": "none",
-		"category": "webdev"
-	}
+  "from": "server1.conn3.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [
+      {
+        "type": "NaN"
+      }
+    ],
+    "columnNumber": 27,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(NaN)",
+    "functionName": "triggerPacket",
+    "groupName": "",
+    "level": "log",
+    "lineNumber": 1,
+    "private": false,
+    "styles": [],
+    "timeStamp": 1479159898667,
+    "timer": null,
+    "workerType": "none",
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.log(null)", {
-	"from": "server1.conn4.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [
-			{
-				"type": "null"
-			}
-		],
-		"columnNumber": 27,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(null)",
-		"functionName": "triggerPacket",
-		"groupName": "",
-		"level": "log",
-		"lineNumber": 1,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"styles": [],
-		"timeStamp": 1479159900151,
-		"timer": null,
-		"workerType": "none",
-		"category": "webdev"
-	}
+  "from": "server1.conn4.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [
+      {
+        "type": "null"
+      }
+    ],
+    "columnNumber": 27,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(null)",
+    "functionName": "triggerPacket",
+    "groupName": "",
+    "level": "log",
+    "lineNumber": 1,
+    "private": false,
+    "styles": [],
+    "timeStamp": 1479159900151,
+    "timer": null,
+    "workerType": "none",
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.log('鼬')", {
-	"from": "server1.conn5.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [
-			"鼬"
-		],
-		"columnNumber": 27,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%E9%BC%AC%27)",
-		"functionName": "triggerPacket",
-		"groupName": "",
-		"level": "log",
-		"lineNumber": 1,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"styles": [],
-		"timeStamp": 1479159901470,
-		"timer": null,
-		"workerType": "none",
-		"category": "webdev"
-	}
+  "from": "server1.conn5.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [
+      "鼬"
+    ],
+    "columnNumber": 27,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%E9%BC%AC%27)",
+    "functionName": "triggerPacket",
+    "groupName": "",
+    "level": "log",
+    "lineNumber": 1,
+    "private": false,
+    "styles": [],
+    "timeStamp": 1479159901470,
+    "timer": null,
+    "workerType": "none",
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.clear()", {
-	"from": "server1.conn6.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [],
-		"columnNumber": 27,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.clear()",
-		"functionName": "triggerPacket",
-		"groupName": "",
-		"level": "clear",
-		"lineNumber": 1,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"timeStamp": 1479159902721,
-		"timer": null,
-		"workerType": "none",
-		"styles": [],
-		"category": "webdev"
-	}
+  "from": "server1.conn6.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [],
+    "columnNumber": 27,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.clear()",
+    "functionName": "triggerPacket",
+    "groupName": "",
+    "level": "clear",
+    "lineNumber": 1,
+    "private": false,
+    "timeStamp": 1479159902721,
+    "timer": null,
+    "workerType": "none",
+    "styles": [],
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.count('bar')", {
-	"from": "server1.conn7.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [
-			"bar"
-		],
-		"columnNumber": 27,
-		"counter": {
-			"count": 1,
-			"label": "bar"
-		},
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.count(%27bar%27)",
-		"functionName": "triggerPacket",
-		"groupName": "",
-		"level": "count",
-		"lineNumber": 1,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"timeStamp": 1479159903982,
-		"timer": null,
-		"workerType": "none",
-		"styles": [],
-		"category": "webdev"
-	}
+  "from": "server1.conn7.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [
+      "bar"
+    ],
+    "columnNumber": 27,
+    "counter": {
+      "count": 1,
+      "label": "bar"
+    },
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.count(%27bar%27)",
+    "functionName": "triggerPacket",
+    "groupName": "",
+    "level": "count",
+    "lineNumber": 1,
+    "private": false,
+    "timeStamp": 1479159903982,
+    "timer": null,
+    "workerType": "none",
+    "styles": [],
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.assert(false, {message: 'foobar'})", {
-	"from": "server1.conn8.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [
-			{
-				"type": "object",
-				"actor": "server1.conn8.child1/obj31",
-				"class": "Object",
-				"extensible": true,
-				"frozen": false,
-				"sealed": false,
-				"ownPropertyLength": 1,
-				"preview": {
-					"kind": "Object",
-					"ownProperties": {
-						"message": {
-							"configurable": true,
-							"enumerable": true,
-							"writable": true,
-							"value": "foobar"
-						}
-					},
-					"ownPropertiesLength": 1,
-					"safeGetterValues": {}
-				}
-			}
-		],
-		"columnNumber": 27,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)",
-		"functionName": "triggerPacket",
-		"groupName": "",
-		"level": "assert",
-		"lineNumber": 1,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"styles": [],
-		"timeStamp": 1479159905182,
-		"timer": null,
-		"stacktrace": [
-			{
-				"columnNumber": 27,
-				"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)",
-				"functionName": "triggerPacket",
-				"language": 2,
-				"lineNumber": 1
-			}
-		],
-		"workerType": "none",
-		"category": "webdev"
-	}
+  "from": "server1.conn8.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [
+      {
+        "type": "object",
+        "actor": "server1.conn8.child1/obj31",
+        "class": "Object",
+        "extensible": true,
+        "frozen": false,
+        "sealed": false,
+        "ownPropertyLength": 1,
+        "preview": {
+          "kind": "Object",
+          "ownProperties": {
+            "message": {
+              "configurable": true,
+              "enumerable": true,
+              "writable": true,
+              "value": "foobar"
+            }
+          },
+          "ownPropertiesLength": 1,
+          "safeGetterValues": {}
+        }
+      }
+    ],
+    "columnNumber": 27,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)",
+    "functionName": "triggerPacket",
+    "groupName": "",
+    "level": "assert",
+    "lineNumber": 1,
+    "private": false,
+    "styles": [],
+    "timeStamp": 1479159905182,
+    "timer": null,
+    "stacktrace": [
+      {
+        "columnNumber": 27,
+        "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)",
+        "functionName": "triggerPacket",
+        "language": 2,
+        "lineNumber": 1
+      }
+    ],
+    "workerType": "none",
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.log('hello \nfrom \rthe \"string world!')", {
-	"from": "server1.conn9.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [
-			"hello \nfrom \rthe \"string world!"
-		],
-		"columnNumber": 27,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27hello%20%5Cnfrom%20%5Crthe%20%5C%22string%20world!%27)",
-		"functionName": "triggerPacket",
-		"groupName": "",
-		"level": "log",
-		"lineNumber": 1,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"styles": [],
-		"timeStamp": 1479159906444,
-		"timer": null,
-		"workerType": "none",
-		"category": "webdev"
-	}
+  "from": "server1.conn9.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [
+      "hello \nfrom \rthe \"string world!"
+    ],
+    "columnNumber": 27,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27hello%20%5Cnfrom%20%5Crthe%20%5C%22string%20world!%27)",
+    "functionName": "triggerPacket",
+    "groupName": "",
+    "level": "log",
+    "lineNumber": 1,
+    "private": false,
+    "styles": [],
+    "timeStamp": 1479159906444,
+    "timer": null,
+    "workerType": "none",
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.log('úṇĩçödê țĕșť')", {
-	"from": "server1.conn10.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [
-			"úṇĩçödê țĕșť"
-		],
-		"columnNumber": 27,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%C3%BA%E1%B9%87%C4%A9%C3%A7%C3%B6d%C3%AA%20%C8%9B%C4%95%C8%99%C5%A5%27)",
-		"functionName": "triggerPacket",
-		"groupName": "",
-		"level": "log",
-		"lineNumber": 1,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"styles": [],
-		"timeStamp": 1479159907704,
-		"timer": null,
-		"workerType": "none",
-		"category": "webdev"
-	}
+  "from": "server1.conn10.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [
+      "úṇĩçödê țĕșť"
+    ],
+    "columnNumber": 27,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%C3%BA%E1%B9%87%C4%A9%C3%A7%C3%B6d%C3%AA%20%C8%9B%C4%95%C8%99%C5%A5%27)",
+    "functionName": "triggerPacket",
+    "groupName": "",
+    "level": "log",
+    "lineNumber": 1,
+    "private": false,
+    "styles": [],
+    "timeStamp": 1479159907704,
+    "timer": null,
+    "workerType": "none",
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.dirxml(window)", {
-	"from": "server1.conn11.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [
-			{
-				"type": "object",
-				"actor": "server1.conn11.child1/obj31",
-				"class": "Window",
-				"extensible": true,
-				"frozen": false,
-				"sealed": false,
-				"ownPropertyLength": 812,
-				"preview": {
-					"kind": "ObjectWithURL",
-					"url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html"
-				}
-			}
-		],
-		"columnNumber": 27,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.dirxml(window)",
-		"functionName": "triggerPacket",
-		"groupName": "",
-		"level": "dirxml",
-		"lineNumber": 1,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"timeStamp": 1479159908948,
-		"timer": null,
-		"workerType": "none",
-		"styles": [],
-		"category": "webdev"
-	}
+  "from": "server1.conn11.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [
+      {
+        "type": "object",
+        "actor": "server1.conn11.child1/obj31",
+        "class": "Window",
+        "extensible": true,
+        "frozen": false,
+        "sealed": false,
+        "ownPropertyLength": 811,
+        "preview": {
+          "kind": "ObjectWithURL",
+          "url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html"
+        }
+      }
+    ],
+    "columnNumber": 27,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.dirxml(window)",
+    "functionName": "triggerPacket",
+    "groupName": "",
+    "level": "dirxml",
+    "lineNumber": 1,
+    "private": false,
+    "timeStamp": 1479159908948,
+    "timer": null,
+    "workerType": "none",
+    "styles": [],
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.trace()", {
-	"from": "server1.conn12.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [],
-		"columnNumber": 3,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()",
-		"functionName": "testStacktraceFiltering",
-		"groupName": "",
-		"level": "trace",
-		"lineNumber": 3,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"timeStamp": 1479159910198,
-		"timer": null,
-		"stacktrace": [
-			{
-				"columnNumber": 3,
-				"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()",
-				"functionName": "testStacktraceFiltering",
-				"language": 2,
-				"lineNumber": 3
-			},
-			{
-				"columnNumber": 3,
-				"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()",
-				"functionName": "foo",
-				"language": 2,
-				"lineNumber": 6
-			},
-			{
-				"columnNumber": 1,
-				"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()",
-				"functionName": "triggerPacket",
-				"language": 2,
-				"lineNumber": 9
-			}
-		],
-		"workerType": "none",
-		"styles": [],
-		"category": "webdev"
-	}
+  "from": "server1.conn12.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [],
+    "columnNumber": 3,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()",
+    "functionName": "testStacktraceFiltering",
+    "groupName": "",
+    "level": "trace",
+    "lineNumber": 3,
+    "private": false,
+    "timeStamp": 1479159910198,
+    "timer": null,
+    "stacktrace": [
+      {
+        "columnNumber": 3,
+        "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()",
+        "functionName": "testStacktraceFiltering",
+        "language": 2,
+        "lineNumber": 3
+      },
+      {
+        "columnNumber": 3,
+        "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()",
+        "functionName": "foo",
+        "language": 2,
+        "lineNumber": 6
+      },
+      {
+        "columnNumber": 1,
+        "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()",
+        "functionName": "triggerPacket",
+        "language": 2,
+        "lineNumber": 9
+      }
+    ],
+    "workerType": "none",
+    "styles": [],
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.time('bar')", {
-	"from": "server1.conn13.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [
-			"bar"
-		],
-		"columnNumber": 1,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)",
-		"functionName": "triggerPacket",
-		"groupName": "",
-		"level": "time",
-		"lineNumber": 2,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"timeStamp": 1479159911476,
-		"timer": {
-			"name": "bar",
-			"started": 1166.305
-		},
-		"workerType": "none",
-		"styles": [],
-		"category": "webdev"
-	}
+  "from": "server1.conn13.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [
+      "bar"
+    ],
+    "columnNumber": 1,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)",
+    "functionName": "triggerPacket",
+    "groupName": "",
+    "level": "time",
+    "lineNumber": 2,
+    "private": false,
+    "timeStamp": 1479159911476,
+    "timer": {
+      "name": "bar",
+      "started": 1166.305
+    },
+    "workerType": "none",
+    "styles": [],
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.timeEnd('bar')", {
-	"from": "server1.conn13.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [
-			"bar"
-		],
-		"columnNumber": 1,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)",
-		"functionName": "triggerPacket",
-		"groupName": "",
-		"level": "timeEnd",
-		"lineNumber": 3,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"timeStamp": 1479159911478,
-		"timer": {
-			"duration": 1.3550000000000182,
-			"name": "bar"
-		},
-		"workerType": "none",
-		"styles": [],
-		"category": "webdev"
-	}
+  "from": "server1.conn13.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [
+      "bar"
+    ],
+    "columnNumber": 1,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)",
+    "functionName": "triggerPacket",
+    "groupName": "",
+    "level": "timeEnd",
+    "lineNumber": 3,
+    "private": false,
+    "timeStamp": 1479159911478,
+    "timer": {
+      "duration": 1.3550000000000182,
+      "name": "bar"
+    },
+    "workerType": "none",
+    "styles": [],
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.table('bar')", {
-	"from": "server1.conn14.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [
-			"bar"
-		],
-		"columnNumber": 1,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%27bar%27)",
-		"functionName": "triggerPacket",
-		"groupName": "",
-		"level": "table",
-		"lineNumber": 2,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"timeStamp": 1479159912655,
-		"timer": null,
-		"workerType": "none",
-		"styles": [],
-		"category": "webdev"
-	}
+  "from": "server1.conn14.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [
+      "bar"
+    ],
+    "columnNumber": 1,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%27bar%27)",
+    "functionName": "triggerPacket",
+    "groupName": "",
+    "level": "table",
+    "lineNumber": 2,
+    "private": false,
+    "timeStamp": 1479159912655,
+    "timer": null,
+    "workerType": "none",
+    "styles": [],
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.table(['a', 'b', 'c'])", {
-	"from": "server1.conn15.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [
-			{
-				"type": "object",
-				"actor": "server1.conn15.child1/obj31",
-				"class": "Array",
-				"extensible": true,
-				"frozen": false,
-				"sealed": false,
-				"ownPropertyLength": 4,
-				"preview": {
-					"kind": "ArrayLike",
-					"length": 3,
-					"items": [
-						"a",
-						"b",
-						"c"
-					]
-				}
-			}
-		],
-		"columnNumber": 1,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%5B%27a%27%2C%20%27b%27%2C%20%27c%27%5D)",
-		"functionName": "triggerPacket",
-		"groupName": "",
-		"level": "table",
-		"lineNumber": 2,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"timeStamp": 1479159913807,
-		"timer": null,
-		"workerType": "none",
-		"styles": [],
-		"category": "webdev"
-	}
+  "from": "server1.conn15.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [
+      {
+        "type": "object",
+        "actor": "server1.conn15.child1/obj31",
+        "class": "Array",
+        "extensible": true,
+        "frozen": false,
+        "sealed": false,
+        "ownPropertyLength": 4,
+        "preview": {
+          "kind": "ArrayLike",
+          "length": 3,
+          "items": [
+            "a",
+            "b",
+            "c"
+          ]
+        }
+      }
+    ],
+    "columnNumber": 1,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%5B%27a%27%2C%20%27b%27%2C%20%27c%27%5D)",
+    "functionName": "triggerPacket",
+    "groupName": "",
+    "level": "table",
+    "lineNumber": 2,
+    "private": false,
+    "timeStamp": 1479159913807,
+    "timer": null,
+    "workerType": "none",
+    "styles": [],
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.group('bar')", {
-	"from": "server1.conn16.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [
-			"bar"
-		],
-		"columnNumber": 1,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)",
-		"functionName": "triggerPacket",
-		"groupName": "bar",
-		"level": "group",
-		"lineNumber": 2,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"timeStamp": 1479159914984,
-		"timer": null,
-		"workerType": "none",
-		"styles": [],
-		"category": "webdev"
-	}
+  "from": "server1.conn16.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [
+      "bar"
+    ],
+    "columnNumber": 1,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)",
+    "functionName": "triggerPacket",
+    "groupName": "bar",
+    "level": "group",
+    "lineNumber": 2,
+    "private": false,
+    "timeStamp": 1479159914984,
+    "timer": null,
+    "workerType": "none",
+    "styles": [],
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.groupEnd('bar')", {
-	"from": "server1.conn16.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [
-			"bar"
-		],
-		"columnNumber": 1,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)",
-		"functionName": "triggerPacket",
-		"groupName": "bar",
-		"level": "groupEnd",
-		"lineNumber": 3,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"timeStamp": 1479159914987,
-		"timer": null,
-		"workerType": "none",
-		"styles": [],
-		"category": "webdev"
-	}
+  "from": "server1.conn16.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [
+      "bar"
+    ],
+    "columnNumber": 1,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)",
+    "functionName": "triggerPacket",
+    "groupName": "bar",
+    "level": "groupEnd",
+    "lineNumber": 3,
+    "private": false,
+    "timeStamp": 1479159914987,
+    "timer": null,
+    "workerType": "none",
+    "styles": [],
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.groupCollapsed('foo')", {
-	"from": "server1.conn17.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [
-			"foo"
-		],
-		"columnNumber": 1,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)",
-		"functionName": "triggerPacket",
-		"groupName": "foo",
-		"level": "groupCollapsed",
-		"lineNumber": 2,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"timeStamp": 1479159916153,
-		"timer": null,
-		"workerType": "none",
-		"styles": [],
-		"category": "webdev"
-	}
+  "from": "server1.conn17.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [
+      "foo"
+    ],
+    "columnNumber": 1,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)",
+    "functionName": "triggerPacket",
+    "groupName": "foo",
+    "level": "groupCollapsed",
+    "lineNumber": 2,
+    "private": false,
+    "timeStamp": 1479159916153,
+    "timer": null,
+    "workerType": "none",
+    "styles": [],
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.groupEnd('foo')", {
-	"from": "server1.conn17.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [
-			"foo"
-		],
-		"columnNumber": 1,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)",
-		"functionName": "triggerPacket",
-		"groupName": "foo",
-		"level": "groupEnd",
-		"lineNumber": 3,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"timeStamp": 1479159916155,
-		"timer": null,
-		"workerType": "none",
-		"styles": [],
-		"category": "webdev"
-	}
+  "from": "server1.conn17.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [
+      "foo"
+    ],
+    "columnNumber": 1,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)",
+    "functionName": "triggerPacket",
+    "groupName": "foo",
+    "level": "groupEnd",
+    "lineNumber": 3,
+    "private": false,
+    "timeStamp": 1479159916155,
+    "timer": null,
+    "workerType": "none",
+    "styles": [],
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.group()", {
-	"from": "server1.conn18.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [],
-		"columnNumber": 1,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()",
-		"functionName": "triggerPacket",
-		"groupName": "",
-		"level": "group",
-		"lineNumber": 2,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"timeStamp": 1479159917524,
-		"timer": null,
-		"workerType": "none",
-		"styles": [],
-		"category": "webdev"
-	}
+  "from": "server1.conn18.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [],
+    "columnNumber": 1,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()",
+    "functionName": "triggerPacket",
+    "groupName": "",
+    "level": "group",
+    "lineNumber": 2,
+    "private": false,
+    "timeStamp": 1479159917524,
+    "timer": null,
+    "workerType": "none",
+    "styles": [],
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.groupEnd()", {
-	"from": "server1.conn18.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [],
-		"columnNumber": 1,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()",
-		"functionName": "triggerPacket",
-		"groupName": "",
-		"level": "groupEnd",
-		"lineNumber": 3,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"timeStamp": 1479159917526,
-		"timer": null,
-		"workerType": "none",
-		"styles": [],
-		"category": "webdev"
-	}
+  "from": "server1.conn18.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [],
+    "columnNumber": 1,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()",
+    "functionName": "triggerPacket",
+    "groupName": "",
+    "level": "groupEnd",
+    "lineNumber": 3,
+    "private": false,
+    "timeStamp": 1479159917526,
+    "timer": null,
+    "workerType": "none",
+    "styles": [],
+    "category": "webdev"
+  }
 });
 
 stubPackets.set("console.log(%cfoobar)", {
-	"from": "server1.conn19.child1/consoleActor2",
-	"type": "consoleAPICall",
-	"message": {
-		"arguments": [
-			"foo",
-			"bar"
-		],
-		"columnNumber": 1,
-		"counter": null,
-		"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%25cfoobar)",
-		"functionName": "triggerPacket",
-		"groupName": "",
-		"level": "log",
-		"lineNumber": 2,
-		"originAttributes": {
-			"addonId": "",
-			"appId": 0,
-			"firstPartyDomain": "",
-			"inIsolatedMozBrowser": false,
-			"privateBrowsingId": 0,
-			"userContextId": 0
-		},
-		"private": false,
-		"styles": [
-			"color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px",
-			"color:red;background:url('http://example.com/test')"
-		],
-		"timeStamp": 1479159919144,
-		"timer": null,
-		"workerType": "none",
-		"category": "webdev"
-	}
+  "from": "server1.conn19.child1/consoleActor2",
+  "type": "consoleAPICall",
+  "message": {
+    "arguments": [
+      "foo",
+      "bar"
+    ],
+    "columnNumber": 1,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%25cfoobar)",
+    "functionName": "triggerPacket",
+    "groupName": "",
+    "level": "log",
+    "lineNumber": 2,
+    "private": false,
+    "styles": [
+      "color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px",
+      "color:red;background:url('http://example.com/test')"
+    ],
+    "timeStamp": 1479159919144,
+    "timer": null,
+    "workerType": "none",
+    "category": "webdev"
+  }
 });
 
-
 module.exports = {
   stubPreparedMessages,
   stubPackets,
-}
\ No newline at end of file
+};
--- a/devtools/client/webconsole/new-console-output/test/fixtures/stubs/cssMessage.js
+++ b/devtools/client/webconsole/new-console-output/test/fixtures/stubs/cssMessage.js
@@ -1,107 +1,105 @@
 /* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */
+/* eslint-disable max-len */
 
 "use strict";
 
 /*
  * THIS FILE IS AUTOGENERATED. DO NOT MODIFY BY HAND. RUN TESTS IN FIXTURES/ TO UPDATE.
  */
 
-const { ConsoleMessage, NetworkEventMessage } = require("devtools/client/webconsole/new-console-output/types");
+const { ConsoleMessage } =
+  require("devtools/client/webconsole/new-console-output/types");
 
 let stubPreparedMessages = new Map();
 let stubPackets = new Map();
-
-
 stubPreparedMessages.set("Unknown property ‘such-unknown-property’.  Declaration dropped.", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "css",
-	"timeStamp": 1479159920406,
-	"type": "log",
-	"level": "warn",
-	"messageText": "Unknown property ‘such-unknown-property’.  Declaration dropped.",
-	"parameters": null,
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"css\",\"timeStamp\":1479159920406,\"type\":\"log\",\"level\":\"warn\",\"messageText\":\"Unknown property ‘such-unknown-property’.  Declaration dropped.\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.css?key=Unknown%20property\",\"line\":3,\"column\":23},\"groupId\":null,\"userProvidedStyles\":null}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.css?key=Unknown%20property",
-		"line": 3,
-		"column": 23
-	},
-	"groupId": null,
-	"userProvidedStyles": null
+  "id": "1",
+  "allowRepeating": true,
+  "source": "css",
+  "timeStamp": 1479159920406,
+  "type": "log",
+  "level": "warn",
+  "messageText": "Unknown property ‘such-unknown-property’.  Declaration dropped.",
+  "parameters": null,
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"css\",\"timeStamp\":1479159920406,\"type\":\"log\",\"level\":\"warn\",\"messageText\":\"Unknown property ‘such-unknown-property’.  Declaration dropped.\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.css?key=Unknown%20property\",\"line\":3,\"column\":23},\"groupId\":null,\"userProvidedStyles\":null}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.css?key=Unknown%20property",
+    "line": 3,
+    "column": 23
+  },
+  "groupId": null,
+  "userProvidedStyles": null
 }));
 
 stubPreparedMessages.set("Error in parsing value for ‘padding-top’.  Declaration dropped.", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "css",
-	"timeStamp": 1479159920465,
-	"type": "log",
-	"level": "warn",
-	"messageText": "Error in parsing value for ‘padding-top’.  Declaration dropped.",
-	"parameters": null,
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"css\",\"timeStamp\":1479159920465,\"type\":\"log\",\"level\":\"warn\",\"messageText\":\"Error in parsing value for ‘padding-top’.  Declaration dropped.\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.css?key=Invalid%20property%20value\",\"line\":3,\"column\":15},\"groupId\":null,\"userProvidedStyles\":null}",
-	"stacktrace": null,
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.css?key=Invalid%20property%20value",
-		"line": 3,
-		"column": 15
-	},
-	"groupId": null,
-	"userProvidedStyles": null
+  "id": "1",
+  "allowRepeating": true,
+  "source": "css",
+  "timeStamp": 1479159920465,
+  "type": "log",
+  "level": "warn",
+  "messageText": "Error in parsing value for ‘padding-top’.  Declaration dropped.",
+  "parameters": null,
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"css\",\"timeStamp\":1479159920465,\"type\":\"log\",\"level\":\"warn\",\"messageText\":\"Error in parsing value for ‘padding-top’.  Declaration dropped.\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.css?key=Invalid%20property%20value\",\"line\":3,\"column\":15},\"groupId\":null,\"userProvidedStyles\":null}",
+  "stacktrace": null,
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.css?key=Invalid%20property%20value",
+    "line": 3,
+    "column": 15
+  },
+  "groupId": null,
+  "userProvidedStyles": null
 }));
 
-
 stubPackets.set("Unknown property ‘such-unknown-property’.  Declaration dropped.", {
-	"from": "server1.conn0.child1/consoleActor2",
-	"type": "pageError",
-	"pageError": {
-		"errorMessage": "Unknown property ‘such-unknown-property’.  Declaration dropped.",
-		"errorMessageName": "",
-		"sourceName": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.css?key=Unknown%20property",
-		"lineText": "  such-unknown-property: wow;",
-		"lineNumber": 3,
-		"columnNumber": 23,
-		"category": "CSS Parser",
-		"timeStamp": 1479159920406,
-		"warning": true,
-		"error": false,
-		"exception": false,
-		"strict": false,
-		"info": false,
-		"private": false,
-		"stacktrace": null
-	}
+  "from": "server1.conn0.child1/consoleActor2",
+  "type": "pageError",
+  "pageError": {
+    "errorMessage": "Unknown property ‘such-unknown-property’.  Declaration dropped.",
+    "errorMessageName": "",
+    "sourceName": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.css?key=Unknown%20property",
+    "lineText": "  such-unknown-property: wow;",
+    "lineNumber": 3,
+    "columnNumber": 23,
+    "category": "CSS Parser",
+    "timeStamp": 1479159920406,
+    "warning": true,
+    "error": false,
+    "exception": false,
+    "strict": false,
+    "info": false,
+    "private": false,
+    "stacktrace": null
+  }
 });
 
 stubPackets.set("Error in parsing value for ‘padding-top’.  Declaration dropped.", {
-	"from": "server1.conn0.child1/consoleActor2",
-	"type": "pageError",
-	"pageError": {
-		"errorMessage": "Error in parsing value for ‘padding-top’.  Declaration dropped.",
-		"errorMessageName": "",
-		"sourceName": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.css?key=Invalid%20property%20value",
-		"lineText": "  padding-top: invalid value;",
-		"lineNumber": 3,
-		"columnNumber": 15,
-		"category": "CSS Parser",
-		"timeStamp": 1479159920465,
-		"warning": true,
-		"error": false,
-		"exception": false,
-		"strict": false,
-		"info": false,
-		"private": false,
-		"stacktrace": null
-	}
+  "from": "server1.conn0.child1/consoleActor2",
+  "type": "pageError",
+  "pageError": {
+    "errorMessage": "Error in parsing value for ‘padding-top’.  Declaration dropped.",
+    "errorMessageName": "",
+    "sourceName": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.css?key=Invalid%20property%20value",
+    "lineText": "  padding-top: invalid value;",
+    "lineNumber": 3,
+    "columnNumber": 15,
+    "category": "CSS Parser",
+    "timeStamp": 1479159920465,
+    "warning": true,
+    "error": false,
+    "exception": false,
+    "strict": false,
+    "info": false,
+    "private": false,
+    "stacktrace": null
+  }
 });
 
-
 module.exports = {
   stubPreparedMessages,
   stubPackets,
-}
\ No newline at end of file
+};
--- a/devtools/client/webconsole/new-console-output/test/fixtures/stubs/evaluationResult.js
+++ b/devtools/client/webconsole/new-console-output/test/fixtures/stubs/evaluationResult.js
@@ -1,185 +1,183 @@
 /* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */
+/* eslint-disable max-len */
 
 "use strict";
 
 /*
  * THIS FILE IS AUTOGENERATED. DO NOT MODIFY BY HAND. RUN TESTS IN FIXTURES/ TO UPDATE.
  */
 
-const { ConsoleMessage, NetworkEventMessage } = require("devtools/client/webconsole/new-console-output/types");
+const { ConsoleMessage } =
+  require("devtools/client/webconsole/new-console-output/types");
 
 let stubPreparedMessages = new Map();
 let stubPackets = new Map();
-
-
 stubPreparedMessages.set("new Date(0)", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "javascript",
-	"timeStamp": 1479159921364,
-	"type": "result",
-	"level": "log",
-	"parameters": {
-		"type": "object",
-		"actor": "server1.conn0.child1/obj30",
-		"class": "Date",
-		"extensible": true,
-		"frozen": false,
-		"sealed": false,
-		"ownPropertyLength": 0,
-		"preview": {
-			"timestamp": 0
-		}
-	},
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"timeStamp\":1479159921364,\"type\":\"result\",\"level\":\"log\",\"parameters\":{\"type\":\"object\",\"actor\":\"server1.conn0.child1/obj30\",\"class\":\"Date\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":0,\"preview\":{\"timestamp\":0}},\"repeatId\":null,\"stacktrace\":null,\"frame\":null,\"groupId\":null,\"userProvidedStyles\":null}",
-	"stacktrace": null,
-	"frame": null,
-	"groupId": null,
-	"userProvidedStyles": null
+  "id": "1",
+  "allowRepeating": true,
+  "source": "javascript",
+  "timeStamp": 1479159921364,
+  "type": "result",
+  "level": "log",
+  "parameters": {
+    "type": "object",
+    "actor": "server1.conn0.child1/obj30",
+    "class": "Date",
+    "extensible": true,
+    "frozen": false,
+    "sealed": false,
+    "ownPropertyLength": 0,
+    "preview": {
+      "timestamp": 0
+    }
+  },
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"timeStamp\":1479159921364,\"type\":\"result\",\"level\":\"log\",\"parameters\":{\"type\":\"object\",\"actor\":\"server1.conn0.child1/obj30\",\"class\":\"Date\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":0,\"preview\":{\"timestamp\":0}},\"repeatId\":null,\"stacktrace\":null,\"frame\":null,\"groupId\":null,\"userProvidedStyles\":null}",
+  "stacktrace": null,
+  "frame": null,
+  "groupId": null,
+  "userProvidedStyles": null
 }));
 
 stubPreparedMessages.set("asdf()", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "javascript",
-	"timeStamp": 1479159921377,
-	"type": "result",
-	"level": "error",
-	"messageText": "ReferenceError: asdf is not defined",
-	"parameters": {
-		"type": "undefined"
-	},
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"timeStamp\":1479159921377,\"type\":\"result\",\"level\":\"error\",\"messageText\":\"ReferenceError: asdf is not defined\",\"parameters\":{\"type\":\"undefined\"},\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"debugger eval code\",\"line\":1,\"column\":1},\"groupId\":null,\"exceptionDocURL\":\"https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default\",\"userProvidedStyles\":null}",
-	"stacktrace": null,
-	"frame": {
-		"source": "debugger eval code",
-		"line": 1,
-		"column": 1
-	},
-	"groupId": null,
-	"exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default",
-	"userProvidedStyles": null
+  "id": "1",
+  "allowRepeating": true,
+  "source": "javascript",
+  "timeStamp": 1479159921377,
+  "type": "result",
+  "level": "error",
+  "messageText": "ReferenceError: asdf is not defined",
+  "parameters": {
+    "type": "undefined"
+  },
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"timeStamp\":1479159921377,\"type\":\"result\",\"level\":\"error\",\"messageText\":\"ReferenceError: asdf is not defined\",\"parameters\":{\"type\":\"undefined\"},\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"debugger eval code\",\"line\":1,\"column\":1},\"groupId\":null,\"exceptionDocURL\":\"https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default\",\"userProvidedStyles\":null}",
+  "stacktrace": null,
+  "frame": {
+    "source": "debugger eval code",
+    "line": 1,
+    "column": 1
+  },
+  "groupId": null,
+  "exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default",
+  "userProvidedStyles": null
 }));
 
 stubPreparedMessages.set("1 + @", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "javascript",
-	"timeStamp": 1479159921399,
-	"type": "result",
-	"level": "error",
-	"messageText": "SyntaxError: illegal character",
-	"parameters": {
-		"type": "undefined"
-	},
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"timeStamp\":1479159921399,\"type\":\"result\",\"level\":\"error\",\"messageText\":\"SyntaxError: illegal character\",\"parameters\":{\"type\":\"undefined\"},\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"debugger eval code\",\"line\":1,\"column\":4},\"groupId\":null,\"userProvidedStyles\":null}",
-	"stacktrace": null,
-	"frame": {
-		"source": "debugger eval code",
-		"line": 1,
-		"column": 4
-	},
-	"groupId": null,
-	"userProvidedStyles": null
+  "id": "1",
+  "allowRepeating": true,
+  "source": "javascript",
+  "timeStamp": 1479159921399,
+  "type": "result",
+  "level": "error",
+  "messageText": "SyntaxError: illegal character",
+  "parameters": {
+    "type": "undefined"
+  },
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"timeStamp\":1479159921399,\"type\":\"result\",\"level\":\"error\",\"messageText\":\"SyntaxError: illegal character\",\"parameters\":{\"type\":\"undefined\"},\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"debugger eval code\",\"line\":1,\"column\":4},\"groupId\":null,\"userProvidedStyles\":null}",
+  "stacktrace": null,
+  "frame": {
+    "source": "debugger eval code",
+    "line": 1,
+    "column": 4
+  },
+  "groupId": null,
+  "userProvidedStyles": null
 }));
 
-
 stubPackets.set("new Date(0)", {
-	"from": "server1.conn0.child1/consoleActor2",
-	"input": "new Date(0)",
-	"result": {
-		"type": "object",
-		"actor": "server1.conn0.child1/obj30",
-		"class": "Date",
-		"extensible": true,
-		"frozen": false,
-		"sealed": false,
-		"ownPropertyLength": 0,
-		"preview": {
-			"timestamp": 0
-		}
-	},
-	"timestamp": 1479159921364,
-	"exception": null,
-	"frame": null,
-	"helperResult": null
+  "from": "server1.conn0.child1/consoleActor2",
+  "input": "new Date(0)",
+  "result": {
+    "type": "object",
+    "actor": "server1.conn0.child1/obj30",
+    "class": "Date",
+    "extensible": true,
+    "frozen": false,
+    "sealed": false,
+    "ownPropertyLength": 0,
+    "preview": {
+      "timestamp": 0
+    }
+  },
+  "timestamp": 1479159921364,
+  "exception": null,
+  "frame": null,
+  "helperResult": null
 });
 
 stubPackets.set("asdf()", {
-	"from": "server1.conn0.child1/consoleActor2",
-	"input": "asdf()",
-	"result": {
-		"type": "undefined"
-	},
-	"timestamp": 1479159921377,
-	"exception": {
-		"type": "object",
-		"actor": "server1.conn0.child1/obj32",
-		"class": "Error",
-		"extensible": true,
-		"frozen": false,
-		"sealed": false,
-		"ownPropertyLength": 4,
-		"preview": {
-			"kind": "Error",
-			"name": "ReferenceError",
-			"message": "asdf is not defined",
-			"stack": "@debugger eval code:1:1\n",
-			"fileName": "debugger eval code",
-			"lineNumber": 1,
-			"columnNumber": 1
-		}
-	},
-	"exceptionMessage": "ReferenceError: asdf is not defined",
-	"exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default",
-	"frame": {
-		"source": "debugger eval code",
-		"line": 1,
-		"column": 1
-	},
-	"helperResult": null
+  "from": "server1.conn0.child1/consoleActor2",
+  "input": "asdf()",
+  "result": {
+    "type": "undefined"
+  },
+  "timestamp": 1479159921377,
+  "exception": {
+    "type": "object",
+    "actor": "server1.conn0.child1/obj32",
+    "class": "Error",
+    "extensible": true,
+    "frozen": false,
+    "sealed": false,
+    "ownPropertyLength": 4,
+    "preview": {
+      "kind": "Error",
+      "name": "ReferenceError",
+      "message": "asdf is not defined",
+      "stack": "@debugger eval code:1:1\n",
+      "fileName": "debugger eval code",
+      "lineNumber": 1,
+      "columnNumber": 1
+    }
+  },
+  "exceptionMessage": "ReferenceError: asdf is not defined",
+  "exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default",
+  "frame": {
+    "source": "debugger eval code",
+    "line": 1,
+    "column": 1
+  },
+  "helperResult": null
 });
 
 stubPackets.set("1 + @", {
-	"from": "server1.conn0.child1/consoleActor2",
-	"input": "1 + @",
-	"result": {
-		"type": "undefined"
-	},
-	"timestamp": 1479159921399,
-	"exception": {
-		"type": "object",
-		"actor": "server1.conn0.child1/obj33",
-		"class": "Error",
-		"extensible": true,
-		"frozen": false,
-		"sealed": false,
-		"ownPropertyLength": 4,
-		"preview": {
-			"kind": "Error",
-			"name": "SyntaxError",
-			"message": "illegal character",
-			"stack": "",
-			"fileName": "debugger eval code",
-			"lineNumber": 1,
-			"columnNumber": 4
-		}
-	},
-	"exceptionMessage": "SyntaxError: illegal character",
-	"frame": {
-		"source": "debugger eval code",
-		"line": 1,
-		"column": 4
-	},
-	"helperResult": null
+  "from": "server1.conn0.child1/consoleActor2",
+  "input": "1 + @",
+  "result": {
+    "type": "undefined"
+  },
+  "timestamp": 1479159921399,
+  "exception": {
+    "type": "object",
+    "actor": "server1.conn0.child1/obj33",
+    "class": "Error",
+    "extensible": true,
+    "frozen": false,
+    "sealed": false,
+    "ownPropertyLength": 4,
+    "preview": {
+      "kind": "Error",
+      "name": "SyntaxError",
+      "message": "illegal character",
+      "stack": "",
+      "fileName": "debugger eval code",
+      "lineNumber": 1,
+      "columnNumber": 4
+    }
+  },
+  "exceptionMessage": "SyntaxError: illegal character",
+  "frame": {
+    "source": "debugger eval code",
+    "line": 1,
+    "column": 4
+  },
+  "helperResult": null
 });
 
-
 module.exports = {
   stubPreparedMessages,
   stubPackets,
-}
\ No newline at end of file
+};
--- a/devtools/client/webconsole/new-console-output/test/fixtures/stubs/networkEvent.js
+++ b/devtools/client/webconsole/new-console-output/test/fixtures/stubs/networkEvent.js
@@ -1,192 +1,190 @@
 /* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */
+/* eslint-disable max-len */
 
 "use strict";
 
 /*
  * THIS FILE IS AUTOGENERATED. DO NOT MODIFY BY HAND. RUN TESTS IN FIXTURES/ TO UPDATE.
  */
 
-const { ConsoleMessage, NetworkEventMessage } = require("devtools/client/webconsole/new-console-output/types");
+const { NetworkEventMessage } =
+  require("devtools/client/webconsole/new-console-output/types");
 
 let stubPreparedMessages = new Map();
 let stubPackets = new Map();
-
-
 stubPreparedMessages.set("GET request", new NetworkEventMessage({
-	"id": "1",
-	"actor": "server1.conn0.child1/netEvent29",
-	"level": "log",
-	"isXHR": false,
-	"request": {
-		"url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
-		"method": "GET"
-	},
-	"response": {},
-	"source": "network",
-	"type": "log",
-	"timeStamp": 1479159937660,
-	"groupId": null
+  "id": "1",
+  "actor": "server1.conn0.child1/netEvent29",
+  "level": "log",
+  "isXHR": false,
+  "request": {
+    "url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
+    "method": "GET"
+  },
+  "response": {},
+  "source": "network",
+  "type": "log",
+  "timeStamp": 1479159937660,
+  "groupId": null
 }));
 
 stubPreparedMessages.set("XHR GET request", new NetworkEventMessage({
-	"id": "1",
-	"actor": "server1.conn1.child1/netEvent29",
-	"level": "log",
-	"isXHR": true,
-	"request": {
-		"url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
-		"method": "GET"
-	},
-	"response": {},
-	"source": "network",
-	"type": "log",
-	"timeStamp": 1479159938522,
-	"groupId": null
+  "id": "1",
+  "actor": "server1.conn1.child1/netEvent29",
+  "level": "log",
+  "isXHR": true,
+  "request": {
+    "url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
+    "method": "GET"
+  },
+  "response": {},
+  "source": "network",
+  "type": "log",
+  "timeStamp": 1479159938522,
+  "groupId": null
 }));
 
 stubPreparedMessages.set("XHR POST request", new NetworkEventMessage({
-	"id": "1",
-	"actor": "server1.conn2.child1/netEvent29",
-	"level": "log",
-	"isXHR": true,
-	"request": {
-		"url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
-		"method": "POST"
-	},
-	"response": {},
-	"source": "network",
-	"type": "log",
-	"timeStamp": 1479159939328,
-	"groupId": null
+  "id": "1",
+  "actor": "server1.conn2.child1/netEvent29",
+  "level": "log",
+  "isXHR": true,
+  "request": {
+    "url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
+    "method": "POST"
+  },
+  "response": {},
+  "source": "network",
+  "type": "log",
+  "timeStamp": 1479159939328,
+  "groupId": null
 }));
 
-
 stubPackets.set("GET request", {
-	"from": "server1.conn0.child1/consoleActor2",
-	"type": "networkEvent",
-	"eventActor": {
-		"actor": "server1.conn0.child1/netEvent29",
-		"startedDateTime": "2016-10-15T23:12:04.196Z",
-		"timeStamp": 1479159937660,
-		"url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
-		"method": "GET",
-		"isXHR": false,
-		"cause": {
-			"type": 3,
-			"loadingDocumentUri": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-network-event.html",
-			"stacktrace": [
-				{
-					"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js",
-					"lineNumber": 3,
-					"columnNumber": 1,
-					"functionName": "triggerPacket",
-					"asyncCause": null
-				},
-				{
-					"filename": "chrome://mochikit/content/tests/BrowserTestUtils/content-task.js line 52 > eval",
-					"lineNumber": 4,
-					"columnNumber": 7,
-					"functionName": null,
-					"asyncCause": null
-				},
-				{
-					"filename": "chrome://mochikit/content/tests/BrowserTestUtils/content-task.js",
-					"lineNumber": 53,
-					"columnNumber": 20,
-					"functionName": null,
-					"asyncCause": null
-				}
-			]
-		},
-		"private": false
-	}
+  "from": "server1.conn0.child1/consoleActor2",
+  "type": "networkEvent",
+  "eventActor": {
+    "actor": "server1.conn0.child1/netEvent29",
+    "startedDateTime": "2016-10-15T23:12:04.196Z",
+    "timeStamp": 1479159937660,
+    "url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
+    "method": "GET",
+    "isXHR": false,
+    "cause": {
+      "type": 3,
+      "loadingDocumentUri": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-network-event.html",
+      "stacktrace": [
+        {
+          "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js",
+          "lineNumber": 3,
+          "columnNumber": 1,
+          "functionName": "triggerPacket",
+          "asyncCause": null
+        },
+        {
+          "filename": "chrome://mochikit/content/tests/BrowserTestUtils/content-task.js line 52 > eval",
+          "lineNumber": 4,
+          "columnNumber": 7,
+          "functionName": null,
+          "asyncCause": null
+        },
+        {
+          "filename": "chrome://mochikit/content/tests/BrowserTestUtils/content-task.js",
+          "lineNumber": 53,
+          "columnNumber": 20,
+          "functionName": null,
+          "asyncCause": null
+        }
+      ]
+    },
+    "private": false
+  }
 });
 
 stubPackets.set("XHR GET request", {
-	"from": "server1.conn1.child1/consoleActor2",
-	"type": "networkEvent",
-	"eventActor": {
-		"actor": "server1.conn1.child1/netEvent29",
-		"startedDateTime": "2016-10-15T23:12:05.690Z",
-		"timeStamp": 1479159938522,
-		"url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
-		"method": "GET",
-		"isXHR": true,
-		"cause": {
-			"type": 11,
-			"loadingDocumentUri": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-network-event.html",
-			"stacktrace": [
-				{
-					"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js",
-					"lineNumber": 4,
-					"columnNumber": 1,
-					"functionName": "triggerPacket",
-					"asyncCause": null
-				},
-				{
-					"filename": "chrome://mochikit/content/tests/BrowserTestUtils/content-task.js line 52 > eval",
-					"lineNumber": 4,
-					"columnNumber": 7,
-					"functionName": null,
-					"asyncCause": null
-				},
-				{
-					"filename": "chrome://mochikit/content/tests/BrowserTestUtils/content-task.js",
-					"lineNumber": 53,
-					"columnNumber": 20,
-					"functionName": null,
-					"asyncCause": null
-				}
-			]
-		},
-		"private": false
-	}
+  "from": "server1.conn1.child1/consoleActor2",
+  "type": "networkEvent",
+  "eventActor": {
+    "actor": "server1.conn1.child1/netEvent29",
+    "startedDateTime": "2016-10-15T23:12:05.690Z",
+    "timeStamp": 1479159938522,
+    "url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
+    "method": "GET",
+    "isXHR": true,
+    "cause": {
+      "type": 11,
+      "loadingDocumentUri": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-network-event.html",
+      "stacktrace": [
+        {
+          "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js",
+          "lineNumber": 4,
+          "columnNumber": 1,
+          "functionName": "triggerPacket",
+          "asyncCause": null
+        },
+        {
+          "filename": "chrome://mochikit/content/tests/BrowserTestUtils/content-task.js line 52 > eval",
+          "lineNumber": 4,
+          "columnNumber": 7,
+          "functionName": null,
+          "asyncCause": null
+        },
+        {
+          "filename": "chrome://mochikit/content/tests/BrowserTestUtils/content-task.js",
+          "lineNumber": 53,
+          "columnNumber": 20,
+          "functionName": null,
+          "asyncCause": null
+        }
+      ]
+    },
+    "private": false
+  }
 });
 
 stubPackets.set("XHR POST request", {
-	"from": "server1.conn2.child1/consoleActor2",
-	"type": "networkEvent",
-	"eventActor": {
-		"actor": "server1.conn2.child1/netEvent29",
-		"startedDateTime": "2016-10-15T23:12:07.158Z",
-		"timeStamp": 1479159939328,
-		"url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
-		"method": "POST",
-		"isXHR": true,
-		"cause": {
-			"type": 11,
-			"loadingDocumentUri": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-network-event.html",
-			"stacktrace": [
-				{
-					"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js",
-					"lineNumber": 4,
-					"columnNumber": 1,
-					"functionName": "triggerPacket",
-					"asyncCause": null
-				},
-				{
-					"filename": "chrome://mochikit/content/tests/BrowserTestUtils/content-task.js line 52 > eval",
-					"lineNumber": 4,
-					"columnNumber": 7,
-					"functionName": null,
-					"asyncCause": null
-				},
-				{
-					"filename": "chrome://mochikit/content/tests/BrowserTestUtils/content-task.js",
-					"lineNumber": 53,
-					"columnNumber": 20,
-					"functionName": null,
-					"asyncCause": null
-				}
-			]
-		},
-		"private": false
-	}
+  "from": "server1.conn2.child1/consoleActor2",
+  "type": "networkEvent",
+  "eventActor": {
+    "actor": "server1.conn2.child1/netEvent29",
+    "startedDateTime": "2016-10-15T23:12:07.158Z",
+    "timeStamp": 1479159939328,
+    "url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
+    "method": "POST",
+    "isXHR": true,
+    "cause": {
+      "type": 11,
+      "loadingDocumentUri": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-network-event.html",
+      "stacktrace": [
+        {
+          "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js",
+          "lineNumber": 4,
+          "columnNumber": 1,
+          "functionName": "triggerPacket",
+          "asyncCause": null
+        },
+        {
+          "filename": "chrome://mochikit/content/tests/BrowserTestUtils/content-task.js line 52 > eval",
+          "lineNumber": 4,
+          "columnNumber": 7,
+          "functionName": null,
+          "asyncCause": null
+        },
+        {
+          "filename": "chrome://mochikit/content/tests/BrowserTestUtils/content-task.js",
+          "lineNumber": 53,
+          "columnNumber": 20,
+          "functionName": null,
+          "asyncCause": null
+        }
+      ]
+    },
+    "private": false
+  }
 });
 
-
 module.exports = {
   stubPreparedMessages,
   stubPackets,
-}
\ No newline at end of file
+};
--- a/devtools/client/webconsole/new-console-output/test/fixtures/stubs/pageError.js
+++ b/devtools/client/webconsole/new-console-output/test/fixtures/stubs/pageError.js
@@ -1,102 +1,102 @@
 /* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */
+/* eslint-disable max-len */
 
 "use strict";
 
 /*
  * THIS FILE IS AUTOGENERATED. DO NOT MODIFY BY HAND. RUN TESTS IN FIXTURES/ TO UPDATE.
  */
 
-const { ConsoleMessage, NetworkEventMessage } = require("devtools/client/webconsole/new-console-output/types");
+const { ConsoleMessage } =
+  require("devtools/client/webconsole/new-console-output/types");
 
 let stubPreparedMessages = new Map();
 let stubPackets = new Map();
-
-
 stubPreparedMessages.set("ReferenceError: asdf is not defined", new ConsoleMessage({
-	"id": "1",
-	"allowRepeating": true,
-	"source": "javascript",
-	"type": "log",
-	"level": "error",
-	"messageText": "ReferenceError: asdf is not defined",
-	"parameters": null,
-	"repeat": 1,
-	"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"type\":\"log\",\"level\":\"error\",\"messageText\":\"ReferenceError: asdf is not defined\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":[{\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"lineNumber\":3,\"columnNumber\":5,\"functionName\":\"bar\"},{\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"lineNumber\":6,\"columnNumber\":5,\"functionName\":\"foo\"},{\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"lineNumber\":9,\"columnNumber\":3,\"functionName\":null}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"line\":3,\"column\":5},\"groupId\":null,\"exceptionDocURL\":\"https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default\"}",
-	"stacktrace": [
-		{
-			"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error",
-			"lineNumber": 3,
-			"columnNumber": 5,
-			"functionName": "bar"
-		},
-		{
-			"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error",
-			"lineNumber": 6,
-			"columnNumber": 5,
-			"functionName": "foo"
-		},
-		{
-			"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error",
-			"lineNumber": 9,
-			"columnNumber": 3,
-			"functionName": null
-		}
-	],
-	"frame": {
-		"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error",
-		"line": 3,
-		"column": 5
-	},
-	"groupId": null,
-	"exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default"
+  "id": "1",
+  "allowRepeating": true,
+  "source": "javascript",
+  "timeStamp": 1476573167137,
+  "type": "log",
+  "level": "error",
+  "messageText": "ReferenceError: asdf is not defined",
+  "parameters": null,
+  "repeat": 1,
+  "repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"timeStamp\":1476573167137,\"type\":\"log\",\"level\":\"error\",\"messageText\":\"ReferenceError: asdf is not defined\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":[{\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"lineNumber\":3,\"columnNumber\":5,\"functionName\":\"bar\"},{\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"lineNumber\":6,\"columnNumber\":5,\"functionName\":\"foo\"},{\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"lineNumber\":9,\"columnNumber\":3,\"functionName\":null}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"line\":3,\"column\":5},\"groupId\":null,\"exceptionDocURL\":\"https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default\",\"userProvidedStyles\":null}",
+  "stacktrace": [
+    {
+      "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error",
+      "lineNumber": 3,
+      "columnNumber": 5,
+      "functionName": "bar"
+    },
+    {
+      "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error",
+      "lineNumber": 6,
+      "columnNumber": 5,
+      "functionName": "foo"
+    },
+    {
+      "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error",
+      "lineNumber": 9,
+      "columnNumber": 3,
+      "functionName": null
+    }
+  ],
+  "frame": {
+    "source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error",
+    "line": 3,
+    "column": 5
+  },
+  "groupId": null,
+  "exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default",
+  "userProvidedStyles": null
 }));
 
-
 stubPackets.set("ReferenceError: asdf is not defined", {
-	"from": "server1.conn0.child1/consoleActor2",
-	"type": "pageError",
-	"pageError": {
-		"errorMessage": "ReferenceError: asdf is not defined",
-		"errorMessageName": "JSMSG_NOT_DEFINED",
-		"exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default",
-		"sourceName": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error",
-		"lineText": "",
-		"lineNumber": 3,
-		"columnNumber": 5,
-		"category": "content javascript",
-		"timeStamp": 1476573167137,
-		"warning": false,
-		"error": false,
-		"exception": true,
-		"strict": false,
-		"info": false,
-		"private": false,
-		"stacktrace": [
-			{
-				"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error",
-				"lineNumber": 3,
-				"columnNumber": 5,
-				"functionName": "bar"
-			},
-			{
-				"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error",
-				"lineNumber": 6,
-				"columnNumber": 5,
-				"functionName": "foo"
-			},
-			{
-				"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error",
-				"lineNumber": 9,
-				"columnNumber": 3,
-				"functionName": null
-			}
-		]
-	}
+  "from": "server1.conn0.child1/consoleActor2",
+  "type": "pageError",
+  "pageError": {
+    "errorMessage": "ReferenceError: asdf is not defined",
+    "errorMessageName": "JSMSG_NOT_DEFINED",
+    "exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default",
+    "sourceName": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error",
+    "lineText": "",
+    "lineNumber": 3,
+    "columnNumber": 5,
+    "category": "content javascript",
+    "timeStamp": 1476573167137,
+    "warning": false,
+    "error": false,
+    "exception": true,
+    "strict": false,
+    "info": false,
+    "private": false,
+    "stacktrace": [
+      {
+        "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error",
+        "lineNumber": 3,
+        "columnNumber": 5,
+        "functionName": "bar"
+      },
+      {
+        "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error",
+        "lineNumber": 6,
+        "columnNumber": 5,
+        "functionName": "foo"
+      },
+      {
+        "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error",
+        "lineNumber": 9,
+        "columnNumber": 3,
+        "functionName": null
+      }
+    ]
+  }
 });
 
-
 module.exports = {
   stubPreparedMessages,
   stubPackets,
-}
\ No newline at end of file
+};
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_console_table.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_console_table.js
@@ -132,42 +132,43 @@ add_task(function* () {
   }
 
   let consoleTableNodes = hud.ui.experimentalOutputNode.querySelectorAll(
     ".message .new-consoletable");
 
   is(consoleTableNodes.length, testCases.length,
     "console has the expected number of consoleTable items");
 
-  testCases.forEach((testCase, index) => {
-    info(testCase.info);
+  testCases.forEach((testCase, index) => testItem(testCase, nodes[index]));
+});
 
-    let node = nodes[index];
-    let columns = Array.from(node.querySelectorAll("thead th"));
-    let rows = Array.from(node.querySelectorAll("tbody tr"));
+function testItem(testCase, node) {
+  info(testCase.info);
 
-    is(
-      JSON.stringify(testCase.expected.columns),
-      JSON.stringify(columns.map(column => column.textContent)),
-      "table has the expected columns"
-    );
+  let columns = Array.from(node.querySelectorAll("thead th"));
+  let rows = Array.from(node.querySelectorAll("tbody tr"));
 
-    is(testCase.expected.rows.length, rows.length,
-      "table has the expected number of rows");
+  is(
+    JSON.stringify(testCase.expected.columns),
+    JSON.stringify(columns.map(column => column.textContent)),
+    "table has the expected columns"
+  );
+
+  is(testCase.expected.rows.length, rows.length,
+    "table has the expected number of rows");
 
-    testCase.expected.rows.forEach((expectedRow, rowIndex) => {
-      let row = rows[rowIndex];
-      let cells = row.querySelectorAll("td");
-      is(expectedRow.length, cells.length, "row has the expected number of cells");
+  testCase.expected.rows.forEach((expectedRow, rowIndex) => {
+    let row = rows[rowIndex];
+    let cells = row.querySelectorAll("td");
+    is(expectedRow.length, cells.length, "row has the expected number of cells");
 
-      expectedRow.forEach((expectedCell, cellIndex) => {
-        let cell = cells[cellIndex];
-        is(expectedCell, cell.textContent, "cell has the expected content");
-      });
+    expectedRow.forEach((expectedCell, cellIndex) => {
+      let cell = cells[cellIndex];
+      is(expectedCell, cell.textContent, "cell has the expected content");
     });
   });
-});
+}
 
 function findConsoleTable(node, index) {
   let condition = node.querySelector(
     `.message:nth-of-type(${index + 1}) .new-consoletable`);
   return condition;
 }
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_init.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_init.js
@@ -14,22 +14,22 @@ add_task(function* () {
 
   ok(ui.jsterm, "jsterm exists");
   ok(ui.newConsoleOutput, "newConsoleOutput exists");
 
   // @TODO: fix proptype errors
   let receievedMessages = waitForMessages({
     hud,
     messages: [{
-      text: '0',
+      text: "0",
     }, {
-      text: '1',
+      text: "1",
     }, {
-      text: '2',
+      text: "2",
     }],
   });
 
-  yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
+  yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function () {
     content.wrappedJSObject.doLogs(3);
   });
 
   yield receievedMessages;
 });
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_observer_notifications.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_observer_notifications.js
@@ -16,30 +16,33 @@ add_task(function* () {
   yield openNewTabAndConsole(TEST_URI);
   yield waitFor(() => created);
 
   yield closeTabAndToolbox(gBrowser.selectedTab);
   yield waitFor(() => destroyed);
 });
 
 function setupObserver() {
+  const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
+
   const observer = {
     QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
 
     observe: function observe(subject, topic) {
       subject = subject.QueryInterface(Ci.nsISupportsString);
 
       switch (topic) {
         case "web-console-created":
           ok(HUDService.getHudReferenceById(subject.data), "We have a hud reference");
           Services.obs.removeObserver(observer, "web-console-created");
           created = true;
           break;
         case "web-console-destroyed":
-          ok(!HUDService.getHudReferenceById(subject.data), "We do not have a hud reference");
+          ok(!HUDService.getHudReferenceById(subject.data),
+            "We do not have a hud reference");
           Services.obs.removeObserver(observer, "web-console-destroyed");
           destroyed = true;
           break;
       }
     },
   };
 
   Services.obs.addObserver(observer, "web-console-created", false);
--- a/devtools/client/webconsole/new-console-output/test/mochitest/head.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/head.js
@@ -1,13 +1,14 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 /* import-globals-from ../../../../framework/test/shared-head.js */
+/* exported WCUL10n, openNewTabAndConsole, waitForMessages, waitFor, findMessage */
 
 "use strict";
 
 // shared-head.js handles imports, constants, and utility functions
 // Load the shared-head file first.
 Services.scriptloader.loadSubScript(
   "chrome://mochitests/content/browser/devtools/client/framework/test/shared-head.js",
   this);
@@ -45,44 +46,48 @@ var openNewTabAndConsole = Task.async(fu
   return hud;
 });
 
 /**
  * Wait for messages in the web console output, resolving once they are receieved.
  *
  * @param object options
  *        - hud: the webconsole
- *        - messages: Array[Object]. An array of messages to match. Current supported options:
+ *        - messages: Array[Object]. An array of messages to match.
+            Current supported options:
  *            - text: Exact text match in .message-body
  */
 function waitForMessages({ hud, messages }) {
   return new Promise(resolve => {
     let numMatched = 0;
-    let receivedLog = hud.ui.on("new-messages", function messagesReceieved(e, newMessages) {
-      for (let message of messages) {
-        if (message.matched) {
-          continue;
-        }
+    let receivedLog = hud.ui.on("new-messages",
+      function messagesReceieved(e, newMessages) {
+        for (let message of messages) {
+          if (message.matched) {
+            continue;
+          }
 
-        for (let newMessage of newMessages) {
-          if (newMessage.node.querySelector(".message-body").textContent == message.text) {
-            numMatched++;
-            message.matched = true;
-            info("Matched a message with text: " + message.text + ", still waiting for " + (messages.length - numMatched) + " messages");
-            break;
+          for (let newMessage of newMessages) {
+            let messageBody = newMessage.node.querySelector(".message-body");
+            if (messageBody.textContent == message.text) {
+              numMatched++;
+              message.matched = true;
+              info("Matched a message with text: " + message.text +
+                ", still waiting for " + (messages.length - numMatched) + " messages");
+              break;
+            }
+          }
+
+          if (numMatched === messages.length) {
+            hud.ui.off("new-messages", messagesReceieved);
+            resolve(receivedLog);
+            return;
           }
         }
-
-        if (numMatched === messages.length) {
-          hud.ui.off("new-messages", messagesReceieved);
-          resolve(receivedLog);
-          return;
-        }
-      }
-    });
+      });
   });
 }
 
 /**
  * Wait for a predicate to return a result.
  *
  * @param function condition
  *        Invoked once in a while until it returns a truthy value. This should be an
--- a/devtools/client/webconsole/new-console-output/test/mochitest/test-batching.html
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/test-batching.html
@@ -2,16 +2,17 @@
 <html lang="en">
   <head>
     <meta charset="utf-8">
     <title>Webconsole batch console calls test page</title>
   </head>
   <body>
     <p>batch console calls test page</p>
     <script>
+    /* exported batchLog, batchLogAndClear */
     "use strict";
 
     function batchLog(numMessages = 0) {
       for (let i = 0; i < numMessages; i++) {
         console.log(i);
       }
     }
 
--- a/devtools/client/webconsole/new-console-output/test/mochitest/test-console-filters.html
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/test-console-filters.html
@@ -2,16 +2,18 @@
 <html lang="en">
   <head>
     <meta charset="utf-8">
     <title>Webconsole filters test page</title>
   </head>
   <body>
     <p>Webconsole filters test page</p>
     <script>
+      "use strict";
+
       console.log("console log");
       console.warn("console warn");
       console.error("console error");
       console.info("console info");
       console.count("console debug");
     </script>
   </body>
 </html>
--- a/devtools/client/webconsole/new-console-output/test/mochitest/test-console-group.html
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/test-console-group.html
@@ -2,27 +2,28 @@
 <html lang="en">
   <head>
     <meta charset="utf-8">
     <title>Webconsole console.group test page</title>
   </head>
   <body>
     <p>console.group() & console.groupCollapsed() test page</p>
     <script>
+    /* exported doLog */
     "use strict";
 
     function doLog() {
-        console.group("group-1");
-        console.log("log-1");
-        console.group("group-2");
-        console.log("log-2");
-        console.groupEnd("group-2");
-        console.log("log-3");
-        console.groupEnd("group-1");
-        console.log("log-4");
-        console.groupCollapsed("group-3");
-        console.log("log-5");
-        console.groupEnd("group-3");
-        console.log("log-6");
+      console.group("group-1");
+      console.log("log-1");
+      console.group("group-2");
+      console.log("log-2");
+      console.groupEnd("group-2");
+      console.log("log-3");
+      console.groupEnd("group-1");
+      console.log("log-4");
+      console.groupCollapsed("group-3");
+      console.log("log-5");
+      console.groupEnd("group-3");
+      console.log("log-6");
     }
     </script>
   </body>
 </html>
--- a/devtools/client/webconsole/new-console-output/test/mochitest/test-console-table.html
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/test-console-table.html
@@ -2,16 +2,19 @@
 <html lang="en">
   <head>
     <meta charset="utf-8">
     <title>Simple webconsole test page</title>
   </head>
   <body>
     <p>console.table() test page</p>
     <script>
+      /* exported doConsoleTable */
+      "use strict";
+
       function doConsoleTable(data, constrainedHeaders = null) {
         if (constrainedHeaders) {
           console.table(data, constrainedHeaders);
         } else {
           console.table(data);
         }
       }
     </script>
--- a/devtools/client/webconsole/new-console-output/test/mochitest/test-console.html
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/test-console.html
@@ -2,17 +2,20 @@
 <html lang="en">
   <head>
     <meta charset="utf-8">
     <title>Simple webconsole test page</title>
   </head>
   <body>
     <p>Simple webconsole test page</p>
     <script>
+      /* exported doLogs */
+      "use strict";
+
       function doLogs(num) {
         num = num || 1;
-        for (var i = 0; i < num; i++) {
+        for (let i = 0; i < num; i++) {
           console.log(i);
         }
       }
     </script>
   </body>
 </html>
--- a/devtools/client/webconsole/new-console-output/test/require-helper.js
+++ b/devtools/client/webconsole/new-console-output/test/require-helper.js
@@ -34,9 +34,10 @@ requireHacker.global_hook("default", pat
     case "devtools/shared/plural-form":
       return `module.exports = require("devtools/client/webconsole/new-console-output/test/fixtures/PluralForm")`;
     case "Services":
     case "Services.default":
       return `module.exports = require("devtools/client/webconsole/new-console-output/test/fixtures/Services")`;
     case "devtools/shared/client/main":
       return `module.exports = require("devtools/client/webconsole/new-console-output/test/fixtures/ObjectClient")`;
   }
+  return undefined;
 });
--- a/dom/animation/EffectCompositor.cpp
+++ b/dom/animation/EffectCompositor.cpp
@@ -920,16 +920,35 @@ EffectCompositor::GetBaseStyle(nsCSSProp
   MOZ_ASSERT(success, "Should be able to extract computed animation value");
   MOZ_ASSERT(!result.IsNull(), "Should have a valid StyleAnimationValue");
 
   effectSet->PutBaseStyle(aProperty, result);
 
   return result;
 }
 
+/* static */ StyleAnimationValue
+EffectCompositor::GetBaseStyle(nsCSSPropertyID aProperty,
+                               const nsIFrame* aFrame)
+{
+  MOZ_ASSERT(aFrame->StyleContext(),
+             "The frame should have a valid style context");
+
+  Maybe<NonOwningAnimationTarget> pseudoElement =
+    EffectCompositor::GetAnimationElementAndPseudoForFrame(aFrame);
+
+  MOZ_ASSERT(pseudoElement && pseudoElement->mElement,
+             "The frame should have an associated element");
+
+  return EffectCompositor::GetBaseStyle(aProperty,
+                                        aFrame->StyleContext(),
+                                        *pseudoElement->mElement,
+                                        pseudoElement->mPseudoType);
+}
+
 /* static */ void
 EffectCompositor::ClearBaseStyles(dom::Element& aElement,
                                   CSSPseudoElementType aPseudoType)
 {
   EffectSet* effectSet =
     EffectSet::GetEffectSet(&aElement, aPseudoType);
   if (!effectSet) {
     return;
--- a/dom/animation/EffectCompositor.h
+++ b/dom/animation/EffectCompositor.h
@@ -221,16 +221,22 @@ public:
   // If there is no cached base style for the property, a new base style value
   // is resolved with |aStyleContext|. The new resolved base style is cached
   // until ClearBaseStyles is called.
   static StyleAnimationValue GetBaseStyle(nsCSSPropertyID aProperty,
                                           nsStyleContext* aStyleContext,
                                           dom::Element& aElement,
                                           CSSPseudoElementType aPseudoType);
 
+  // Returns the base style corresponding to |aFrame|.
+  // This function should be called only after restyle process has done, i.e.
+  // |aFrame| has a resolved style context.
+  static StyleAnimationValue GetBaseStyle(nsCSSPropertyID aProperty,
+                                          const nsIFrame* aFrame);
+
   // Clear cached base styles of (pseudo-)element.
   static void ClearBaseStyles(dom::Element& aElement,
                               CSSPseudoElementType aPseudoType);
 
 private:
   ~EffectCompositor() = default;
 
   // Rebuilds the animation rule corresponding to |aCascadeLevel| on the
--- a/dom/animation/EffectSet.h
+++ b/dom/animation/EffectSet.h
@@ -194,16 +194,18 @@ public:
   {
     return mPropertiesWithImportantRules;
   }
   nsCSSPropertyIDSet& PropertiesForAnimationsLevel()
   {
     return mPropertiesForAnimationsLevel;
   }
 
+  // This function is intended to be called by EffectCompositor::GetBaseStyle
+  // and should not be called directly.
   StyleAnimationValue GetBaseStyle(nsCSSPropertyID aProperty) const
   {
     StyleAnimationValue result;
     DebugOnly<bool> hasProperty = mBaseStyleValues.Get(aProperty, &result);
     MOZ_ASSERT(hasProperty || result.IsNull());
     return result;
   }
 
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/crashtests/1322382-1.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<style>
+details {
+  background-color: blue;
+  width: 100px;
+  height: 100px;
+}
+</style>
+<html>
+<details id=o1><div></div></details>
+<script>
+window.onload = function(){
+  o1.animate([{'transform': 'none'}], 100);
+};
+</script>
+</html>
--- a/dom/animation/test/crashtests/crashtests.list
+++ b/dom/animation/test/crashtests/crashtests.list
@@ -7,8 +7,9 @@ pref(dom.animations-api.core.enabled,tru
 pref(dom.animations-api.core.enabled,true) load 1216842-5.html
 pref(dom.animations-api.core.enabled,true) load 1216842-6.html
 pref(dom.animations-api.core.enabled,true) load 1272475-1.html
 pref(dom.animations-api.core.enabled,true) load 1272475-2.html
 pref(dom.animations-api.core.enabled,true) load 1278485-1.html
 pref(dom.animations-api.core.enabled,true) load 1277272-1.html
 pref(dom.animations-api.core.enabled,true) load 1290535-1.html
 pref(dom.animations-api.core.enabled,true) load 1304886-1.html
+pref(dom.animations-api.core.enabled,true) load 1322382-1.html
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -12552,17 +12552,19 @@ class CGDictionary(CGThing):
         we can avoid atomizing strings all the time, then we just spit
         out the getMemberConversion() output for each member,
         separated by newlines.
 
         """
         body = dedent("""
             // Passing a null JSContext is OK only if we're initing from null,
             // Since in that case we will not have to do any property gets
-            MOZ_ASSERT_IF(!cx, val.isNull());
+            // Also evaluate isNullOrUndefined in order to avoid false-positive
+            // checkers by static analysis tools
+            MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
             """)
 
         if self.needToInitIds:
             body += fill(
                 """
                 ${dictName}Atoms* atomsCache = nullptr;
                 if (cx) {
                   atomsCache = GetAtomCache<${dictName}Atoms>(cx);
--- a/dom/bindings/test/test_exceptions_from_jsimplemented.html
+++ b/dom/bindings/test/test_exceptions_from_jsimplemented.html
@@ -8,24 +8,24 @@ https://bugzilla.mozilla.org/show_bug.cg
   <title>Test for Bug 923010</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <script type="application/javascript">
   /** Test for Bug 923010 **/
   try {
     var conn = new RTCPeerConnection();
 
-    var candidate = new RTCIceCandidate({candidate: null });
+    var candidate = new RTCIceCandidate({candidate: "x" });
     conn.addIceCandidate(candidate)
     .then(function() {
       ok(false, "addIceCandidate succeeded when it should have failed");
     }, function(reason) {
       is(reason.lineNumber, 17, "Rejection should have been on line 17");
       is(reason.message,
-         "Invalid candidate passed to addIceCandidate!",
+         "Invalid candidate (both sdpMid and sdpMLineIndex are null).",
          "Should have the rejection we expect");
     })
     .catch(function(reason) {
       ok(false, "unexpected error: " + reason);
     });
   } catch (e) {
     // b2g has no WebRTC, apparently
     todo(false, "No WebRTC on b2g yet");
--- a/dom/gamepad/Gamepad.cpp
+++ b/dom/gamepad/Gamepad.cpp
@@ -33,21 +33,23 @@ Gamepad::UpdateTimestamp()
       mTimestamp =  perf->Now();
     }
   }
 }
 
 Gamepad::Gamepad(nsISupports* aParent,
                  const nsAString& aID, uint32_t aIndex,
                  GamepadMappingType aMapping,
+                 GamepadHand aHand,
                  uint32_t aNumButtons, uint32_t aNumAxes)
   : mParent(aParent),
     mID(aID),
     mIndex(aIndex),
     mMapping(aMapping),
+    mHand(aHand),
     mConnected(true),
     mButtons(aNumButtons),
     mAxes(aNumAxes),
     mTimestamp(0)
 {
   for (unsigned i = 0; i < aNumButtons; i++) {
     mButtons.InsertElementAt(i, new GamepadButton(mParent));
   }
@@ -117,27 +119,28 @@ Gamepad::SyncState(Gamepad* aOther)
   }
   if (changed) {
     GamepadBinding::ClearCachedAxesValue(this);
   }
 
   if (Preferences::GetBool(kGamepadExtEnabledPref)) {
     MOZ_ASSERT(aOther->GetPose());
     mPose->SetPoseState(aOther->GetPose()->GetPoseState());
+    mHand = aOther->Hand();
   }
 
   UpdateTimestamp();
 }
 
 already_AddRefed<Gamepad>
 Gamepad::Clone(nsISupports* aParent)
 {
   RefPtr<Gamepad> out =
     new Gamepad(aParent, mID, mIndex, mMapping,
-                mButtons.Length(), mAxes.Length());
+                mHand, mButtons.Length(), mAxes.Length());
   out->SyncState(this);
   return out.forget();
 }
 
 /* virtual */ JSObject*
 Gamepad::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return GamepadBinding::Wrap(aCx, this, aGivenProto);
--- a/dom/gamepad/Gamepad.h
+++ b/dom/gamepad/Gamepad.h
@@ -36,17 +36,17 @@ const int kRightStickYAxis = 3;
 
 
 class Gamepad final : public nsISupports,
                       public nsWrapperCache
 {
 public:
   Gamepad(nsISupports* aParent,
           const nsAString& aID, uint32_t aIndex,
-          GamepadMappingType aMapping,
+          GamepadMappingType aMapping, GamepadHand aHand,
           uint32_t aNumButtons, uint32_t aNumAxes);
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Gamepad)
 
   void SetConnected(bool aConnected);
   void SetButton(uint32_t aButton, bool aPressed, double aValue);
   void SetAxis(uint32_t aAxis, double aValue);
   void SetIndex(uint32_t aIndex);
@@ -76,16 +76,21 @@ public:
      return mTimestamp;
   }
 
   GamepadMappingType Mapping()
   {
     return mMapping;
   }
 
+  GamepadHand Hand()
+  {
+    return mHand;
+  }
+
   bool Connected() const
   {
     return mConnected;
   }
 
   uint32_t Index() const
   {
     return mIndex;
@@ -112,16 +117,17 @@ private:
 
 protected:
   nsCOMPtr<nsISupports> mParent;
   nsString mID;
   uint32_t mIndex;
 
   // The mapping in use.
   GamepadMappingType mMapping;
+  GamepadHand mHand;
 
   // true if this gamepad is currently connected.
   bool mConnected;
 
   // Current state of buttons, axes.
   nsTArray<RefPtr<GamepadButton>> mButtons;
   nsTArray<double> mAxes;
   DOMHighResTimeStamp mTimestamp;
--- a/dom/gamepad/GamepadManager.cpp
+++ b/dom/gamepad/GamepadManager.cpp
@@ -223,26 +223,28 @@ uint32_t GamepadManager::GetGamepadIndex
 
   return newIndex;
 }
 
 void
 GamepadManager::AddGamepad(uint32_t aIndex,
                            const nsAString& aId,
                            GamepadMappingType aMapping,
+                           GamepadHand aHand,
                            GamepadServiceType aServiceType,
                            uint32_t aNumButtons,
                            uint32_t aNumAxes)
 {
   //TODO: bug 852258: get initial button/axis state
   RefPtr<Gamepad> gamepad =
     new Gamepad(nullptr,
                 aId,
                 0, // index is set by global window
                 aMapping,
+                aHand,
                 aNumButtons,
                 aNumAxes);
 
   uint32_t newIndex = GetGamepadIndexWithServiceType(aIndex, aServiceType);
 
   // We store the gamepad related to its index given by the parent process,
   // and no duplicate index is allowed.
   MOZ_ASSERT(!mGamepads.Get(newIndex, nullptr));
@@ -629,16 +631,17 @@ GamepadManager::SetWindowHasSeenGamepad(
 
 void
 GamepadManager::Update(const GamepadChangeEvent& aEvent)
 {
   if (aEvent.type() == GamepadChangeEvent::TGamepadAdded) {
     const GamepadAdded& a = aEvent.get_GamepadAdded();
     AddGamepad(a.index(), a.id(),
                static_cast<GamepadMappingType>(a.mapping()),
+               static_cast<GamepadHand>(a.hand()),
                a.service_type(),
                a.num_buttons(), a.num_axes());
     return;
   }
   if (aEvent.type() == GamepadChangeEvent::TGamepadRemoved) {
     const GamepadRemoved& a = aEvent.get_GamepadRemoved();
     RemoveGamepad(a.index(), a.service_type());
     return;
--- a/dom/gamepad/GamepadManager.h
+++ b/dom/gamepad/GamepadManager.h
@@ -46,17 +46,18 @@ class GamepadManager final : public nsIO
 
   // Indicate that |aWindow| wants to receive gamepad events.
   void AddListener(nsGlobalWindow* aWindow);
   // Indicate that |aWindow| should no longer receive gamepad events.
   void RemoveListener(nsGlobalWindow* aWindow);
 
   // Add a gamepad to the list of known gamepads.
   void AddGamepad(uint32_t aIndex, const nsAString& aID, GamepadMappingType aMapping,
-                  GamepadServiceType aServiceType, uint32_t aNumButtons, uint32_t aNumAxes);
+                  GamepadHand aHand, GamepadServiceType aServiceType,
+                  uint32_t aNumButtons, uint32_t aNumAxes);
 
   // Remove the gamepad at |aIndex| from the list of known gamepads.
   void RemoveGamepad(uint32_t aIndex, GamepadServiceType aServiceType);
 
   // Update the state of |aButton| for the gamepad at |aIndex| for all
   // windows that are listening and visible, and fire one of
   // a gamepadbutton{up,down} event at them as well.
   // aPressed is used for digital buttons, aValue is for analog buttons.
--- a/dom/gamepad/GamepadPlatformService.cpp
+++ b/dom/gamepad/GamepadPlatformService.cpp
@@ -90,17 +90,18 @@ GamepadPlatformService::AddGamepad(const
 {
   // This method is called by monitor thread populated in
   // platform-dependent backends
   MOZ_ASSERT(XRE_IsParentProcess());
   MOZ_ASSERT(!NS_IsMainThread());
 
   uint32_t index = ++mGamepadIndex;
   GamepadAdded a(NS_ConvertUTF8toUTF16(nsDependentCString(aID)), index,
-                 static_cast<uint32_t>(aMapping), GamepadServiceType::Standard, aNumButtons, aNumAxes);
+                 static_cast<uint32_t>(aMapping), static_cast<uint32_t>(GamepadHand::_empty),
+                 GamepadServiceType::Standard, aNumButtons, aNumAxes);
   NotifyGamepadChange<GamepadAdded>(a);
   return index;
 }
 
 void
 GamepadPlatformService::RemoveGamepad(uint32_t aIndex)
 {
   // This method is called by monitor thread populated in
--- a/dom/gamepad/GamepadServiceTest.cpp
+++ b/dom/gamepad/GamepadServiceTest.cpp
@@ -118,17 +118,17 @@ GamepadServiceTest::AddGamepad(const nsA
                                uint32_t aNumAxes,
                                ErrorResult& aRv)
 {
   if (mShuttingDown) {
     return nullptr;
   }
 
   GamepadAdded a(nsString(aID), 0,
-                 aMapping,
+                 aMapping, static_cast<uint32_t>(GamepadHand::_empty),
                  GamepadServiceType::Standard,
                  aNumButtons, aNumAxes);
   GamepadChangeEvent e(a);
   nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
 
   RefPtr<Promise> p = Promise::Create(go, aRv);
   if (aRv.Failed()) {
     return nullptr;
--- a/dom/gamepad/ipc/GamepadEventTypes.ipdlh
+++ b/dom/gamepad/ipc/GamepadEventTypes.ipdlh
@@ -11,16 +11,20 @@ namespace dom {
 
 struct GamepadAdded {
   nsString id;
   uint32_t index;
   // Ideally, mapping should be a GamepadMappingType
   // But, we have dependency problems in non MOZ_GAMEPAD
   // platforms. Therefore, we make it as an uint32_t here.
   uint32_t mapping;
+  // Ideally, hand should be a GamepadHand
+  // But, we have dependency problems in non MOZ_GAMEPAD
+  // platforms. Therefore, we make it as an uint32_t here.
+  uint32_t hand;
   GamepadServiceType service_type;
   uint32_t num_buttons;
   uint32_t num_axes;
 };
 
 struct GamepadRemoved {
   uint32_t index;
   GamepadServiceType service_type;
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -3,16 +3,17 @@
 /* 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 "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/dom/HTMLMediaElementBinding.h"
 #include "mozilla/dom/HTMLSourceElement.h"
 #include "mozilla/dom/ElementInlines.h"
+#include "mozilla/dom/Promise.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/dom/MediaEncryptedEvent.h"
 #include "mozilla/EMEUtils.h"
 
 #include "base/basictypes.h"
 #include "nsIDOMHTMLMediaElement.h"
@@ -148,16 +149,32 @@ static const double THRESHOLD_HIGH_PLAYB
 static const double THRESHOLD_LOW_PLAYBACKRATE_AUDIO = 0.5;
 
 // Media error values.  These need to match the ones in MediaError.webidl.
 static const unsigned short MEDIA_ERR_ABORTED = 1;
 static const unsigned short MEDIA_ERR_NETWORK = 2;
 static const unsigned short MEDIA_ERR_DECODE = 3;
 static const unsigned short MEDIA_ERR_SRC_NOT_SUPPORTED = 4;
 
+static void
+ResolvePromisesWithUndefined(const nsTArray<RefPtr<Promise>>& aPromises)
+{
+  for (auto& promise : aPromises) {
+    promise->MaybeResolveWithUndefined();
+  }
+}
+
+static void
+RejectPromises(const nsTArray<RefPtr<Promise>>& aPromises, nsresult aError)
+{
+  for (auto& promise : aPromises) {
+    promise->MaybeReject(aError);
+  }
+}
+
 // Under certain conditions there may be no-one holding references to
 // a media element from script, DOM parent, etc, but the element may still
 // fire meaningful events in the future so we can't destroy it yet:
 // 1) If the element is delaying the load event (or would be, if it were
 // in a document), then events up to loadeddata or error could be fired,
 // so we need to stay alive.
 // 2) If the element is not paused and playback has not ended, then
 // we will (or might) play, sending timeupdate and ended events and possibly
@@ -238,16 +255,84 @@ public:
     // Silently cancel if our load has been cancelled.
     if (IsCancelled())
       return NS_OK;
 
     return mElement->DispatchEvent(mName);
   }
 };
 
+/*
+ * If no error is passed while constructing an instance, the instance will
+ * resolve the passed promises with undefined; otherwise, the instance will
+ * reject the passed promises with the passed error.
+ *
+ * The constructor appends the constructed instance into the passed media
+ * element's mPendingPlayPromisesRunners member and once the the runner is run
+ * (whether fulfilled or canceled), it removes itself from
+ * mPendingPlayPromisesRunners.
+ */
+class HTMLMediaElement::nsResolveOrRejectPendingPlayPromisesRunner : public nsMediaEvent
+{
+  nsTArray<RefPtr<Promise>> mPromises;
+  nsresult mError;
+
+public:
+  nsResolveOrRejectPendingPlayPromisesRunner(HTMLMediaElement* aElement,
+                                             nsTArray<RefPtr<Promise>>&& aPromises,
+                                             nsresult aError = NS_OK)
+  : nsMediaEvent(aElement)
+  , mPromises(Move(aPromises))
+  , mError(aError)
+  {
+    mElement->mPendingPlayPromisesRunners.AppendElement(this);
+  }
+
+  void ResolveOrReject()
+  {
+    if (NS_SUCCEEDED(mError)) {
+      ResolvePromisesWithUndefined(mPromises);
+    } else {
+      RejectPromises(mPromises, mError);
+    }
+  }
+
+  NS_IMETHOD Run() override
+  {
+    if (!IsCancelled()) {
+      ResolveOrReject();
+    }
+
+    mElement->mPendingPlayPromisesRunners.RemoveElement(this);
+    return NS_OK;
+  }
+};
+
+class HTMLMediaElement::nsNotifyAboutPlayingRunner : public nsResolveOrRejectPendingPlayPromisesRunner
+{
+public:
+  nsNotifyAboutPlayingRunner(HTMLMediaElement* aElement,
+                             nsTArray<RefPtr<Promise>>&& aPendingPlayPromises)
+  : nsResolveOrRejectPendingPlayPromisesRunner(aElement,
+                                               Move(aPendingPlayPromises))
+  {
+  }
+
+  NS_IMETHOD Run() override
+  {
+    if (IsCancelled()) {
+      mElement->mPendingPlayPromisesRunners.RemoveElement(this);
+      return NS_OK;
+    }
+
+    mElement->DispatchEvent(NS_LITERAL_STRING("playing"));
+    return nsResolveOrRejectPendingPlayPromisesRunner::Run();
+  }
+};
+
 class nsSourceErrorEventRunner : public nsMediaEvent
 {
 private:
   nsCOMPtr<nsIContent> mSource;
 public:
   nsSourceErrorEventRunner(HTMLMediaElement* aElement,
                            nsIContent* aSource)
     : nsMediaEvent(aElement),
@@ -1276,16 +1361,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputStreams[i].mStream);
   }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlayed);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTextTrackManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioTrackList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVideoTrackList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeys)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelectedVideoStreamTrack)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingPlayPromises)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTMLElement)
   if (tmp->mSrcStream) {
     // Need to EndMediaStreamPlayback to clear mSrcStream and make sure everything
     // gets unhooked correctly.
     tmp->EndSrcMediaStreamPlayback();
   }
@@ -1304,16 +1390,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_IN
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutputStreams[i].mStream)
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPlayed)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTextTrackManager)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioTrackList)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mVideoTrackList)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMediaKeys)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mSelectedVideoStreamTrack)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingPlayPromises)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLMediaElement)
   NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLMediaElement)
 NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
 
 // nsIDOMHTMLMediaElement
 NS_IMPL_URI_ATTR(HTMLMediaElement, Src, src)
@@ -1489,16 +1576,24 @@ void HTMLMediaElement::AbortExistingLoad
   }
   // Abort any already-running instance of the resource selection algorithm.
   mLoadWaitStatus = NOT_WAITING;
 
   // Set a new load ID. This will cause events which were enqueued
   // with a different load ID to silently be cancelled.
   mCurrentLoadID++;
 
+  // Immediately reject or resolve the already-dispatched
+  // nsResolveOrRejectPendingPlayPromisesRunners. These runners won't be
+  // executed again later since the mCurrentLoadID had been changed.
+  for (auto& runner : mPendingPlayPromisesRunners) {
+    runner->ResolveOrReject();
+  }
+  mPendingPlayPromisesRunners.Clear();
+
   if (mChannelLoader) {
     mChannelLoader->Cancel();
     mChannelLoader = nullptr;
   }
 
   bool fireTimeUpdate = false;
 
   // We need to remove StreamSizeListener before VideoTracks get emptied.
@@ -1550,17 +1645,20 @@ void HTMLMediaElement::AbortExistingLoad
   mSourcePointer = nullptr;
 
   mTags = nullptr;
 
   if (mNetworkState != nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
     NS_ASSERTION(!mDecoder && !mSrcStream, "How did someone setup a new stream/decoder already?");
     // ChangeNetworkState() will call UpdateAudioChannelPlayingState()
     // indirectly which depends on mPaused. So we need to update mPaused first.
-    mPaused = true;
+    if (!mPaused) {
+      mPaused = true;
+      RejectPromises(TakePendingPlayPromises(), NS_ERROR_DOM_MEDIA_ABORT_ERR);
+    }
     ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY);
     ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_NOTHING);
 
     //TODO: Apply the rules for text track cue rendering Bug 865407
     if (mTextTrackManager) {
       mTextTrackManager->GetTextTracks()->SetCuesInactive();
     }
 
@@ -1592,16 +1690,17 @@ void HTMLMediaElement::AbortExistingLoad
 void HTMLMediaElement::NoSupportedMediaSourceError(const nsACString& aErrorDetails)
 {
   if (mDecoder) {
     ShutdownDecoder();
   }
   mErrorSink->SetError(MEDIA_ERR_SRC_NOT_SUPPORTED, aErrorDetails);
   ChangeDelayLoadStatus(false);
   UpdateAudioChannelPlayingState();
+  RejectPromises(TakePendingPlayPromises(), NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR);
 }
 
 typedef void (HTMLMediaElement::*SyncSectionFn)();
 
 // Runs a "synchronous section", a function that must run once the event loop
 // has reached a "stable state". See:
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#synchronous-section
 class nsSyncSection : public nsMediaEvent
@@ -2392,24 +2491,17 @@ IsInRanges(dom::TimeRanges& aRanges,
 already_AddRefed<Promise>
 HTMLMediaElement::Seek(double aTime,
                        SeekTarget::Type aSeekType,
                        ErrorResult& aRv)
 {
   // aTime should be non-NaN.
   MOZ_ASSERT(!mozilla::IsNaN(aTime));
 
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(OwnerDoc()->GetInnerWindow());
-
-  if (!global) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-
-  RefPtr<Promise> promise = Promise::Create(global, aRv);
+  RefPtr<Promise> promise = CreateDOMPromise(aRv);
 
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
   // Detect if user has interacted with element by seeking so that
   // play will not be blocked when initiated by a script.
   if (EventStateManager::IsHandlingUserInput()) {
@@ -2643,16 +2735,17 @@ HTMLMediaElement::Pause(ErrorResult& aRv
   // We changed mPaused and mAutoplaying which can affect AddRemoveSelfReference
   AddRemoveSelfReference();
   UpdateSrcMediaStreamPlaying();
   UpdateAudioChannelPlayingState();
 
   if (!oldPaused) {
     FireTimeUpdate(false);
     DispatchAsyncEvent(NS_LITERAL_STRING("pause"));
+    AsyncRejectPendingPlayPromises(NS_ERROR_DOM_MEDIA_ABORT_ERR);
   }
 }
 
 NS_IMETHODIMP HTMLMediaElement::Pause()
 {
   ErrorResult rv;
   Pause(rv);
   return rv.StealNSResult();
@@ -3584,123 +3677,201 @@ void HTMLMediaElement::SetPlayedOrSeeked
 }
 
 void
 HTMLMediaElement::NotifyXPCOMShutdown()
 {
   ShutdownDecoder();
 }
 
-void
+already_AddRefed<Promise>
 HTMLMediaElement::Play(ErrorResult& aRv)
 {
   if (mAudioChannelWrapper && mAudioChannelWrapper->IsPlaybackBlocked()) {
-    // NOTE: for promise-based-play, will return a pending promise here.
     MaybeDoLoad();
-    return;
-  }
-
-  nsresult rv = PlayInternal();
-  if (NS_FAILED(rv)) {
-    aRv.Throw(rv);
-  }
+
+    // A blocked media element will be resumed later, so we return a pending
+    // promise which might be resolved/rejected depends on the result of
+    // resuming the blocked media element.
+    RefPtr<Promise> promise = CreateDOMPromise(aRv);
+
+    if (NS_WARN_IF(aRv.Failed())) {
+      return nullptr;
+    }
+
+    mPendingPlayPromises.AppendElement(promise);
+    return promise.forget();
+  }
+
+  RefPtr<Promise> promise = PlayInternal(aRv);
 
   UpdateCustomPolicyAfterPlayed();
-}
-
-nsresult
-HTMLMediaElement::PlayInternal()
-{
+
+  return promise.forget();
+}
+
+already_AddRefed<Promise>
+HTMLMediaElement::PlayInternal(ErrorResult& aRv)
+{
+  MOZ_ASSERT(!aRv.Failed());
+
+  // 4.8.12.8
+  // When the play() method on a media element is invoked, the user agent must
+  // run the following steps.
+
+  // 4.8.12.8 - Step 1:
+  // If the media element is not allowed to play, return a promise rejected
+  // with a "NotAllowedError" DOMException and abort these steps.
   if (!IsAllowedToPlay()) {
     // NOTE: for promise-based-play, will return a rejected promise here.
-    return NS_OK;
-  }
+    aRv.Throw(NS_ERROR_DOM_MEDIA_NOT_ALLOWED_ERR);
+    return nullptr;
+  }
+
+  // 4.8.12.8 - Step 2:
+  // If the media element's error attribute is not null and its code
+  // attribute has the value MEDIA_ERR_SRC_NOT_SUPPORTED, return a promise
+  // rejected with a "NotSupportedError" DOMException and abort these steps.
+  if (GetError() && GetError()->Code() == MEDIA_ERR_SRC_NOT_SUPPORTED) {
+    aRv.Throw(NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR);
+    return nullptr;
+  }
+
+  // 4.8.12.8 - Step 3:
+  // Let promise be a new promise and append promise to the list of pending
+  // play promises.
+  RefPtr<Promise> promise = CreateDOMPromise(aRv);
+  if (NS_WARN_IF(aRv.Failed())) {
+    return nullptr;
+  }
+  mPendingPlayPromises.AppendElement(promise);
 
   // Play was not blocked so assume user interacted with the element.
   mHasUserInteraction = true;
 
   StopSuspendingAfterFirstFrame();
   SetPlayedOrSeeked(true);
 
+  // 4.8.12.8 - Step 4:
+  // If the media element's networkState attribute has the value NETWORK_EMPTY,
+  // invoke the media element's resource selection algorithm.
   MaybeDoLoad();
   if (mSuspendedForPreloadNone) {
     ResumeLoad(PRELOAD_ENOUGH);
   }
 
+  // 4.8.12.8 - Step 5:
+  // If the playback has ended and the direction of playback is forwards,
+  // seek to the earliest possible position of the media resource.
+
   // Even if we just did Load() or ResumeLoad(), we could already have a decoder
   // here if we managed to clone an existing decoder.
   if (mDecoder) {
     if (mDecoder->IsEnded()) {
       SetCurrentTime(0);
     }
     if (!mPausedForInactiveDocumentOrChannel) {
       nsresult rv = mDecoder->Play();
       if (NS_FAILED(rv)) {
-        return rv;
+        // We don't need to remove the _promise_ from _mPendingPlayPromises_ here.
+        // If something wrong between |mPendingPlayPromises.AppendElement(promise);|
+        // and here, the _promise_ should already have been rejected. Otherwise,
+        // the _promise_ won't be returned to JS at all, so just leave it in the
+        // _mPendingPlayPromises_ and let it be resolved/rejected with the
+        // following actions and the promise-resolution won't be observed at all.
+        aRv.Throw(rv);
+        return nullptr;
       }
     }
   }
 
   if (mCurrentPlayRangeStart == -1.0) {
     mCurrentPlayRangeStart = CurrentTime();
   }
 
-  bool oldPaused = mPaused;
+  const bool oldPaused = mPaused;
   mPaused = false;
   mAutoplaying = false;
 
   // We changed mPaused and mAutoplaying which can affect AddRemoveSelfReference
   // and our preload status.
   AddRemoveSelfReference();
   UpdatePreloadAction();
   UpdateSrcMediaStreamPlaying();
 
   // TODO: If the playback has ended, then the user agent must set
   // seek to the effective start.
+
+  // 4.8.12.8 - Step 6:
+  // If the media element's paused attribute is true, run the following steps:
   if (oldPaused) {
+    // 6.1. Change the value of paused to false. (Already done.)
+    // This step is uplifted because the "block-media-playback" feature needs
+    // the mPaused to be false before UpdateAudioChannelPlayingState() being
+    // called.
+
+    // 6.2. If the show poster flag is true, set the element's show poster flag
+    //      to false and run the time marches on steps.
+
+    // 6.3. Queue a task to fire a simple event named play at the element.
     DispatchAsyncEvent(NS_LITERAL_STRING("play"));
+
+    // 6.4. If the media element's readyState attribute has the value
+    //      HAVE_NOTHING, HAVE_METADATA, or HAVE_CURRENT_DATA, queue a task to
+    //      fire a simple event named waiting at the element.
+    //      Otherwise, the media element's readyState attribute has the value
+    //      HAVE_FUTURE_DATA or HAVE_ENOUGH_DATA: notify about playing for the
+    //      element.
     switch (mReadyState) {
     case nsIDOMHTMLMediaElement::HAVE_NOTHING:
       DispatchAsyncEvent(NS_LITERAL_STRING("waiting"));
       break;
     case nsIDOMHTMLMediaElement::HAVE_METADATA:
     case nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA:
       FireTimeUpdate(false);
       DispatchAsyncEvent(NS_LITERAL_STRING("waiting"));
       break;
     case nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA:
     case nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA:
       FireTimeUpdate(false);
-      DispatchAsyncEvent(NS_LITERAL_STRING("playing"));
+      NotifyAboutPlaying();
       break;
     }
-  }
-
-  return NS_OK;
+  } else if (mReadyState >= nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA) {
+    // 7. Otherwise, if the media element's readyState attribute has the value
+    //    HAVE_FUTURE_DATA or HAVE_ENOUGH_DATA, take pending play promises and
+    //    queue a task to resolve pending play promises with the result.
+    AsyncResolvePendingPlayPromises();
+  }
+
+  // 8. Set the media element's autoplaying flag to false. (Already done.)
+
+  // 9. Return promise.
+  return promise.forget();
 }
 
 void
 HTMLMediaElement::MaybeDoLoad()
 {
   if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
     DoLoad();
   }
 }
 
 NS_IMETHODIMP HTMLMediaElement::Play()
 {
   if (mAudioChannelWrapper && mAudioChannelWrapper->IsPlaybackBlocked()) {
-    // NOTE: for promise-based-play, will return a pending promise here.
     MaybeDoLoad();
     return NS_OK;
   }
 
-  nsresult rv = PlayInternal();
-  if (NS_FAILED(rv)) {
-    return rv;
+  ErrorResult rv;
+  RefPtr<Promise> toBeIgnored = PlayInternal(rv);
+  if (rv.Failed()) {
+    return rv.StealNSResult();
   }
 
   UpdateCustomPolicyAfterPlayed();
   return NS_OK;
 }
 
 HTMLMediaElement::WakeLockBoolWrapper&
 HTMLMediaElement::WakeLockBoolWrapper::operator=(bool val)
@@ -5042,25 +5213,29 @@ void HTMLMediaElement::PlaybackEnded()
     DispatchAsyncEvent(NS_LITERAL_STRING("durationchange"));
   }
 
   if (HasAttr(kNameSpaceID_None, nsGkAtoms::loop)) {
     SetCurrentTime(0);
     return;
   }
 
-  Pause();
+  FireTimeUpdate(false);
+
+  if (!mPaused) {
+    Pause();
+    AsyncRejectPendingPlayPromises(NS_ERROR_DOM_MEDIA_ABORT_ERR);
+  }
 
   if (mSrcStream) {
     // A MediaStream that goes from inactive to active shall be eligible for
     // autoplay again according to the mediacapture-main spec.
     mAutoplaying = true;
   }
 
-  FireTimeUpdate(false);
   DispatchAsyncEvent(NS_LITERAL_STRING("ended"));
 }
 
 void HTMLMediaElement::SeekStarted()
 {
   DispatchAsyncEvent(NS_LITERAL_STRING("seeking"));
 }
 
@@ -5442,17 +5617,17 @@ void HTMLMediaElement::ChangeReadyState(
     mLoadedDataFired = true;
   }
 
   if (oldState < nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA &&
       mReadyState >= nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA) {
     DispatchAsyncEvent(NS_LITERAL_STRING("canplay"));
     if (!mPaused) {
       mWaitingForKey = NOT_WAITING_FOR_KEY;
-      DispatchAsyncEvent(NS_LITERAL_STRING("playing"));
+      NotifyAboutPlaying();
     }
   }
 
   CheckAutoplayDataReady();
 
   if (oldState < nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA &&
       mReadyState >= nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA) {
     DispatchAsyncEvent(NS_LITERAL_STRING("canplaythrough"));
@@ -5693,17 +5868,24 @@ nsresult HTMLMediaElement::DispatchAsync
 
   // Save events that occur while in the bfcache. These will be dispatched
   // if the page comes out of the bfcache.
   if (mEventDeliveryPaused) {
     mPendingEvents.AppendElement(aName);
     return NS_OK;
   }
 
-  nsCOMPtr<nsIRunnable> event = new nsAsyncEventRunner(aName, this);
+  nsCOMPtr<nsIRunnable> event;
+
+  if (aName.EqualsLiteral("playing")) {
+    event = new nsNotifyAboutPlayingRunner(this, TakePendingPlayPromises());
+  } else {
+    event = new nsAsyncEventRunner(aName, this);
+  }
+
   OwnerDoc()->Dispatch("HTMLMediaElement::DispatchAsyncEvent",
                        TaskCategory::Other,
                        event.forget());
 
   if ((aName.EqualsLiteral("play") || aName.EqualsLiteral("playing"))) {
     mPlayTime.Start();
     if (IsHidden()) {
       HiddenVideoStart();
@@ -6920,10 +7102,71 @@ void
 HTMLMediaElement::UpdateCustomPolicyAfterPlayed()
 {
   OpenUnsupportedMediaWithExternalAppIfNeeded();
   if (mAudioChannelWrapper) {
     mAudioChannelWrapper->NotifyPlayStarted();
   }
 }
 
+nsTArray<RefPtr<Promise>>
+HTMLMediaElement::TakePendingPlayPromises()
+{
+  return Move(mPendingPlayPromises);
+}
+
+void
+HTMLMediaElement::NotifyAboutPlaying()
+{
+  // Stick to the DispatchAsyncEvent() call path for now because we want to
+  // trigger some telemetry-related codes in the DispatchAsyncEvent() method.
+  DispatchAsyncEvent(NS_LITERAL_STRING("playing"));
+}
+
+already_AddRefed<Promise>
+HTMLMediaElement::CreateDOMPromise(ErrorResult& aRv) const
+{
+  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(OwnerDoc()->GetInnerWindow());
+
+  if (!global) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
+  }
+
+  return Promise::Create(global, aRv);
+}
+
+void
+HTMLMediaElement::AsyncResolvePendingPlayPromises()
+{
+  if (mShuttingDown) {
+    return;
+  }
+
+  nsCOMPtr<nsIRunnable> event
+    = new nsResolveOrRejectPendingPlayPromisesRunner(this,
+                                                     TakePendingPlayPromises());
+
+  OwnerDoc()->Dispatch("HTMLMediaElement::AsyncResolvePendingPlayPromises",
+                       TaskCategory::Other,
+                       event.forget());
+}
+
+void
+HTMLMediaElement::AsyncRejectPendingPlayPromises(nsresult aError)
+{
+  if (mShuttingDown) {
+    return;
+  }
+
+  nsCOMPtr<nsIRunnable> event
+    = new nsResolveOrRejectPendingPlayPromisesRunner(this,
+                                                     TakePendingPlayPromises(),
+                                                     aError);
+
+  OwnerDoc()->Dispatch("HTMLMediaElement::AsyncRejectPendingPlayPromises",
+                       TaskCategory::Other,
+                       event.forget());
+}
+
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -11,17 +11,16 @@
 #include "nsGenericHTMLElement.h"
 #include "MediaDecoderOwner.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIObserver.h"
 #include "mozilla/CORSMode.h"
 #include "DecoderTraits.h"
 #include "nsIAudioChannelAgent.h"
 #include "mozilla/Attributes.h"
-#include "mozilla/dom/Promise.h"
 #include "mozilla/dom/TextTrackManager.h"
 #include "mozilla/WeakPtr.h"
 #include "MediaDecoder.h"
 #include "mozilla/dom/MediaKeys.h"
 #include "mozilla/StateWatching.h"
 #include "nsGkAtoms.h"
 #include "PrincipalChangeObserver.h"
 
@@ -68,16 +67,17 @@ class nsRange;
 namespace mozilla {
 namespace dom {
 
 // Number of milliseconds between timeupdate events as defined by spec
 #define TIMEUPDATE_MS 250
 
 class MediaError;
 class MediaSource;
+class Promise;
 class TextTrackList;
 class AudioTrackList;
 class VideoTrackList;
 
 class HTMLMediaElement : public nsGenericHTMLElement,
                          public nsIDOMHTMLMediaElement,
                          public MediaDecoderOwner,
                          public PrincipalChangeObserver<DOMMediaStream>,
@@ -534,17 +534,17 @@ public:
     return GetBoolAttr(nsGkAtoms::loop);
   }
 
   void SetLoop(bool aValue, ErrorResult& aRv)
   {
     SetHTMLBoolAttr(nsGkAtoms::loop, aValue, aRv);
   }
 
-  void Play(ErrorResult& aRv);
+  already_AddRefed<Promise> Play(ErrorResult& aRv);
 
   void Pause(ErrorResult& aRv);
 
   bool Controls() const
   {
     return GetBoolAttr(nsGkAtoms::controls);
   }
 
@@ -805,17 +805,17 @@ protected:
     bool mCapturingDecoder;
     bool mCapturingMediaStream;
 
     // The following members are keeping state for a captured MediaStream.
     TrackID mNextAvailableTrackID;
     nsTArray<Pair<nsString, RefPtr<MediaInputPort>>> mTrackPorts;
   };
 
-  nsresult PlayInternal();
+  already_AddRefed<Promise> PlayInternal(ErrorResult& aRv);
 
   /** Use this method to change the mReadyState member, so required
    * events can be fired.
    */
   void ChangeReadyState(nsMediaReadyState aState);
 
   /**
    * Use this method to change the mNetworkState member, so required
@@ -951,16 +951,17 @@ protected:
   /**
    * Execute the initial steps of the load algorithm that ensure existing
    * loads are aborted, the element is emptied, and a new load ID is
    * created.
    */
   void AbortExistingLoads();
 
   /**
+   * This is the dedicated media source failure steps.
    * Called when all potential resources are exhausted. Changes network
    * state to NETWORK_NO_SOURCE, and sends error event with code
    * MEDIA_ERR_SRC_NOT_SUPPORTED.
    */
   void NoSupportedMediaSourceError(const nsACString& aErrorDetails = nsCString());
 
   /**
    * Attempts to load resources from the <source> children. This is a
@@ -1226,23 +1227,43 @@ protected:
 
   // If the network state is empty and then we would trigger DoLoad().
   void MaybeDoLoad();
 
   // Anything we need to check after played success and not related with spec.
   void UpdateCustomPolicyAfterPlayed();
 
   class nsAsyncEventRunner;
+  class nsNotifyAboutPlayingRunner;
+  class nsResolveOrRejectPendingPlayPromisesRunner;
   using nsGenericHTMLElement::DispatchEvent;
   // For nsAsyncEventRunner.
   nsresult DispatchEvent(const nsAString& aName);
 
   // Open unsupported types media with the external app when the media element
   // triggers play() after loaded fail. eg. preload the data before start play.
   void OpenUnsupportedMediaWithExternalAppIfNeeded() const;
+  
+  // This method moves the mPendingPlayPromises into a temperate object. So the
+  // mPendingPlayPromises is cleared after this method call.
+  nsTArray<RefPtr<Promise>> TakePendingPlayPromises();
+
+  // This method snapshots the mPendingPlayPromises by TakePendingPlayPromises()
+  // and queues a task to resolve them.
+  void AsyncResolvePendingPlayPromises();
+
+  // This method snapshots the mPendingPlayPromises by TakePendingPlayPromises()
+  // and queues a task to reject them.
+  void AsyncRejectPendingPlayPromises(nsresult aError);
+
+  // This method snapshots the mPendingPlayPromises by TakePendingPlayPromises()
+  // and queues a task to resolve them also to dispatch a "playing" event.
+  void NotifyAboutPlaying();
+
+  already_AddRefed<Promise> CreateDOMPromise(ErrorResult& aRv) const;
 
   // The current decoder. Load() has been called on this decoder.
   // At most one of mDecoder and mSrcStream can be non-null.
   RefPtr<MediaDecoder> mDecoder;
 
   // Observers listening to changes to the mDecoder principal.
   // Used by streams captured from this element.
   nsTArray<DecoderPrincipalChangeObserver*> mDecoderPrincipalChangeObservers;
@@ -1666,14 +1687,25 @@ private:
   Visibility mVisibilityState;
 
   UniquePtr<ErrorSink> mErrorSink;
 
   // This wrapper will handle all audio channel related stuffs, eg. the operations
   // of tab audio indicator, Fennec's media control.
   // Note: mAudioChannelWrapper might be null after GC happened.
   RefPtr<AudioChannelAgentCallback> mAudioChannelWrapper;
+  
+  // A list of pending play promises. The elements are pushed during the play()
+  // method call and are resolved/rejected during further playback steps.
+  nsTArray<RefPtr<Promise>> mPendingPlayPromises;
+
+  // A list of already-dispatched but not yet run
+  // nsResolveOrRejectPendingPlayPromisesRunners.
+  // Runners whose Run() method is called remove themselves from this list.
+  // We keep track of these because the load algorithm resolves/rejects all
+  // already-dispatched pending play promises.
+  nsTArray<nsResolveOrRejectPendingPlayPromisesRunner*> mPendingPlayPromisesRunners;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLMediaElement_h
--- a/dom/media/PeerConnection.js
+++ b/dom/media/PeerConnection.js
@@ -224,32 +224,28 @@ GlobalPCList.prototype = {
   },
 
   _registerPeerConnectionLifecycleCallback: function(winID, cb) {
     this._lifecycleobservers[winID] = cb;
   },
 };
 var _globalPCList = new GlobalPCList();
 
-function RTCIceCandidate() {
-  this.candidate = this.sdpMid = this.sdpMLineIndex = null;
-}
+function RTCIceCandidate() {}
 RTCIceCandidate.prototype = {
   classDescription: "RTCIceCandidate",
   classID: PC_ICE_CID,
   contractID: PC_ICE_CONTRACT,
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
                                          Ci.nsIDOMGlobalPropertyInitializer]),
 
   init: function(win) { this._win = win; },
 
   __init: function(dict) {
-    this.candidate = dict.candidate;
-    this.sdpMid = dict.sdpMid;
-    this.sdpMLineIndex = ("sdpMLineIndex" in dict)? dict.sdpMLineIndex : null;
+    Object.assign(this, dict);
   }
 };
 
 function RTCSessionDescription() {}
 RTCSessionDescription.prototype = {
   classDescription: "RTCSessionDescription",
   classID: PC_SESSION_CID,
   contractID: PC_SESSION_CONTRACT,
@@ -361,16 +357,19 @@ function RTCPeerConnection() {
   this._remoteType = null;
   // http://rtcweb-wg.github.io/jsep/#rfc.section.4.1.9
   // canTrickle == null means unknown; when a remote description is received it
   // is set to true or false based on the presence of the "trickle" ice-option
   this._canTrickle = null;
 
   // States
   this._iceGatheringState = this._iceConnectionState = "new";
+
+  this._hasStunServer = this._hasTurnServer = false;
+  this._iceGatheredRelayCandidates = false;
 }
 RTCPeerConnection.prototype = {
   classDescription: "RTCPeerConnection",
   classID: PC_CID,
   contractID: PC_CONTRACT,
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
                                          Ci.nsIDOMGlobalPropertyInitializer]),
   init: function(win) { this._win = win; },
@@ -586,16 +585,18 @@ RTCPeerConnection.prototype = {
       try {
         return ios.newURI(uriStr, null, null);
       } catch (e if (e.result == Cr.NS_ERROR_MALFORMED_URI)) {
         throw new this._win.DOMException(msg + " - malformed URI: " + uriStr,
                                          "SyntaxError");
       }
     };
 
+    var stunServers = 0;
+
     rtcConfig.iceServers.forEach(server => {
       if (!server.urls) {
         throw new this._win.DOMException(msg + " - missing urls", "InvalidAccessError");
       }
       server.urls.forEach(urlStr => {
         let url = nicerNewURI(urlStr);
         if (url.scheme in { turn:1, turns:1 }) {
           if (server.username == undefined) {
@@ -607,24 +608,35 @@ RTCPeerConnection.prototype = {
                                              "InvalidAccessError");
           }
           if (server.credentialType != "password") {
             this.logWarning("RTCConfiguration TURN credentialType \""+
                             server.credentialType +
                             "\" is not yet implemented. Treating as password."+
                             " https://bugzil.la/1247616");
           }
+          this._hasTurnServer = true;
+          stunServers += 1;
+        }
+        else if (url.scheme in { stun:1, stuns:1 }) {
+          this._hasStunServer = true;
+          stunServers += 1;
         }
         else if (!(url.scheme in { stun:1, stuns:1 })) {
           throw new this._win.DOMException(msg + " - improper scheme: " + url.scheme,
                                            "SyntaxError");
         }
         if (url.scheme in { stuns:1, turns:1 }) {
           this.logWarning(url.scheme.toUpperCase() + " is not yet supported.");
         }
+        if (stunServers >= 5) {
+          this.logError("Using five or more STUN/TURN servers causes problems");
+        } else if (stunServers > 2) {
+          this.logWarning("Using more than two STUN/TURN servers slows down discovery");
+        }
       });
     });
   },
 
   // Ideally, this should be of the form _checkState(state),
   // where the state is taken from an enumeration containing
   // the valid peer connection states defined in the WebRTC
   // spec. See Bug 831756.
@@ -729,18 +741,17 @@ RTCPeerConnection.prototype = {
       return this._chain(() => {
         let p = Promise.all([this.getPermission(), this._certificateReady])
           .then(() => new this._win.Promise((resolve, reject) => {
             this._onCreateOfferSuccess = resolve;
             this._onCreateOfferFailure = reject;
             this._impl.createOffer(options);
           }));
         p = this._addIdentityAssertion(p, origin);
-        return p.then(
-          sdp => new this._win.RTCSessionDescription({ type: "offer", sdp: sdp }));
+        return p.then(sdp => Cu.cloneInto({ type: "offer", sdp: sdp }, this._win));
       });
     });
   },
 
   createAnswer: function(optionsOrOnSuccess, onError) {
     // This entry-point handles both new and legacy call sig. Decipher which one
     let onSuccess, options;
     if (typeof optionsOrOnSuccess == "function") {
@@ -764,19 +775,17 @@ RTCPeerConnection.prototype = {
               throw new this._win.DOMException("No outstanding offer",
                                                "InvalidStateError");
             }
             this._onCreateAnswerSuccess = resolve;
             this._onCreateAnswerFailure = reject;
             this._impl.createAnswer();
           }));
         p = this._addIdentityAssertion(p, origin);
-        return p.then(sdp => {
-          return new this._win.RTCSessionDescription({ type: "answer", sdp: sdp });
-        });
+        return p.then(sdp => Cu.cloneInto({ type: "answer", sdp: sdp }, this._win));
       });
     });
   },
 
   getPermission: function() {
     if (this._havePermission) {
       return this._havePermission;
     }
@@ -976,22 +985,25 @@ RTCPeerConnection.prototype = {
     }
 
     let sections = desc.sdp.split(/(?:\r\n?|\n)m=/);
     let topSection = sections.shift();
     this._canTrickle =
       containsTrickle(topSection) || sections.every(containsTrickle);
   },
 
-
   addIceCandidate: function(c, onSuccess, onError) {
     return this._legacyCatchAndCloseGuard(onSuccess, onError, () => {
-      if (!c.candidate && !c.sdpMLineIndex) {
-        throw new this._win.DOMException("Invalid candidate passed to addIceCandidate!",
-                                         "InvalidParameterError");
+      if (!c) {
+        // TODO: Implement processing for end-of-candidates (bug 1318167)
+        return Promise.resolve();
+      }
+      if (c.sdpMid === null && c.sdpMLineIndex === null) {
+        throw new this._win.DOMException("Invalid candidate (both sdpMid and sdpMLineIndex are null).",
+                                         "TypeError");
       }
       return this._chain(() => new this._win.Promise((resolve, reject) => {
         this._onAddIceCandidateSuccess = resolve;
         this._onAddIceCandidateError = reject;
         this._impl.addIceCandidate(c.candidate, c.sdpMid || "", c.sdpMLineIndex);
       }));
     });
   },
@@ -1125,28 +1137,26 @@ RTCPeerConnection.prototype = {
 
   get localDescription() {
     this._checkClosed();
     let sdp = this._impl.localDescription;
     if (sdp.length == 0) {
       return null;
     }
 
-    return new this._win.RTCSessionDescription({ type: this._localType,
-                                                    sdp: sdp });
+    return new this._win.RTCSessionDescription({ type: this._localType, sdp });
   },
 
   get remoteDescription() {
     this._checkClosed();
     let sdp = this._impl.remoteDescription;
     if (sdp.length == 0) {
       return null;
     }
-    return new this._win.RTCSessionDescription({ type: this._remoteType,
-                                                    sdp: sdp });
+    return new this._win.RTCSessionDescription({ type: this._remoteType, sdp });
   },
 
   get peerIdentity() { return this._peerIdentity; },
   get idpLoginUrl() { return this._localIdp.idpLoginUrl; },
   get id() { return this._impl.id; },
   set id(s) { this._impl.id = s; },
   get iceGatheringState()  { return this._iceGatheringState; },
   get iceConnectionState() { return this._iceConnectionState; },
@@ -1302,16 +1312,19 @@ PeerConnectionObserver.prototype = {
   onAddIceCandidateError: function(code, message) {
     this._dompc._onAddIceCandidateError(this.newError(message, code));
   },
 
   onIceCandidate: function(level, mid, candidate) {
     if (candidate == "") {
       this.foundIceCandidate(null);
     } else {
+      if (candidate.includes(" typ relay ")) {
+        this._dompc._iceGatheredRelayCandidates = true;
+      }
       this.foundIceCandidate(new this._dompc._win.RTCIceCandidate(
           {
               candidate: candidate,
               sdpMid: mid,
               sdpMLineIndex: level
           }
       ));
     }
@@ -1375,17 +1388,28 @@ PeerConnectionObserver.prototype = {
           iceConnectionState === 'connected') {
         success_histogram.add(true);
       } else if (iceConnectionState === 'failed') {
         success_histogram.add(false);
       }
     }
 
     if (iceConnectionState === 'failed') {
-      pc.logError("ICE failed, see about:webrtc for more details");
+      if (!pc._hasStunServer) {
+        pc.logError("ICE failed, add a STUN server and see about:webrtc for more details");
+      }
+      else if (!pc._hasTurnServer) {
+        pc.logError("ICE failed, add a TURN server and see about:webrtc for more details");
+      }
+      else if (pc._hasTurnServer && !pc._iceGatheredRelayCandidates) {
+        pc.logError("ICE failed, your TURN server appears to be broken, see about:webrtc for more details");
+      }
+      else {
+        pc.logError("ICE failed, see about:webrtc for more details");
+      }
     }
 
     pc.changeIceConnectionState(iceConnectionState);
   },
 
   // This method is responsible for updating iceGatheringState. This
   // state is defined in the WebRTC specification as follows:
   //
--- a/dom/media/mediasink/VideoSink.cpp
+++ b/dom/media/mediasink/VideoSink.cpp
@@ -287,16 +287,17 @@ VideoSink::Redraw(const VideoInfo& aInfo
   // No video track, nothing to draw.
   if (!aInfo.IsValid() || !mContainer) {
     return;
   }
 
   RefPtr<MediaData> frame = VideoQueue().PeekFront();
   if (frame) {
     VideoData* video = frame->As<VideoData>();
+    video->MarkSentToCompositor();
     mContainer->SetCurrentFrame(video->mDisplay, video->mImage, TimeStamp::Now());
     return;
   }
 
   // When we reach here, it means there are no frames in this video track.
   // Draw a blank frame to ensure there is something in the image container
   // to fire 'loadeddata'.
   RefPtr<Image> blank =
--- a/dom/media/mediasource/ContainerParser.cpp
+++ b/dom/media/mediasource/ContainerParser.cpp
@@ -347,17 +347,17 @@ public:
     ContainerParser::IsInitSegmentPresent(aData);
     // Each MP4 atom has a chunk size and chunk type. The root chunk in an MP4
     // file is the 'ftyp' atom followed by a file type. We just check for a
     // vaguely valid 'ftyp' atom.
     AtomParser parser(mType, aData);
     if (!parser.IsValid()) {
       return MediaResult(
         NS_ERROR_FAILURE,
-        RESULT_DETAIL("Invalid Box:%s", parser.LastInvalidBox()));
+        RESULT_DETAIL("Invalid Top-Level Box:%s", parser.LastInvalidBox()));
     }
     return parser.StartWithInitSegment() ? NS_OK : NS_ERROR_NOT_AVAILABLE;
   }
 
   MediaResult IsMediaSegmentPresent(MediaByteBuffer* aData) override
   {
     AtomParser parser(mType, aData);
     if (!parser.IsValid()) {
@@ -380,16 +380,18 @@ private:
 
       // Valid top-level boxes defined in ISO/IEC 14496-12 (Table 1)
       static const mp4_demuxer::AtomType validBoxes[] = {
         "ftyp", "moov", // init segment
         "pdin", "free", "sidx", // optional prior moov box
         "styp", "moof", "mdat", // media segment
         "mfra", "skip", "meta", "meco", "ssix", "prft" // others.
         "pssh", // optional with encrypted EME, though ignored.
+        "emsg", // ISO23009-1:2014 Section 5.10.3.3
+        "bloc", "uuid" // boxes accepted by chrome.
       };
 
       while (reader.Remaining() >= 8) {
         uint64_t size = reader.ReadU32();
         const uint8_t* typec = reader.Peek(4);
         mp4_demuxer::AtomType type(reader.ReadU32());
         MSE_DEBUGV(AtomParser ,"Checking atom:'%c%c%c%c' @ %u",
                    typec[0], typec[1], typec[2], typec[3],
@@ -398,20 +400,20 @@ private:
         for (const auto& boxType : validBoxes) {
           if (type == boxType) {
             mValid = true;
             break;
           }
         }
         if (!mValid) {
           // No point continuing.
-          mLastInvalidBox[0] = typec[3];
-          mLastInvalidBox[1] = typec[2];
-          mLastInvalidBox[2] = typec[1];
-          mLastInvalidBox[3] = typec[0];
+          mLastInvalidBox[0] = typec[0];
+          mLastInvalidBox[1] = typec[1];
+          mLastInvalidBox[2] = typec[2];
+          mLastInvalidBox[3] = typec[3];
           mLastInvalidBox[4] = '\0';
           break;
         }
         if (mInitOffset.isNothing() &&
             mp4_demuxer::AtomType(type) == initAtom) {
           mInitOffset = Some(reader.Offset());
         }
         if (mMediaOffset.isNothing() &&
--- a/dom/media/test/mochitest.ini
+++ b/dom/media/test/mochitest.ini
@@ -492,16 +492,17 @@ support-files =
   owl-funny-id3.mp3
   owl-funny-id3.mp3^headers^
   owl.mp3
   owl.mp3^headers^
   owl-short.mp3
   owl-short.mp3^headers^
   parser.vtt
   pixel_aspect_ratio.mp4
+  play_promise.js
   r11025_msadpcm_c1.wav
   r11025_msadpcm_c1.wav^headers^
   r11025_s16_c1.wav
   r11025_s16_c1.wav^headers^
   r11025_s16_c1_trailing.wav
   r11025_s16_c1_trailing.wav^headers^
   r11025_s16_c1-short.wav
   r11025_s16_c1-short.wav^headers^
@@ -792,16 +793,52 @@ tags=msg
 [test_multiple_mediastreamtracks.html]
 [test_networkState.html]
 [test_new_audio.html]
 [test_no_load_event.html]
 [test_paused.html]
 [test_paused_after_ended.html]
 [test_play_events.html]
 [test_play_events_2.html]
+[test_play_promise_1.html]
+tags=promise-play
+[test_play_promise_2.html]
+tags=promise-play
+[test_play_promise_3.html]
+tags=promise-play
+[test_play_promise_4.html]
+tags=promise-play
+[test_play_promise_5.html]
+tags=promise-play
+[test_play_promise_6.html]
+tags=promise-play
+[test_play_promise_7.html]
+tags=promise-play
+[test_play_promise_8.html]
+tags=promise-play
+[test_play_promise_9.html]
+tags=promise-play
+[test_play_promise_10.html]
+tags=promise-play
+[test_play_promise_11.html]
+tags=promise-play
+[test_play_promise_12.html]
+tags=promise-play
+[test_play_promise_13.html]
+tags=promise-play
+[test_play_promise_14.html]
+tags=promise-play
+[test_play_promise_15.html]
+tags=promise-play
+[test_play_promise_16.html]
+tags=promise-play
+[test_play_promise_17.html]
+tags=promise-play
+[test_play_promise_18.html]
+tags=promise-play
 [test_play_twice.html]
 # Seamonkey: Bug 598252
 skip-if = appname == "seamonkey"
 [test_playback.html]
 [test_playback_errors.html]
 [test_playback_rate.html]
 [test_playback_rate_playpause.html]
 [test_playback_reactivate.html]
new file mode 100644
--- /dev/null
+++ b/dom/media/test/play_promise.js
@@ -0,0 +1,3 @@
+function getNotSupportedFile(name) {
+  return name + ".bad";
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_play_promise_1.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media test: promise-based play() method</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<pre id="test">
+
+<script>
+// Name: playBeforeCanPlay
+// Case: invoke play() on an element that doesn't have enough data
+// Expected result: resolve the promise
+
+let manager = new MediaTestManager;
+
+function initTest(test, token) {
+  manager.started(token);
+
+  let element = document.createElement(getMajorMimeType(test.type));
+  element.src = test.name;
+  ok(element.readyState == HTMLMediaElement.HAVE_NOTHING);
+
+  element.play().then(
+    (result) => {
+      if (result == undefined) {
+        ok(true, `${token} is resolved with ${result}.`);
+      } else {
+        ok(false, `${token} is resolved with ${result}.`);
+      }
+    },
+    (error) => {
+      ok(false, `${token} is rejected with ${error.name}.`);
+    }
+  ).then( () => { manager.finished(token); } );
+}
+
+manager.runTests(gSmallTests, initTest);
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_play_promise_10.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media test: promise-based play() method</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<pre id="test">
+
+<script>
+// Name: loadRejectsPendingPromises
+// Case: invoke load() on an element with pending promises.
+// Expected result: reject all the pending promises with AbortError DOM exception.
+
+let manager = new MediaTestManager;
+
+function initTest(test, token) {
+  manager.started(token);
+
+  let element = document.createElement(getMajorMimeType(test.type));
+  element.play().then(
+    (result) => {
+      ok(false, `${token} is resolved with ${result}.`);
+    },
+    (error) => {
+      if (error.name == "AbortError") {
+        ok(true, `${token} is rejected with ${error.name}.`);
+      } else {
+        ok(false, `${token} is rejected with ${error.name}.`);
+      }
+    }
+  ).then( () => { manager.finished(token); } );
+  element.load();
+}
+
+manager.runTests(gSmallTests, initTest);
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_play_promise_11.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media test: promise-based play() method</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<pre id="test">
+
+<script>
+// Name: newSrcRejectPendingPromises
+// Case: change src of an element with pending promises.
+// Expected result: reject all the pending promises.
+
+let manager = new MediaTestManager;
+
+function initTest(test, token) {
+  manager.started(token);
+
+  let element = document.createElement(getMajorMimeType(test.type));
+  element.play().then(
+    (result) => {
+      ok(false, `${token} is resolved with ${result}.`);
+    },
+    (error) => {
+      if (error.name == "AbortError") {
+        ok(true, `${token} is rejected with ${error.name}.`);
+      } else {
+        ok(false, `${token} is rejected with ${error.name}.`);
+      }
+    }
+  ).then( () => { manager.finished(token); } );
+  element.src = test.name;
+}
+
+manager.runTests(gSmallTests, initTest);
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_play_promise_12.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media test: promise-based play() method</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<pre id="test">
+
+<script>
+// Name: pausePlayAfterPlaybackStarted
+// Case: invoke pause() and then play() on an element that is already playing.
+// Expected result: resolve the promise with undefined.
+
+let manager = new MediaTestManager;
+
+function initTest(test, token) {
+  manager.started(token);
+
+  let element = document.createElement(getMajorMimeType(test.type));
+  element.preload = "auto";
+  element.src = test.name;
+  element.play();
+  once(element, "playing").then(() => {
+    element.pause();
+    element.play().then(
+      (result) => {
+        if (result == undefined) {
+          ok(true, `${token} is resolved with ${result}.`);
+        } else {
+          ok(false, `${token} is resolved with ${result}.`);
+        }
+      },
+      (error) => {
+        ok(false, `${token} is rejected with ${error.name}.`);
+      }
+    ).then( () => { manager.finished(token); } );
+  });
+}
+
+manager.runTests(gSmallTests, initTest);
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_play_promise_13.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media test: promise-based play() method</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<pre id="test">
+
+<script>
+// Name: loadAlgorithmDoesNotCancelTasks
+// Case: re-invoke the load() on an element which had dispatched a task to resolve a promise.
+// Expected result: the already dispatched promise should still be resolved with undefined.
+
+let manager = new MediaTestManager;
+
+function initTest(test, token) {
+  manager.started(token);
+
+  let element = document.createElement(getMajorMimeType(test.type));
+  element.preload = "auto";
+  element.src = test.name;
+
+  // We must wait for "canplay" event; otherwise, invoke play() will lead to a
+  // pending promise and will then be rejected by the following load().
+  once(element, "canplay").then(() => {
+    // The play() promise will be queued to be resolved immediately, which means
+    // the promise is not in the pending list.
+    element.play().then(
+      (result) => {
+        if (result == undefined) {
+          ok(true, `${token} is resolved with ${result}.`);
+        } else {
+          ok(false, `${token} is resolved with ${result}.`);
+        }
+      },
+      (error) => {
+        ok(false, `${token} is rejected with ${error.name}.`);
+      }
+    ).then( () => { manager.finished(token); } );
+    element.src = test.name; // Re-invoke the load algorithm again.
+  });
+}
+
+manager.runTests(gSmallTests, initTest);
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_play_promise_14.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media test: promise-based play() method</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<pre id="test">
+
+<script>
+// Name: loadAlgorithmKeepPromisesPendingWhenNotPausing
+// Case: step1: create an element with its paused member to be fause and networkState to be NETWORK_EMPTY.
+//       stpe2: invoke load() on the element and the load() leaves the promise pending.
+// Expected result: the pending promise should finally be resolved.
+
+let manager = new MediaTestManager;
+
+function initTest(test, token) {
+  manager.started(token);
+
+  let element = document.createElement(getMajorMimeType(test.type));
+  // Invoke play() -> (1) the promise will be left pending.
+  //                  (2) invoke load() -> (1) set the networkState to be NETWORK_NO_SOURCE.
+  //                                       (2) queue a task to run resouce selection algorithm.
+  element.play().then(
+    (result) => {
+      if (result == undefined) {
+        ok(true, `${token} is resolved with ${result}.`);
+      } else {
+        ok(false, `${token} is resolved with ${result}.`);
+      }
+    },
+    (error) => {
+      ok(false, `${token} is rejected with ${error.name}.`);
+    }
+  ).then( () => { manager.finished(token); } );
+
+  once(element, "play").then(() => {
+    // The resouce selection algorithm has been done.
+    // -> set the networkState to be NETWORK_EMPTY because there is no valid resource to load.
+    ok(element.networkState == HTMLMediaElement.NETWORK_EMPTY);
+
+    // Invoke load() again and since the networkState is NETWORK_EMPTY, the load() does not reject the pending promise.
+    // The load() will queue a task to run resouce selection algorithm which will change the readyState and finally resolve the pending promise.
+    element.src = test.name;
+
+    // Since the networkState is NETWORK_EMPTY, the load() does not set paused to be true.
+    ok(!element.paused, `loadAlgorithmKeepPromisesPendingWhenNotPausing(${token}).paused should be false.`);
+  });
+}
+
+manager.runTests(gSmallTests, initTest);
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_play_promise_15.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media test: promise-based play() method</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<pre id="test">
+
+<script>
+// Name: loadAlgorithmRejectPromisesWhenPausing
+// Case: step1: create an element with its paused member to be fause and networkState to be NETWORK_NO_SOURCE.
+//       stpe2: invoke load() on the element and the load() rejects the pending promise.
+// Expected result: reject the pending promise with AbortError DOM exception.
+
+let manager = new MediaTestManager;
+
+function initTest(test, token) {
+  manager.started(token);
+
+  let element = document.createElement(getMajorMimeType(test.type));
+  // Invoke play() -> (1) the promise will be left pending.
+  //                  (2) invoke load() -> (1) set the networkState to be NETWORK_NO_SOURCE.
+  //                                       (2) queue a task to run resouce selection algorithm.
+  element.play().then(
+    (result) => {
+      ok(false, `${token} is resolved with ${result}.`);
+    },
+    (error) => {
+      if (error.name == "AbortError") {
+        ok(true, `${token} is rejected with ${error.name}.`);
+      } else {
+        ok(false, `${token} is rejected with ${error.name}.`);
+      }
+    }
+  ).then( () => { manager.finished(token); } );
+
+  ok(element.networkState == HTMLMediaElement.NETWORK_NO_SOURCE);
+
+  // Invoke load() again and since the networkState is NETWORK_NO_SOURCE, the load() rejects the pending promise.
+  element.src = test.name;
+
+  // Since the networkState is not NETWORK_EMPTY, the load() sets paused to be true.
+  ok(element.paused, `loadAlgorithmRejectPromisesWhenPausing(${token}).paused should be true.`);
+}
+
+manager.runTests(gSmallTests, initTest);
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_play_promise_16.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media test: promise-based play() method</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<pre id="test">
+
+<script>
+// Name: loadAlgorithmResolveOrdering
+// Case: invoke load() on an element should resolve pending promises in order.
+// Expected result: the pending promises are resolved in order.
+
+let manager = new MediaTestManager;
+
+function initTest(test, token) {
+  manager.started(token);
+
+  let element = document.createElement(getMajorMimeType(test.type));
+  element.preload = "auto";
+  element.src = test.name;
+  once(element, "canplay").then(() => {
+    let firstPromiseResolved = false;
+
+    // play
+    element.play().then(
+      () => { firstPromiseResolved = true; },
+      () => { ok(false,  `loadAlgorithmResolveOrdering(${token}) should not be rejected.`); }
+    );
+
+    // play again
+    element.play().then(
+      () => { ok(firstPromiseResolved, `loadAlgorithmResolveOrdering(${token}), the first play should already be resolved.`); },
+      () => { ok(false,  `loadAlgorithmResolveOrdering(${token}) should not be rejected.`); }
+    ).then( () => { manager.finished(token); } );
+
+    // triger load
+    element.src = test.name;
+  });
+}
+
+manager.runTests(gSmallTests, initTest);
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_play_promise_17.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media test: promise-based play() method</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<pre id="test">
+
+<script>
+// Name: loadAlgorithmRejectOrdering
+// Case: invoke load() on an element should reject pending promises in order.
+// Expected result: the pending promises are rejected in order.
+
+let manager = new MediaTestManager;
+
+function initTest(test, token) {
+  manager.started(token);
+
+  let element = document.createElement(getMajorMimeType(test.type));
+  let firstPromiseRejected = false;
+
+  // play
+  element.play().then(
+    () => { ok(false,  `loadAlgorithmRejectOrdering(${token}) should not be resolved.`); },
+    () => { firstPromiseRejected = true; }
+  );
+
+  // play again
+  element.play().then(
+    () => { ok(false,  `loadAlgorithmRejectOrdering(${token}) should not be resolved.`); },
+    () => { ok(firstPromiseRejected, `loadAlgorithmRejectOrdering(${token}), the first play should already be rejected.`); }
+  ).then( () => { manager.finished(token); } );
+
+  // triger load
+  element.src = test.name;
+}
+
+manager.runTests(gSmallTests, initTest);
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_play_promise_18.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media test: promise-based play() method</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<pre id="test">
+
+<script>
+// Name: 'playing' event should come before promise resolving
+// Case: invoke play() on an element which has valis source
+// Expected result: receive a 'playing' event before the promise is resolved
+
+let manager = new MediaTestManager;
+
+function initTest(test, token) {
+  manager.started(token);
+
+  let element = document.createElement(getMajorMimeType(test.type));
+  element.src = test.name;
+  element.receivedPlayingEvent = false;
+
+  element.addEventListener("playing", () => {
+    element.receivedPlayingEvent = true;
+  });
+
+  element.play().then(
+    (result) => {
+      if (result == undefined && element.receivedPlayingEvent) {
+        ok(true, `${token} is resolved with ${result}.`);
+      } else {
+        ok(false, `${token} is resolved with ${result} and receivedPlayingEvent = ${element.receivedPlayingEvent}`);
+      }
+    },
+    (error) => {
+      ok(false, `${token} is rejected with ${error.name}.`);
+    }
+  ).then( () => { manager.finished(token); } );
+}
+
+manager.runTests(gSmallTests, initTest);
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_play_promise_2.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media test: promise-based play() method</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<pre id="test">
+
+<script>
+// Name: playWhenCanPlay
+// Case: invoke play() on an element that has enough data
+// Expected result: resolve the promise
+
+let manager = new MediaTestManager;
+
+function initTest(test, token) {
+  manager.started(token);
+
+  let element = document.createElement(getMajorMimeType(test.type));
+  element.preload = "auto";
+  element.src = test.name;
+  once(element, "canplay").then(() => {
+    element.play().then(
+      (result) => {
+        if (result == undefined) {
+          ok(true, `${token} is resolved with ${result}.`);
+        } else {
+          ok(false, `${token} is resolved with ${result}.`);
+        }
+      },
+      (error) => {
+        ok(false, `${token} is rejected with ${error.name}.`);
+      }
+    ).then( () => { manager.finished(token); } );
+  });
+}
+
+manager.runTests(gSmallTests, initTest);
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_play_promise_3.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media test: promise-based play() method</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<pre id="test">
+
+<script>
+// Name: playAfterPlaybackStarted
+// Case: invoke play() on an element that is already playing
+// Expected result: resolve the promise
+
+let manager = new MediaTestManager;
+
+function initTest(test, token) {
+  manager.started(token);
+
+  let element = document.createElement(getMajorMimeType(test.type));
+  element.preload = "auto";
+  element.src = test.name;
+  once(element, "playing").then(() => {
+    ok(element.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA, `playAfterPlaybackStarted(${token})`);
+    ok(!element.paused, `playAfterPlaybackStarted(${token})`);
+    element.play().then(
+      (result) => {
+        if (result == undefined) {
+          ok(true, `${token} is resolved with ${result}.`);
+        } else {
+          ok(false, `${token} is resolved with ${result}.`);
+        }
+      },
+      (error) => {
+        ok(false, `${token} is rejected with ${error.name}.`);
+      }
+    ).then( () => { manager.finished(token); } );
+  });
+
+  element.play();
+}
+
+manager.runTests(gSmallTests, initTest);
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_play_promise_4.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media test: promise-based play() method</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+  <script type="text/javascript" src="play_promise.js"></script>
+</head>
+<body>
+<pre id="test">
+
+<script>
+// Name: playNotSupportedContent
+// Case: invoke play() on an element with an unsupported content
+// Expected result: reject the promise with NotSupportedError DOM exception
+
+let manager = new MediaTestManager;
+
+function initTest(test, token) {
+  manager.started(token);
+
+  let element = document.createElement(getMajorMimeType(test.type));
+  element.src = getNotSupportedFile(test.name);
+  element.play().then(
+    (result) => {
+      ok(false, `${token} is resolved with ${result}.`);
+    },
+    (error) => {
+      if (error.name == "NotSupportedError") {
+        ok(true, `${token} is rejected with ${error.name}.`);
+      } else {
+        ok(false, `${token} is rejected with ${error.name}.`);
+      }
+    }
+  ).then( () => { manager.finished(token); } );
+}
+
+manager.runTests(gSmallTests, initTest);
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_play_promise_5.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media test: promise-based play() method</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+  <script type="text/javascript" src="play_promise.js"></script>
+</head>
+<body>
+<pre id="test">
+
+<script>
+// Name: playWithErrorAlreadySet
+// Case: invoke play() on an element with MEDIA_ERR_SRC_NOT_SUPPORTED has been set
+// Expected result: reject the promise with NotSupportedError DOM exception
+
+let manager = new MediaTestManager;
+
+function initTest(test, token) {
+  manager.started(token);
+
+  let element = document.createElement(getMajorMimeType(test.type));
+  element.src = getNotSupportedFile(test.name);
+  once(element, "error").then(() => {
+    ok(element.error.code == MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED);
+    element.play().then(
+      (result) => {
+        ok(false, `${token} is resolved with ${result}.`);
+      },
+      (error) => {
+        if (error.name == "NotSupportedError") {
+          ok(true, `${token} is rejected with ${error.name}.`);
+        } else {
+          ok(false, `${token} is rejected with ${error.name}.`);
+        }
+      }
+    ).then( () => { manager.finished(token); } );
+  });
+}
+
+manager.runTests(gSmallTests, initTest);
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_play_promise_6.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media test: promise-based play() method</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+  <script type="text/javascript" src="play_promise.js"></script>
+</head>
+<body>
+<pre id="test">
+
+<script>
+// Name: playSwitchToValidSrcAfterError
+// Case: invoke play() on an element which had its source changed (to a valid source) after suffering from an error
+// Expected result: resolve the promise with undefined
+
+let manager = new MediaTestManager;
+
+function initTest(test, token) {
+  manager.started(token);
+
+  let element = document.createElement(getMajorMimeType(test.type));
+  element.src = getNotSupportedFile(test.name);
+  once(element, "error").then(() => {
+    ok(element.error.code == MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED);
+    element.src = test.name;
+    element.play().then(
+      (result) => {
+        if (result == undefined) {
+          ok(true, `${token} is resolved with ${result}.`);
+        } else {
+          ok(false, `${token} is resolved with ${result}.`);
+        }
+      },
+      (error) => {
+        ok(false, `${token} is rejected with ${error.name}.`);
+      }
+    ).then( () => { manager.finished(token); } );
+  });
+}
+
+manager.runTests(gSmallTests, initTest);
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_play_promise_7.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media test: promise-based play() method</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+  <script type="text/javascript" src="play_promise.js"></script>
+</head>
+<body>
+<pre id="test">
+
+<script>
+// Name: playSwitchToInvalidSrcAfterError
+// Case: invoke play() on an element which had its source changed (to a invalid source) after suffering from an error
+// Expected result: reject the promise with NotSupportedError DOM exception
+
+let manager = new MediaTestManager;
+
+function initTest(test, token) {
+  manager.started(token);
+
+  let element = document.createElement(getMajorMimeType(test.type));
+  element.src = getNotSupportedFile(test.name);
+  once(element, "error").then(() => {
+    ok(element.error.code == MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED);
+    element.src = getNotSupportedFile(test.name);
+    ok(element.error == null);
+    ok(element.readyState == HTMLMediaElement.HAVE_NOTHING);
+    element.play().then(
+      (result) => {
+        ok(false, `${token} is resolved with ${result}.`);
+      },
+      (error) => {
+        if (error.name == "NotSupportedError") {
+          ok(true, `${token} is rejected with ${error.name}.`);
+        } else {
+          ok(false, `${token} is rejected with ${error.name}.`);
+        }
+      }
+    ).then( () => { manager.finished(token); } );
+  });
+}
+
+manager.runTests(gSmallTests, initTest);
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_play_promise_8.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media test: promise-based play() method</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<pre id="test">
+
+<script>
+// Name: playAndPauseWhenCanplay
+// Case: invlke play() and then pause() on an element that already has enough data to play
+// Expected result: resolve the promise
+// Note: the pause() doesn't cancel the play() because it was alredy been queued to be resolved.
+
+let manager = new MediaTestManager;
+
+function initTest(test, token) {
+  manager.started(token);
+
+  let element = document.createElement(getMajorMimeType(test.type));
+  element.preload = "auto";
+  element.src = test.name;
+  once(element, "canplay").then(() => {
+    element.play().then(
+      (result) => {
+        if (result == undefined) {
+          ok(true, `${token} is resolved with ${result}.`);
+        } else {
+          ok(false, `${token} is resolved with ${result}.`);
+        }
+      },
+      (error) => {
+        ok(false, `${token} is rejected with ${error.name}.`);
+      }
+    ).then( () => { manager.finished(token); } );
+    ok(!element.paused, `playAndPauseWhenCanplay(${token}) element should not be paused.`);
+    element.pause();
+    ok(element.paused, `playAndPauseWhenCanplay(${token}) element should be paused.`);
+  });
+}
+
+manager.runTests(gSmallTests, initTest);
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_play_promise_9.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media test: promise-based play() method</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<pre id="test">
+
+<script>
+// Name: playAndPauseBeforeCanPlay
+// Case: invlke play() and then pause() on an element that deoen't have enough data to play.
+// Expected result: reject the promise with AbortError DOM exception.
+// Note: the pause() cancels the play() because the promise is still pending.
+
+let manager = new MediaTestManager;
+
+function initTest(test, token) {
+  manager.started(token);
+
+  let element = document.createElement(getMajorMimeType(test.type));
+  ok(element.readyState == HTMLMediaElement.HAVE_NOTHING);
+  element.play().then(
+    (result) => {
+      ok(false, `${token} is resolved with ${result}.`);
+    },
+    (error) => {
+      if (error.name == "AbortError") {
+        ok(true, `${token} is rejected with ${error.name}.`);
+      } else {
+        ok(false, `${token} is rejected with ${error.name}.`);
+      }
+    }
+  ).then( () => { manager.finished(token); } );
+  ok(!element.paused, `playAndPauseBeforeCanPlay(${token}) element should not be paused.`);
+  element.pause();
+  ok(element.paused, `playAndPauseBeforeCanPlay(${token}) element should be paused.`);
+}
+
+manager.runTests(gSmallTests, initTest);
+
+</script>
\ No newline at end of file
--- a/dom/media/tests/mochitest/identity/test_fingerprints.html
+++ b/dom/media/tests/mochitest/identity/test_fingerprints.html
@@ -81,18 +81,17 @@ function testMultipleFingerprints() {
     .then(assertion => {
       ok(assertion, 'Should have assertion');
 
       var sdp = offer.sdp.slice(0, match.index) +
           'a=identity:' + assertion + '\n' +
           fingerprintSdp(fingerprints.slice(1)) +
           offer.sdp.slice(match.index);
 
-      var desc = new RTCSessionDescription({ type: 'offer', sdp: sdp });
-      return pcStrict.setRemoteDescription(desc);
+      return pcStrict.setRemoteDescription({ type: 'offer', sdp });
     })
     .then(() => {
       ok(true, 'Modified fingerprints were accepted');
     }, error => {
       var e = SpecialPowers.wrap(error);
       ok(false, 'error in test: ' +
          (e.message ? (e.message + '\n' + e.stack) : e));
     })
--- a/dom/media/tests/mochitest/pc.js
+++ b/dom/media/tests/mochitest/pc.js
@@ -329,17 +329,17 @@ PeerConnectionTest.prototype.createOffer
 };
 
 /**
  * Sets the local description for the specified peer connection instance
  * and automatically handles the failure case.
  *
  * @param {PeerConnectionWrapper} peer
           The peer connection wrapper to run the command on
- * @param {RTCSessionDescription} desc
+ * @param {RTCSessionDescriptionInit} desc
  *        Session description for the local description request
  */
 PeerConnectionTest.prototype.setLocalDescription =
 function(peer, desc, stateExpected) {
   var eventFired = new Promise(resolve => {
     peer.onsignalingstatechange = e => {
       info(peer + ": 'signalingstatechange' event received");
       var state = e.target.signalingState;
@@ -398,17 +398,17 @@ PeerConnectionTest.prototype.setOfferOpt
 };
 
 /**
  * Sets the remote description for the specified peer connection instance
  * and automatically handles the failure case.
  *
  * @param {PeerConnectionWrapper} peer
           The peer connection wrapper to run the command on
- * @param {RTCSessionDescription} desc
+ * @param {RTCSessionDescriptionInit} desc
  *        Session description for the remote description request
  */
 PeerConnectionTest.prototype.setRemoteDescription =
 function(peer, desc, stateExpected) {
   var eventFired = new Promise(resolve => {
     peer.onsignalingstatechange = e => {
       info(peer + ": 'signalingstatechange' event received");
       var state = e.target.signalingState;
@@ -1066,48 +1066,48 @@ PeerConnectionWrapper.prototype = {
       return answer;
     });
   },
 
   /**
    * Sets the local description and automatically handles the failure case.
    *
    * @param {object} desc
-   *        RTCSessionDescription for the local description request
+   *        RTCSessionDescriptionInit for the local description request
    */
   setLocalDescription : function(desc) {
     this.observedNegotiationNeeded = undefined;
     return this._pc.setLocalDescription(desc).then(() => {
       info(this + ": Successfully set the local description");
     });
   },
 
   /**
    * Tries to set the local description and expect failure. Automatically
    * causes the test case to fail if the call succeeds.
    *
    * @param {object} desc
-   *        RTCSessionDescription for the local description request
+   *        RTCSessionDescriptionInit for the local description request
    * @returns {Promise}
    *        A promise that resolves to the expected error
    */
   setLocalDescriptionAndFail : function(desc) {
     return this._pc.setLocalDescription(desc).then(
       generateErrorCallback("setLocalDescription should have failed."),
       err => {
         info(this + ": As expected, failed to set the local description");
         return err;
       });
   },
 
   /**
    * Sets the remote description and automatically handles the failure case.
    *
    * @param {object} desc
-   *        RTCSessionDescription for the remote description request
+   *        RTCSessionDescriptionInit for the remote description request
    */
   setRemoteDescription : function(desc) {
     this.observedNegotiationNeeded = undefined;
     return this._pc.setRemoteDescription(desc).then(() => {
       info(this + ": Successfully set remote description");
       if (desc.type == "rollback") {
         this.holdIceCandidates = new Promise(r => this.releaseIceCandidates = r);
 
@@ -1117,17 +1117,17 @@ PeerConnectionWrapper.prototype = {
     });
   },
 
   /**
    * Tries to set the remote description and expect failure. Automatically
    * causes the test case to fail if the call succeeds.
    *
    * @param {object} desc
-   *        RTCSessionDescription for the remote description request
+   *        RTCSessionDescriptionInit for the remote description request
    * @returns {Promise}
    *        a promise that resolve to the returned error
    */
   setRemoteDescriptionAndFail : function(desc) {
     return this._pc.setRemoteDescription(desc).then(
       generateErrorCallback("setRemoteDescription should have failed."),
       err => {
         info(this + ": As expected, failed to set the remote description");
--- a/dom/media/tests/mochitest/templates.js
+++ b/dom/media/tests/mochitest/templates.js
@@ -113,17 +113,17 @@ var checkAllTrackStats = pc => {
 // Commands run once at the beginning of each test, even when performing a
 // renegotiation test.
 var commandsPeerConnectionInitial = [
   function PC_SETUP_SIGNALING_CLIENT(test) {
     if (test.testOptions.steeplechase) {
       test.setupSignalingClient();
       test.registerSignalingCallback("ice_candidate", function (message) {
         var pc = test.pcRemote ? test.pcRemote : test.pcLocal;
-        pc.storeOrAddIceCandidate(new RTCIceCandidate(message.ice_candidate));
+        pc.storeOrAddIceCandidate(message.ice_candidate);
       });
       test.registerSignalingCallback("end_of_trickle_ice", function (message) {
         test.signalingMessagesFinished();
       });
     }
   },
 
   function PC_LOCAL_SETUP_ICE_LOGGER(test) {
--- a/dom/media/tests/mochitest/test_peerConnection_addIceCandidate.html
+++ b/dom/media/tests/mochitest/test_peerConnection_addIceCandidate.html
@@ -14,19 +14,19 @@
   var test;
   runNetworkTest(function () {
     test = new PeerConnectionTest();
     test.setMediaConstraints([{audio: true}], [{audio: true}]);
     test.chain.removeAfter("PC_LOCAL_GET_ANSWER");
 
     test.chain.insertAfter("PC_LOCAL_SET_LOCAL_DESCRIPTION", [
       function PC_LOCAL_ADD_CANDIDATE_EARLY(test) {
-        var candidate = new RTCIceCandidate(
-          {candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
-           sdpMLineIndex: 0});
+        var candidate = {
+          candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
+          sdpMLineIndex: 0};
         return test.pcLocal._pc.addIceCandidate(candidate).then(
           generateErrorCallback("addIceCandidate should have failed."),
           err => {
             is(err.name, "InvalidStateError", "Error is InvalidStateError");
           });
         }
     ]);
     test.chain.insertAfter("PC_REMOTE_SET_LOCAL_DESCRIPTION", [
@@ -49,55 +49,58 @@
         return test.pcRemote._pc.addIceCandidate(bogus)
         .then(
           generateErrorCallback("addIceCandidate should have failed."),
           err => {
             is(err.name, "InvalidCandidateError", "Error is InvalidCandidateError");
           }
         );
       },
-      function PC_REMOTE_ADD_CANDIDATE_MISSING_INDEX(test) {
-        // Note: it is probably not a good idea to automatically fill a missing
-        //       MLineIndex with a default value of zero, see bug 1157034
+      function PC_REMOTE_ADD_MISSING_MID_AND_MISSING_INDEX(test) {
         var broken = new RTCIceCandidate(
           {candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host"});
         return test.pcRemote._pc.addIceCandidate(broken)
         .then(
-          // FIXME this needs to be updated once bug 1157034 is fixed
-          todo(false, "Missing index in got automatically set to a valid value bz://1157034")
+          generateErrorCallback("addIceCandidate should have failed."),
+          err => {
+            is(err.name, "TypeError", "Error is TypeError");
+          }
         );
       },
       function PC_REMOTE_ADD_VALID_CANDIDATE(test) {
-        var candidate = new RTCIceCandidate(
-          {candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
-           sdpMLineIndex: 0});
+        var candidate = {
+          candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
+          sdpMLineIndex: 0};
         return test.pcRemote._pc.addIceCandidate(candidate)
-        .then(ok(true, "Successfully added valid ICE candidate"));
+        .then(() => ok(true, "Successfully added valid ICE candidate"));
       },
       // bug 1095793
       function PC_REMOTE_ADD_MISMATCHED_MID_AND_LEVEL_CANDIDATE(test) {
         var bogus = new mozRTCIceCandidate(
           {candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
            sdpMLineIndex: 0,
            sdpMid: "sdparta_1"});
         return test.pcRemote._pc.addIceCandidate(bogus)
-        .then(
-          generateErrorCallback("addIceCandidate should have failed."),
-          err => {
-            is(err.name, "InvalidCandidateError", "Error is InvalidCandidateError");
-          }
-        );
+        .then(generateErrorCallback("addIceCandidate should have failed."),
+              err => is(err.name, "InvalidCandidateError", "Error is InvalidCandidateError"));
+      },
+      function PC_REMOTE_ADD_MID_AND_MISSING_INDEX(test) {
+        var candidate = new RTCIceCandidate(
+          {candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
+           sdpMid: "sdparta_0"});
+        return test.pcRemote._pc.addIceCandidate(candidate)
+        .then(() => ok(true, "Successfully added valid ICE candidate"));
       },
       function PC_REMOTE_ADD_MATCHING_MID_AND_LEVEL_CANDIDATE(test) {
-        var candidate = new mozRTCIceCandidate(
+        var candidate = new RTCIceCandidate(
           {candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
            sdpMLineIndex: 0,
            sdpMid: "sdparta_0"});
         return test.pcRemote._pc.addIceCandidate(candidate)
-        .then(ok(true, "Successfully added valid ICE candidate with matching mid and level"));
+        .then(() => ok(true, "Successfully added valid ICE candidate with matching mid and level"));
       }
     ]);
     test.run();
   });
 </script>
 </pre>
 </body>
 </html>
--- a/dom/media/tests/mochitest/test_peerConnection_closeDuringIce.html
+++ b/dom/media/tests/mochitest/test_peerConnection_closeDuringIce.html
@@ -16,22 +16,22 @@
 
 function PC_LOCAL_SETUP_NULL_ICE_HANDLER(test) {
   test.pcLocal.setupIceCandidateHandler(test, function() {}, function () {});
 }
 function PC_REMOTE_SETUP_NULL_ICE_HANDLER(test) {
   test.pcRemote.setupIceCandidateHandler(test, function() {}, function () {});
 }
 function PC_REMOTE_ADD_FAKE_ICE_CANDIDATE(test) {
-  var cand = new RTCIceCandidate({"candidate":"candidate:0 1 UDP 2130379007 192.0.2.1 12345 typ host","sdpMid":"","sdpMLineIndex":0});
+  var cand = {"candidate":"candidate:0 1 UDP 2130379007 192.0.2.1 12345 typ host","sdpMid":"","sdpMLineIndex":0};
   test.pcRemote.storeOrAddIceCandidate(cand);
   info(test.pcRemote + " Stored fake candidate: " + JSON.stringify(cand));
 }
 function PC_LOCAL_ADD_FAKE_ICE_CANDIDATE(test) {
-  var cand = new RTCIceCandidate({"candidate":"candidate:0 1 UDP 2130379007 192.0.2.2 56789 typ host","sdpMid":"","sdpMLineIndex":0});
+  var cand = {"candidate":"candidate:0 1 UDP 2130379007 192.0.2.2 56789 typ host","sdpMid":"","sdpMLineIndex":0};
     test.pcLocal.storeOrAddIceCandidate(cand);
   info(test.pcLocal + " Stored fake candidate: " + JSON.stringify(cand));
 }
 function PC_LOCAL_CLOSE_DURING_ICE(test) {
   return test.pcLocal.iceChecking.then(() => {
     test.pcLocal.onsignalingstatechange = function () {};
     test.pcLocal.close();
     });
--- a/dom/media/tests/mochitest/test_peerConnection_errorCallbacks.html
+++ b/dom/media/tests/mochitest/test_peerConnection_errorCallbacks.html
@@ -22,27 +22,25 @@
     return pc.createAnswer()
     .then(generateErrorCallback("createAnswer before offer should fail"),
           validateReason);
   };
 
   function testSetLocalDescriptionError() {
     var pc = new RTCPeerConnection();
     info ("Testing setLocalDescription error");
-    return pc.setLocalDescription(new RTCSessionDescription({ sdp: "Picklechips!",
-                                                                 type: "offer" }))
+    return pc.setLocalDescription({ sdp: "Picklechips!", type: "offer" })
     .then(generateErrorCallback("setLocalDescription with nonsense SDP should fail"),
           validateReason);
   };
 
   function testSetRemoteDescriptionError() {
     var pc = new RTCPeerConnection();
     info ("Testing setRemoteDescription error");
-    return pc.setRemoteDescription(new RTCSessionDescription({ sdp: "Who?",
-                                                                  type: "offer" }))
+    return pc.setRemoteDescription({ sdp: "Who?", type: "offer" })
     .then(generateErrorCallback("setRemoteDescription with nonsense SDP should fail"),
           validateReason);
   };
 
   // No test for createOffer errors -- there's nothing we can do at this
   // level to evoke an error in createOffer.
 
   runNetworkTest(function () {
--- a/dom/media/tests/mochitest/test_peerConnection_iceFailure.html
+++ b/dom/media/tests/mochitest/test_peerConnection_iceFailure.html
@@ -15,22 +15,22 @@
 
 function PC_LOCAL_SETUP_NULL_ICE_HANDLER(test) {
   test.pcLocal.setupIceCandidateHandler(test, function() {}, function () {});
 }
 function PC_REMOTE_SETUP_NULL_ICE_HANDLER(test) {
   test.pcRemote.setupIceCandidateHandler(test, function() {}, function () {});
 }
 function PC_REMOTE_ADD_FAKE_ICE_CANDIDATE(test) {
-  var cand = new RTCIceCandidate({"candidate":"candidate:0 1 UDP 2130379007 192.0.2.1 12345 typ host","sdpMid":"","sdpMLineIndex":0});
+  var cand = {"candidate":"candidate:0 1 UDP 2130379007 192.0.2.1 12345 typ host","sdpMid":"","sdpMLineIndex":0};
   test.pcRemote.storeOrAddIceCandidate(cand);
   info(test.pcRemote + " Stored fake candidate: " + JSON.stringify(cand));
 }
 function PC_LOCAL_ADD_FAKE_ICE_CANDIDATE(test) {
-  var cand = new RTCIceCandidate({"candidate":"candidate:0 1 UDP 2130379007 192.0.2.2 56789 typ host","sdpMid":"","sdpMLineIndex":0});
+  var cand = {"candidate":"candidate:0 1 UDP 2130379007 192.0.2.2 56789 typ host","sdpMid":"","sdpMLineIndex":0};
     test.pcLocal.storeOrAddIceCandidate(cand);
   info(test.pcLocal + " Stored fake candidate: " + JSON.stringify(cand));
 }
 function PC_LOCAL_WAIT_FOR_ICE_FAILURE(test) {
   return test.pcLocal.iceFailed.then(() => {
     ok(true, this.pcLocal + " Ice Failure Reached.");
 	});
 }
--- a/dom/media/tests/mochitest/test_peerConnection_localReofferRollback.html
+++ b/dom/media/tests/mochitest/test_peerConnection_localReofferRollback.html
@@ -32,20 +32,19 @@
 
         function PC_REMOTE_CREATE_AND_SET_OFFER(test) {
           return test.createOffer(test.pcRemote).then(offer => {
             return test.setLocalDescription(test.pcRemote, offer, HAVE_LOCAL_OFFER);
           });
         },
 
         function PC_REMOTE_ROLLBACK(test) {
-          return test.setLocalDescription(
-              test.pcRemote,
-              new RTCSessionDescription({ type: "rollback", sdp: ""}),
-              STABLE);
+          return test.setLocalDescription(test.pcRemote,
+                                          { type: "rollback", sdp: "" },
+                                          STABLE);
         },
 
         // Rolling back should shut down gathering
         function PC_REMOTE_WAIT_FOR_END_OF_TRICKLE(test) {
           return test.pcRemote.endOfTrickleIce;
         },
     ]);
     test.setMediaConstraints([{audio: true}], [{audio: true}]);
--- a/dom/media/tests/mochitest/test_peerConnection_localRollback.html
+++ b/dom/media/tests/mochitest/test_peerConnection_localRollback.html
@@ -18,20 +18,19 @@
     test.chain.insertBefore('PC_LOCAL_CREATE_OFFER', [
         function PC_REMOTE_CREATE_AND_SET_OFFER(test) {
           return test.createOffer(test.pcRemote).then(offer => {
             return test.setLocalDescription(test.pcRemote, offer, HAVE_LOCAL_OFFER);
           });
         },
 
         function PC_REMOTE_ROLLBACK(test) {
-          return test.setLocalDescription(
-              test.pcRemote,
-              new RTCSessionDescription({ type: "rollback", sdp: ""}),
-              STABLE);
+          return test.setLocalDescription(test.pcRemote,
+                                          { type: "rollback", sdp: "" },
+                                          STABLE);
         },
 
         // Rolling back should shut down gathering
         function PC_REMOTE_WAIT_FOR_END_OF_TRICKLE(test) {
           return test.pcRemote.endOfTrickleIce;
         },
 
         function PC_REMOTE_SETUP_ICE_HANDLER(test) {
--- a/dom/media/tests/mochitest/test_peerConnection_remoteReofferRollback.html
+++ b/dom/media/tests/mochitest/test_peerConnection_remoteReofferRollback.html
@@ -30,20 +30,18 @@
           if (test.testOptions.steeplechase) {
             test.pcLocal.endOfTrickleIce.then(() => {
               send_message({"type": "end_of_trickle_ice"});
             });
           }
         },
 
         function PC_REMOTE_ROLLBACK(test) {
-          return test.setRemoteDescription(
-              test.pcRemote,
-              new RTCSessionDescription({ type: "rollback" }),
-              STABLE)
+          return test.setRemoteDescription(test.pcRemote, { type: "rollback" },
+                                           STABLE)
             .then(() => test.pcRemote.rollbackRemoteTracksIfNotNegotiated());
         },
 
         function PC_LOCAL_ROLLBACK(test) {
           // We haven't negotiated the new stream yet.
           test.pcLocal.expectNegotiationNeeded();
           return test.setLocalDescription(
               test.pcLocal,
--- a/dom/media/tests/mochitest/test_peerConnection_remoteRollback.html
+++ b/dom/media/tests/mochitest/test_peerConnection_remoteRollback.html
@@ -15,20 +15,18 @@
   runNetworkTest(function (options) {
     test = new PeerConnectionTest(options);
     test.setMediaConstraints([{audio: true}], [{audio: true}]);
     test.chain.removeAfter('PC_REMOTE_CHECK_CAN_TRICKLE_SYNC');
     test.chain.append([
       function PC_REMOTE_ROLLBACK(test) {
         // We still haven't negotiated the tracks
         test.pcRemote.expectNegotiationNeeded();
-        return test.setRemoteDescription(
-          test.pcRemote,
-          new RTCSessionDescription({ type: "rollback" }),
-          STABLE)
+        return test.setRemoteDescription(test.pcRemote, { type: "rollback" },
+                                         STABLE)
           .then(() => test.pcRemote.rollbackRemoteTracksIfNotNegotiated());
       },
 
       function PC_REMOTE_CHECK_CAN_TRICKLE_REVERT_SYNC(test) {
         is(test.pcRemote._pc.canTrickleIceCandidates, null,
            "Remote canTrickleIceCandidates is reverted to null");
       },
 
--- a/dom/media/tests/mochitest/test_peerConnection_restartIceLocalAndRemoteRollback.html
+++ b/dom/media/tests/mochitest/test_peerConnection_restartIceLocalAndRemoteRollback.html
@@ -46,20 +46,18 @@
         function PC_LOCAL_EXPECT_ICE_CONNECTED(test) {
           test.pcLocal.iceCheckingIceRollbackExpected = true;
         },
         function PC_REMOTE_EXPECT_ICE_CONNECTED(test) {
           test.pcRemote.iceCheckingIceRollbackExpected = true;
         },
 
         function PC_REMOTE_ROLLBACK(test) {
-          return test.setRemoteDescription(
-              test.pcRemote,
-              new RTCSessionDescription({ type: "rollback" }),
-              STABLE);
+          return test.setRemoteDescription(test.pcRemote, { type: "rollback" },
+                                           STABLE);
         },
 
         function PC_LOCAL_ROLLBACK(test) {
           // We haven't negotiated the new stream yet.
           test.pcLocal.expectNegotiationNeeded();
           return test.setLocalDescription(
               test.pcLocal,
               new RTCSessionDescription({ type: "rollback", sdp: ""}),
--- a/dom/media/tests/mochitest/test_peerConnection_restartIceLocalRollback.html
+++ b/dom/media/tests/mochitest/test_peerConnection_restartIceLocalRollback.html
@@ -37,21 +37,19 @@
                                             offer,
                                             HAVE_LOCAL_OFFER);
           });
         },
         function PC_LOCAL_EXPECT_ICE_CONNECTED(test) {
           test.pcLocal.iceCheckingIceRollbackExpected = true;
         },
         function PC_LOCAL_ROLLBACK(test) {
-          return test.setLocalDescription(
-              test.pcLocal,
-              new RTCSessionDescription({ type: "rollback",
-                                          sdp: ""}),
-              STABLE);
+          return test.setLocalDescription(test.pcLocal,
+                                          { type: "rollback", sdp: ""},
+                                          STABLE);
         },
         // Rolling back should shut down gathering
         function PC_LOCAL_WAIT_FOR_END_OF_TRICKLE(test) {
           return test.pcLocal.endOfTrickleIce;
         },
         function PC_LOCAL_EXPECT_ICE_CHECKING(test) {
           test.pcLocal.expectIceChecking();
         },
--- a/dom/webidl/Gamepad.webidl
+++ b/dom/webidl/Gamepad.webidl
@@ -1,19 +1,30 @@
 /* -*- 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/. */
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * The origin of this IDL file is
+ * https://w3c.github.io/gamepad/
+ * https://w3c.github.io/gamepad/extensions.html
+ */
 
 [Pref="dom.gamepad.enabled"]
 interface GamepadButton {
   readonly    attribute boolean pressed;
   readonly    attribute double  value;
 };
 
+enum GamepadHand {
+  "",
+  "left",
+  "right"
+};
+
 enum GamepadMappingType {
   "",
   "standard"
 };
 
 [Pref="dom.gamepad.enabled"]
 interface Gamepad {
   /**
@@ -29,16 +40,23 @@ interface Gamepad {
 
   /**
    * The mapping in use for this device. The empty string
    * indicates that no mapping is in use.
    */
   readonly attribute GamepadMappingType mapping;
 
   /**
+   * The hand in use for this device. The empty string
+   * indicates that unknown, both hands, or not applicable
+   */
+  [Pref="dom.gamepad.extensions.enabled"]
+  readonly attribute GamepadHand hand;
+
+  /**
    * true if this gamepad is currently connected to the system.
    */
   readonly attribute boolean connected;
 
   /**
    * The current state of all buttons on the device, an
    * array of GamepadButton.
    */
--- a/dom/webidl/HTMLMediaElement.webidl
+++ b/dom/webidl/HTMLMediaElement.webidl
@@ -63,17 +63,17 @@ interface HTMLMediaElement : HTMLElement
   [NewObject]
   readonly attribute TimeRanges seekable;
   readonly attribute boolean ended;
   [SetterThrows]
            attribute boolean autoplay;
   [SetterThrows]
            attribute boolean loop;
   [Throws]
-  void play();
+  Promise<void> play();
   [Throws]
   void pause();
 
   // TODO: Bug 847377 - mediaGroup and MediaController
   // media controller
   //         attribute DOMString mediaGroup;
   //         attribute MediaController? controller;
 
--- a/dom/webidl/RTCIceCandidate.webidl
+++ b/dom/webidl/RTCIceCandidate.webidl
@@ -3,23 +3,23 @@
  * 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 origin of this IDL file is
  * http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCIceCandidate
  */
 
 dictionary RTCIceCandidateInit {
-  DOMString? candidate = null;
+  required DOMString candidate;
   DOMString? sdpMid = null;
-  unsigned short sdpMLineIndex;
+  unsigned short? sdpMLineIndex = null;
 };
 
 [Pref="media.peerconnection.enabled",
  JSImplementation="@mozilla.org/dom/rtcicecandidate;1",
- Constructor(optional RTCIceCandidateInit candidateInitDict)]
+ Constructor(RTCIceCandidateInit candidateInitDict)]
 interface RTCIceCandidate {
-  attribute DOMString?      candidate;
+  attribute DOMString       candidate;
   attribute DOMString?      sdpMid;
   attribute unsigned short? sdpMLineIndex;
 
   jsonifier;
 };
--- a/dom/webidl/RTCPeerConnection.webidl
+++ b/dom/webidl/RTCPeerConnection.webidl
@@ -2,17 +2,17 @@
 /* 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 origin of this IDL file is
  * http://w3c.github.io/webrtc-pc/#interface-definition
  */
 
-callback RTCSessionDescriptionCallback = void (RTCSessionDescription sdp);
+callback RTCSessionDescriptionCallback = void (RTCSessionDescriptionInit description);
 callback RTCPeerConnectionErrorCallback = void (DOMError error);
 callback VoidFunction = void ();
 callback RTCStatsCallback = void (RTCStatsReport report);
 
 enum RTCSignalingState {
     "stable",
     "have-local-offer",
     "have-remote-offer",
@@ -77,24 +77,24 @@ interface RTCPeerConnection : EventTarge
   static Promise<RTCCertificate> generateCertificate (AlgorithmIdentifier keygenAlgorithm);
 
   [Pref="media.peerconnection.identity.enabled"]
   void setIdentityProvider (DOMString provider,
                             optional DOMString protocol,
                             optional DOMString username);
   [Pref="media.peerconnection.identity.enabled"]
   Promise<DOMString> getIdentityAssertion();
-  Promise<RTCSessionDescription> createOffer (optional RTCOfferOptions options);
-  Promise<RTCSessionDescription> createAnswer (optional RTCAnswerOptions options);
-  Promise<void> setLocalDescription (RTCSessionDescription description);
-  Promise<void> setRemoteDescription (RTCSessionDescription description);
+  Promise<RTCSessionDescriptionInit> createOffer (optional RTCOfferOptions options);
+  Promise<RTCSessionDescriptionInit> createAnswer (optional RTCAnswerOptions options);
+  Promise<void> setLocalDescription (RTCSessionDescriptionInit description);
+  Promise<void> setRemoteDescription (RTCSessionDescriptionInit description);
   readonly attribute RTCSessionDescription? localDescription;
   readonly attribute RTCSessionDescription? remoteDescription;
   readonly attribute RTCSignalingState signalingState;
-  Promise<void> addIceCandidate (RTCIceCandidate candidate);
+  Promise<void> addIceCandidate ((RTCIceCandidateInit or RTCIceCandidate)? candidate);
   readonly attribute boolean? canTrickleIceCandidates;
   readonly attribute RTCIceGatheringState iceGatheringState;
   readonly attribute RTCIceConnectionState iceConnectionState;
   [Pref="media.peerconnection.identity.enabled"]
   readonly attribute Promise<RTCIdentityAssertion> peerIdentity;
   [Pref="media.peerconnection.identity.enabled"]
   readonly attribute DOMString? idpLoginUrl;
 
@@ -149,20 +149,20 @@ partial interface RTCPeerConnection {
   // Dummy Promise<void> return values avoid "WebIDL.WebIDLError: error:
   // We have overloads with both Promise and non-Promise return types"
 
   Promise<void> createOffer (RTCSessionDescriptionCallback successCallback,
                              RTCPeerConnectionErrorCallback failureCallback,
                              optional RTCOfferOptions options);
   Promise<void> createAnswer (RTCSessionDescriptionCallback successCallback,
                               RTCPeerConnectionErrorCallback failureCallback);
-  Promise<void> setLocalDescription (RTCSessionDescription description,
+  Promise<void> setLocalDescription (RTCSessionDescriptionInit description,
                                      VoidFunction successCallback,
                                      RTCPeerConnectionErrorCallback failureCallback);
-  Promise<void> setRemoteDescription (RTCSessionDescription description,
+  Promise<void> setRemoteDescription (RTCSessionDescriptionInit description,
                                       VoidFunction successCallback,
                                       RTCPeerConnectionErrorCallback failureCallback);
   Promise<void> addIceCandidate (RTCIceCandidate candidate,
                                  VoidFunction successCallback,
                                  RTCPeerConnectionErrorCallback failureCallback);
   Promise<void> getStats (MediaStreamTrack? selector,
                           RTCStatsCallback successCallback,
                           RTCPeerConnectionErrorCallback failureCallback);
--- a/gfx/layers/BufferTexture.cpp
+++ b/gfx/layers/BufferTexture.cpp
@@ -277,28 +277,37 @@ BufferTextureData::BorrowDrawTarget()
 
   if (mDescriptor.type() != BufferDescriptor::TRGBDescriptor) {
     return nullptr;
   }
 
   const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor();
 
   uint32_t stride = ImageDataSerializer::GetRGBStride(rgb);
-  mDrawTarget = gfx::Factory::CreateDrawTargetForData(mMoz2DBackend,
-                                                      GetBuffer(), rgb.size(),
-                                                      stride, rgb.format(), true);
+  if (gfx::Factory::DoesBackendSupportDataDrawtarget(mMoz2DBackend)) {
+    mDrawTarget = gfx::Factory::CreateDrawTargetForData(mMoz2DBackend,
+                                                        GetBuffer(), rgb.size(),
+                                                        stride, rgb.format(), true);
+  } else {
+    // Fall back to supported platform backend.  Note that mMoz2DBackend
+    // does not match the draw target type.
+    mDrawTarget = gfxPlatform::CreateDrawTargetForData(GetBuffer(), rgb.size(),
+                                                       stride, rgb.format(),
+                                                       true);
+  }
 
   if (mDrawTarget) {
     RefPtr<gfx::DrawTarget> dt = mDrawTarget;
     return dt.forget();
   }
 
   // TODO - should we warn? should we really fallback to cairo? perhaps
   // at least update mMoz2DBackend...
   if (mMoz2DBackend != gfx::BackendType::CAIRO) {
+    gfxCriticalNote << "Falling to CAIRO from " << (int)mMoz2DBackend;
     mDrawTarget = gfx::Factory::CreateDrawTargetForData(gfx::BackendType::CAIRO,
                                                         GetBuffer(), rgb.size(),
                                                         stride, rgb.format(), true);
   }
 
   if (!mDrawTarget) {
     gfxCriticalNote << "BorrowDrawTarget failure, original backend " << (int)mMoz2DBackend;
   }
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -1464,32 +1464,37 @@ gfxPlatform::CreateSimilarSoftwareDrawTa
 #endif
     dt = Factory::CreateDrawTarget(backendType, aSize, aFormat);
   }
 
   return dt.forget();
 }
 
 /* static */ already_AddRefed<DrawTarget>
-gfxPlatform::CreateDrawTargetForData(unsigned char* aData, const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat)
+gfxPlatform::CreateDrawTargetForData(unsigned char* aData,
+                                     const IntSize& aSize,
+                                     int32_t aStride,
+                                     SurfaceFormat aFormat,
+                                     bool aUninitialized)
 {
   BackendType backendType = gfxVars::ContentBackend();
   NS_ASSERTION(backendType != BackendType::NONE, "No backend.");
 
   if (!Factory::DoesBackendSupportDataDrawtarget(backendType)) {
 #ifdef USE_SKIA
     backendType = BackendType::SKIA;
 #else
     backendType = BackendType::CAIRO;
 #endif
   }
 
   RefPtr<DrawTarget> dt = Factory::CreateDrawTargetForData(backendType,
                                                            aData, aSize,
-                                                           aStride, aFormat);
+                                                           aStride, aFormat,
+                                                           aUninitialized);
 
   return dt.forget();
 }
 
 /* static */ BackendType
 gfxPlatform::BackendTypeForName(const nsCString& aName)
 {
   if (aName.EqualsLiteral("cairo"))
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -236,18 +236,21 @@ public:
 
     already_AddRefed<DrawTarget>
       CreateOffscreenCanvasDrawTarget(const mozilla::gfx::IntSize& aSize, mozilla::gfx::SurfaceFormat aFormat);
 
     already_AddRefed<DrawTarget>
       CreateSimilarSoftwareDrawTarget(DrawTarget* aDT, const IntSize &aSize, mozilla::gfx::SurfaceFormat aFormat);
 
     static already_AddRefed<DrawTarget>
-      CreateDrawTargetForData(unsigned char* aData, const mozilla::gfx::IntSize& aSize, 
-                              int32_t aStride, mozilla::gfx::SurfaceFormat aFormat);
+      CreateDrawTargetForData(unsigned char* aData,
+                              const mozilla::gfx::IntSize& aSize, 
+                              int32_t aStride,
+                              mozilla::gfx::SurfaceFormat aFormat,
+                              bool aUninitialized = false);
 
     /**
      * Returns true if rendering to data surfaces produces the same results as
      * rendering to offscreen surfaces on this platform, making it safe to
      * render content to data surfaces. This is generally false on platforms
      * which use different backends for each type of DrawTarget.
      */
     virtual bool CanRenderContentToDataSurface() const {
--- a/gfx/vr/VRManager.cpp
+++ b/gfx/vr/VRManager.cpp
@@ -79,17 +79,17 @@ VRManager::VRManager()
 #if defined(XP_WIN) || defined(XP_MACOSX) || defined(XP_LINUX)
   // OpenVR is cross platform compatible
   mgr = VRDisplayManagerOpenVR::Create();
   if (mgr) {
     mManagers.AppendElement(mgr);
   }
 
   controllerMgr = VRControllerManagerOpenVR::Create();
-  if (mgr) {
+  if (controllerMgr) {
     mControllerManagers.AppendElement(controllerMgr);
   }
 
   // OSVR is cross platform compatible
   mgr = VRDisplayManagerOSVR::Create();
   if (mgr) {
       mManagers.AppendElement(mgr);
   }
--- a/gfx/vr/gfxVR.cpp
+++ b/gfx/vr/gfxVR.cpp
@@ -63,21 +63,21 @@ VRFieldOfView::ConstructProjectionMatrix
 
 /* static */ uint32_t
 VRControllerManager::AllocateControllerID()
 {
   return ++sControllerBase;
 }
 
 void
-VRControllerManager::AddGamepad(const char* aID, uint32_t aMapping,
+VRControllerManager::AddGamepad(const char* aID, uint32_t aMapping, uint32_t aHand,
                                 uint32_t aNumButtons, uint32_t aNumAxes)
 {
   dom::GamepadAdded a(NS_ConvertUTF8toUTF16(nsDependentCString(aID)), mControllerCount,
-                     aMapping, dom::GamepadServiceType::VR, aNumButtons,
+                     aMapping, aHand, dom::GamepadServiceType::VR, aNumButtons,
                      aNumAxes);
 
   VRManager* vm = VRManager::Get();
   MOZ_ASSERT(vm);
   vm->NotifyGamepadChange<dom::GamepadAdded>(a);
 }
 
 void
--- a/gfx/vr/gfxVR.h
+++ b/gfx/vr/gfxVR.h
@@ -226,22 +226,22 @@ struct VRControllerInfo
   uint32_t mControllerID;
   VRDeviceType mType;
   nsCString mControllerName;
   uint32_t mMappingType;
   uint32_t mNumButtons;
   uint32_t mNumAxes;
 
   bool operator==(const VRControllerInfo& other) const {
-  return mType == other.mType &&
-         mControllerID == other.mControllerID &&
-         mControllerName == other.mControllerName &&
-         mMappingType == other.mMappingType &&
-         mNumButtons == other.mNumButtons &&
-         mNumAxes == other.mNumAxes;
+    return mType == other.mType &&
+           mControllerID == other.mControllerID &&
+           mControllerName == other.mControllerName &&
+           mMappingType == other.mMappingType &&
+           mNumButtons == other.mNumButtons &&
+           mNumAxes == other.mNumAxes;
   }
 
   bool operator!=(const VRControllerInfo& other) const {
     return !(*this == other);
   }
 };
 
 class VRControllerManager {
@@ -253,17 +253,17 @@ public:
   virtual void Destroy() = 0;
   virtual void HandleInput() = 0;
   virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult) = 0;
   virtual void ScanForDevices() = 0;
   virtual void RemoveDevices() = 0;
   void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed);
   void NewAxisMove(uint32_t aIndex, uint32_t aAxis, double aValue);
   void NewPoseState(uint32_t aIndex, const dom::GamepadPoseState& aPose);
-  void AddGamepad(const char* aID, uint32_t aMapping,
+  void AddGamepad(const char* aID, uint32_t aMapping, uint32_t aHand,
                   uint32_t aNumButtons, uint32_t aNumAxes);
   void RemoveGamepad(uint32_t aIndex);
 
 protected:
   VRControllerManager() : mInstalled(false), mControllerCount(0) {}
   virtual ~VRControllerManager() {}
 
   bool mInstalled;
--- a/gfx/vr/gfxVROpenVR.cpp
+++ b/gfx/vr/gfxVROpenVR.cpp
@@ -487,18 +487,16 @@ VRDisplayManagerOpenVR::GetHMDs(nsTArray
 
 VRControllerOpenVR::VRControllerOpenVR()
   : VRControllerHost(VRDeviceType::OpenVR)
 {
   MOZ_COUNT_CTOR_INHERITED(VRControllerOpenVR, VRControllerHost);
   mControllerInfo.mControllerName.AssignLiteral("OpenVR HMD");
 #ifdef MOZ_GAMEPAD
   mControllerInfo.mMappingType = static_cast<uint32_t>(GamepadMappingType::_empty);
-#else
-  mControllerInfo.mMappingType = 0;
 #endif
   mControllerInfo.mNumButtons = gNumOpenVRButtonMask;
   mControllerInfo.mNumAxes = gNumOpenVRAxis;
 }
 
 VRControllerOpenVR::~VRControllerOpenVR()
 {
   MOZ_COUNT_DTOR_INHERITED(VRControllerOpenVR, VRControllerHost);
@@ -741,26 +739,43 @@ VRControllerManagerOpenVR::ScanForDevice
       RemoveGamepad(mOpenVRController[i]->GetIndex());
     }
     mControllerCount = 0;
     mOpenVRController.Clear();
 
     // Re-adding controllers to VRControllerManager.
     for (vr::TrackedDeviceIndex_t i = 0; i < newControllerCount; ++i) {
       vr::TrackedDeviceIndex_t trackedDevice = trackedIndexArray[i];
+  #ifdef MOZ_GAMEPAD
+      vr::ETrackedControllerRole role =
+      mVRSystem->GetControllerRoleForTrackedDeviceIndex(trackedDevice);
+      GamepadHand hand;
+
+      switch(role) {
+        case vr::ETrackedControllerRole::TrackedControllerRole_Invalid:
+          hand = GamepadHand::_empty;
+          break;
+        case vr::ETrackedControllerRole::TrackedControllerRole_LeftHand:
+          hand = GamepadHand::Left;
+          break;
+        case vr::ETrackedControllerRole::TrackedControllerRole_RightHand:
+          hand = GamepadHand::Right;
+          break;
+      }
+  #endif
       RefPtr<VRControllerOpenVR> openVRController = new VRControllerOpenVR();
       openVRController->SetIndex(mControllerCount);
       openVRController->SetTrackedIndex(trackedDevice);
       mOpenVRController.AppendElement(openVRController);
 
   // Only in MOZ_GAMEPAD platform, We add gamepads.
   #ifdef MOZ_GAMEPAD
       // Not already present, add it.
-      AddGamepad("OpenVR Gamepad", static_cast<uint32_t>(GamepadMappingType::_empty),
-                 gNumOpenVRButtonMask, gNumOpenVRAxis);
+       AddGamepad("OpenVR Gamepad", static_cast<uint32_t>(GamepadMappingType::_empty),
+               static_cast<uint32_t>(hand), gNumOpenVRButtonMask, gNumOpenVRAxis);
       ++mControllerCount;
   #endif
     }
   }
 }
 
 void
 VRControllerManagerOpenVR::RemoveDevices()
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -549,19 +549,18 @@ GetMinAndMaxScaleForAnimationProperty(co
       const AnimationProperty& prop = effect->Properties()[propIdx];
       if (prop.mProperty != eCSSProperty_transform) {
         continue;
       }
 
       // We need to factor in the scale of the base style if the base style
       // will be used on the compositor.
       if (effect->NeedsBaseStyle(prop.mProperty)) {
-        EffectSet* effects = EffectSet::GetEffectSet(aFrame);
         StyleAnimationValue baseStyle =
-          effects->GetBaseStyle(prop.mProperty);
+          EffectCompositor::GetBaseStyle(prop.mProperty, aFrame);
         MOZ_ASSERT(!baseStyle.IsNull(), "The base value should be set");
         UpdateMinMaxScale(aFrame, baseStyle, aMinScale, aMaxScale);
       }
 
       for (const AnimationPropertySegment& segment : prop.mSegments) {
         // In case of add or accumulate composite, StyleAnimationValue does
         // not have a valid value.
         if (segment.mFromComposite == dom::CompositeOperation::Replace) {
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -423,18 +423,18 @@ SetAnimatable(nsCSSPropertyID aProperty,
 static void
 SetBaseAnimationStyle(nsCSSPropertyID aProperty,
                       nsIFrame* aFrame,
                       const TransformReferenceBox& aRefBox,
                       layers::BaseAnimationStyle& aBaseStyle)
 {
   MOZ_ASSERT(aFrame);
 
-  EffectSet* effects = EffectSet::GetEffectSet(aFrame);
-  StyleAnimationValue baseValue = effects->GetBaseStyle(aProperty);
+  StyleAnimationValue baseValue =
+    EffectCompositor::GetBaseStyle(aProperty, aFrame);
   MOZ_ASSERT(!baseValue.IsNull(),
              "The base value should be already there");
 
   layers::Animatable animatable;
   SetAnimatable(aProperty, baseValue, aFrame, aRefBox, animatable);
   aBaseStyle = animatable;
 }
 
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -912,19 +912,16 @@ pref("identity.sync.tokenserver.uri", "h
 
 #ifndef RELEASE_OR_BETA
 // Enable Presentation API on Nightly
 pref("dom.presentation.enabled", true);
 pref("dom.presentation.controller.enabled", true); // enable 1-UA mode
 pref("dom.presentation.receiver.enabled", true); // enable 1-UA mode
 #endif
 
-pref("dom.presentation.discovery.enabled", true);
-pref("dom.presentation.discovery.legacy.enabled", true); // for TV 2.5 backward capability
-
 pref("dom.audiochannel.audioCompeting", true);
 pref("dom.audiochannel.mediaControl", true);
 
 // Space separated list of URLS that are allowed to send objects (instead of
 // only strings) through webchannels. This list is duplicated in browser/app/profile/firefox.js
 pref("webchannel.allowObject.urlWhitelist", "https://accounts.firefox.com https://content.cdn.mozilla.net https://input.mozilla.org https://support.mozilla.org https://install.mozilla.org");
 
 pref("media.openUnsupportedTypeWithExternalApp", true);
--- a/mobile/android/chrome/content/CastingApps.js
+++ b/mobile/android/chrome/content/CastingApps.js
@@ -54,74 +54,16 @@ var mediaPlayerDevice = {
       uuid: display.uuid,
       manufacturer: display.manufacturer,
       modelName: display.modelName,
       mirror: display.mirror
     };
   }
 };
 
-var fxOSTVDevice = {
-  id: "app://fling-player.gaiamobile.org",
-  target: "app://fling-player.gaiamobile.org/index.html",
-  factory: function(aService) {
-    Cu.import("resource://gre/modules/PresentationApp.jsm");
-    let request = new window.PresentationRequest(this.target);
-    return new PresentationApp(aService, request);
-  },
-  init: function() {
-    Services.obs.addObserver(this, "presentation-device-change", false);
-    SimpleServiceDiscovery.addExternalDiscovery(this);
-  },
-  observe: function(subject, topic, data) {
-    let device = subject.QueryInterface(Ci.nsIPresentationDevice);
-    let service = this.toService(device);
-    switch (data) {
-      case "add":
-        SimpleServiceDiscovery.addService(service);
-        break;
-      case "update":
-        SimpleServiceDiscovery.updateService(service);
-        break;
-      case "remove":
-        if(SimpleServiceDiscovery.findServiceForID(device.id)) {
-          SimpleServiceDiscovery.removeService(device.id);
-        }
-        break;
-    }
-  },
-  toService: function(device) {
-    return {
-      location: device.id,
-      target: fxOSTVDevice.target,
-      friendlyName: device.name,
-      uuid: device.id,
-      manufacturer: "Firefox OS TV",
-      modelName: "Firefox OS TV",
-    };
-  },
-  startDiscovery: function() {
-    window.navigator.mozPresentationDeviceInfo.forceDiscovery();
-
-    // need to update the lastPing time for known device.
-    window.navigator.mozPresentationDeviceInfo.getAll()
-    .then(function(devices) {
-      for (let device of devices) {
-        let service = fxOSTVDevice.toService(device);
-        SimpleServiceDiscovery.addService(service);
-      }
-    });
-  },
-  stopDiscovery: function() {
-    // do nothing
-  },
-  types: ["video/mp4", "video/webm"],
-  extensions: ["mp4", "webm"],
-};
-
 var CastingApps = {
   _castMenuId: -1,
   mirrorStartMenuId: -1,
   mirrorStopMenuId: -1,
   _blocked: null,
   _bound: null,
   _interval: 120 * 1000, // 120 seconds
 
@@ -132,22 +74,16 @@ var CastingApps = {
 
     // Register targets
     SimpleServiceDiscovery.registerDevice(rokuDevice);
 
     // MediaPlayerDevice will notify us any time the native device list changes.
     mediaPlayerDevice.init();
     SimpleServiceDiscovery.registerDevice(mediaPlayerDevice);
 
-    // Presentation Device will notify us any time the available device list changes.
-    if (window.PresentationRequest) {
-      fxOSTVDevice.init();
-      SimpleServiceDiscovery.registerDevice(fxOSTVDevice);
-    }
-
     // Search for devices continuously
     SimpleServiceDiscovery.search(this._interval);
 
     this._castMenuId = NativeWindow.contextmenus.add(
       Strings.browser.GetStringFromName("contextmenu.sendToDevice"),
       this.filterCast,
       this.handleContextMenu.bind(this)
     );
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -509,17 +509,16 @@ var BrowserApp = {
 
     // Notify Java that Gecko has loaded.
     Messaging.sendRequest({ type: "Gecko:Ready" });
 
     this.deck.addEventListener("DOMContentLoaded", function BrowserApp_delayedStartup() {
       BrowserApp.deck.removeEventListener("DOMContentLoaded", BrowserApp_delayedStartup, false);
 
       InitLater(() => Cu.import("resource://gre/modules/NotificationDB.jsm"));
-      InitLater(() => Cu.import("resource://gre/modules/PresentationDeviceInfoManager.jsm"));
 
       InitLater(() => Services.obs.notifyObservers(window, "browser-delayed-startup-finished", ""));
       InitLater(() => Messaging.sendRequest({ type: "Gecko:DelayedStartup" }));
 
       if (!AppConstants.RELEASE_OR_BETA) {
         InitLater(() => WebcompatReporter.init());
       }
 
--- a/python/mozboot/mozboot/base.py
+++ b/python/mozboot/mozboot/base.py
@@ -68,26 +68,43 @@ the $PATH environment variable.
 
 We recommend the following tools for installing Python:
 
     pyenv   -- https://github.com/yyuu/pyenv)
     pythonz -- https://github.com/saghul/pythonz
     official installers -- http://www.python.org/
 '''
 
-RUST_NOT_IN_PATH = '''
-You have some rust files in %(cargo_bin)s, but they're not part of the
-standard PATH.'''
+RUST_INSTALL_COMPLETE = '''
+Rust installation complete. You should now have rustc and cargo
+in %(cargo_bin)s
+
+The installer tries to add these to your default shell PATH, so
+restarting your shell and running this script again may work.
+If it doesn't, you'll need to add the new command location
+manually.
+
+If restarting doesn't work, edit your shell initialization
+script, which may be called ~/.bashrc or ~/.bash_profile or
+~/.profile, and add the following line:
 
-RUST_PATH_ADVICE = '''
-To make these available, please add this directory to the PATH variable
-in your shell initialization script, which may be called ~/.bashrc or
-~/.bash_profile or ~/.profile. Edit this and add the following line:
+    %(cmd)s
+
+Then restart your shell and run the bootstrap script again.
+'''
 
-    source %(cargo_home)s/env
+RUST_NOT_IN_PATH = '''
+You have some rust files in %(cargo_bin)s
+but they're not part of this shell's PATH.
+
+To add these to the PATH, edit your shell initialization
+script, which may be called ~/.bashrc or ~/.bash_profile or
+~/.profile, and add the following line:
+
+    %(cmd)s
 
 Then restart your shell and run the bootstrap script again.
 '''
 
 RUSTUP_OLD = '''
 We found an executable called `rustup` which we normally use to install
 and upgrade Rust programming language support, but we didn't understand
 its output. It may be an old version, or not be the installer from
@@ -103,18 +120,17 @@ We attempted to upgrade Rust to a modern
 However, you appear to still have version %s.
 
 It's possible rustup failed. It's also possible the new Rust is not being
 installed in the search path for this shell. Try creating a new shell and
 run this bootstrapper again.
 
 If this continues to fail and you are sure you have a modern Rust on your
 system, ensure it is on the $PATH and try again. If that fails, you'll need to
-install Rust manually and ensure the path with the rustc and cargo  binaries
-are listed in the $PATH environment variable.
+install Rust manually.
 
 We recommend the installer from https://rustup.rs/ for installing Rust,
 but you may be able to get a recent enough version from a software install
 tool or package manager on your system, or directly from https://rust-lang.org/
 '''
 
 BROWSER_ARTIFACT_MODE_MOZCONFIG = '''
 Paste the lines between the chevrons (>>> and <<<) into your mozconfig file:
@@ -516,36 +532,51 @@ class BaseBootstrapper(object):
         return our >= MODERN_RUST_VERSION, our
 
     def cargo_home(self):
         cargo_home = os.environ.get('CARGO_HOME',
                 os.path.expanduser(os.path.join('~', '.cargo')))
         cargo_bin = os.path.join(cargo_home, 'bin')
         return cargo_home, cargo_bin
 
+    def print_rust_path_advice(self, template, cargo_home, cargo_bin):
+        # Suggest ~/.cargo/env if it exists.
+        if os.path.exists(os.path.join(cargo_home, 'env')):
+            cmd = 'source %s/env' % cargo_home
+        else:
+            # On Windows rustup doesn't write out ~/.cargo/env
+            # so fall back to a manual PATH update. Bootstrap
+            # only runs under msys, so a unix-style shell command
+            # is appropriate there.
+            cmd = 'export PATH=%s:$PATH' % cargo_bin
+        print(template % {
+            'cargo_bin': cargo_bin,
+            'cmd': cmd,
+        })
+
     def ensure_rust_modern(self):
         modern, version = self.is_rust_modern()
 
         if modern:
             print('Your version of Rust (%s) is new enough.' % version)
             return
 
         if not version:
             # Rust wasn't in PATH. Check the standard location.
             cargo_home, cargo_bin = self.cargo_home()
             try_rustc = os.path.join(cargo_bin, 'rustc' + rust.exe_suffix())
             try_cargo = os.path.join(cargo_bin, 'cargo' + rust.exe_suffix())
             have_rustc = os.path.exists(try_rustc)
             have_cargo = os.path.exists(try_cargo)
             if have_rustc or have_cargo:
-                print(RUST_NOT_IN_PATH % { 'cargo_bin': cargo_bin })
-                print(RUST_PATH_ADVICE % { 'cargo_home': cargo_home })
+                self.print_rust_path_advice(RUST_NOT_IN_PATH,
+                        cargo_home, cargo_bin)
                 sys.exit(1)
-
-        print('Your version of Rust (%s) is too old.' % version)
+        else:
+            print('Your version of Rust (%s) is too old.' % version)
 
         rustup = self.which('rustup')
         if rustup:
             rustup_version = self._parse_version(rustup)
             if not rustup_version:
                 print(RUSTUP_OLD)
                 sys.exit(1)
             print('Found rustup. Will try to upgrade.')
@@ -586,19 +617,18 @@ class BaseBootstrapper(object):
             os.chmod(rustup_init, mode | stat.S_IRWXU)
             print('Ok')
             print('Running rustup-init...')
             subprocess.check_call([rustup_init, '-y',
                 '--default-toolchain', 'stable',
                 '--default-host', platform,
             ])
             cargo_home, cargo_bin = self.cargo_home()
-            print('Rust installation complete.')
-            print('You should now have rustc and cargo in %s' % cargo_bin)
-            print(RUST_PATH_ADVICE % { 'cargo_home': cargo_home })
+            self.print_rust_path_advice(RUST_INSTALL_COMPLETE,
+                    cargo_home, cargo_bin)
         finally:
             try:
                 os.remove(rustup_init)
             except OSError as e:
                 if e.errno != errno.ENOENT:
                     raise
 
     def http_download_and_save(self, url, dest, sha256hexhash):
--- a/testing/web-platform/meta/html/dom/interfaces.html.ini
+++ b/testing/web-platform/meta/html/dom/interfaces.html.ini
@@ -3095,19 +3095,16 @@
     expected: FAIL
 
   [HTMLMediaElement interface: new Audio() must inherit property "audioTracks" with the proper type (38)]
     expected: FAIL
 
   [HTMLMediaElement interface: new Audio() must inherit property "videoTracks" with the proper type (39)]
     expected: FAIL
 
-  [HTMLMediaElement interface: operation play()]
-    expected: FAIL
-
   [HTMLInputElement interface: document.createElement("input") must inherit property "labels" with the proper type (46)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("text") must inherit property "labels" with the proper type (46)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("hidden") must inherit property "labels" with the proper type (46)]
     expected: FAIL
--- a/toolkit/modules/FinderHighlighter.jsm
+++ b/toolkit/modules/FinderHighlighter.jsm
@@ -155,17 +155,17 @@ FinderHighlighter.prototype = {
    * For each window we track a number of properties which _at least_ consist of
    *  - {Boolean} detectedGeometryChange Whether the geometry of the found ranges'
    *                                     rectangles has changed substantially
    *  - {Set}     dynamicRangesSet       Set of ranges that may move around, depending
    *                                     on page layout changes and user input
    *  - {Map}     frames                 Collection of frames that were encountered
    *                                     when inspecting the found ranges
    *  - {Map}     modalHighlightRectsMap Collection of ranges and their corresponding
-   *                                     Rects
+   *                                     Rects and texts
    *
    * @param  {nsIDOMWindow} window
    * @return {Object}
    */
   getForWindow(window, propName = null) {
     if (!gWindows.has(window)) {
       gWindows.set(window, {
         detectedGeometryChange: false,
@@ -826,17 +826,17 @@ FinderHighlighter.prototype = {
    * Read and store the rectangles that encompass the entire region of a range
    * for use by the drawing function of the highlighter.
    *
    * @param  {nsIDOMRange} range  Range to fetch the rectangles from
    * @param  {Object}      [dict] Dictionary of properties belonging to
    *                              the currently active window
    * @return {Set}         Set of rects that were found for the range
    */
-  _getRangeRects(range, dict = null) {
+  _getRangeRectsAndTexts(range, dict = null) {
     let window = range.startContainer.ownerDocument.defaultView;
     let bounds;
     // If the window is part of a frameset, try to cache the bounds query.
     if (dict && dict.frames.has(window)) {
       bounds = dict.frames.get(window);
       if (!bounds) {
         bounds = this._getRootBounds(window);
         dict.frames.set(window, bounds);
@@ -844,25 +844,26 @@ FinderHighlighter.prototype = {
     } else
       bounds = this._getRootBounds(window);
 
     let topBounds = this._getRootBounds(window.top, false);
     let rects = [];
     // A range may consist of multiple rectangles, we can also do these kind of
     // precise cut-outs. range.getBoundingClientRect() returns the fully
     // encompassing rectangle, which is too much for our purpose here.
-    for (let rect of range.getClientRects()) {
+    let {rectList, textList} = range.getClientRectsAndTexts();
+    for (let rect of rectList) {
       rect = Rect.fromRect(rect);
       rect.x += bounds.x;
       rect.y += bounds.y;
       // If the rect is not even visible from the top document, we can ignore it.
       if (rect.intersects(topBounds))
         rects.push(rect);
     }
-    return rects;
+    return {rectList: rects, textList};
   },
 
   /**
    * Read and store the rectangles that encompass the entire region of a range
    * for use by the drawing function of the highlighter and store them in the
    * cache.
    *
    * @param  {nsIDOMRange} range            Range to fetch the rectangles from
@@ -871,29 +872,29 @@ FinderHighlighter.prototype = {
    *                                        `_isInDynamicContainer()`. Optional,
    *                                        defaults to `true`
    * @param  {Object}      [dict]           Dictionary of properties belonging to
    *                                        the currently active window
    * @return {Set}         Set of rects that were found for the range
    */
   _updateRangeRects(range, checkIfDynamic = true, dict = null) {
     let window = range.startContainer.ownerDocument.defaultView;
-    let rects = this._getRangeRects(range, dict);
+    let rectsAndTexts = this._getRangeRectsAndTexts(range, dict);
 
     // Only fetch the rect at this point, if not passed in as argument.
     dict = dict || this.getForWindow(window.top);
-    let oldRects = dict.modalHighlightRectsMap.get(range);
-    dict.modalHighlightRectsMap.set(range, rects);
+    let oldRectsAndTexts = dict.modalHighlightRectsMap.get(range);
+    dict.modalHighlightRectsMap.set(range, rectsAndTexts);
     // Check here if we suddenly went down to zero rects from more than zero before,
     // which indicates that we should re-iterate the document.
-    if (oldRects && oldRects.length && !rects.length)
+    if (oldRectsAndTexts && oldRectsAndTexts.rectList.length && !rectsAndTexts.rectList.length)
       dict.detectedGeometryChange = true;
     if (checkIfDynamic && this._isInDynamicContainer(range))
       dict.dynamicRangesSet.add(range);
-    return rects;
+    return rectsAndTexts;
   },
 
   /**
    * Re-read the rectangles of the ranges that we keep track of separately,
    * because they're enclosed by a position: fixed container DOM node or (i)frame.
    *
    * @param {Object} dict Dictionary of properties belonging to the currently
    *                      active window
@@ -923,21 +924,21 @@ FinderHighlighter.prototype = {
     let range = dict.currentFoundRange;
     if (!range)
       return;
 
     fontStyle = fontStyle || this._getRangeFontStyle(range);
     // Text color in the outline is determined by kModalStyles.
     delete fontStyle.color;
 
-    let rects = this._getRangeRects(range);
+    let rectsAndTexts = this._getRangeRectsAndTexts(range);
     textContent = textContent || this._getRangeContentArray(range);
 
     let outlineAnonNode = dict.modalHighlightOutline;
-    let rectCount = rects.length;
+    let rectCount = rectsAndTexts.rectList.length;
     // (re-)Building the outline is conditional and happens when one of the
     // following conditions is met:
     // 1. No outline nodes were built before, or
     // 2. When the amount of rectangles to draw is different from before, or
     // 3. When there's more than one rectangle to draw, because it's impossible
     //    to animate that consistently with AnonymousContent nodes.
     let rebuildOutline = (!outlineAnonNode || rectCount !== dict.previousRangeRectsCount ||
       rectCount != 1);
@@ -953,48 +954,45 @@ FinderHighlighter.prototype = {
         try {
           document.removeAnonymousContent(outlineAnonNode);
         } catch (ex) {}
       }
       dict.modalHighlightOutline = null;
     }
 
     // Abort when there's no text to highlight.
-    if (!textContent.length)
+    if (!rectsAndTexts.textList.length)
       return;
 
     let outlineBox;
     if (rebuildOutline) {
       // Create the main (yellow) highlight outline box.
       outlineBox = document.createElementNS(kNSHTML, "div");
       outlineBox.setAttribute("id", kModalOutlineId);
     }
 
     const kModalOutlineTextId = kModalOutlineId + "-text";
     let i = 0;
-    for (let rect of rects) {
-      // if the current rect is the last rect, then text is set to the rest of
-      // the textContent with single spaces injected between the text. Otherwise
-      // text is set to the current textContent for the matching rect.
-      let text = (i == rectCount - 1) ? textContent.slice(i).join(" ") : textContent[i];
+    for (let rect of rectsAndTexts.rectList) {
+      let text = rectsAndTexts.textList[i];
 
       // Next up is to check of the outline box' borders will not overlap with
       // rects that we drew before or will draw after this one.
       // We're taking the width of the border into account, which is
       // `kOutlineBoxBorderSize` pixels.
       // When left and/ or right sides will overlap with the current, previous
       // or next rect, make sure to make the necessary adjustments to the style.
       // These adjustments will override the styles as defined in `kModalStyles.outlineNode`.
       let intersectingSides = new Set();
-      let previous = rects[i - 1];
+      let previous = rectsAndTexts.rectList[i - 1];
       if (previous &&
           rect.left - previous.right <= 2 * kOutlineBoxBorderSize) {
         intersectingSides.add("left");
       }
-      let next = rects[i + 1];
+      let next = rectsAndTexts.rectList[i + 1];
       if (next &&
           next.left - rect.right <= 2 * kOutlineBoxBorderSize) {
         intersectingSides.add("right");
       }
       let borderStyles = [...intersectingSides].map(side => [ "border-" + side, 0 ]);
       if (intersectingSides.size) {
         borderStyles.push([ "margin",  `-${kOutlineBoxBorderSize}px 0 0 ${
           intersectingSides.has("left") ? 0 : -kOutlineBoxBorderSize}px !important`]);
@@ -1133,26 +1131,26 @@ FinderHighlighter.prototype = {
 
     this._updateRangeOutline(dict);
 
     let allRects = [];
     if (paintContent || dict.modalHighlightAllMask) {
       this._updateDynamicRangesRects(dict);
 
       let DOMRect = window.DOMRect;
-      for (let [range, rects] of dict.modalHighlightRectsMap) {
+      for (let [range, rectsAndTexts] of dict.modalHighlightRectsMap) {
         if (dict.updateAllRanges)
-          rects = this._updateRangeRects(range);
+          rectsAndTexts = this._updateRangeRects(range);
 
         // If a geometry change was detected, we bail out right away here, because
         // the current set of ranges has been invalidated.
         if (dict.detectedGeometryChange)
           return;
 
-        for (let rect of rects)
+        for (let rect of rectsAndTexts.rectList)
           allRects.push(new DOMRect(rect.x, rect.y, rect.width, rect.height));
       }
       dict.updateAllRanges = false;
     }
 
     dict.modalHighlightAllMask.setCutoutRectsForElement(kMaskId, allRects);
   },
 
--- a/toolkit/modules/Preferences.jsm
+++ b/toolkit/modules/Preferences.jsm
@@ -66,19 +66,19 @@ Preferences._get = function(prefName, de
     case Ci.nsIPrefBranch.PREF_BOOL:
       return this._prefBranch.getBoolPref(prefName);
 
     case Ci.nsIPrefBranch.PREF_INVALID:
       return defaultValue;
 
     default:
       // This should never happen.
-      throw "Error getting pref " + prefName + "; its value's type is " +
-            this._prefBranch.getPrefType(prefName) + ", which I don't " +
-            "know how to handle.";
+      throw new Error(`Error getting pref ${prefName}; its value's type is ` +
+                      `${this._prefBranch.getPrefType(prefName)}, which I don't ` +
+                      `know how to handle.`);
   }
 };
 
 /**
  * Set a preference to a value.
  *
  * You can set multiple prefs by passing an object as the only parameter.
  * In that case, this method will treat the properties of the object
@@ -125,36 +125,37 @@ Preferences._set = function(prefName, pr
       break;
 
     case "Number":
       // We throw if the number is outside the range, since the result
       // will never be what the consumer wanted to store, but we only warn
       // if the number is non-integer, since the consumer might not mind
       // the loss of precision.
       if (prefValue > MAX_INT || prefValue < MIN_INT)
-        throw ("you cannot set the " + prefName + " pref to the number " +
-              prefValue + ", as number pref values must be in the signed " +
-              "32-bit integer range -(2^31-1) to 2^31-1.  To store numbers " +
-              "outside that range, store them as strings.");
+        throw new Error(
+              `you cannot set the ${prefName} pref to the number ` +
+              `${prefValue}, as number pref values must be in the signed ` +
+              `32-bit integer range -(2^31-1) to 2^31-1.  To store numbers ` +
+              `outside that range, store them as strings.`);
       this._prefBranch.setIntPref(prefName, prefValue);
       if (prefValue % 1 != 0)
         Cu.reportError("Warning: setting the " + prefName + " pref to the " +
                        "non-integer number " + prefValue + " converted it " +
                        "to the integer number " + this.get(prefName) +
                        "; to retain fractional precision, store non-integer " +
                        "numbers as strings.");
       break;
 
     case "Boolean":
       this._prefBranch.setBoolPref(prefName, prefValue);
       break;
 
     default:
-      throw "can't set pref " + prefName + " to value '" + prefValue +
-            "'; it isn't a String, Number, or Boolean";
+      throw new Error(`can't set pref ${prefName} to value '${prefValue}'; ` +
+                      `it isn't a String, Number, or Boolean`);
   }
 };
 
 /**
  * Whether or not the given pref has a value.  This is different from isSet
  * because it returns true whether the value of the pref is a default value
  * or a user-set value, while isSet only returns true if the value
  * is a user-set value.
--- a/toolkit/modules/moz.build
+++ b/toolkit/modules/moz.build
@@ -73,17 +73,16 @@ EXTRA_JS_MODULES += [
     'PromiseUtils.jsm',
     'PropertyListUtils.jsm',
     'RemoteController.jsm',
     'RemoteFinder.jsm',
     'RemotePageManager.jsm',
     'RemoteSecurityUI.jsm',
     'RemoteWebProgress.jsm',
     'ResetProfile.jsm',
-    'secondscreen/PresentationApp.jsm',
     'secondscreen/RokuApp.jsm',
     'secondscreen/SimpleServiceDiscovery.jsm',
     'SelectContentHelper.jsm',
     'SelectParentHelper.jsm',
     'Services.jsm',
     'SessionRecorder.jsm',
     'sessionstore/FormData.jsm',
     'sessionstore/ScrollPosition.jsm',
deleted file mode 100644
--- a/toolkit/modules/secondscreen/PresentationApp.jsm
+++ /dev/null
@@ -1,190 +0,0 @@
-// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = ["PresentationApp"];
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "sysInfo", () => {
-  return Cc["@mozilla.org/system-info;1"].getService(Ci.nsIPropertyBag2);
-});
-
-const DEBUG = false;
-
-const STATE_UNINIT = "uninitialized" // RemoteMedia status
-const STATE_STARTED = "started"; // RemoteMedia status
-const STATE_PAUSED = "paused"; // RemoteMedia status
-const STATE_SHUTDOWN = "shutdown"; // RemoteMedia status
-
-function debug(msg) {
-  Services.console.logStringMessage("PresentationApp: " + msg);
-}
-
-// PresentationApp is a wrapper for interacting with a Presentation Receiver Device.
-function PresentationApp(service, request) {
-  this.service = service;
-  this.request = request;
-}
-
-PresentationApp.prototype = {
-  start: function start(callback) {
-    this.request.startWithDevice(this.service.uuid)
-    .then((session) => {
-      this._session = session;
-      if (callback) {
-        session.addEventListener('connect', () => {
-          callback(true);
-        });
-      }
-    }, () => {
-      if (callback) {
-        callback(false);
-      }
-    });
-  },
-
-  stop: function stop(callback) {
-    if (this._session && this._session.state === "connected") {
-      this._session.terminate();
-    }
-
-    delete this._session;
-
-    if (callback) {
-      callback(true);
-    }
-  },
-
-  remoteMedia: function remoteMedia(callback, listener) {
-    if (callback) {
-      if (!this._session) {
-        callback();
-        return;
-      }
-
-      callback(new RemoteMedia(this._session, listener));
-    }
-  }
-}
-
-/* RemoteMedia provides a wrapper for using Presentation API to control Firefox TV app.
- * The server implementation must be built into the Firefox TV receiver app.
- * see https://github.com/mozilla-b2g/gaia/tree/master/tv_apps/fling-player
- */
-function RemoteMedia(session, listener) {
-  this._session = session ;
-  this._listener = listener;
-  this._status = STATE_UNINIT;
-
-  this._session.addEventListener("message", this);
-  this._session.addEventListener("terminate", this);
-
-  if (this._listener && "onRemoteMediaStart" in this._listener) {
-    Services.tm.mainThread.dispatch((function() {
-      this._listener.onRemoteMediaStart(this);
-    }).bind(this), Ci.nsIThread.DISPATCH_NORMAL);
-  }
-}
-
-RemoteMedia.prototype = {
-  _seq: 0,
-
-  handleEvent: function(e) {
-    switch (e.type) {
-      case "message":
-        this._onmessage(e);
-        break;
-      case "terminate":
-        this._onterminate(e);
-        break;
-    }
-  },
-
-  _onmessage: function(e) {
-    DEBUG && debug("onmessage: " + e.data);
-    if (this.status === STATE_SHUTDOWN) {
-      return;
-    }
-
-    if (e.data.indexOf("stopped") > -1) {
-      if (this.status !== STATE_PAUSED) {
-        this._status = STATE_PAUSED;
-        if (this._listener && "onRemoteMediaStatus" in this._listener) {
-          this._listener.onRemoteMediaStatus(this);
-        }
-      }
-    } else if (e.data.indexOf("playing") > -1) {
-      if (this.status !== STATE_STARTED) {
-        this._status = STATE_STARTED;
-        if (this._listener && "onRemoteMediaStatus" in this._listener) {
-          this._listener.onRemoteMediaStatus(this);
-        }
-      }
-    }
-  },
-
-  _onterminate: function(e) {
-    DEBUG && debug("onterminate: " + this._session.state);
-    this._status = STATE_SHUTDOWN;
-    if (this._listener && "onRemoteMediaStop" in this._listener) {
-      this._listener.onRemoteMediaStop(this);
-    }
-  },
-
-  _sendCommand: function(command, data) {
-    let msg = {
-      'type': command,
-      'seq': ++this._seq
-    };
-
-    if (data) {
-      for (var k in data) {
-        msg[k] = data[k];
-      }
-    }
-
-    let raw = JSON.stringify(msg);
-    DEBUG && debug("send command: " + raw);
-
-    this._session.send(raw);
-  },
-
-  shutdown: function shutdown() {
-    DEBUG && debug("RemoteMedia - shutdown");
-    this._sendCommand("close");
-  },
-
-  play: function play() {
-    DEBUG && debug("RemoteMedia - play");
-    this._sendCommand("play");
-  },
-
-  pause: function pause() {
-    DEBUG && debug("RemoteMedia - pause");
-    this._sendCommand("pause");
-  },
-
-  load: function load(data) {
-    DEBUG && debug("RemoteMedia - load: " + data);
-    this._sendCommand("load", { "url": data.source });
-
-    let deviceName;
-    if (Services.appinfo.widgetToolkit == "android") {
-      deviceName = sysInfo.get("device");
-    } else {
-      deviceName = sysInfo.get("host");
-    }
-    this._sendCommand("device-info", { "displayName": deviceName });
-  },
-
-  get status() {
-    return this._status;
-  }
-}
--- a/toolkit/modules/tests/browser/browser_FinderHighlighter.js
+++ b/toolkit/modules/tests/browser/browser_FinderHighlighter.js
@@ -453,8 +453,34 @@ add_task(function* testHideOnClear() {
       removeCalls: [1, 2]
     });
     findbar.clear();
     yield promise;
 
     findbar.close(true);
   });
 });
+
+add_task(function* testRectsAndTexts() {
+  let url = "data:text/html;charset=utf-8," +
+    encodeURIComponent("<div style=\"width: 150px; border: 1px solid black\">" +
+    "Here are a lot of words Please use find to highlight some words that wrap" +
+    " across a line boundary and see what happens.</div>");
+  yield BrowserTestUtils.withNewTab(url, function* (browser) {
+    let findbar = gBrowser.getFindBar();
+    yield promiseOpenFindbar(findbar);
+
+    let word = "words please use find to";
+    let expectedResult = {
+      rectCount: 2,
+      insertCalls: [2, 4],
+      removeCalls: [0, 2]
+    };
+    let promise = promiseTestHighlighterOutput(browser, word, expectedResult, (maskNode, outlineNode) => {
+      let boxes = outlineNode.getElementsByTagName("span");
+      Assert.equal(boxes.length, 2, "There should be two outline boxes containing text");
+      Assert.equal(boxes[0].textContent.trim(), "words", "First text should match");
+      Assert.equal(boxes[1].textContent.trim(), "Please use find to", "Second word should match");
+    });
+    yield promiseEnterStringIntoFindField(findbar, word);
+    yield promise;
+  });
+});