merge fx-team to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 13 Sep 2016 11:54:01 +0200
changeset 339307 bdf56e1152aa2678b498cfcc0c0a36728c0cefa7
parent 339292 4fb8ce27c37fd72b2ea08fe299f590071dc60f8c (current diff)
parent 339306 4850895eb2fbee98b74a885ea00be1cadc352313 (diff)
child 339399 f5d043ce6d36a3c461cbd829d4a4a38394b7c436
push id10033
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:50:26 +0000
treeherdermozilla-aurora@5dddbefdf759 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone51.0a1
merge fx-team to mozilla-central a=merge
devtools/client/locales/en-US/promisedebugger.properties
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -5,18 +5,16 @@
 
 #include "nsXULAppAPI.h"
 #include "mozilla/AppData.h"
 #include "application.ini.h"
 #include "nsXPCOMGlue.h"
 #if defined(XP_WIN)
 #include <windows.h>
 #include <stdlib.h>
-#include <io.h>
-#include <fcntl.h>
 #elif defined(XP_UNIX)
 #include <sys/resource.h>
 #include <unistd.h>
 #endif
 
 #include <stdio.h>
 #include <stdarg.h>
 #include <time.h>
@@ -279,18 +277,18 @@ InitXPCOMGlue(const char *argv0, nsIFile
 
   nsresult rv = mozilla::BinaryPath::Get(argv0, exePath);
   if (NS_FAILED(rv)) {
     Output("Couldn't find the application directory.\n");
     return rv;
   }
 
   char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
-  if (!lastSlash || (size_t(lastSlash - exePath) > MAXPATHLEN -
-sizeof(XPCOM_DLL) - 1))
+  if (!lastSlash ||
+      (size_t(lastSlash - exePath) > MAXPATHLEN - sizeof(XPCOM_DLL) - 1))
     return NS_ERROR_FAILURE;
 
   strcpy(lastSlash + 1, XPCOM_DLL);
 
   if (!FileExists(exePath)) {
     Output("Could not find the Mozilla runtime.\n");
     return NS_ERROR_FAILURE;
   }
--- a/devtools/client/canvasdebugger/test/browser_canvas-frontend-call-stack-01.js
+++ b/devtools/client/canvasdebugger/test/browser_canvas-frontend-call-stack-01.js
@@ -1,15 +1,21 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Tests if the a function call's stack is properly displayed in the UI.
  */
 
+// Force the old debugger UI since it's directly used (see Bug 1301705)
+Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
+registerCleanupFunction(function* () {
+  Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
+});
+
 function* ifTestingSupported() {
   let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_DEEP_STACK_URL);
   let { window, $, $all, EVENTS, SnapshotsListView, CallsListView } = panel.panelWin;
 
   yield reload(target);
 
   let recordingFinished = once(window, EVENTS.SNAPSHOT_RECORDING_FINISHED);
   let callListPopulated = once(window, EVENTS.CALL_LIST_POPULATED);
--- a/devtools/client/canvasdebugger/test/browser_canvas-frontend-call-stack-02.js
+++ b/devtools/client/canvasdebugger/test/browser_canvas-frontend-call-stack-02.js
@@ -1,16 +1,22 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Tests if the a function call's stack is properly displayed in the UI
  * and jumping to source in the debugger for the topmost call item works.
  */
 
+// Force the old debugger UI since it's directly used (see Bug 1301705)
+Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
+registerCleanupFunction(function* () {
+  Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
+});
+
 function* ifTestingSupported() {
   let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_DEEP_STACK_URL);
   let { window, $, $all, EVENTS, SnapshotsListView, CallsListView } = panel.panelWin;
 
   yield reload(target);
 
   let recordingFinished = once(window, EVENTS.SNAPSHOT_RECORDING_FINISHED);
   let callListPopulated = once(window, EVENTS.CALL_LIST_POPULATED);
--- a/devtools/client/debugger/new/panel.js
+++ b/devtools/client/debugger/new/panel.js
@@ -17,16 +17,17 @@ DebuggerPanel.prototype = {
       targetPromise = Promise.resolve(this.toolbox.target);
     }
 
     return targetPromise.then(() => {
       this.panelWin.Debugger.bootstrap({
         threadClient: this.toolbox.threadClient,
         tabTarget: this.toolbox.target
       });
+      this.isReady = true;
       return this;
     });
   },
 
   _store: function() {
     return this.panelWin.Debugger.store;
   },
 
