diff --git a/devtools/client/application/test/browser.ini b/devtools/client/application/test/browser.ini index aae729fbf96d..f5e5f31e7fc5 100644 --- a/devtools/client/application/test/browser.ini +++ b/devtools/client/application/test/browser.ini @@ -12,7 +12,6 @@ support-files = service-workers/simple.html service-workers/simple-unicode.html !/devtools/client/debugger/new/test/mochitest/helpers.js - !/devtools/client/debugger/new/test/mochitest/helpers/context.js !/devtools/client/shared/test/frame-script-utils.js !/devtools/client/shared/test/shared-head.js !/devtools/client/shared/test/telemetry-test-helpers.js diff --git a/devtools/client/application/test/browser_application_panel_debug-service-worker.js b/devtools/client/application/test/browser_application_panel_debug-service-worker.js index d73e25bfc417..6283b62a133b 100644 --- a/devtools/client/application/test/browser_application_panel_debug-service-worker.js +++ b/devtools/client/application/test/browser_application_panel_debug-service-worker.js @@ -8,11 +8,6 @@ Services.scriptloader.loadSubScript( "chrome://mochitests/content/browser/devtools/client/debugger/new/test/mochitest/helpers.js", this); -/* import-globals-from ../../debugger/new/test/mochitest/helpers/context.js */ -Services.scriptloader.loadSubScript( - "chrome://mochitests/content/browser/devtools/client/debugger/new/test/mochitest/helpers/context.js", - this); - const TAB_URL = URL_ROOT + "service-workers/debug.html"; add_task(async function() { diff --git a/devtools/client/canvasdebugger/test/browser.ini b/devtools/client/canvasdebugger/test/browser.ini index 7149df2e2088..7139680c29a0 100644 --- a/devtools/client/canvasdebugger/test/browser.ini +++ b/devtools/client/canvasdebugger/test/browser.ini @@ -17,7 +17,6 @@ support-files = head.js !/devtools/client/shared/test/frame-script-utils.js !/devtools/client/shared/test/shared-head.js - !/devtools/client/debugger/new/test/mochitest/helpers/context.js !/devtools/client/shared/test/telemetry-test-helpers.js [browser_canvas-actor-test-01.js] diff --git a/devtools/client/canvasdebugger/test/browser_canvas-frontend-call-stack-01.js b/devtools/client/canvasdebugger/test/browser_canvas-frontend-call-stack-01.js index 880e4887ede6..eac69542e0e4 100644 --- a/devtools/client/canvasdebugger/test/browser_canvas-frontend-call-stack-01.js +++ b/devtools/client/canvasdebugger/test/browser_canvas-frontend-call-stack-01.js @@ -5,7 +5,11 @@ * Tests if the a function call's stack is properly displayed in the UI. */ -requestLongerTimeout(2); +// 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"); +}); async function ifTestingSupported() { const { target, panel } = await initCanvasDebuggerFrontend(SIMPLE_CANVAS_DEEP_STACK_URL); @@ -66,8 +70,12 @@ async function ifTestingSupported() { await jumpedToSource; const toolbox = await gDevTools.getToolbox(target); - const dbg = createDebuggerContext(toolbox); - await validateDebuggerLocation(dbg, SIMPLE_CANVAS_DEEP_STACK_URL, 26); + const { panelWin: { DebuggerView: view } } = toolbox.getPanel("jsdebugger"); + + is(view.Sources.selectedValue, getSourceActor(view.Sources, SIMPLE_CANVAS_DEEP_STACK_URL), + "The expected source was shown in the debugger."); + is(view.editor.getCursor().line, 25, + "The expected source line is highlighted in the debugger."); await teardown(panel); finish(); diff --git a/devtools/client/canvasdebugger/test/browser_canvas-frontend-call-stack-02.js b/devtools/client/canvasdebugger/test/browser_canvas-frontend-call-stack-02.js index 4434eb125c99..5314d8da146e 100644 --- a/devtools/client/canvasdebugger/test/browser_canvas-frontend-call-stack-02.js +++ b/devtools/client/canvasdebugger/test/browser_canvas-frontend-call-stack-02.js @@ -6,7 +6,11 @@ * and jumping to source in the debugger for the topmost call item works. */ -requestLongerTimeout(2); +// 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"); +}); async function ifTestingSupported() { const { target, panel } = await initCanvasDebuggerFrontend(SIMPLE_CANVAS_DEEP_STACK_URL); @@ -41,8 +45,12 @@ async function ifTestingSupported() { await jumpedToSource; const toolbox = await gDevTools.getToolbox(target); - const dbg = createDebuggerContext(toolbox); - await validateDebuggerLocation(dbg, SIMPLE_CANVAS_DEEP_STACK_URL, 24); + const { panelWin: { DebuggerView: view } } = toolbox.getPanel("jsdebugger"); + + is(view.Sources.selectedValue, getSourceActor(view.Sources, SIMPLE_CANVAS_DEEP_STACK_URL), + "The expected source was shown in the debugger."); + is(view.editor.getCursor().line, 23, + "The expected source line is highlighted in the debugger."); await teardown(panel); finish(); diff --git a/devtools/client/canvasdebugger/test/head.js b/devtools/client/canvasdebugger/test/head.js index 15e50578a6b7..5dcc536abd40 100644 --- a/devtools/client/canvasdebugger/test/head.js +++ b/devtools/client/canvasdebugger/test/head.js @@ -3,7 +3,6 @@ /* eslint no-unused-vars: [2, {"vars": "local"}] */ /* import-globals-from ../../shared/test/shared-head.js */ -/* import-globals-from ../../debugger/new/test/mochitest/helpers/context.js */ "use strict"; @@ -12,11 +11,6 @@ Services.scriptloader.loadSubScript( "chrome://mochitests/content/browser/devtools/client/shared/test/shared-head.js", this); -// Import helpers for the new debugger -Services.scriptloader.loadSubScript( - "chrome://mochitests/content/browser/devtools/client/debugger/new/test/mochitest/helpers/context.js", - this); - var { generateUUID } = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator); var { DebuggerClient } = require("devtools/shared/client/debugger-client"); @@ -179,13 +173,3 @@ function getSourceActor(aSources, aURL) { const item = aSources.getItemForAttachment(a => a.source.url === aURL); return item ? item.value : null; } - -async function validateDebuggerLocation(dbg, url, line) { - const location = dbg.selectors.getSelectedLocation(dbg.getState()); - const sourceUrl = dbg.selectors.getSelectedSource(dbg.getState()).url; - - is(sourceUrl, url, - "The expected source was shown in the debugger."); - is(location.line, line, - "The expected source line is highlighted in the debugger."); -} diff --git a/devtools/client/debugger/new/test/mochitest/browser.ini b/devtools/client/debugger/new/test/mochitest/browser.ini index be0270051f77..9e1cb2b39948 100644 --- a/devtools/client/debugger/new/test/mochitest/browser.ini +++ b/devtools/client/debugger/new/test/mochitest/browser.ini @@ -5,7 +5,6 @@ skip-if = (os == 'linux' && debug && bits == 32) support-files = head.js helpers.js - helpers/context.js !/devtools/client/shared/test/shared-head.js !/devtools/client/shared/test/telemetry-test-helpers.js ## START-SOURCEMAPPED-FIXTURES - Generated by examples/sourcemapped/build.js diff --git a/devtools/client/debugger/new/test/mochitest/helpers.js b/devtools/client/debugger/new/test/mochitest/helpers.js index a958baf0e21b..abfbda51ae30 100644 --- a/devtools/client/debugger/new/test/mochitest/helpers.js +++ b/devtools/client/debugger/new/test/mochitest/helpers.js @@ -6,11 +6,6 @@ * required from other panel test files. */ -// Import helpers for the new debugger -Services.scriptloader.loadSubScript( - "chrome://mochitests/content/browser/devtools/client/debugger/new/test/mochitest/helpers/context.js", - this); - var { Toolbox } = require("devtools/client/framework/toolbox"); var { Task } = require("devtools/shared/task"); var asyncStorage = require("devtools/shared/async-storage"); @@ -467,6 +462,23 @@ function isSelectedFrameSelected(dbg, state) { return source.id == sourceId; } +function createDebuggerContext(toolbox) { + const panel = toolbox.getPanel("jsdebugger"); + const win = panel.panelWin; + const { store, client, selectors, actions } = panel.getVarsForTests(); + + return { + actions: actions, + selectors: selectors, + getState: store.getState, + store: store, + client: client, + toolbox: toolbox, + win: win, + panel: panel + }; +} + /** * Clear all the debugger related preferences. */ diff --git a/devtools/client/debugger/new/test/mochitest/helpers/context.js b/devtools/client/debugger/new/test/mochitest/helpers/context.js deleted file mode 100644 index d8af581c47f2..000000000000 --- a/devtools/client/debugger/new/test/mochitest/helpers/context.js +++ /dev/null @@ -1,23 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -/** - * Helper method to create a "dbg" context for other tools to use - */ - -function createDebuggerContext(toolbox) { - const panel = toolbox.getPanel("jsdebugger"); - const win = panel.panelWin; - const { store, client, selectors, actions } = panel.getVarsForTests(); - - return { - actions: actions, - selectors: selectors, - getState: store.getState, - store: store, - client: client, - toolbox: toolbox, - win: win, - panel: panel - }; -} \ No newline at end of file diff --git a/devtools/client/framework/attach-thread.js b/devtools/client/framework/attach-thread.js index 2388d83d2ce0..ae9bdba673e0 100644 --- a/devtools/client/framework/attach-thread.js +++ b/devtools/client/framework/attach-thread.js @@ -42,9 +42,16 @@ function attachThread(toolbox) { // Sourcemaps are always turned off when using the new debugger // frontend. This is because it does sourcemapping on the // client-side, so the server should not do it. - const useSourceMaps = false; - const autoBlackBox = false; - const ignoreFrameEnvironment = true; + let useSourceMaps = false; + let autoBlackBox = false; + let ignoreFrameEnvironment = false; + const newDebuggerEnabled = Services.prefs.getBoolPref("devtools.debugger.new-debugger-frontend"); + if (!newDebuggerEnabled) { + useSourceMaps = Services.prefs.getBoolPref("devtools.debugger.source-maps-enabled"); + autoBlackBox = Services.prefs.getBoolPref("devtools.debugger.auto-black-box"); + } else { + ignoreFrameEnvironment = true; + } const threadOptions = { useSourceMaps, autoBlackBox, ignoreFrameEnvironment }; diff --git a/devtools/client/framework/test/browser_keybindings_01.js b/devtools/client/framework/test/browser_keybindings_01.js index d26a73635dd8..dce005e1769a 100644 --- a/devtools/client/framework/test/browser_keybindings_01.js +++ b/devtools/client/framework/test/browser_keybindings_01.js @@ -51,6 +51,12 @@ function setupKeyBindingsTest() { } add_task(async function() { + // Use the new debugger frontend because the old one swallows the netmonitor shortcut: + // https://bugzilla.mozilla.org/show_bug.cgi?id=1370442#c7 + await SpecialPowers.pushPrefEnv({set: [ + ["devtools.debugger.new-debugger-frontend", true] + ]}); + await addTab(TEST_URL); await new Promise(done => waitForFocus(done)); diff --git a/devtools/client/framework/test/browser_source_map-01.js b/devtools/client/framework/test/browser_source_map-01.js index 662db85300fb..a18960841318 100644 --- a/devtools/client/framework/test/browser_source_map-01.js +++ b/devtools/client/framework/test/browser_source_map-01.js @@ -21,6 +21,8 @@ const JS_URL = `${URL_ROOT}code_binary_search.js`; const COFFEE_URL = `${URL_ROOT}code_binary_search.coffee`; add_task(async function() { + await pushPref("devtools.debugger.new-debugger-frontend", true); + const toolbox = await openNewTabAndToolbox(PAGE_URL, "jsdebugger"); const service = toolbox.sourceMapURLService; diff --git a/devtools/client/framework/test/browser_source_map-absolute.js b/devtools/client/framework/test/browser_source_map-absolute.js index 7b4ccbed459b..02d7cbbabbfb 100644 --- a/devtools/client/framework/test/browser_source_map-absolute.js +++ b/devtools/client/framework/test/browser_source_map-absolute.js @@ -16,6 +16,8 @@ const JS_URL = `${URL_ROOT}code_binary_search_absolute.js`; const ORIGINAL_URL = `${URL_ROOT}code_binary_search.coffee`; add_task(async function() { + await pushPref("devtools.debugger.new-debugger-frontend", true); + const toolbox = await openNewTabAndToolbox(PAGE_URL, "jsdebugger"); const service = toolbox.sourceMapURLService; diff --git a/devtools/client/framework/test/browser_source_map-inline.js b/devtools/client/framework/test/browser_source_map-inline.js index 3e81eb2d0921..1cdb9b6b31ad 100644 --- a/devtools/client/framework/test/browser_source_map-inline.js +++ b/devtools/client/framework/test/browser_source_map-inline.js @@ -18,6 +18,8 @@ const JS_URL = `${TEST_ROOT}code_inline_bundle.js`; const ORIGINAL_URL = "webpack:///code_inline_original.js"; add_task(async function() { + await pushPref("devtools.debugger.new-debugger-frontend", true); + const toolbox = await openNewTabAndToolbox(PAGE_URL, "jsdebugger"); const service = toolbox.sourceMapURLService; diff --git a/devtools/client/framework/test/browser_source_map-reload.js b/devtools/client/framework/test/browser_source_map-reload.js index a396ce6cf727..f6197fc0ce7d 100644 --- a/devtools/client/framework/test/browser_source_map-reload.js +++ b/devtools/client/framework/test/browser_source_map-reload.js @@ -16,6 +16,8 @@ const GENERATED_LINE = 86; const ORIGINAL_LINE = 13; add_task(async function() { + await pushPref("devtools.debugger.new-debugger-frontend", true); + // Start with the empty page, then navigate, so that we can properly // listen for new sources arriving. const toolbox = await openNewTabAndToolbox(INITIAL_URL, "webconsole"); diff --git a/devtools/client/framework/test/browser_toolbox_split_console.js b/devtools/client/framework/test/browser_toolbox_split_console.js index 807a3276319e..fa40ba1268d0 100644 --- a/devtools/client/framework/test/browser_toolbox_split_console.js +++ b/devtools/client/framework/test/browser_toolbox_split_console.js @@ -14,6 +14,12 @@ let panelWin = null; const URL = "data:text/html;charset=utf8,test split console key delegation"; +// 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(async function() { const tab = await addTab(URL); const target = TargetFactory.forTab(tab); diff --git a/devtools/client/framework/test/browser_toolbox_view_source_01.js b/devtools/client/framework/test/browser_toolbox_view_source_01.js index ac1e09a24227..49949929817e 100644 --- a/devtools/client/framework/test/browser_toolbox_view_source_01.js +++ b/devtools/client/framework/test/browser_toolbox_view_source_01.js @@ -11,6 +11,12 @@ 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"); +}); + async function viewSource() { const toolbox = await openNewTabAndToolbox(URL); @@ -20,7 +26,14 @@ async function viewSource() { ok(debuggerPanel, "The debugger panel was opened."); is(toolbox.currentToolId, "jsdebugger", "The debugger panel was selected."); - assertSelectedLocationInDebugger(debuggerPanel, 2, undefined); + const { DebuggerView } = debuggerPanel.panelWin; + const Sources = DebuggerView.Sources; + + is(Sources.selectedValue, getSourceActor(Sources, JS_URL), + "The correct source is shown in the debugger."); + is(DebuggerView.editor.getCursor().line + 1, 2, + "The correct line is highlighted in the debugger's source editor."); + await closeToolboxAndTab(toolbox); finish(); } diff --git a/devtools/client/framework/test/browser_toolbox_view_source_02.js b/devtools/client/framework/test/browser_toolbox_view_source_02.js index f604cf1f0ba3..2854eacbba42 100644 --- a/devtools/client/framework/test/browser_toolbox_view_source_02.js +++ b/devtools/client/framework/test/browser_toolbox_view_source_02.js @@ -10,9 +10,26 @@ 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"); +}); + async function viewSource() { const toolbox = await openNewTabAndToolbox(URL); - await toolbox.selectTool("jsdebugger"); + const { panelWin: debuggerWin } = await toolbox.selectTool("jsdebugger"); + const debuggerEvents = debuggerWin.EVENTS; + const { DebuggerView } = debuggerWin; + const Sources = DebuggerView.Sources; + + await debuggerWin.once(debuggerEvents.SOURCE_SHOWN); + ok("A source was shown in the debugger."); + + is(Sources.selectedValue, getSourceActor(Sources, JS_URL), + "The correct source is initially shown in the debugger."); + is(DebuggerView.editor.getCursor().line, 0, + "The correct line is initially highlighted in the debugger's source editor."); await toolbox.viewSourceInDebugger(JS_URL, 2); @@ -20,7 +37,10 @@ async function viewSource() { ok(debuggerPanel, "The debugger panel was opened."); is(toolbox.currentToolId, "jsdebugger", "The debugger panel was selected."); - assertSelectedLocationInDebugger(debuggerPanel, 2, undefined); + is(Sources.selectedValue, getSourceActor(Sources, JS_URL), + "The correct source is shown in the debugger."); + is(DebuggerView.editor.getCursor().line + 1, 2, + "The correct line is highlighted in the debugger's source editor."); await closeToolboxAndTab(toolbox); finish(); diff --git a/devtools/client/framework/test/head.js b/devtools/client/framework/test/head.js index 30b7383f7393..7ea3d5b7f331 100644 --- a/devtools/client/framework/test/head.js +++ b/devtools/client/framework/test/head.js @@ -371,11 +371,3 @@ async function resizeWindow(toolbox, width, height) { hostWindow.resizeTo(toWidth, toHeight); await onResize; } - -function assertSelectedLocationInDebugger(debuggerPanel, line, column) { - const location = debuggerPanel._selectors.getSelectedLocation( - debuggerPanel._getState() - ); - is(location.line, line); - is(location.column, column); -} diff --git a/devtools/client/framework/toolbox-options.js b/devtools/client/framework/toolbox-options.js index 2e733c0ae855..c4ea1ecc5cf3 100644 --- a/devtools/client/framework/toolbox-options.js +++ b/devtools/client/framework/toolbox-options.js @@ -368,6 +368,11 @@ OptionsPanel.prototype = { // Labels for these new buttons are nightly only and mostly intended for working on // devtools. const prefDefinitions = [{ + pref: "devtools.debugger.new-debugger-frontend", + label: L10N.getStr("toolbox.options.enableNewDebugger.label"), + id: "devtools-new-debugger", + parentId: "debugger-options" + }, { pref: "devtools.performance.new-panel-enabled", label: "Enable new performance recorder (then re-open DevTools)", id: "devtools-new-performance", diff --git a/devtools/client/framework/toolbox-process-window.js b/devtools/client/framework/toolbox-process-window.js index e7fd7d6ff174..c3a3acdb20df 100644 --- a/devtools/client/framework/toolbox-process-window.js +++ b/devtools/client/framework/toolbox-process-window.js @@ -108,6 +108,7 @@ function setPrefDefaults() { Services.prefs.setBoolPref("devtools.command-button-noautohide.enabled", true); // Bug 1225160 - Using source maps with browser debugging can lead to a crash Services.prefs.setBoolPref("devtools.debugger.source-maps-enabled", false); + Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", true); Services.prefs.setBoolPref("devtools.preference.new-panel-enabled", false); Services.prefs.setBoolPref("layout.css.emulate-moz-box-with-flex", false); diff --git a/devtools/client/inspector/markup/test/browser.ini b/devtools/client/inspector/markup/test/browser.ini index 92890a526efd..8fb39cdf965a 100644 --- a/devtools/client/inspector/markup/test/browser.ini +++ b/devtools/client/inspector/markup/test/browser.ini @@ -70,7 +70,6 @@ support-files = lib_react_with_addons_15.4.1.js react_external_listeners.js !/devtools/client/debugger/new/test/mochitest/helpers.js - !/devtools/client/debugger/new/test/mochitest/helpers/context.js !/devtools/client/inspector/test/head.js !/devtools/client/inspector/test/shared-head.js !/devtools/client/shared/test/shared-head.js diff --git a/devtools/client/inspector/markup/test/browser_markup_shadowdom_open_debugger.js b/devtools/client/inspector/markup/test/browser_markup_shadowdom_open_debugger.js index 75b943dc4518..f40cdbefd607 100644 --- a/devtools/client/inspector/markup/test/browser_markup_shadowdom_open_debugger.js +++ b/devtools/client/inspector/markup/test/browser_markup_shadowdom_open_debugger.js @@ -15,11 +15,6 @@ Services.scriptloader.loadSubScript( "chrome://mochitests/content/browser/devtools/client/debugger/new/test/mochitest/helpers.js", this); -/* import-globals-from ../../../debugger/new/test/mochitest/helpers/context.js */ -Services.scriptloader.loadSubScript( - "chrome://mochitests/content/browser/devtools/client/debugger/new/test/mochitest/helpers/context.js", - this); - const TEST_URL = `data:text/html;charset=utf-8,` + encodeURIComponent(` some-content diff --git a/devtools/client/shared/view-source.js b/devtools/client/shared/view-source.js index 117d578fe9b5..450e985f9fc7 100644 --- a/devtools/client/shared/view-source.js +++ b/devtools/client/shared/view-source.js @@ -6,6 +6,7 @@ var Services = require("Services"); var { gDevTools } = require("devtools/client/framework/devtools"); +var { getSourceText } = require("devtools/client/debugger/content/queries"); /** * Tries to open a Stylesheet file in the Style Editor. If the file is not @@ -50,14 +51,73 @@ exports.viewSourceInStyleEditor = async function(toolbox, sourceURL, */ exports.viewSourceInDebugger = async function(toolbox, sourceURL, sourceLine, reason = "unknown") { + // If the Debugger was already open, switch to it and try to show the + // source immediately. Otherwise, initialize it and wait for the sources + // to be added first. + const debuggerAlreadyOpen = toolbox.getPanel("jsdebugger"); const dbg = await toolbox.loadTool("jsdebugger"); - const source = dbg.getSource(sourceURL); - if (source) { + + // New debugger frontend + if (Services.prefs.getBoolPref("devtools.debugger.new-debugger-frontend")) { + const source = dbg.getSource(sourceURL); + if (source) { + await toolbox.selectTool("jsdebugger", reason); + dbg.selectSource(sourceURL, sourceLine); + return true; + } + + exports.viewSource(toolbox, sourceURL, sourceLine); + return false; + } + + const win = dbg.panelWin; + + // Old debugger frontend + if (!debuggerAlreadyOpen) { + await win.DebuggerController.waitForSourcesLoaded(); + } + + const { DebuggerView } = win; + const { Sources } = DebuggerView; + + const item = Sources.getItemForAttachment(a => a.source.url === sourceURL); + if (item) { await toolbox.selectTool("jsdebugger", reason); - dbg.selectSource(sourceURL, sourceLine); + + // Determine if the source has already finished loading. There's two cases + // in which we need to wait for the source to be shown: + // 1) The requested source is not yet selected and will be shown once it is + // selected and loaded + // 2) The requested source is selected BUT the source text is still loading. + const { actor } = item.attachment.source; + const state = win.DebuggerController.getState(); + + // (1) Is the source selected? + const selected = state.sources.selectedSource; + const isSelected = selected === actor; + + // (2) Has the source text finished loading? + let isLoading = false; + + // Only check if the source is loading when the source is already selected. + // If the source is not selected, we will select it below and the already + // pending load will be cancelled and this check is useless. + if (isSelected) { + const sourceTextInfo = getSourceText(state, selected); + isLoading = sourceTextInfo && sourceTextInfo.loading; + } + + // Select the requested source + DebuggerView.setEditorLocation(actor, sourceLine, { noDebug: true }); + + // Wait for it to load + if (!isSelected || isLoading) { + await win.DebuggerController.waitForSourceShown(sourceURL); + } return true; } + // If not found, still attempt to open in View Source exports.viewSource(toolbox, sourceURL, sourceLine); return false; }; diff --git a/devtools/client/webconsole/test/mochitest/browser.ini b/devtools/client/webconsole/test/mochitest/browser.ini index a2112ec8d5b1..b43fea5aad4d 100644 --- a/devtools/client/webconsole/test/mochitest/browser.ini +++ b/devtools/client/webconsole/test/mochitest/browser.ini @@ -156,8 +156,6 @@ support-files = !/devtools/client/netmonitor/test/sjs_cors-test-server.sjs !/image/test/mochitest/blue.png !/devtools/client/shared/test/shared-head.js - !/devtools/client/debugger/new/test/mochitest/helpers.js - !/devtools/client/debugger/new/test/mochitest/helpers/context.js !/devtools/client/shared/test/telemetry-test-helpers.js !/devtools/client/shared/test/test-actor.js !/devtools/client/shared/test/test-actor-registry.js @@ -253,6 +251,7 @@ tags = mcb [browser_webconsole_close_unfocused_window.js] [browser_webconsole_closing_after_completion.js] [browser_webconsole_close_sidebar.js] +[browser_webconsole_closure_inspection.js] skip-if = true # Bug 1405250 [browser_webconsole_console_api_iframe.js] [browser_webconsole_console_dir.js] diff --git a/devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_in_debugger_stackframe.js b/devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_in_debugger_stackframe.js index 62d337a945a4..d12a766b8f66 100644 --- a/devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_in_debugger_stackframe.js +++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_in_debugger_stackframe.js @@ -21,6 +21,9 @@ add_task(async function() { }); async function performTests() { + // Force the old debugger UI since it's directly used (see Bug 1301705) + await pushPref("devtools.debugger.new-debugger-frontend", false); + const { jsterm } = await openNewTabAndConsole(TEST_URI); const { autocompletePopup: popup, @@ -57,12 +60,10 @@ async function performTests() { `"foo1Obj.prop2." gave the expected suggestions`); info("Opening Debugger"); - await openDebugger(); - const dbg = createDebuggerContext(toolbox); + const {panel} = await openDebugger(); info("Waiting for pause"); - await pauseDebugger(dbg); - const stackFrames = dbg.selectors.getCallStackFrames(dbg.getState()); + const stackFrames = await pauseDebugger(panel); info("Opening Console again"); await toolbox.selectTool("webconsole"); @@ -76,7 +77,7 @@ async function performTests() { await openDebugger(); // Select the frame for the `firstCall` function. - await dbg.actions.selectFrame(stackFrames[1]); + stackFrames.selectFrame(1); info("openConsole"); await toolbox.selectTool("webconsole"); @@ -108,10 +109,18 @@ function getPopupLabels(popup) { return popup.getItems().map(item => item.label); } -async function pauseDebugger(dbg) { - info("Waiting for debugger to pause"); - ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() { - content.wrappedJSObject.firstCall(); +function pauseDebugger(debuggerPanel) { + const debuggerWin = debuggerPanel.panelWin; + const debuggerController = debuggerWin.DebuggerController; + const thread = debuggerController.activeThread; + + return new Promise(resolve => { + thread.addOneTimeListener("framesadded", () => + resolve(debuggerController.StackFrames)); + + info("firstCall()"); + ContentTask.spawn(gBrowser.selectedBrowser, {}, function() { + content.wrappedJSObject.firstCall(); + }); }); - await waitForPaused(dbg); } diff --git a/devtools/client/webconsole/test/mochitest/browser_webconsole_click_function_to_source.js b/devtools/client/webconsole/test/mochitest/browser_webconsole_click_function_to_source.js index df6fd358a3c3..9db871c758f1 100644 --- a/devtools/client/webconsole/test/mochitest/browser_webconsole_click_function_to_source.js +++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_click_function_to_source.js @@ -7,21 +7,19 @@ "use strict"; -requestLongerTimeout(5); - const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" + "test/mochitest/" + "test-click-function-to-source.html"; -const TEST_SCRIPT_URI = "http://example.com/browser/devtools/client/webconsole/" + - "test/mochitest/" + - "test-click-function-to-source.js"; +// Force the old debugger UI since it's directly used (see Bug 1301705) +pushPref("devtools.debugger.new-debugger-frontend", false); add_task(async function() { const hud = await openNewTabAndConsole(TEST_URI); info("Open the Debugger panel."); - await openDebugger(); + const {panel} = await openDebugger(); + const panelWin = panel.panelWin; info("And right after come back to the Console panel."); await openConsole(); @@ -36,13 +34,13 @@ add_task(async function() { ok(jumpIcon, "A jump to definition button is rendered, as expected"); info("Click on the jump to definition button."); + const onEditorLocationSet = panelWin.once(panelWin.EVENTS.EDITOR_LOCATION_SET); jumpIcon.click(); + await onEditorLocationSet; - const toolbox = gDevTools.getToolbox(hud.target); - const dbg = createDebuggerContext(toolbox); - await waitForSelectedSource(dbg, TEST_SCRIPT_URI); - - const pendingLocation = dbg.selectors.getPendingSelectedLocation(dbg.getState()); - const {line} = pendingLocation; - is(line, 9, "Debugger is open at the expected line"); + const {editor} = panelWin.DebuggerView; + const {line, ch} = editor.getCursor(); + // Source editor starts counting line and column numbers from 0. + is(line, 8, "Debugger is open at the expected line"); + is(ch, 0, "Debugger is open at the expected character"); }); diff --git a/devtools/client/webconsole/test/mochitest/browser_webconsole_closure_inspection.js b/devtools/client/webconsole/test/mochitest/browser_webconsole_closure_inspection.js new file mode 100644 index 000000000000..fe5cf1609a34 --- /dev/null +++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_closure_inspection.js @@ -0,0 +1,104 @@ +/* -*- 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/ */ + +// XXX Remove this when the file is migrated to the new frontend. +/* eslint-disable no-undef */ + +// Check that inspecting a closure in the variables view sidebar works when +// execution is paused. + +"use strict"; + +const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" + + "test/mochitest/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"); + toolbox.selectTool("webconsole").then(() => consoleOpened(hud)); + deferred.resolve(); + }); + } + + loadTab(TEST_URI).then(() => { + openConsole().then((hud) => { + openDebugger().then(({ toolbox, panelWin }) => { + const deferred = defer(); + fetchScopes(hud, toolbox, panelWin, deferred); + + // eslint-disable-next-line + ContentTask.spawn(gBrowser.selectedBrowser, {}, () => { + const button = content.document.querySelector("button"); + ok(button, "button element found"); + button.click(); + }); + + return deferred.promise; + }); + }); + }); +} + +function consoleOpened(hud) { + gWebConsole = hud; + gJSTerm = hud.jsterm; + gJSTerm.execute("window.george.getName"); + + waitForMessages({ + webconsole: gWebConsole, + messages: [{ + text: "getName()", + category: CATEGORY_OUTPUT, + objects: true, + }], + }).then(onExecuteGetName); +} + +function onExecuteGetName(results) { + const clickable = results[0].clickableElements[0]; + ok(clickable, "clickable object found"); + + gJSTerm.once("variablesview-fetched", onGetNameFetch); + const contextMenu = + gWebConsole.iframeWindow.document.getElementById("output-contextmenu"); + waitForContextMenu(contextMenu, clickable, () => { + const openInVarView = contextMenu.querySelector("#menu_openInVarView"); + ok(openInVarView.disabled === false, + "the \"Open In Variables View\" context menu item should be clickable"); + // EventUtils.synthesizeMouseAtCenter seems to fail here in Mac OSX + openInVarView.click(); + }); +} + +function onGetNameFetch(view) { + gVariablesView = view._variablesView; + ok(gVariablesView, "variables view object"); + + findVariableViewProperties(view, [ + { name: /_pfactory/, value: "" }, + ], { webconsole: gWebConsole }).then(onExpandClosure); +} + +function onExpandClosure(results) { + const prop = results[0].matchedProp; + ok(prop, "matched the name property in the variables view"); + + gVariablesView.window.focus(); + gJSTerm.once("sidebar-closed", finishTest); + EventUtils.synthesizeKey("VK_ESCAPE", {}, gVariablesView.window); +} diff --git a/devtools/client/webconsole/test/mochitest/browser_webconsole_eval_in_debugger_stackframe.js b/devtools/client/webconsole/test/mochitest/browser_webconsole_eval_in_debugger_stackframe.js index abafbe601477..52d17cf697aa 100644 --- a/devtools/client/webconsole/test/mochitest/browser_webconsole_eval_in_debugger_stackframe.js +++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_eval_in_debugger_stackframe.js @@ -12,6 +12,9 @@ const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" + "test/mochitest/test-eval-in-stackframe.html"; add_task(async function() { + // Force the old debugger UI since it's directly used (see Bug 1301705). + await pushPref("devtools.debugger.new-debugger-frontend", false); + info("open the console"); const hud = await openNewTabAndConsole(TEST_URI); const {jsterm} = hud; @@ -29,9 +32,8 @@ add_task(async function() { ok(true, "'newFoo' is displayed after adding `foo2`"); info("Open the debugger and then select the console again"); - await openDebugger(); - const toolbox = gDevTools.getToolbox(hud.target); - const dbg = createDebuggerContext(toolbox); + const {panel} = await openDebugger(); + const {activeThread, StackFrames: stackFrames} = panel.panelWin.DebuggerController; await openConsole(); @@ -42,9 +44,13 @@ add_task(async function() { info("Select the debugger again"); await openDebugger(); - await pauseDebugger(dbg); - const stackFrames = dbg.selectors.getCallStackFrames(dbg.getState()); + const onFirstCallFramesAdded = activeThread.addOneTimeListener("framesadded"); + // firstCall calls secondCall, which has a debugger statement, so we'll be paused. + ContentTask.spawn(gBrowser.selectedBrowser, {}, function() { + content.wrappedJSObject.firstCall(); + }); + await onFirstCallFramesAdded; info("frames added, select the console again"); await openConsole(); @@ -56,9 +62,7 @@ add_task(async function() { info("select the debugger and select the frame (1)"); await openDebugger(); - - await dbg.actions.selectFrame(stackFrames[1]); - + stackFrames.selectFrame(1); await openConsole(); info("Check `foo + foo2 + foo3` value when paused on a given frame"); @@ -78,11 +82,3 @@ add_task(async function() { ok(!content.wrappedJSObject.foo3, "`foo3` was not added to the content window"); }); }); - -async function pauseDebugger(dbg) { - info("Waiting for debugger to pause"); - ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() { - content.wrappedJSObject.firstCall(); - }); - await waitForPaused(dbg); -} diff --git a/devtools/client/webconsole/test/mochitest/browser_webconsole_eval_in_debugger_stackframe2.js b/devtools/client/webconsole/test/mochitest/browser_webconsole_eval_in_debugger_stackframe2.js index d991b5afbdf0..e2b785d1a4a7 100644 --- a/devtools/client/webconsole/test/mochitest/browser_webconsole_eval_in_debugger_stackframe2.js +++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_eval_in_debugger_stackframe2.js @@ -13,16 +13,18 @@ const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" + "test/mochitest/test-eval-in-stackframe.html"; add_task(async function() { + // Force the old debugger UI since it's directly used (see Bug 1301705). + await pushPref("devtools.debugger.new-debugger-frontend", false); + info("open the console"); const hud = await openNewTabAndConsole(TEST_URI); const {jsterm} = hud; info("open the debugger"); - await openDebugger(); - - const toolbox = gDevTools.getToolbox(hud.target); - const dbg = createDebuggerContext(toolbox); + const {panel} = await openDebugger(); + const {activeThread} = panel.panelWin.DebuggerController; + const onFirstCallFramesAdded = activeThread.addOneTimeListener("framesadded"); // firstCall calls secondCall, which has a debugger statement, so we'll be paused. const onFirstCallMessageReceived = waitForMessage(hud, "undefined"); @@ -34,7 +36,7 @@ add_task(async function() { jsterm.execute("firstCall()"); info("Waiting for a frame to be added"); - await waitForPaused(dbg); + await onFirstCallFramesAdded; info("frames added, select the console again"); await openConsole(); @@ -55,7 +57,7 @@ add_task(async function() { ok(firstCallEvaluationResult === unresolvedSymbol, "firstCall was not evaluated yet"); info("Resuming the thread"); - dbg.actions.resume(dbg.getState()); + activeThread.resume(); message = await onFirstCallMessageReceived; ok(firstCallEvaluationResult !== unresolvedSymbol, diff --git a/devtools/client/webconsole/test/mochitest/browser_webconsole_location_debugger_link.js b/devtools/client/webconsole/test/mochitest/browser_webconsole_location_debugger_link.js index 1a8da1b4dfd1..54efd21ad337 100644 --- a/devtools/client/webconsole/test/mochitest/browser_webconsole_location_debugger_link.js +++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_location_debugger_link.js @@ -19,6 +19,9 @@ const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" + "test/mochitest/test-location-debugger-link.html"; add_task(async function() { + // Force the new debugger UI, in case this gets uplifted with the old + // debugger still turned on + await pushPref("devtools.debugger.new-debugger-frontend", true); await pushPref("devtools.webconsole.filter.error", true); await pushPref("devtools.webconsole.filter.log", true); diff --git a/devtools/client/webconsole/test/mochitest/browser_webconsole_object_inspector_while_debugging_and_inspecting.js b/devtools/client/webconsole/test/mochitest/browser_webconsole_object_inspector_while_debugging_and_inspecting.js index c22e2564e19c..3b8a7bb811d9 100644 --- a/devtools/client/webconsole/test/mochitest/browser_webconsole_object_inspector_while_debugging_and_inspecting.js +++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_object_inspector_while_debugging_and_inspecting.js @@ -12,6 +12,8 @@ const TEST_URI = "https://example.com/browser/devtools/client/webconsole/" + "test/mochitest/test-eval-in-stackframe.html"; add_task(async function() { + // Force the old debugger UI since it's directly used (see Bug 1301705) + await pushPref("devtools.debugger.new-debugger-frontend", false); const hud = await openNewTabAndConsole(TEST_URI); info("Switch to the debugger"); @@ -22,9 +24,7 @@ add_task(async function() { await gDevTools.showToolbox(target, "inspector"); info("Call firstCall() and wait for the debugger statement to be reached."); - const toolbox = gDevTools.getToolbox(target); - const dbg = createDebuggerContext(toolbox); - await pauseDebugger(dbg); + await waitForFrameAdded(); info("Switch back to the console"); await gDevTools.showToolbox(target, "webconsole"); @@ -63,10 +63,16 @@ add_task(async function() { ok(oiNodes[2].textContent.includes(`: Object { \u2026 }`)); }); -async function pauseDebugger(dbg) { - info("Waiting for debugger to pause"); - ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() { - content.wrappedJSObject.firstCall(); +async function waitForFrameAdded() { + const target = TargetFactory.forTab(gBrowser.selectedTab); + const toolbox = gDevTools.getToolbox(target); + const thread = toolbox.threadClient; + + info("Waiting for framesadded"); + await new Promise(resolve => { + thread.addOneTimeListener("framesadded", resolve); + ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() { + content.wrappedJSObject.firstCall(); + }); }); - await waitForPaused(dbg); } diff --git a/devtools/client/webconsole/test/mochitest/browser_webconsole_optimized_out_vars.js b/devtools/client/webconsole/test/mochitest/browser_webconsole_optimized_out_vars.js index a08afad55c58..180f42a32a34 100644 --- a/devtools/client/webconsole/test/mochitest/browser_webconsole_optimized_out_vars.js +++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_optimized_out_vars.js @@ -13,17 +13,27 @@ const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" + "test-closure-optimized-out.html"; add_task(async function() { + // Force the old debugger UI since it's directly used (see Bug 1301705) + await pushPref("devtools.debugger.new-debugger-frontend", false); + const hud = await openNewTabAndConsole(TEST_URI); - await openDebugger(); + const { toolbox, panel: debuggerPanel } = await openDebugger(); - const toolbox = gDevTools.getToolbox(hud.target); - const dbg = createDebuggerContext(toolbox); + const sources = debuggerPanel.panelWin.DebuggerView.Sources; + await debuggerPanel.addBreakpoint({ actor: sources.values[0], line: 18 }); + await ensureThreadClientState(debuggerPanel, "resumed"); - await addBreakpoint(dbg, "test-closure-optimized-out.html", 18); - await waitForThreadEvents(dbg, "resumed"); + const { FETCHED_SCOPES } = debuggerPanel.panelWin.EVENTS; + const fetchedScopes = debuggerPanel.panelWin.once(FETCHED_SCOPES); // Cause the debuggee to pause - await pauseDebugger(dbg); + ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() { + const button = content.document.querySelector("button"); + button.click(); + }); + + await fetchedScopes; + ok(true, "Scopes were fetched"); await toolbox.selectTool("webconsole"); @@ -37,11 +47,13 @@ add_task(async function() { ok(true, "Optimized out message logged"); }); -async function pauseDebugger(dbg) { - info("Waiting for debugger to pause"); - ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() { - const button = content.document.querySelector("button"); - button.click(); - }); - await waitForPaused(dbg); +// Debugger helper functions adapted from devtools/client/debugger/test/head.js. + +async function ensureThreadClientState(debuggerPanel, state) { + const thread = debuggerPanel.panelWin.gThreadClient; + info(`Thread is: '${thread.state}'.`); + if (thread.state != state) { + info("Waiting for thread event: '${state}'."); + await thread.addOneTimeListener(state); + } } diff --git a/devtools/client/webconsole/test/mochitest/browser_webconsole_sourcemap_nosource.js b/devtools/client/webconsole/test/mochitest/browser_webconsole_sourcemap_nosource.js index eb371e1e0c67..bbd4db30b28d 100644 --- a/devtools/client/webconsole/test/mochitest/browser_webconsole_sourcemap_nosource.js +++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_sourcemap_nosource.js @@ -25,6 +25,9 @@ const PAGE_URL = `data:text/html, `; add_task(async function() { + // Force the new debugger UI, in case this gets uplifted with the old + // debugger still turned on + await pushPref("devtools.debugger.new-debugger-frontend", true); await pushPref("devtools.source-map.client-service.enabled", true); const hud = await openNewTabAndConsole(PAGE_URL); diff --git a/devtools/client/webconsole/test/mochitest/browser_webconsole_stacktrace_location_debugger_link.js b/devtools/client/webconsole/test/mochitest/browser_webconsole_stacktrace_location_debugger_link.js index 1f7c2c5c60b8..6ce8c0fdd74c 100644 --- a/devtools/client/webconsole/test/mochitest/browser_webconsole_stacktrace_location_debugger_link.js +++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_stacktrace_location_debugger_link.js @@ -19,8 +19,12 @@ const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" + "test-stacktrace-location-debugger-link.html"; add_task(async function() { + // Force the new debugger UI, in case this gets uplifted with the old + // debugger still turned on + Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", true); Services.prefs.setBoolPref("devtools.webconsole.filter.log", true); registerCleanupFunction(async function() { + Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend"); Services.prefs.clearUserPref("devtools.webconsole.filter.log"); }); diff --git a/devtools/client/webconsole/test/mochitest/head.js b/devtools/client/webconsole/test/mochitest/head.js index 822f7333f7ac..772fe18cf085 100644 --- a/devtools/client/webconsole/test/mochitest/head.js +++ b/devtools/client/webconsole/test/mochitest/head.js @@ -19,18 +19,6 @@ Services.scriptloader.loadSubScript( "chrome://mochitests/content/browser/devtools/client/shared/test/shared-head.js", this); -// Import helpers for the new debugger -/* import-globals-from ../../../debugger/new/test/mochitest/helpers.js */ -Services.scriptloader.loadSubScript( - "chrome://mochitests/content/browser/devtools/client/debugger/new/test/mochitest/helpers.js", - this); - -// Import helpers for the new debugger -/* import-globals-from ../../../debugger/new/test/mochitest/helpers/context.js */ -Services.scriptloader.loadSubScript( - "chrome://mochitests/content/browser/devtools/client/debugger/new/test/mochitest/helpers/context.js", - this); - var {HUDService} = require("devtools/client/webconsole/hudservice"); var WCUL10n = require("devtools/client/webconsole/webconsole-l10n"); const DOCS_GA_PARAMS = `?${new URLSearchParams({ @@ -547,17 +535,9 @@ async function openDebugger(options = {}) { const panel = toolbox.getCurrentPanel(); // Do not clear VariableView lazily so it doesn't disturb test ending. - if (panel._view) { - panel._view.Variables.lazyEmpty = false; - } + panel._view.Variables.lazyEmpty = false; - // Old debugger - if (panel.panelWin && panel.panelWin.DebuggerController) { - await panel.panelWin.DebuggerController.waitForSourcesLoaded(); - } else { - // New debugger - await toolbox.threadClient.getSources(); - } + await panel.panelWin.DebuggerController.waitForSourcesLoaded(); return {target, toolbox, panel}; }