diff options
Diffstat (limited to 'devtools')
30 files changed, 308 insertions, 144 deletions
diff --git a/devtools/client/canvasdebugger/test/browser_profiling-canvas.js b/devtools/client/canvasdebugger/test/browser_profiling-canvas.js index ede8a4dbf..75f8da4f3 100644..100755 --- a/devtools/client/canvasdebugger/test/browser_profiling-canvas.js +++ b/devtools/client/canvasdebugger/test/browser_profiling-canvas.js @@ -37,7 +37,7 @@ function* ifTestingSupported() { for (let i = 0; i < functionCalls.length - 1; i += 2) { ok(functionCalls[i].timestamp > 0, "The timestamp of the called function is larger than 0."); ok(functionCalls[i].timestamp < currentTime, "The timestamp has been minus the frame start time."); - ok(functionCalls[i + 1].timestamp > functionCalls[i].timestamp, "The timestamp of the called function is correct."); + ok(functionCalls[i + 1].timestamp >= functionCalls[i].timestamp, "The timestamp of the called function is correct."); } yield removeTab(target.tab); diff --git a/devtools/client/commandline/test/browser_cmd_csscoverage_startstop.js b/devtools/client/commandline/test/browser_cmd_csscoverage_startstop.js index 2bdb86d86..c48136989 100644 --- a/devtools/client/commandline/test/browser_cmd_csscoverage_startstop.js +++ b/devtools/client/commandline/test/browser_cmd_csscoverage_startstop.js @@ -4,6 +4,7 @@ // Tests that the addon commands works as they should const csscoverage = require("devtools/shared/fronts/csscoverage"); +const {gDevTools} = require("devtools/client/framework/devtools"); const PAGE_1 = TEST_BASE_HTTPS + "browser_cmd_csscoverage_page1.html"; const PAGE_2 = TEST_BASE_HTTPS + "browser_cmd_csscoverage_page2.html"; diff --git a/devtools/client/debugger/test/mochitest/browser_dbg_closure-inspection.js b/devtools/client/debugger/test/mochitest/browser_dbg_closure-inspection.js index 739d3b2a7..b2fa66872 100644 --- a/devtools/client/debugger/test/mochitest/browser_dbg_closure-inspection.js +++ b/devtools/client/debugger/test/mochitest/browser_dbg_closure-inspection.js @@ -53,13 +53,13 @@ function test() { .getAttribute("value"), "getName", "Should have the right property name for 'getName' in person."); is(personNode.get("getName").target.querySelector(".value") - .getAttribute("value"), "_pfactory/<.getName()", + .getAttribute("value"), "getName()", "'getName' in person should have the right value."); is(personNode.get("getFoo").target.querySelector(".name") .getAttribute("value"), "getFoo", "Should have the right property name for 'getFoo' in person."); is(personNode.get("getFoo").target.querySelector(".value") - .getAttribute("value"), "_pfactory/<.getFoo()", + .getAttribute("value"), "getFoo()", "'getFoo' in person should have the right value."); // Expand the function nodes. This causes their properties to be diff --git a/devtools/client/framework/browser-menus.js b/devtools/client/framework/browser-menus.js index 3d6c4def6..e62afddac 100644 --- a/devtools/client/framework/browser-menus.js +++ b/devtools/client/framework/browser-menus.js @@ -133,10 +133,11 @@ function attachKeybindingsToBrowser(doc, keys) { */ function createToolMenuElements(toolDefinition, doc) { let id = toolDefinition.id; + let appmenuId = "appmenuitem_" + id; let menuId = "menuitem_" + id; // Prevent multiple entries for the same tool. - if (doc.getElementById(menuId)) { + if (doc.getElementById(appmenuId) || doc.getElementById(menuId)) { return; } @@ -156,6 +157,13 @@ function createToolMenuElements(toolDefinition, doc) { }); } + let appmenuitem = createMenuItem({ + doc, + id: "appmenuitem_" + id, + label: toolDefinition.menuLabel || toolDefinition.label, + accesskey: null + }); + let menuitem = createMenuItem({ doc, id: "menuitem_" + id, @@ -166,10 +174,12 @@ function createToolMenuElements(toolDefinition, doc) { // Refer to the key in order to display the key shortcut at menu ends menuitem.setAttribute("key", key.id); } + appmenuitem.addEventListener("command", oncommand); menuitem.addEventListener("command", oncommand); return { key, + appmenuitem, menuitem }; } @@ -186,22 +196,34 @@ function createToolMenuElements(toolDefinition, doc) { * The tool definition after which the tool menu item is to be added. */ function insertToolMenuElements(doc, toolDefinition, prevDef) { - let { key, menuitem } = createToolMenuElements(toolDefinition, doc); + let { key, appmenuitem, menuitem } = createToolMenuElements(toolDefinition, doc); if (key) { attachKeybindingsToBrowser(doc, key); } - let ref; + let amp; + if (prevDef) { + let appmenuitem = doc.getElementById("appmenuitem_" + prevDef.id); + amp = appmenuitem && appmenuitem.nextSibling ? appmenuitem.nextSibling : null; + } else { + amp = doc.getElementById("appmenu_devtools_separator"); + } + + if (amp) { + amp.parentNode.insertBefore(appmenuitem, amp); + } + + let mp; if (prevDef) { let menuitem = doc.getElementById("menuitem_" + prevDef.id); - ref = menuitem && menuitem.nextSibling ? menuitem.nextSibling : null; + mp = menuitem && menuitem.nextSibling ? menuitem.nextSibling : null; } else { - ref = doc.getElementById("menu_devtools_separator"); + mp = doc.getElementById("menu_devtools_separator"); } - if (ref) { - ref.parentNode.insertBefore(menuitem, ref); + if (mp) { + mp.parentNode.insertBefore(menuitem, mp); } } exports.insertToolMenuElements = insertToolMenuElements; @@ -220,6 +242,11 @@ function removeToolFromMenu(toolId, doc) { key.remove(); } + let appmenuitem = doc.getElementById("appmenuitem_" + toolId); + if (appmenuitem) { + appmenuitem.remove(); + } + let menuitem = doc.getElementById("menuitem_" + toolId); if (menuitem) { menuitem.remove(); @@ -235,6 +262,7 @@ exports.removeToolFromMenu = removeToolFromMenu; */ function addAllToolsToMenu(doc) { let fragKeys = doc.createDocumentFragment(); + let fragAppMenuItems = doc.createDocumentFragment(); let fragMenuItems = doc.createDocumentFragment(); for (let toolDefinition of gDevTools.getToolDefinitionArray()) { @@ -251,11 +279,17 @@ function addAllToolsToMenu(doc) { if (elements.key) { fragKeys.appendChild(elements.key); } + fragAppMenuItems.appendChild(elements.appmenuitem); fragMenuItems.appendChild(elements.menuitem); } attachKeybindingsToBrowser(doc, fragKeys); + let amps = doc.getElementById("appmenu_devtools_separator"); + if (amps) { + amps.parentNode.insertBefore(fragAppMenuItems, amps); + } + let mps = doc.getElementById("menu_devtools_separator"); if (mps) { mps.parentNode.insertBefore(fragMenuItems, mps); @@ -270,18 +304,29 @@ function addAllToolsToMenu(doc) { */ function addTopLevelItems(doc) { let keys = doc.createDocumentFragment(); + let appmenuItems = doc.createDocumentFragment(); let menuItems = doc.createDocumentFragment(); let { menuitems } = require("../menus"); for (let item of menuitems) { if (item.separator) { + let appseparator = doc.createElement("menuseparator"); + appseparator.id = "app" + item.id; let separator = doc.createElement("menuseparator"); separator.id = item.id; + appmenuItems.appendChild(appseparator); menuItems.appendChild(separator); } else { let { id, l10nKey } = item; // Create a <menuitem> + let appmenuitem = createMenuItem({ + doc, + id: "app" + id, + label: l10n(l10nKey + ".label"), + accesskey: null, + isCheckbox: item.checkbox + }); let menuitem = createMenuItem({ doc, id, @@ -289,7 +334,9 @@ function addTopLevelItems(doc) { accesskey: l10n(l10nKey + ".accesskey"), isCheckbox: item.checkbox }); + appmenuitem.addEventListener("command", item.oncommand); menuitem.addEventListener("command", item.oncommand); + appmenuItems.appendChild(appmenuitem); menuItems.appendChild(menuitem); if (item.key && l10nKey) { @@ -330,6 +377,9 @@ function addTopLevelItems(doc) { for (let node of keys.children) { nodes.push(node); } + for (let node of appmenuItems.children) { + nodes.push(node); + } for (let node of menuItems.children) { nodes.push(node); } @@ -337,15 +387,33 @@ function addTopLevelItems(doc) { attachKeybindingsToBrowser(doc, keys); + // There are hardcoded menu items in the Web Developer menus plus it is a + // location of menu items via overlays from extensions so we want to make + // sure the last seperator and the "Get More Tools..." items are last. + // This will emulate the behavior when devtools menu items were actually + // physically present in browser.xul + + // Tools > Web Developer let menu = doc.getElementById("menuWebDeveloperPopup"); - menu.appendChild(menuItems); - - // There is still "Page Source" menuitem hardcoded into browser.xul. Instead - // of manually inserting everything around it, move it to the expected - // position. - let pageSource = doc.getElementById("menu_pageSource"); - let endSeparator = doc.getElementById("devToolsEndSeparator"); - menu.insertBefore(pageSource, endSeparator); + // Insert the Devtools Menu Items before everything else + menu.insertBefore(menuItems, menu.firstChild); + // Move the devtools last seperator and Get More Tools menu items to the bottom + let menu_endSeparator = doc.getElementById("menu_devToolsEndSeparator"); + let menu_getMoreDevtools = doc.getElementById("menu_getMoreDevtools"); + menu.insertBefore(menu_getMoreDevtools, null); + menu.insertBefore(menu_endSeparator, menu_getMoreDevtools); + + // Application Menu > Web Developer (If existant) + let appmenu = doc.getElementById("appmenu_webDeveloper_popup"); + if (appmenu) { + // Insert the Devtools Menu Items after the hardcoded idless seperator + appmenu.insertBefore(appmenuItems, appmenu.childNodes[2].nextSibling); + // Move the devtools last seperator and Get More Tools menu items to the bottom + let appmenu_endSeparator = doc.getElementById("appmenu_devToolsEndSeparator"); + let appmenu_getMoreDevtools = doc.getElementById("appmenu_getMoreDevtools"); + appmenu.insertBefore(appmenu_getMoreDevtools, null); + appmenu.insertBefore(appmenu_endSeparator, appmenu_getMoreDevtools); + } } /** diff --git a/devtools/client/framework/devtools-browser.js b/devtools/client/framework/devtools-browser.js index b9f4d92ba..f032f82aa 100644 --- a/devtools/client/framework/devtools-browser.js +++ b/devtools/client/framework/devtools-browser.js @@ -8,7 +8,7 @@ * This is the main module loaded in Firefox desktop that handles browser * windows and coordinates devtools around each window. * - * This module is loaded lazily by devtools-clhandler.js, once the first + * This module is loaded lazily by devtools-startup.js, once the first * browser window is ready (i.e. fired browser-delayed-startup-finished event) **/ @@ -27,8 +27,10 @@ loader.lazyRequireGetter(this, "DebuggerServer", "devtools/server/main", true); loader.lazyRequireGetter(this, "DebuggerClient", "devtools/shared/client/main", true); loader.lazyRequireGetter(this, "BrowserMenus", "devtools/client/framework/browser-menus"); -loader.lazyImporter(this, "CustomizableUI", "resource:///modules/CustomizableUI.jsm"); loader.lazyImporter(this, "AppConstants", "resource://gre/modules/AppConstants.jsm"); +#ifdef MC_BASILISK +loader.lazyImporter(this, "CustomizableUI", "resource:///modules/CustomizableUI.jsm"); +#endif const {LocalizationHelper} = require("devtools/shared/l10n"); const L10N = new LocalizationHelper("devtools/client/locales/toolbox.properties"); @@ -85,6 +87,9 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = { function toggleMenuItem(id, isEnabled) { let cmd = doc.getElementById(id); + if (!cmd) { + return; + } if (isEnabled) { cmd.removeAttribute("disabled"); cmd.removeAttribute("hidden"); @@ -94,22 +99,39 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = { } } + let idEls = []; + // Enable developer toolbar? let devToolbarEnabled = Services.prefs.getBoolPref("devtools.toolbar.enabled"); - toggleMenuItem("menu_devToolbar", devToolbarEnabled); - let focusEl = doc.getElementById("menu_devToolbar"); - if (devToolbarEnabled) { - focusEl.removeAttribute("disabled"); - } else { - focusEl.setAttribute("disabled", "true"); - } + idEls = [ + "appmenu_devToolbar", + "menu_devToolbar" + ]; + idEls.forEach(function (idEl) { + toggleMenuItem(idEl, devToolbarEnabled); + let focusEl = doc.getElementById(idEl); + if (!focusEl) { + return; + } + if (devToolbarEnabled) { + focusEl.removeAttribute("disabled"); + } else { + focusEl.setAttribute("disabled", "true"); + } + }); if (devToolbarEnabled && Services.prefs.getBoolPref("devtools.toolbar.visible")) { win.DeveloperToolbar.show(false).catch(console.error); } // Enable WebIDE? let webIDEEnabled = Services.prefs.getBoolPref("devtools.webide.enabled"); - toggleMenuItem("menu_webide", webIDEEnabled); + idEls = [ + "appmenu_webide", + "menu_webide" + ]; + idEls.forEach(function (idEl) { + toggleMenuItem(idEl, webIDEEnabled); + }); let showWebIDEWidget = Services.prefs.getBoolPref("devtools.webide.widget.enabled"); if (webIDEEnabled && showWebIDEWidget) { @@ -122,11 +144,29 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = { let chromeEnabled = Services.prefs.getBoolPref("devtools.chrome.enabled"); let devtoolsRemoteEnabled = Services.prefs.getBoolPref("devtools.debugger.remote-enabled"); let remoteEnabled = chromeEnabled && devtoolsRemoteEnabled; - toggleMenuItem("menu_browserToolbox", remoteEnabled); - toggleMenuItem("menu_browserContentToolbox", remoteEnabled && win.gMultiProcessBrowser); + idEls = [ + "appmenu_browserToolbox", + "menu_browserToolbox" + ]; + idEls.forEach(function (idEl) { + toggleMenuItem(idEl, remoteEnabled); + }); + idEls = [ + "appmenu_browserContentToolbox", + "menu_browserContentToolbox" + ]; + idEls.forEach(function (idEl) { + toggleMenuItem(idEl, remoteEnabled && win.gMultiProcessBrowser); + }); // Enable DevTools connection screen, if the preference allows this. - toggleMenuItem("menu_devtools_connect", devtoolsRemoteEnabled); + idEls = [ + "appmenu_devtools_connect", + "menu_devtools_connect" + ]; + idEls.forEach(function (idEl) { + toggleMenuItem(idEl, devtoolsRemoteEnabled); + }); }, observe: function (subject, topic, prefName) { @@ -295,6 +335,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = { * Install Developer widget */ installDeveloperWidget: function () { +#ifdef MC_BASILISK let id = "developer-button"; let widget = CustomizableUI.getWidget(id); if (widget && widget.provider == CustomizableUI.PROVIDER_API) { @@ -343,6 +384,9 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = { doc.getElementById("PanelUI-multiView").appendChild(view); } }); +#else + return; +#endif }, /** @@ -350,6 +394,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = { */ // Used by itself installWebIDEWidget: function () { +#ifdef MC_BASILISK if (this.isWebIDEWidgetInstalled()) { return; } @@ -371,11 +416,18 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = { gDevToolsBrowser.openWebIDE(); } }); +#else + return; +#endif }, isWebIDEWidgetInstalled: function () { +#ifdef MC_BASILISK let widgetWrapper = CustomizableUI.getWidget("webide-button"); return !!(widgetWrapper && widgetWrapper.provider == CustomizableUI.PROVIDER_API); +#else + return false; +#endif }, /** @@ -387,10 +439,14 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = { * Uninstall WebIDE widget */ uninstallWebIDEWidget: function () { +#ifdef MC_BASILISK if (this.isWebIDEWidgetInstalled()) { CustomizableUI.removeWidgetFromArea("webide-button"); } CustomizableUI.destroyWidget("webide-button"); +#else + return; +#endif }, /** @@ -398,7 +454,11 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = { */ // Used by webide.js moveWebIDEWidgetInNavbar: function () { +#ifdef MC_BASILISK CustomizableUI.addWidgetToArea("webide-button", CustomizableUI.AREA_NAVBAR); +#else + return; +#endif }, /** @@ -591,12 +651,23 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = { let hasToolbox = gDevToolsBrowser.hasToolboxOpened(win); - let menu = win.document.getElementById("menu_devToolbox"); - if (hasToolbox) { - menu.setAttribute("checked", "true"); - } else { - menu.removeAttribute("checked"); - } + let idEls = []; + + idEls = [ + "appmenu_devToolbox", + "menu_devToolbox" + ]; + idEls.forEach(function (idEl) { + let menu = win.document.getElementById(idEl); + if (!menu) { + return; + } + if (hasToolbox) { + menu.setAttribute("checked", "true"); + } else { + menu.removeAttribute("checked"); + } + }); } }, diff --git a/devtools/client/framework/moz.build b/devtools/client/framework/moz.build index 7b28b4b9e..407e21f8b 100644 --- a/devtools/client/framework/moz.build +++ b/devtools/client/framework/moz.build @@ -13,7 +13,6 @@ DevToolsModules( 'about-devtools-toolbox.js', 'attach-thread.js', 'browser-menus.js', - 'devtools-browser.js', 'devtools.js', 'gDevTools.jsm', 'location-store.js', @@ -31,3 +30,7 @@ DevToolsModules( 'toolbox.js', 'ToolboxProcess.jsm', ) + +FINAL_TARGET_PP_FILES.chrome.devtools.modules.devtools.client.framework += [ + 'devtools-browser.js', +] diff --git a/devtools/client/framework/test/browser_keybindings_01.js b/devtools/client/framework/test/browser_keybindings_01.js index 4e4effb07..134fb127c 100644 --- a/devtools/client/framework/test/browser_keybindings_01.js +++ b/devtools/client/framework/test/browser_keybindings_01.js @@ -8,6 +8,9 @@ const TEST_URL = "data:text/html,<html><head><title>Test for the " + "highlighter keybindings</title></head><body>" + "<h1>Keybindings!</h1></body></html>" + +const {gDevToolsBrowser} = require("devtools/client/framework/devtools-browser"); + function test() { waitForExplicitFinish(); diff --git a/devtools/client/framework/test/browser_toolbox_textbox_context_menu.js b/devtools/client/framework/test/browser_toolbox_textbox_context_menu.js index 2e5f3210e..e2e961255 100644 --- a/devtools/client/framework/test/browser_toolbox_textbox_context_menu.js +++ b/devtools/client/framework/test/browser_toolbox_textbox_context_menu.js @@ -36,15 +36,12 @@ add_task(function* () { is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled"); is(cmdSelectAll.getAttribute("disabled"), "true", "cmdSelectAll is disabled"); - // Cut/Copy items are enabled in context menu even if there - // is no selection. See also Bug 1303033 + // Cut/Copy/Paste items are enabled in context menu even if there + // is no selection. See also Bug 1303033, and 1317322 is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled"); is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled"); - if (isWindows()) { - // emptyClipboard only works on Windows (666254), assert paste only for this OS. - is(cmdPaste.getAttribute("disabled"), "true", "cmdPaste is disabled"); - } + is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled"); yield cleanup(toolbox); }); diff --git a/devtools/client/inspector/computed/test/browser_computed_search-filter_context-menu.js b/devtools/client/inspector/computed/test/browser_computed_search-filter_context-menu.js index b5dbe4475..b04a247f5 100644 --- a/devtools/client/inspector/computed/test/browser_computed_search-filter_context-menu.js +++ b/devtools/client/inspector/computed/test/browser_computed_search-filter_context-menu.js @@ -45,15 +45,12 @@ add_task(function* () { is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled"); is(cmdSelectAll.getAttribute("disabled"), "true", "cmdSelectAll is disabled"); - // Cut/Copy items are enabled in context menu even if there - // is no selection. See also Bug 1303033 + // Cut/Copy/Paste items are enabled in context menu even if there is no + // selection. See also Bug 1303033, and 1317322 is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled"); is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled"); - if (isWindows()) { - // emptyClipboard only works on Windows (666254), assert paste only for this OS. - is(cmdPaste.getAttribute("disabled"), "true", "cmdPaste is disabled"); - } + is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled"); info("Closing context menu"); let onContextMenuHidden = once(searchContextMenu, "popuphidden"); diff --git a/devtools/client/inspector/markup/test/browser_markup_events3.js b/devtools/client/inspector/markup/test/browser_markup_events3.js index a9dc2a499..a38e9a011 100644 --- a/devtools/client/inspector/markup/test/browser_markup_events3.js +++ b/devtools/client/inspector/markup/test/browser_markup_events3.js @@ -115,7 +115,7 @@ const TEST_DATA = [ // eslint-disable-line expected: [ { type: "click", - filename: TEST_URL + ":1", + filename: TEST_URL + ":0", attributes: [ "Bubbling", "DOM2" @@ -129,7 +129,7 @@ const TEST_DATA = [ // eslint-disable-line expected: [ { type: "click", - filename: TEST_URL + ":1", + filename: TEST_URL + ":0", attributes: [ "Bubbling", "DOM2" diff --git a/devtools/client/inspector/rules/test/browser_rules_search-filter_context-menu.js b/devtools/client/inspector/rules/test/browser_rules_search-filter_context-menu.js index 349f1b9b3..d66df91ab 100644 --- a/devtools/client/inspector/rules/test/browser_rules_search-filter_context-menu.js +++ b/devtools/client/inspector/rules/test/browser_rules_search-filter_context-menu.js @@ -44,15 +44,12 @@ add_task(function* () { is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled"); is(cmdSelectAll.getAttribute("disabled"), "true", "cmdSelectAll is disabled"); - // Cut/Copy items are enabled in context menu even if there - // is no selection. See also Bug 1303033 + // Cut/Copy/Paste items are enabled in context menu even if there is no + // selection. See also Bug 1303033, and 1317322 is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled"); is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled"); - if (isWindows()) { - // emptyClipboard only works on Windows (666254), assert paste only for this OS. - is(cmdPaste.getAttribute("disabled"), "true", "cmdPaste is disabled"); - } + is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled"); info("Closing context menu"); let onContextMenuHidden = once(searchContextMenu, "popuphidden"); diff --git a/devtools/client/inspector/test/browser_inspector_search-filter_context-menu.js b/devtools/client/inspector/test/browser_inspector_search-filter_context-menu.js index 137456468..7bd4b5e6f 100644 --- a/devtools/client/inspector/test/browser_inspector_search-filter_context-menu.js +++ b/devtools/client/inspector/test/browser_inspector_search-filter_context-menu.js @@ -43,14 +43,11 @@ add_task(function* () { is(cmdSelectAll.getAttribute("disabled"), "true", "cmdSelectAll is disabled"); // Cut/Copy items are enabled in context menu even if there - // is no selection. See also Bug 1303033 + // is no selection. See also Bug 1303033, and 1317322 is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled"); is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled"); - if (isWindows()) { - // emptyClipboard only works on Windows (666254), assert paste only for this OS. - is(cmdPaste.getAttribute("disabled"), "true", "cmdPaste is disabled"); - } + is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled"); info("Closing context menu"); let onContextMenuHidden = once(searchContextMenu, "popuphidden"); diff --git a/devtools/client/menus.js b/devtools/client/menus.js index 7e36839da..1d2168967 100644 --- a/devtools/client/menus.js +++ b/devtools/client/menus.js @@ -183,9 +183,9 @@ exports.menuitems = [ } }, { separator: true, - id: "devToolsEndSeparator" + id: "menu_devToolsEndSeparator" }, - { id: "getMoreDevtools", + { id: "menu_getMoreDevtools", l10nKey: "getMoreDevtoolsCmd", oncommand(event) { let window = event.target.ownerDocument.defaultView; diff --git a/devtools/client/netmonitor/request-list-context-menu.js b/devtools/client/netmonitor/request-list-context-menu.js index 331a7bde3..bacb7dc33 100644 --- a/devtools/client/netmonitor/request-list-context-menu.js +++ b/devtools/client/netmonitor/request-list-context-menu.js @@ -186,7 +186,6 @@ RequestListContextMenu.prototype = { * Opens selected item in a new tab. */ openRequestInTab() { - let win = Services.wm.getMostRecentWindow(gDevTools.chromeWindowType); openRequestInTab(this.selectedItem.attachment); }, diff --git a/devtools/client/scratchpad/test/head.js b/devtools/client/scratchpad/test/head.js index 15619a169..955c037d7 100644 --- a/devtools/client/scratchpad/test/head.js +++ b/devtools/client/scratchpad/test/head.js @@ -9,6 +9,7 @@ const {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm", {}); const {console} = Cu.import("resource://gre/modules/Console.jsm", {}); const {ScratchpadManager} = Cu.import("resource://devtools/client/scratchpad/scratchpad-manager.jsm", {}); const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {}); +const {gDevTools} = require("devtools/client/framework/devtools"); const Services = require("Services"); const DevToolsUtils = require("devtools/shared/DevToolsUtils"); const flags = require("devtools/shared/flags"); diff --git a/devtools/client/shared/developer-toolbar.js b/devtools/client/shared/developer-toolbar.js index 2528591a6..d84402418 100644 --- a/devtools/client/shared/developer-toolbar.js +++ b/devtools/client/shared/developer-toolbar.js @@ -449,7 +449,15 @@ DeveloperToolbar.prototype.show = function (focus) { [ this.tooltipPanel, this.outputPanel ] = panels; - this._doc.getElementById("menu_devToolbar").setAttribute("checked", "true"); + let checkboxValue = "true"; + let appmenuEl = this._doc.getElementById("appmenu_devToolbar"); + let menuEl = this._doc.getElementById("menu_devToolbar"); + if (appmenuEl) { + appmenuEl.setAttribute("checked", checkboxValue); + } + if (menuEl) { + menuEl.setAttribute("checked", checkboxValue); + } this.target = TargetFactory.forTab(this._chromeWindow.gBrowser.selectedTab); const options = { @@ -569,7 +577,15 @@ DeveloperToolbar.prototype.hide = function () { Services.prefs.setBoolPref("devtools.toolbar.visible", false); - this._doc.getElementById("menu_devToolbar").setAttribute("checked", "false"); + let checkboxValue = "false"; + let appmenuEl = this._doc.getElementById("appmenu_devToolbar"); + let menuEl = this._doc.getElementById("menu_devToolbar"); + if (appmenuEl) { + appmenuEl.setAttribute("checked", checkboxValue); + } + if (menuEl) { + menuEl.setAttribute("checked", checkboxValue); + } this.destroy(); this._telemetry.toolClosed("developertoolbar"); diff --git a/devtools/client/shared/widgets/TableWidget.js b/devtools/client/shared/widgets/TableWidget.js index a0f0dfc11..57d2914d5 100644 --- a/devtools/client/shared/widgets/TableWidget.js +++ b/devtools/client/shared/widgets/TableWidget.js @@ -463,7 +463,14 @@ TableWidget.prototype = { return; } - let selectedCell = this.tbody.querySelector(".theme-selected"); + // We need to get the first *visible* selected cell. Some columns are hidden + // e.g. because they contain a unique compound key for cookies that is never + // displayed in the UI. To do this we get all selected cells and filter out + // any that are hidden. + let selectedCells = [...this.tbody.querySelectorAll(".theme-selected")] + .filter(cell => cell.clientWidth > 0); + // Select the first visible selected cell. + let selectedCell = selectedCells[0]; if (!selectedCell) { return; } diff --git a/devtools/client/storage/ui.js b/devtools/client/storage/ui.js index 7745c8da9..5bd29d297 100644 --- a/devtools/client/storage/ui.js +++ b/devtools/client/storage/ui.js @@ -482,24 +482,27 @@ StorageUI.prototype = { * @param {object} See onUpdate docs */ handleChangedItems: function (changed) { - if (this.tree.selectedItem) { - let [type, host, db, objectStore] = this.tree.selectedItem; - if (!changed[type] || !changed[type][host] || - changed[type][host].length == 0) { - return; - } - try { - let toUpdate = []; - for (let name of changed[type][host]) { - let names = JSON.parse(name); - if (names[0] == db && names[1] == objectStore && names[2]) { - toUpdate.push(name); - } + let selectedItem = this.tree.selectedItem; + if (!selectedItem) { + return; + } + + let [type, host, db, objectStore] = selectedItem; + if (!changed[type] || !changed[type][host] || + changed[type][host].length == 0) { + return; + } + try { + let toUpdate = []; + for (let name of changed[type][host]) { + let names = JSON.parse(name); + if (names[0] == db && names[1] == objectStore && names[2]) { + toUpdate.push(name); } - this.fetchStorageObjects(type, host, toUpdate, REASON.UPDATE); - } catch (ex) { - this.fetchStorageObjects(type, host, changed[type][host], REASON.UPDATE); } + this.fetchStorageObjects(type, host, toUpdate, REASON.UPDATE); + } catch (ex) { + this.fetchStorageObjects(type, host, changed[type][host], REASON.UPDATE); } }, @@ -830,6 +833,7 @@ StorageUI.prototype = { if (!item) { return; } + this.table.clear(); this.hideSidebar(); this.searchBox.value = ""; @@ -1136,11 +1140,13 @@ StorageUI.prototype = { * Handles adding an item from the storage */ onAddItem: function () { - if (!this.tree.selectedItem) { + let selectedItem = this.tree.selectedItem; + if (!selectedItem) { return; } + let front = this.getCurrentFront(); - let [, host] = this.tree.selectedItem; + let [, host] = selectedItem; // Prepare to scroll into view. this.table.scrollIntoViewOnUpdate = true; diff --git a/devtools/client/webconsole/new-console-output/test/mochitest/head.js b/devtools/client/webconsole/new-console-output/test/mochitest/head.js index b71eaec4f..049f3d1ce 100644 --- a/devtools/client/webconsole/new-console-output/test/mochitest/head.js +++ b/devtools/client/webconsole/new-console-output/test/mochitest/head.js @@ -14,6 +14,7 @@ Services.scriptloader.loadSubScript( var {Utils: WebConsoleUtils} = require("devtools/client/webconsole/utils"); const WEBCONSOLE_STRINGS_URI = "devtools/client/locales/webconsole.properties"; +var {HUDService} = require("devtools/client/webconsole/hudservice"); var WCUL10n = new WebConsoleUtils.L10n(WEBCONSOLE_STRINGS_URI); Services.prefs.setBoolPref("devtools.webconsole.new-frontend-enabled", true); diff --git a/devtools/client/webconsole/test/browser_webconsole_closure_inspection.js b/devtools/client/webconsole/test/browser_webconsole_closure_inspection.js index 6a29d61aa..769fc0fe5 100644 --- a/devtools/client/webconsole/test/browser_webconsole_closure_inspection.js +++ b/devtools/client/webconsole/test/browser_webconsole_closure_inspection.js @@ -58,7 +58,7 @@ function consoleOpened(hud) { waitForMessages({ webconsole: gWebConsole, messages: [{ - text: "function _pfactory/<.getName()", + text: "getName()", category: CATEGORY_OUTPUT, objects: true, }], diff --git a/devtools/client/webconsole/test/browser_webconsole_jsterm.js b/devtools/client/webconsole/test/browser_webconsole_jsterm.js index 221c96fa6..ae5dc71fe 100644 --- a/devtools/client/webconsole/test/browser_webconsole_jsterm.js +++ b/devtools/client/webconsole/test/browser_webconsole_jsterm.js @@ -175,7 +175,6 @@ function* testJSTerm(hud) { "JSMSG_BAD_RADIX": "(42).toString(0);", "JSMSG_BAD_ARRAY_LENGTH": "([]).length = -1", "JSMSG_NEGATIVE_REPETITION_COUNT": "'abc'.repeat(-1);", - "JSMSG_BAD_FORMAL": "var f = Function('x y', 'return x + y;');", "JSMSG_PRECISION_RANGE": "77.1234.toExponential(-1);", }; diff --git a/devtools/client/webconsole/test/browser_webconsole_output_02.js b/devtools/client/webconsole/test/browser_webconsole_output_02.js index 8018669a9..4c61cf041 100644 --- a/devtools/client/webconsole/test/browser_webconsole_output_02.js +++ b/devtools/client/webconsole/test/browser_webconsole_output_02.js @@ -36,10 +36,10 @@ var inputTests = [ suppressClick: true }, - // 3 - anonymous function, but spidermonkey gives us an inferred name. + // 3 - anonymous function, but gets name. { input: "testobj1.testfn2", - output: "function testobj1.testfn2()", + output: "function testfn2()", printOutput: "function () { return 42; }", suppressClick: true }, diff --git a/devtools/client/webconsole/webconsole.xul b/devtools/client/webconsole/webconsole.xul index cd3e44d82..1310fb57d 100644 --- a/devtools/client/webconsole/webconsole.xul +++ b/devtools/client/webconsole/webconsole.xul @@ -7,6 +7,8 @@ %webConsoleDTD; ]> <?xml-stylesheet href="chrome://global/skin/" type="text/css"?> +<?xml-stylesheet href="resource://devtools/client/themes/common.css" + type="text/css"?> <?xml-stylesheet href="chrome://devtools/skin/widgets.css" type="text/css"?> <?xml-stylesheet href="chrome://devtools/skin/webconsole.css" diff --git a/devtools/server/actors/errordocs.js b/devtools/server/actors/errordocs.js index 27f687dc7..7c4b3acff 100644 --- a/devtools/server/actors/errordocs.js +++ b/devtools/server/actors/errordocs.js @@ -18,7 +18,6 @@ const ErrorDocs = { JSMSG_RESULTING_STRING_TOO_LARGE: "Resulting_string_too_large", JSMSG_BAD_RADIX: "Bad_radix", JSMSG_PRECISION_RANGE: "Precision_range", - JSMSG_BAD_FORMAL: "Malformed_formal_parameter", JSMSG_STMT_AFTER_RETURN: "Stmt_after_return", JSMSG_NOT_A_CODEPOINT: "Not_a_codepoint", JSMSG_BAD_SORT_ARG: "Array_sort_argument", diff --git a/devtools/server/actors/object.js b/devtools/server/actors/object.js index 1f417b951..06e95a5f0 100644 --- a/devtools/server/actors/object.js +++ b/devtools/server/actors/object.js @@ -1158,11 +1158,6 @@ DebuggerServer.ObjectActorPreviewers = { }], RegExp: [function ({obj, hooks}, grip) { - // Avoid having any special preview for the RegExp.prototype itself. - if (!obj.proto || obj.proto.class != "RegExp") { - return false; - } - let str = RegExp.prototype.toString.call(obj.unsafeDereference()); grip.displayString = hooks.createValueGrip(str); return true; diff --git a/devtools/server/actors/webconsole.js b/devtools/server/actors/webconsole.js index 9712ff32d..a1eba84ed 100644 --- a/devtools/server/actors/webconsole.js +++ b/devtools/server/actors/webconsole.js @@ -778,8 +778,8 @@ WebConsoleActor.prototype = } // See `window` definition. It isn't always a DOM Window. - let requestStartTime = this.window && this.window.performance ? - this.window.performance.timing.requestStart : 0; + let winStartTime = this.window && this.window.performance ? + this.window.performance.timing.navigationStart : 0; let cache = this.consoleAPIListener .getCachedMessages(!this.parentActor.isRootActor); @@ -787,7 +787,7 @@ WebConsoleActor.prototype = // Filter out messages that came from a ServiceWorker but happened // before the page was requested. if (aMessage.innerID === "ServiceWorker" && - requestStartTime > aMessage.timeStamp) { + winStartTime > aMessage.timeStamp) { return; } diff --git a/devtools/server/event-parsers.js b/devtools/server/event-parsers.js index a813d8e9b..6245af190 100644 --- a/devtools/server/event-parsers.js +++ b/devtools/server/event-parsers.js @@ -91,44 +91,58 @@ var parsers = [ return jQueryLiveGetListeners(node, false); }, normalizeHandler: function (handlerDO) { - let paths = [ - [".event.proxy/", ".event.proxy/", "*"], - [".proxy/", "*"] - ]; - - let name = handlerDO.displayName; + function isFunctionInProxy(funcDO) { + // If the anonymous function is inside the |proxy| function and the + // function only has guessed atom, the guessed atom should starts with + // "proxy/". + let displayName = funcDO.displayName; + if (displayName && displayName.startsWith("proxy/")) { + return true; + } - if (!name) { - return handlerDO; + // If the anonymous function is inside the |proxy| function and the + // function gets name at compile time by SetFunctionName, its guessed + // atom doesn't contain "proxy/". In that case, check if the caller is + // "proxy" function, as a fallback. + let calleeDO = funcDO.environment.callee; + if (!calleeDO) { + return false; + } + let calleeName = calleeDO.displayName; + return calleeName == "proxy"; } - for (let path of paths) { - if (name.includes(path[0])) { - path.splice(0, 1); - - for (let point of path) { - let names = handlerDO.environment.names(); + function getFirstFunctionVariable(funcDO) { + // The handler function inside the |proxy| function should point the + // unwrapped function via environment variable. + let names = funcDO.environment.names(); + for (let varName of names) { + let varDO = handlerDO.environment.getVariable(varName); + if (!varDO) { + continue; + } + if (varDO.class == "Function") { + return varDO; + } + } + return null; + } - for (let varName of names) { - let temp = handlerDO.environment.getVariable(varName); - if (!temp) { - continue; - } + if (!isFunctionInProxy(handlerDO)) { + return handlerDO; + } - let displayName = temp.displayName; - if (!displayName) { - continue; - } + const MAX_NESTED_HANDLER_COUNT = 2; + for (let i = 0; i < MAX_NESTED_HANDLER_COUNT; i++) { + let funcDO = getFirstFunctionVariable(handlerDO); + if (!funcDO) + return handlerDO; - if (temp.class === "Function" && - (displayName.includes(point) || point === "*")) { - handlerDO = temp; - break; - } - } - } - break; + handlerDO = funcDO; + if (isFunctionInProxy(handlerDO)) { + continue; } + break; } return handlerDO; diff --git a/devtools/server/tests/mochitest/test_memory_allocations_05.html b/devtools/server/tests/mochitest/test_memory_allocations_05.html index 0eeb7bd16..4b6b4f0ea 100644..100755 --- a/devtools/server/tests/mochitest/test_memory_allocations_05.html +++ b/devtools/server/tests/mochitest/test_memory_allocations_05.html @@ -70,8 +70,9 @@ window.onload = function() { if (lastTimestamp) { var delta = timestamp - lastTimestamp; info("delta since last timestamp", delta); - ok(delta >= 1 /* ms */, - "The timestamp should be about 1 ms after the last timestamp."); + // If we're unlucky, we might have rounded down to 0ms + // ok(delta >= 1 /* ms */, + // "The timestamp should be about 1 ms after the last timestamp."); } lastTimestamp = timestamp; diff --git a/devtools/server/tests/unit/test_functiongrips-01.js b/devtools/server/tests/unit/test_functiongrips-01.js index c41a7cad5..81b1b7767 100644 --- a/devtools/server/tests/unit/test_functiongrips-01.js +++ b/devtools/server/tests/unit/test_functiongrips-01.js @@ -52,7 +52,7 @@ function test_inferred_name_function() { do_check_eq(args[0].class, "Function"); // No name for an anonymous function, but it should have an inferred name. do_check_eq(args[0].name, undefined); - do_check_eq(args[0].displayName, "o.m"); + do_check_eq(args[0].displayName, "m"); let objClient = gThreadClient.pauseGrip(args[0]); objClient.getParameterNames(function (aResponse) { diff --git a/devtools/shared/webconsole/test/test_page_errors.html b/devtools/shared/webconsole/test/test_page_errors.html index 19e5ba4b4..78138856e 100644 --- a/devtools/shared/webconsole/test/test_page_errors.html +++ b/devtools/shared/webconsole/test/test_page_errors.html @@ -102,16 +102,6 @@ function doPageErrors() warning: false, exception: true, }, - "var f = Function('x y', 'return x + y;');": { - errorMessage: /malformed formal/, - errorMessageName: "JSMSG_BAD_FORMAL", - sourceName: /test_page_errors/, - category: "chrome javascript", - timeStamp: /^\d+$/, - error: false, - warning: false, - exception: true, - }, "function a() { return; 1 + 1; }": { errorMessage: /unreachable code/, errorMessageName: "JSMSG_STMT_AFTER_RETURN", |