--- a/devtools/client/debugger/test/mochitest/head.js
+++ b/devtools/client/debugger/test/mochitest/head.js
@@ -26,17 +26,21 @@ const chromeRegistry = Cc["@mozilla.org/
 // Override promise with deprecated-sync-thenables
 promise = Cu.import("resource://devtools/shared/deprecated-sync-thenables.js", {}).Promise;
 
 const EXAMPLE_URL = "http://example.com/browser/devtools/client/debugger/test/mochitest/";
 const FRAME_SCRIPT_URL = getRootDirectory(gTestPath) + "code_frame-script.js";
 const CHROME_URL = "chrome://mochitests/content/browser/devtools/client/debugger/test/mochitest/";
 const CHROME_URI = Services.io.newURI(CHROME_URL, null, null);
 
+Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
+
 registerCleanupFunction(function* () {
+  Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
+
   info("finish() was called, cleaning up...");
   Services.prefs.setBoolPref("devtools.debugger.log", gEnableLogging);
 
   while (gBrowser && gBrowser.tabs && gBrowser.tabs.length > 1) {
     info("Destroying toolbox.");
     let target = TargetFactory.forTab(gBrowser.selectedTab);
     yield gDevTools.closeToolbox(target);
 
--- a/devtools/client/framework/test/browser_source_map-01.js
+++ b/devtools/client/framework/test/browser_source_map-01.js
@@ -8,16 +8,22 @@ thisTestLeaksUncaughtRejectionsAndShould
   "TypeError: this.transport is null");
 
 /**
  * Tests the SourceMapService updates generated sources when source maps
  * are subsequently found. Also checks when no column is provided, and
  * when tagging an already source mapped location initially.
  */
 
+// Force the old debugger UI since it's directly used (see Bug 1301705)
+Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
+registerCleanupFunction(function* () {
+  Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
+});
+
 const DEBUGGER_ROOT = "http://example.com/browser/devtools/client/debugger/test/mochitest/";
 // Empty page
 const PAGE_URL = `${DEBUGGER_ROOT}doc_empty-tab-01.html`;
 const JS_URL = `${URL_ROOT}code_binary_search.js`;
 const COFFEE_URL = `${URL_ROOT}code_binary_search.coffee`;
 const { SourceMapService } = require("devtools/client/framework/source-map-service");
 const { serialize } = require("devtools/client/framework/location-store");
 
--- a/devtools/client/framework/test/browser_source_map-02.js
+++ b/devtools/client/framework/test/browser_source_map-02.js
@@ -2,16 +2,22 @@
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Tests the SourceMapService updates generated sources when pretty printing
  * and un pretty printing.
  */
 
+// Force the old debugger UI since it's directly used (see Bug 1301705)
+Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
+registerCleanupFunction(function* () {
+  Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
+});
+
 const DEBUGGER_ROOT = "http://example.com/browser/devtools/client/debugger/test/mochitest/";
 // Empty page
 const PAGE_URL = `${DEBUGGER_ROOT}doc_empty-tab-01.html`;
 const JS_URL = `${URL_ROOT}code_ugly.js`;
 const { SourceMapService } = require("devtools/client/framework/source-map-service");
 
 add_task(function* () {
   let toolbox = yield openNewTabAndToolbox(PAGE_URL, "jsdebugger");
--- a/devtools/client/framework/test/browser_toolbox_split_console.js
+++ b/devtools/client/framework/test/browser_toolbox_split_console.js
@@ -8,16 +8,22 @@
 //  * toolbox.isSplitConsoleFocused
 
 let gToolbox = null;
 let panelWin = null;
 
 const URL = "data:text/html;charset=utf8,test split console key delegation";
 const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
+// Force the old debugger UI since it's directly used (see Bug 1301705)
+Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
+registerCleanupFunction(function* () {
+  Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
+});
+
 add_task(function* () {
   let tab = yield addTab(URL);
   let target = TargetFactory.forTab(tab);
   gToolbox = yield gDevTools.showToolbox(target, "jsdebugger");
   panelWin = gToolbox.getPanel("jsdebugger").panelWin;
 
   yield gToolbox.openSplitConsole();
   yield testIsSplitConsoleFocused();
--- a/devtools/client/framework/test/browser_toolbox_view_source_01.js
+++ b/devtools/client/framework/test/browser_toolbox_view_source_01.js
@@ -6,16 +6,22 @@
 /**
  * Tests that Toolbox#viewSourceInDebugger works when debugger is not
  * yet opened.
  */
 
 var URL = `${URL_ROOT}doc_viewsource.html`;
 var JS_URL = `${URL_ROOT}code_math.js`;
 
+// Force the old debugger UI since it's directly used (see Bug 1301705)
+Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
+registerCleanupFunction(function* () {
+  Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
+});
+
 function* viewSource() {
   let toolbox = yield openNewTabAndToolbox(URL);
 
   yield toolbox.viewSourceInDebugger(JS_URL, 2);
 
   let debuggerPanel = toolbox.getPanel("jsdebugger");
   ok(debuggerPanel, "The debugger panel was opened.");
   is(toolbox.currentToolId, "jsdebugger", "The debugger panel was selected.");
--- a/devtools/client/framework/test/browser_toolbox_view_source_02.js
+++ b/devtools/client/framework/test/browser_toolbox_view_source_02.js
@@ -5,16 +5,22 @@
 
 /**
  * Tests that Toolbox#viewSourceInDebugger works when debugger is already loaded.
  */
 
 var URL = `${URL_ROOT}doc_viewsource.html`;
 var JS_URL = `${URL_ROOT}code_math.js`;
 
+// Force the old debugger UI since it's directly used (see Bug 1301705)
+Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
+registerCleanupFunction(function* () {
+  Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
+});
+
 function* viewSource() {
   let toolbox = yield openNewTabAndToolbox(URL);
   let { panelWin: debuggerWin } = yield toolbox.selectTool("jsdebugger");
   let debuggerEvents = debuggerWin.EVENTS;
   let { DebuggerView } = debuggerWin;
   let Sources = DebuggerView.Sources;
 
   yield debuggerWin.once(debuggerEvents.SOURCE_SHOWN);
deleted file mode 100644
--- a/devtools/client/locales/en-US/promisedebugger.properties
+++ /dev/null
@@ -1,11 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-# LOCALIZATION NOTE These strings are used inside the Promise debugger
-# which is available as a panel in the Debugger.
-# The correct localization of this file might be to keep it in
-# English, or another language commonly spoken among web developers.
-# You want to make that choice consistent across the developer tools.
-# A good criteria is the language in which you'd find the best
-# documentation on web development on the web.
--- a/devtools/client/preferences/devtools.js
+++ b/devtools/client/preferences/devtools.js
@@ -87,17 +87,22 @@ pref("devtools.debugger.remote-timeout",
 pref("devtools.debugger.pause-on-exceptions", false);
 pref("devtools.debugger.ignore-caught-exceptions", true);
 pref("devtools.debugger.source-maps-enabled", true);
 pref("devtools.debugger.pretty-print-enabled", true);
 pref("devtools.debugger.auto-pretty-print", false);
 pref("devtools.debugger.auto-black-box", true);
 pref("devtools.debugger.workers", false);
 pref("devtools.debugger.promise", false);
+
+#if defined(NIGHTLY_BUILD)
+pref("devtools.debugger.new-debugger-frontend", true);
+#else
 pref("devtools.debugger.new-debugger-frontend", false);
+#endif
 
 // The default Debugger UI settings
 pref("devtools.debugger.ui.panes-workers-and-sources-width", 200);
 pref("devtools.debugger.ui.panes-instruments-width", 300);
 pref("devtools.debugger.ui.panes-visible-on-startup", false);
 pref("devtools.debugger.ui.variables-sorting-enabled", true);
 pref("devtools.debugger.ui.variables-only-enum-visible", false);
 pref("devtools.debugger.ui.variables-searchbox-visible", false);
--- a/devtools/client/sourceeditor/editor.js
+++ b/devtools/client/sourceeditor/editor.js
@@ -273,17 +273,17 @@ Editor.prototype = {
         win.document.documentElement.setAttribute("force-theme", "light");
       }
 
       Services.scriptloader.loadSubScript(
         "chrome://devtools/content/shared/theme-switching.js",
         win, "utf8"
       );
       this.container = env;
-      this._setup(win.document.body);
+      this._setup(win.document.body, el.ownerDocument);
       env.removeEventListener("load", onLoad, true);
 
       def.resolve();
     };
 
     env.addEventListener("load", onLoad, true);
     env.setAttribute("src", CM_IFRAME);
     el.appendChild(env);
@@ -296,17 +296,18 @@ Editor.prototype = {
     this._setup(el);
   },
 
   /**
    * Do the actual appending and configuring of the CodeMirror instance. This is
    * used by both append functions above, and does all the hard work to
    * configure CodeMirror with all the right options/modes/etc.
    */
-  _setup: function (el) {
+  _setup: function (el, doc) {
+    doc = doc || el.ownerDocument;
     let win = el.ownerDocument.defaultView;
 
     let scriptsToInject = CM_SCRIPTS.concat(this.config.externalScripts);
     scriptsToInject.forEach(url => {
       if (url.startsWith("chrome://")) {
         Services.scriptloader.loadSubScript(url, win, "utf8");
       }
     });
@@ -368,17 +369,17 @@ Editor.prototype = {
       ev.preventDefault();
 
       if (!this.config.contextMenu) {
         return;
       }
 
       let popup = this.config.contextMenu;
       if (typeof popup == "string") {
-        popup = el.ownerDocument.getElementById(this.config.contextMenu);
+        popup = doc.getElementById(this.config.contextMenu);
       }
 
       this.emit("popupOpen", ev, popup);
       popup.openPopupAtScreen(ev.screenX, ev.screenY, true);
     }, false);
 
     // Intercept the find and find again keystroke on CodeMirror, to avoid
     // the browser's search
--- a/devtools/client/themes/images/tool-profiler-active.svg
+++ b/devtools/client/themes/images/tool-profiler-active.svg
@@ -1,10 +1,9 @@
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="#5FC749">
-  <path d="M6.9 7.8c-.3.1-.6.4-.6.7-.1.5.2 1 .7 1.1.3 0 .7-.1.9-.3l2.5-2.9-3.5 1.4z"/>
-  <path opacity="0.5" d="M4.7 10.6c.7 1.1 1.9 1.9 3.3 1.9s2.6-.8 3.3-1.9H4.7z"/>
-  <path d="M-12.7-2.5c-3.8 0-6.7 3-6.7 6.7s3 6.7 6.7 6.7c3.8 0 6.7-3 6.7-6.7s-2.9-6.7-6.7-6.7zM-12.8 9c-2.5 0-4.6-2.1-4.8-4.5v-.2h.6c.6 0 1-.4 1-1s-.4-1-1-1h-.4c.4-.9.8-1.4 1.5-1.9l.2.4c.3.5.8.7 1.3.4.5-.2.7-.7.4-1.2l-.2-.4c.4-.1.9-.2 1.4-.2.6 0 1.1.1 1.6.3l-.2.4c-.3.5-.1 1 .4 1.3.5.3 1 .1 1.3-.4l.2-.6c.6.6 1.2 1.5 1.4 1.8h-.4c-.6 0-1 .4-1 1s.4 1 1 1h.6v.2C-8.2 6.9-10.3 9-12.8 9zM-12.8 12.7c-3.4 0-6.2 2.7-6.2 6.2s2.7 6.3 6.3 6.3c3.5 0 6.3-2.7 6.3-6.3-.1-3.4-2.9-6.2-6.4-6.2zm0 11.4c-2.9 0-5.2-2.3-5.2-5.2 0-2.9 2.3-5.2 5.2-5.2s5.2 2.3 5.2 5.2c0 3-2.2 5.2-5.2 5.2z"/>
-  <path d="M-14.5 16.3c-.2 0-.4.2-.4.4v4.5c0 .2.3.4.5.4s.5-.2.5-.4v-4.5c0-.2-.3-.4-.5-.4"/>
-  <path d="M8 2.3C4.5 2.3 1.8 5 1.8 8.5s2.7 6.3 6.3 6.3c3.5 0 6.3-2.7 6.3-6.3-.2-3.4-2.9-6.2-6.4-6.2zm0 11.4c-2.9 0-5.2-2.3-5.2-5.2v-.3h1.7c.2 0 .4-.3.4-.5s-.2-.6-.4-.6H2.9C3.3 5.9 4 4.8 5 4.1l1.4 1.3c.1.1.5.1.6-.1.1-.1.2-.5.1-.6L6 3.6c.6-.2 1.3-.4 2-.4.8 0 1.5.2 2.2.5L9 4.8c-.1.1 0 .5.1.6s.5.2.6.1L11 4.3c1 .7 1.7 1.7 2 2.8h-1.7c-.2 0-.4.3-.4.5s.2.5.4.5h1.9v.3c0 3.1-2.2 5.3-5.2 5.3z"/>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="#5FC749" fill-rule="evenodd">
+  <path d="M15 9.004C14.51 12.394 11.578 15 8.035 15 4.15 15 1 11.866 1 8s3.15-7 7.036-7c1.941 0 3.7.783 4.972 2.048l-.709.709A6.027 6.027 0 0 0 8.036 2c-3.33 0-6.03 2.686-6.03 6s2.7 6 6.03 6a6.023 6.023 0 0 0 5.946-4.993l1.017-.003z"/>
+  <path d="M4.137 9H3.1a5.002 5.002 0 0 0 9.8 0h-.965a4.023 4.023 0 0 1-3.9 3 4.023 4.023 0 0 1-3.898-3z" fill-opacity=".5"/>
+  <path d="M8.036 11a2.994 2.994 0 0 0 2.987-3c0-1.657-1.338-3-2.987-3a2.994 2.994 0 0 0-2.988 3c0 1.657 1.338 3 2.988 3zm0-1c1.11 0 2.011-.895 2.011-2s-.9-2-2.011-2c-1.111 0-2.012.895-2.012 2s.9 2 2.012 2z"/>
+  <path d="M10.354 6.354l4-4a.5.5 0 0 0-.708-.708l-4 4a.5.5 0 1 0 .708.708z"/>
 </svg>
--- a/devtools/client/themes/webconsole.css
+++ b/devtools/client/themes/webconsole.css
@@ -107,16 +107,22 @@ a {
 .message-repeats[value="1"] {
   display: none;
 }
 
 .message-location {
   max-width: 40%;
 }
 
+.stack-trace {
+  /* The markup contains extra whitespace to improve formatting of clipboard text.
+     Make sure this whitespace doesn't affect the HTML rendering */
+  white-space: normal;
+}
+
 .stack-trace .frame-link-source,
 .message-location .frame-link-source {
   /* Makes the file name truncated (and ellipsis shown) on the left side */
   direction: rtl;
   white-space: nowrap;
   overflow: hidden;
   text-overflow: ellipsis;
 }
--- a/devtools/client/webconsole/test/browser_console_optimized_out_vars.js
+++ b/devtools/client/webconsole/test/browser_console_optimized_out_vars.js
@@ -3,16 +3,22 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Check that inspecting an optimized out variable works when execution is
 // paused.
 
 "use strict";
 
+// Force the old debugger UI since it's directly used (see Bug 1301705)
+Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
+registerCleanupFunction(function* () {
+  Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
+});
+
 function test() {
   Task.spawn(function* () {
     const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
                      "test/test-closure-optimized-out.html";
     let {tab} = yield loadTab(TEST_URI);
     let hud = yield openConsole(tab);
     let { toolbox, panel, panelWin } = yield openDebugger();
 
--- a/devtools/client/webconsole/test/browser_console_variables_view_while_debugging.js
+++ b/devtools/client/webconsole/test/browser_console_variables_view_while_debugging.js
@@ -7,28 +7,36 @@
 // from the js debugger, when changing the value of a property in the variables
 // view.
 
 "use strict";
 
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
                  "test/test-eval-in-stackframe.html";
 
+// Force the old debugger UI since it's directly used (see Bug 1301705)
+Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
+registerCleanupFunction(function* () {
+  Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
+});
+
 add_task(function* () {
   yield loadTab(TEST_URI);
   let hud = yield openConsole();
 
   let dbgPanel = yield openDebugger();
-  yield waitForFrameAdded(dbgPanel);
+  yield waitForFrameAdded();
   yield openConsole();
   yield testVariablesView(hud);
 });
 
-function* waitForFrameAdded(dbgPanel) {
-  let thread = dbgPanel.panelWin.DebuggerController.activeThread;
+function* waitForFrameAdded() {
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+  let toolbox = gDevTools.getToolbox(target);
+  let thread = toolbox.threadClient;
 
   info("Waiting for framesadded");
   yield new Promise(resolve => {
     thread.addOneTimeListener("framesadded", resolve);
     ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
       content.wrappedJSObject.firstCall();
     });
   });
--- a/devtools/client/webconsole/test/browser_console_variables_view_while_debugging_and_inspecting.js
+++ b/devtools/client/webconsole/test/browser_console_variables_view_while_debugging_and_inspecting.js
@@ -6,30 +6,38 @@
 // Test that makes sure web console eval works while the js debugger paused the
 // page, and while the inspector is active. See bug 886137.
 
 "use strict";
 
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
                  "test/test-eval-in-stackframe.html";
 
+// Force the old debugger UI since it's directly used (see Bug 1301705)
+Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
+registerCleanupFunction(function* () {
+  Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
+});
+
 add_task(function* () {
   yield loadTab(TEST_URI);
   let hud = yield openConsole();
 
   let dbgPanel = yield openDebugger();
   yield openInspector();
-  yield waitForFrameAdded(dbgPanel);
+  yield waitForFrameAdded();
 
   yield openConsole();
   yield testVariablesView(hud);
 });
 
-function* waitForFrameAdded(dbgPanel) {
-  let thread = dbgPanel.panelWin.DebuggerController.activeThread;
+function* waitForFrameAdded() {
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+  let toolbox = gDevTools.getToolbox(target);
+  let thread = toolbox.threadClient;
 
   info("Waiting for framesadded");
   yield new Promise(resolve => {
     thread.addOneTimeListener("framesadded", resolve);
     ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
       content.wrappedJSObject.firstCall();
     });
   });
--- a/devtools/client/webconsole/test/browser_eval_in_debugger_stackframe.js
+++ b/devtools/client/webconsole/test/browser_eval_in_debugger_stackframe.js
@@ -9,16 +9,22 @@
 "use strict";
 
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
                  "test/test-eval-in-stackframe.html";
 
 var gWebConsole, gJSTerm, gDebuggerWin, gThread, gDebuggerController;
 var gStackframes;
 
+// Force the old debugger UI since it's directly used (see Bug 1301705)
+Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
+registerCleanupFunction(function* () {
+  Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
+});
+
 function test() {
   loadTab(TEST_URI).then(() => {
     openConsole().then(consoleOpened);
   });
 }
 
 function consoleOpened(hud) {
   gWebConsole = hud;
--- a/devtools/client/webconsole/test/browser_eval_in_debugger_stackframe2.js
+++ b/devtools/client/webconsole/test/browser_eval_in_debugger_stackframe2.js
@@ -6,16 +6,23 @@
 // Test to make sure that web console commands can fire while paused at a
 // breakpoint that was triggered from a JS call.  Relies on asynchronous js
 // evaluation over the protocol - see Bug 1088861.
 
 "use strict";
 
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
                  "test/test-eval-in-stackframe.html";
+
+// Force the old debugger UI since it's directly used (see Bug 1301705)
+Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
+registerCleanupFunction(function* () {
+  Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
+});
+
 add_task(function* () {
   yield loadTab(TEST_URI);
 
   info("open the web console");
   let hud = yield openConsole();
   let {jsterm} = hud;
 
   info("open the debugger");
--- a/devtools/client/webconsole/test/browser_webconsole_autocomplete_in_debugger_stackframe.js
+++ b/devtools/client/webconsole/test/browser_webconsole_autocomplete_in_debugger_stackframe.js
@@ -6,16 +6,22 @@
 // Test that makes sure web console autocomplete happens in the user-selected
 // stackframe from the js debugger.
 
 "use strict";
 
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
                  "test/test-autocomplete-in-stackframe.html";
 
+// Force the old debugger UI since it's directly used (see Bug 1301705)
+Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
+registerCleanupFunction(function* () {
+  Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
+});
+
 var gStackframes;
 registerCleanupFunction(function () {
   gStackframes = null;
 });
 
 requestLongerTimeout(2);
 add_task(function* () {
   yield loadTab(TEST_URI);
--- a/devtools/client/webconsole/test/browser_webconsole_bug_1050691_click_function_to_source.js
+++ b/devtools/client/webconsole/test/browser_webconsole_bug_1050691_click_function_to_source.js
@@ -5,16 +5,22 @@
 
 // Tests that clicking on a function displays its source in the debugger.
 
 "use strict";
 
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
                  "test/test-bug_1050691_click_function_to_source.html";
 
+// Force the old debugger UI since it's directly used (see Bug 1301705)
+Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
+registerCleanupFunction(function* () {
+  Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
+});
+
 add_task(function* () {
   yield loadTab(TEST_URI);
   let hud = yield openConsole();
 
   // Open the Debugger panel.
   let debuggerPanel = yield openDebugger();
   // And right after come back to the Console panel.
   yield openConsole();
--- a/devtools/client/webconsole/test/browser_webconsole_bug_766001_JS_Console_in_Debugger.js
+++ b/devtools/client/webconsole/test/browser_webconsole_bug_766001_JS_Console_in_Debugger.js
@@ -6,16 +6,22 @@
 // Test that message source links for js errors and console API calls open in
 // the jsdebugger when clicked.
 
 "use strict";
 
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/test" +
                  "/test-bug-766001-js-console-links.html";
 
+// Force the old debugger UI since it's directly used (see Bug 1301705)
+Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
+registerCleanupFunction(function* () {
+  Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
+});
+
 function test() {
   let hud;
 
   requestLongerTimeout(2);
   Task.spawn(runner).then(finishTest);
 
   function* runner() {
     // On e10s, the exception is triggered in child process
--- a/devtools/client/webconsole/test/browser_webconsole_closure_inspection.js
+++ b/devtools/client/webconsole/test/browser_webconsole_closure_inspection.js
@@ -8,16 +8,22 @@
 
 "use strict";
 
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
                  "test/test-closures.html";
 
 var gWebConsole, gJSTerm, gVariablesView;
 
+// Force the old debugger UI since it's directly used (see Bug 1301705)
+Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
+registerCleanupFunction(function* () {
+  Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
+});
+
 function test() {
   registerCleanupFunction(() => {
     gWebConsole = gJSTerm = gVariablesView = null;
   });
 
   function fetchScopes(hud, toolbox, panelWin, deferred) {
     panelWin.once(panelWin.EVENTS.FETCHED_SCOPES, () => {
       ok(true, "Scopes were fetched");
--- a/devtools/client/webconsole/test/browser_webconsole_input_field_focus_on_panel_select.js
+++ b/devtools/client/webconsole/test/browser_webconsole_input_field_focus_on_panel_select.js
@@ -21,14 +21,14 @@ add_task(function* () {
   hud.ui.filterBox.focus();
 
   is(hud.ui.filterBox.hasAttribute("focused"), true,
      "filterBox should be focused");
 
   is(hud.jsterm.inputNode.hasAttribute("focused"), false,
      "inputNode shouldn't be focused");
 
-  yield openDebugger();
+  yield openInspector();
   hud = yield openConsole();
 
   is(hud.jsterm.inputNode.hasAttribute("focused"), true,
      "inputNode should be focused");
 });
--- a/devtools/client/webconsole/test/browser_webconsole_output_05.js
+++ b/devtools/client/webconsole/test/browser_webconsole_output_05.js
@@ -140,20 +140,21 @@ var inputTests = [
     variablesViewLabel: "Promise"
   },
 
   // 14
   {
     input: "new Object({1: 'this\\nis\\nsupposed\\nto\\nbe\\na\\nvery" +
            "\\nlong\\nstring\\n,shown\\non\\na\\nsingle\\nline', " +
            "2: 'a shorter string', 3: 100})",
-    output: 'Object { 1: "this is supposed to be a very long ' + ELLIPSIS +
-            '", 2: "a shorter string", 3: 100 }',
+    output: '[ <1 empty slot>, "this is supposed to be a very long ' + ELLIPSIS +
+            '", "a shorter string", 100 ]',
     printOutput: "[object Object]",
-    inspectable: false,
+    inspectable: true,
+    variablesViewLabel: "Object[4]"
   },
 
   // 15
   {
     input: "new Proxy({a:1},[1,2,3])",
     output: 'Proxy { <target>: Object, <handler>: Array[3] }',
     printOutput: "[object Object]",
     inspectable: true,
--- a/devtools/client/webconsole/test/browser_webconsole_output_06.js
+++ b/devtools/client/webconsole/test/browser_webconsole_output_06.js
@@ -126,20 +126,20 @@ var inputTests = [
     printOutput: "[object Object]",
     inspectable: true,
     variablesViewLabel: "Object[2]",
   },
 
   // 14
   {
     input: '({0: "a", 42: "b"})',
-    output: 'Object { 0: "a", 42: "b" }',
+    output: '[ "a", <9 empty slots>, 33 more\u2026 ]',
     printOutput: "[object Object]",
     inspectable: true,
-    variablesViewLabel: "Object",
+    variablesViewLabel: "Object[43]",
   },
 
   // 15
   {
     input: '({0: "a", 1: "b", 2: "c", 3: "d", 4: "e", 5: "f", 6: "g", ' +
            '7: "h", 8: "i", 9: "j", 10: "k", 11: "l"})',
     output: 'Object [ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", ' +
             "2 more\u2026 ]",
@@ -184,20 +184,20 @@ var inputTests = [
     printOutput: "[object Object]",
     inspectable: true,
     variablesViewLabel: "Object[0]",
   },
 
   // 20
   {
     input: '({length: 1})',
-    output: 'Object { length: 1 }',
+    output: '[ <1 empty slot> ]',
     printOutput: "[object Object]",
     inspectable: true,
-    variablesViewLabel: "Object",
+    variablesViewLabel: "Object[1]",
   },
 
   // 21
   {
     input: '({0: "a", 1: "b", length: 1})',
     output: 'Object { 1: "b", length: 1, 1 more\u2026 }',
     printOutput: "[object Object]",
     inspectable: true,
@@ -211,38 +211,38 @@ var inputTests = [
     printOutput: "[object Object]",
     inspectable: true,
     variablesViewLabel: "Object[2]",
   },
 
   // 23
   {
     input: '({0: "a", 1: "b", length: 3})',
-    output: 'Object { length: 3, 2 more\u2026 }',
+    output: '[ "a", "b", <1 empty slot> ]',
     printOutput: "[object Object]",
     inspectable: true,
-    variablesViewLabel: "Object",
+    variablesViewLabel: "Object[3]",
   },
 
   // 24
   {
     input: '({0: "a", 2: "b", length: 2})',
     output: 'Object { 2: "b", length: 2, 1 more\u2026 }',
     printOutput: "[object Object]",
     inspectable: true,
     variablesViewLabel: "Object",
   },
 
   // 25
   {
     input: '({0: "a", 2: "b", length: 3})',
-    output: 'Object { length: 3, 2 more\u2026 }',
+    output: '[ "a", <1 empty slot>, "b" ]',
     printOutput: "[object Object]",
     inspectable: true,
-    variablesViewLabel: "Object",
+    variablesViewLabel: "Object[3]",
   },
 
   // 26
   {
     input: '({0: "a", b: "b", length: 1})',
     output: 'Object { b: "b", length: 1, 1 more\u2026 }',
     printOutput: "[object Object]",
     inspectable: true,
@@ -252,16 +252,25 @@ var inputTests = [
   // 27
   {
     input: '({0: "a", b: "b", length: 2})',
     output: 'Object { b: "b", length: 2, 1 more\u2026 }',
     printOutput: "[object Object]",
     inspectable: true,
     variablesViewLabel: "Object",
   },
+
+  // 28
+  {
+    input: '({42: "a"})',
+    output: 'Object { 42: "a" }',
+    printOutput: "[object Object]",
+    inspectable: true,
+    variablesViewLabel: "Object",
+  },
 ];
 
 function test() {
   requestLongerTimeout(2);
   Task.spawn(function* () {
     let {tab} = yield loadTab(TEST_URI);
     let hud = yield openConsole(tab);
     return checkOutputForInputs(hud, inputTests);
--- a/devtools/client/webconsole/test/browser_webconsole_view_source.js
+++ b/devtools/client/webconsole/test/browser_webconsole_view_source.js
@@ -8,16 +8,22 @@
 // have their locations opened in Debugger, we need to test a security message in
 // order to have it opened in the standard View Source window.
 
 "use strict";
 
 const TEST_URI = "https://example.com/browser/devtools/client/webconsole/" +
                  "test/test-mixedcontent-securityerrors.html";
 
+// Force the old debugger UI since it's directly used (see Bug 1301705)
+Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
+registerCleanupFunction(function* () {
+  Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
+});
+
 add_task(function* () {
   yield loadTab(TEST_URI);
   let hud = yield openConsole(null);
   info("console opened");
 
   let [result] = yield waitForMessages({
     webconsole: hud,
     messages: [{
--- a/devtools/server/actors/object.js
+++ b/devtools/server/actors/object.js
@@ -1788,65 +1788,76 @@ DebuggerServer.ObjectActorPreviewers.Obj
       lineNumber: hooks.createValueGrip(rawObj.lineNumber),
       columnNumber: hooks.createValueGrip(rawObj.columnNumber),
     };
 
     return true;
   },
 
   function PseudoArray({obj, hooks}, grip, rawObj) {
-    let length = 0;
+    let length;
 
     let keys = obj.getOwnPropertyNames();
     if (keys.length == 0) {
       return false;
     }
 
-    // Pseudo-arrays should only have array indices and, optionally, a "length" property.
-    // Since array indices are sorted first, check if the last property is "length".
-    if(keys[keys.length-1] === "length") {
-      keys.pop();
-      // The value of "length" should equal the number of other properties. If eventually
-      // we allow sparse pseudo-arrays, we should check whether it's a Uint32 instead.
-      if(rawObj.length !== keys.length) {
-        return false;
-      }
+    // If no item is going to be displayed in preview, better display as sparse object.
+    // The first key should contain the smallest integer index (if any).
+    if(keys[0] >= OBJECT_PREVIEW_MAX_ITEMS) {
+      return false;
     }
 
-    // Ensure that the keys are consecutive integers starting at "0". If eventually we
-    // allow sparse pseudo-arrays, we should check that they are array indices, that is:
-    // `(key >>> 0) + '' === key && key !== "4294967295"`.
-    // Checking the last property first allows us to avoid useless iterations when
-    // there is any property which is not an array index.
-    if(keys.length && keys[keys.length-1] !== keys.length - 1 + '') {
+    // Pseudo-arrays should only have array indices and, optionally, a "length" property.
+    // Since integer indices are sorted first, check if the last property is "length".
+    if(keys[keys.length-1] === "length") {
+      keys.pop();
+      length = DevToolsUtils.getProperty(obj, "length");
+    } else {
+      // Otherwise, let length be the (presumably) greatest array index plus 1.
+      length = +keys[keys.length-1] + 1;
+    }
+    // Check if length is a valid array length, i.e. is a Uint32 number.
+    if(typeof length !== "number" || length >>> 0 !== length) {
       return false;
     }
-    for (let key of keys) {
-      if (key !== (length++) + '') {
+
+    // Ensure all keys are increasing array indices smaller than length. The order is not
+    // guaranteed for exotic objects but, in most cases, big array indices and properties
+    // which are not integer indices should be at the end. Then, iterating backwards
+    // allows us to return earlier when the object is not completely a pseudo-array.
+    let prev = length;
+    for(let i = keys.length - 1; i >= 0; --i) {
+      let key = keys[i];
+      let numKey = key >>> 0; // ToUint32(key)
+      if (numKey + '' !== key || numKey >= prev) {
         return false;
       }
+      prev = numKey;
     }
 
     grip.preview = {
       kind: "ArrayLike",
       length: length,
     };
 
     // Avoid recursive object grips.
     if (hooks.getGripDepth() > 1) {
       return true;
     }
 
     let items = grip.preview.items = [];
+    let numItems = Math.min(OBJECT_PREVIEW_MAX_ITEMS, length);
 
-    let i = 0;
-    for (let key of keys) {
-      if (rawObj.hasOwnProperty(key) && i++ < OBJECT_PREVIEW_MAX_ITEMS) {
-        let value = makeDebuggeeValueIfNeeded(obj, rawObj[key]);
-        items.push(hooks.createValueGrip(value));
+    for (let i = 0; i < numItems; ++i) {
+      let desc = obj.getOwnPropertyDescriptor(i);
+      if (desc && 'value' in desc) {
+        items.push(hooks.createValueGrip(desc.value));
+      } else {
+        items.push(null);
       }
     }
 
     return true;
   },
 
   GenericObject,
 ];
--- a/dom/media/test/test_trackelementevent.html
+++ b/dom/media/test/test_trackelementevent.html
@@ -27,31 +27,39 @@ SpecialPowers.pushPrefEnv({"set": [["med
     trackTwo.src = "bad-signature.vtt";
     trackTwo.kind = "captions";
 
     var trackThree = document.createElement("track");
     trackThree.src = "bad.vtt";
     trackThree.kind = "chapters";
 
     var events = 0;
-    function countEvent() {
-      ok(true, "A load or error event should have happened.");
+    function trackOneEvent() {
+      ok(true, "A load event for trackOne should have happened.");
+      events++ && events == 3 && SimpleTest.finish();
+    }
+    function trackTwoEvent() {
+      ok(true, "An error event for trackTwo should have happened.");
+      events++ && events == 3 && SimpleTest.finish();
+    }
+    function trackThreeEvent() {
+      ok(true, "An error event for trackThree should have happened.");
       events++ && events == 3 && SimpleTest.finish();
     }
 
     function shouldNotBeCalled() {
       ok(false, "Event should not have been called.");
     }
 
-    trackOne.addEventListener("load", countEvent);
+    trackOne.addEventListener("load", trackOneEvent);
     trackOne.addEventListener("error", shouldNotBeCalled)
     trackTwo.addEventListener("load", shouldNotBeCalled);
-    trackTwo.addEventListener("error", countEvent);
+    trackTwo.addEventListener("error", trackTwoEvent);
     trackThree.addEventListener("load", shouldNotBeCalled);
-    trackThree.addEventListener("error", countEvent);
+    trackThree.addEventListener("error", trackThreeEvent);
 
     document.getElementById("content").appendChild(video);
     video.appendChild(trackOne);
     video.appendChild(trackTwo);
     video.appendChild(trackThree);
   }
 );
 </script>