68.14.8 - devtools

This commit is contained in:
Fedor 2025-04-19 19:11:17 +03:00
parent 2c58d3cb35
commit 1217ab2f99
807 changed files with 25709 additions and 38536 deletions

View File

@ -21,8 +21,6 @@ module.exports = {
} }
}, { }, {
"files": [ "files": [
"client/scratchpad/scratchpad-manager.jsm",
"client/scratchpad/scratchpad.js",
"client/shared/*.jsm", "client/shared/*.jsm",
], ],
"rules": { "rules": {
@ -31,7 +29,6 @@ module.exports = {
}, { }, {
"files": [ "files": [
"client/framework/**", "client/framework/**",
"client/scratchpad/**",
"client/shared/*.jsm", "client/shared/*.jsm",
"client/shared/widgets/*.jsm", "client/shared/widgets/*.jsm",
], ],
@ -41,23 +38,13 @@ module.exports = {
}, { }, {
"files": [ "files": [
"client/framework/**", "client/framework/**",
"client/scratchpad/**",
], ],
"rules": { "rules": {
"max-nested-callbacks": "off", "max-nested-callbacks": "off",
} }
}, {
"files": [
"client/scratchpad/test/browser_scratchpad_inspect.js",
"client/scratchpad/test/browser_scratchpad_inspect_primitives.js",
],
"rules": {
"no-labels": "off",
}
}, { }, {
"files": [ "files": [
"client/framework/**", "client/framework/**",
"client/scratchpad/**",
"client/shared/*.jsm", "client/shared/*.jsm",
"client/shared/widgets/*.jsm", "client/shared/widgets/*.jsm",
], ],
@ -67,7 +54,6 @@ module.exports = {
}, { }, {
"files": [ "files": [
"client/framework/test/**", "client/framework/test/**",
"client/scratchpad/**",
], ],
"rules": { "rules": {
"mozilla/var-only-at-top-level": "off", "mozilla/var-only-at-top-level": "off",
@ -75,7 +61,6 @@ module.exports = {
}, { }, {
"files": [ "files": [
"client/framework/**", "client/framework/**",
"client/scratchpad/**",
"client/shared/widgets/*.jsm", "client/shared/widgets/*.jsm",
], ],
"rules": { "rules": {
@ -84,7 +69,6 @@ module.exports = {
}, { }, {
"files": [ "files": [
"client/framework/**", "client/framework/**",
"client/scratchpad/**",
], ],
"rules": { "rules": {
"strict": "off", "strict": "off",

View File

@ -7,7 +7,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>Debugging</title> <title>Debugging</title>
<meta http-equiv="Content-Security-Policy" <meta http-equiv="Content-Security-Policy"
content="default-src chrome: resource:; img-src data: chrome: resource: https:" /> content="default-src chrome: resource:; img-src data: chrome: resource: https:; object-src 'none'" />
<link rel="icon" type="image/png" href="chrome://browser/skin/developer.svg"> <link rel="icon" type="image/png" href="chrome://browser/skin/developer.svg">
<link rel="stylesheet" href="chrome://devtools/content/aboutdebugging/aboutdebugging.css"/> <link rel="stylesheet" href="chrome://devtools/content/aboutdebugging/aboutdebugging.css"/>
<script src="resource://devtools/client/aboutdebugging/initializer.js"></script> <script src="resource://devtools/client/aboutdebugging/initializer.js"></script>

View File

@ -447,8 +447,7 @@ function updateRemoteRuntimes(runtimes, type) {
runtimes.forEach(runtime => { runtimes.forEach(runtime => {
const existingRuntime = findRuntimeById(runtime.id, getState().runtimes); const existingRuntime = findRuntimeById(runtime.id, getState().runtimes);
const isConnectionValid = const isConnectionValid =
existingRuntime && existingRuntime?.runtimeDetails &&
existingRuntime.runtimeDetails &&
!existingRuntime.runtimeDetails.clientWrapper.isClosed(); !existingRuntime.runtimeDetails.clientWrapper.isClosed();
runtime.runtimeDetails = isConnectionValid runtime.runtimeDetails = isConnectionValid
? existingRuntime.runtimeDetails ? existingRuntime.runtimeDetails

View File

@ -90,7 +90,7 @@ class App extends PureComponent {
...this.props.usbRuntimes, ...this.props.usbRuntimes,
]; ];
const runtime = runtimes.find(x => x.id === id); const runtime = runtimes.find(x => x.id === id);
return runtime && runtime.runtimeDetails; return runtime?.runtimeDetails;
}; };
const { dispatch } = this.props; const { dispatch } = this.props;

View File

@ -58,9 +58,9 @@ function getRuntimeEventExtras(runtime) {
const { extra, runtimeDetails } = runtime; const { extra, runtimeDetails } = runtime;
// deviceName can be undefined for non-usb devices, but we should not log "undefined". // deviceName can be undefined for non-usb devices, but we should not log "undefined".
const deviceName = (extra && extra.deviceName) || ""; const deviceName = extra?.deviceName || "";
const runtimeShortName = runtime.type === RUNTIMES.USB ? runtime.name : ""; const runtimeShortName = runtime.type === RUNTIMES.USB ? runtime.name : "";
const runtimeName = (runtimeDetails && runtimeDetails.info.name) || ""; const runtimeName = runtimeDetails?.info.name || "";
return { return {
connection_type: runtime.type, connection_type: runtime.type,
device_name: deviceName, device_name: deviceName,
@ -125,8 +125,7 @@ function onRemoteRuntimesUpdated(action, store) {
const oldRuntime = oldRuntimes.find( const oldRuntime = oldRuntimes.find(
r => r.extra.deviceName === oldDeviceName r => r.extra.deviceName === oldDeviceName
); );
const isUnplugged = const isUnplugged = newRuntime?.isUnplugged && !oldRuntime.isUnplugged;
newRuntime && newRuntime.isUnplugged && !oldRuntime.isUnplugged;
if (oldDeviceName && (!newRuntime || isUnplugged)) { if (oldDeviceName && (!newRuntime || isUnplugged)) {
recordEvent("device_removed", { recordEvent("device_removed", {
connection_type: action.runtimeType, connection_type: action.runtimeType,
@ -153,8 +152,7 @@ function onRemoteRuntimesUpdated(action, store) {
const oldRuntime = oldRuntimes.find( const oldRuntime = oldRuntimes.find(
r => r.extra.deviceName === newDeviceName r => r.extra.deviceName === newDeviceName
); );
const isPlugged = const isPlugged = oldRuntime?.isUnplugged && !newRuntime.isUnplugged;
oldRuntime && oldRuntime.isUnplugged && !newRuntime.isUnplugged;
if (newDeviceName && (!oldRuntime || isPlugged)) { if (newDeviceName && (!oldRuntime || isPlugged)) {
recordEvent("device_added", { recordEvent("device_added", {

View File

@ -257,12 +257,6 @@ async function toolboxTestScript(toolbox, devtoolsTab) {
const waitForNavigated = toolbox.target.once("navigate"); const waitForNavigated = toolbox.target.once("navigate");
popupFrameBtn.click(); popupFrameBtn.click();
// Clicking the menu item may do highlighting.
await waitUntil(() => toolbox.highlighter);
await Promise.race([
toolbox.highlighter.once("node-highlight"),
wait(1000),
]);
await waitForNavigated; await waitForNavigated;
consoleWrapper.dispatchEvaluateExpression( consoleWrapper.dispatchEvaluateExpression(
"myWebExtensionPopupAddonFunction()" "myWebExtensionPopupAddonFunction()"

View File

@ -14,6 +14,7 @@ add_task(async function() {
const { document, tab, window } = await openAboutDebugging(); const { document, tab, window } = await openAboutDebugging();
await selectThisFirefoxPage(document, window.AboutDebugging.store); await selectThisFirefoxPage(document, window.AboutDebugging.store);
await pushPref("extensions.webextensions.warnings-as-errors", false);
await installTemporaryExtensionFromXPI( await installTemporaryExtensionFromXPI(
{ {
id: EXTENSION_ID, id: EXTENSION_ID,
@ -25,6 +26,7 @@ add_task(async function() {
}, },
document document
); );
await SpecialPowers.popPrefEnv();
info("Wait until a debug target item appears"); info("Wait until a debug target item appears");
await waitUntil(() => findDebugTargetByText(EXTENSION_NAME, document)); await waitUntil(() => findDebugTargetByText(EXTENSION_NAME, document));

View File

@ -54,6 +54,7 @@ async function testCloseMessageWithButton(warningMessage, doc) {
} }
async function installExtensionWithWarning(doc) { async function installExtensionWithWarning(doc) {
await pushPref("extensions.webextensions.warnings-as-errors", false);
await installTemporaryExtensionFromXPI( await installTemporaryExtensionFromXPI(
{ {
id: EXTENSION_ID, id: EXTENSION_ID,
@ -65,6 +66,7 @@ async function installExtensionWithWarning(doc) {
}, },
doc doc
); );
await SpecialPowers.popPrefEnv();
info("Wait until a debug target item appears"); info("Wait until a debug target item appears");
await waitUntil(() => findDebugTargetByText(EXTENSION_NAME, doc)); await waitUntil(() => findDebugTargetByText(EXTENSION_NAME, doc));

View File

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict"; "use strict";
/* global EVENTS, gToolbox */ /* global EVENTS */
const nodeConstants = require("devtools/shared/dom-node-constants"); const nodeConstants = require("devtools/shared/dom-node-constants");

View File

@ -4,7 +4,6 @@
:root { :root {
--accessibility-font-size: 12px; --accessibility-font-size: 12px;
--accessibility-toolbar-height: 24px;
--accessibility-toolbar-height-tall: 35px; --accessibility-toolbar-height-tall: 35px;
--accessibility-toolbar-focus: var(--blue-50); --accessibility-toolbar-focus: var(--blue-50);
--accessibility-toolbar-focus-alpha30: rgba(10, 132, 255, 0.3); --accessibility-toolbar-focus-alpha30: rgba(10, 132, 255, 0.3);
@ -12,7 +11,12 @@
--accessibility-horizontal-padding: 5px; --accessibility-horizontal-padding: 5px;
--accessibility-horizontal-indent: 20px; --accessibility-horizontal-indent: 20px;
--accessibility-properties-item-width: calc(100% - var(--accessibility-horizontal-indent)); --accessibility-properties-item-width: calc(100% - var(--accessibility-horizontal-indent));
--accessibility-tree-height: calc(100vh - var(--accessibility-toolbar-height) * 2 - 1px); /* The main content can use the full height minus the height of the toolbar
(including 1px border bottom) */
--accessibility-main-height: calc(100vh - var(--theme-toolbar-height) - 1px);
/* The tree can use the main content height minus the height of the tree
header, which has the same height as the toolbar and a 1px border bottom */
--accessibility-tree-height: calc(var(--accessibility-main-height) - var(--theme-toolbar-height) - 1px);
--accessibility-arrow-horizontal-padding: 4px; --accessibility-arrow-horizontal-padding: 4px;
--accessibility-tree-row-height: 21px; --accessibility-tree-row-height: 21px;
--accessibility-unfocused-tree-focused-node-background: var(--grey-20); --accessibility-unfocused-tree-focused-node-background: var(--grey-20);
@ -96,7 +100,7 @@ body {
} }
.split-box.horz { .split-box.horz {
height: calc(100vh - var(--accessibility-toolbar-height)); height: var(--accessibility-main-height);
} }
.mainFrame .devtools-button, .mainFrame .devtools-button,
@ -369,7 +373,7 @@ body {
background: var(--theme-toolbar-background); background: var(--theme-toolbar-background);
font: message-box; font: message-box;
font-size: var(--accessibility-font-size); font-size: var(--accessibility-font-size);
height: var(--accessibility-toolbar-height); height: var(--theme-toolbar-height);
color: var(--theme-toolbar-color); color: var(--theme-toolbar-color);
} }
@ -452,14 +456,14 @@ body {
.split-box:not(.horz) .right-sidebar { .split-box:not(.horz) .right-sidebar {
position: fixed; position: fixed;
width: inherit; width: inherit;
height: calc(100vh - (var(--accessibility-toolbar-height))); height: var(--accessibility-main-height)
} }
.right-sidebar ._header { .right-sidebar ._header {
background-color: var(--theme-toolbar-background); background-color: var(--theme-toolbar-background);
border-bottom: 1px solid var(--theme-splitter-color); border-bottom: 1px solid var(--theme-splitter-color);
height: var(--accessibility-toolbar-height); height: var(--theme-toolbar-height);
line-height: var(--accessibility-toolbar-height); line-height: var(--theme-toolbar-height);
padding-inline-start: 14px; padding-inline-start: 14px;
padding-inline-end: var(--accessibility-arrow-horizontal-padding); padding-inline-end: var(--accessibility-arrow-horizontal-padding);
display: flex; display: flex;
@ -683,7 +687,7 @@ body {
margin: 0; margin: 0;
font-weight: bold; font-weight: bold;
font-size: var(--accessibility-font-size); font-size: var(--accessibility-font-size);
line-height: var(--accessibility-toolbar-height); line-height: var(--theme-toolbar-height);
} }
.accessibility-color-contrast-annotation { .accessibility-color-contrast-annotation {

View File

@ -190,20 +190,22 @@ class Accessible extends Component {
this.setState({ expanded }); this.setState({ expanded });
} }
showHighlighter(nodeFront) { async showHighlighter(nodeFront) {
if (!gToolbox) { if (!gToolbox) {
return; return;
} }
gToolbox.highlighter.highlight(nodeFront); const { highlighterFront } = nodeFront;
await highlighterFront.highlight(nodeFront);
} }
hideHighlighter() { async hideHighlighter(nodeFront) {
if (!gToolbox) { if (!gToolbox) {
return; return;
} }
gToolbox.highlighter.unhighlight(); const { highlighterFront } = nodeFront;
await highlighterFront.unhighlight();
} }
showAccessibleHighlighter(accessible) { showAccessibleHighlighter(accessible) {
@ -286,7 +288,8 @@ class Accessible extends Component {
if (isNode(object)) { if (isNode(object)) {
valueProps.defaultRep = ElementNode; valueProps.defaultRep = ElementNode;
valueProps.onDOMNodeMouseOut = () => this.hideHighlighter(); valueProps.onDOMNodeMouseOut = () =>
this.hideHighlighter(this.props.DOMNode);
valueProps.onDOMNodeMouseOver = () => valueProps.onDOMNodeMouseOver = () =>
this.showHighlighter(this.props.DOMNode); this.showHighlighter(this.props.DOMNode);
valueProps.onInspectIconClick = () => this.selectNode(this.props.DOMNode); valueProps.onInspectIconClick = () => this.selectNode(this.props.DOMNode);

View File

@ -248,16 +248,11 @@ AccessibilityPanel.prototype = {
return this._toolbox.target; return this._toolbox.target;
}, },
async destroy() { destroy() {
if (this._destroying) { if (this._destroyed) {
await this._destroying;
return; return;
} }
this._destroyed = true;
let resolver;
this._destroying = new Promise(resolve => {
resolver = resolve;
});
this.target.off("navigate", this.onTabNavigated); this.target.off("navigate", this.onTabNavigated);
this._toolbox.off("select", this.onPanelVisibilityChange); this._toolbox.off("select", this.onPanelVisibilityChange);
@ -290,8 +285,6 @@ AccessibilityPanel.prototype = {
this.panelWin.gTelemetry = null; this.panelWin.gTelemetry = null;
this.emit("destroyed"); this.emit("destroyed");
resolver();
}, },
}; };

View File

@ -38,7 +38,7 @@ function accessibles(state = getInitialState(), action) {
} }
function getActorID(accessible) { function getActorID(accessible) {
return accessible.actorID || (accessible._form && accessible._form.actor); return accessible.actorID || accessible._form?.actor;
} }
/** /**

View File

@ -38,8 +38,6 @@ class ApplicationPanel {
this.panelWin = null; this.panelWin = null;
this.toolbox = null; this.toolbox = null;
this.emit("destroyed"); this.emit("destroyed");
return this;
} }
} }

View File

@ -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/>. */
"use strict";
module.exports.PluralForm = {
get(num, str) {
return str;
},
};

View File

@ -0,0 +1,23 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
/**
* Mock for devtools/client/shared/modules/fluent-l10n/fluent-l10n
*/
class FluentL10n {
async init() {}
getBundles() {
return [];
}
getString(id, args) {
return args ? `${id}__${JSON.stringify(args)}` : id;
}
}
// Export the class
exports.FluentL10n = FluentL10n;

View File

@ -1,23 +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/>. */
"use strict";
// @TODO Load the actual strings from instead.
class L10N {
getStr(str) {
switch (str) {
default:
return str;
}
}
getFormatStr(str) {
return this.getStr(str);
}
}
module.exports = {
L10N: new L10N(),
};

View File

@ -9,11 +9,10 @@ module.exports = {
verbose: true, verbose: true,
moduleNameMapper: { moduleNameMapper: {
// Custom name mappers for modules that require m-c specific API. // Custom name mappers for modules that require m-c specific API.
"^../utils/l10n": `${__dirname}/fixtures/l10n`,
"^devtools/client/shared/link": `${__dirname}/fixtures/stub`, "^devtools/client/shared/link": `${__dirname}/fixtures/stub`,
"^devtools/shared/plural-form": `${__dirname}/fixtures/plural-form`,
"^chrome": `${__dirname}/fixtures/Chrome`, "^chrome": `${__dirname}/fixtures/Chrome`,
"^Services": `${__dirname}/fixtures/Services`, "^Services": `${__dirname}/fixtures/Services`,
"^devtools/client/shared/fluent-l10n/fluent-l10n$": `${__dirname}/fixtures/fluent-l10n`,
"^devtools/client/shared/unicode-url": `${__dirname}/fixtures/unicode-url`, "^devtools/client/shared/unicode-url": `${__dirname}/fixtures/unicode-url`,
// Map all require("devtools/...") to the real devtools root. // Map all require("devtools/...") to the real devtools root.
"^devtools\\/(.*)": `${__dirname}/../../../../$1`, "^devtools\\/(.*)": `${__dirname}/../../../../$1`,

View File

@ -20,3 +20,4 @@
suppress_comment=\\(.\\|\n\\)*\\$FlowIgnore suppress_comment=\\(.\\|\n\\)*\\$FlowIgnore
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe
module.name_mapper='^debugger-html$' -> '<PROJECT_ROOT>/src/types.js' module.name_mapper='^debugger-html$' -> '<PROJECT_ROOT>/src/types.js'
esproposal.optional_chaining=enable

View File

@ -32,6 +32,8 @@ module.exports = {
plugins: [ plugins: [
"@babel/plugin-transform-flow-strip-types", "@babel/plugin-transform-flow-strip-types",
"@babel/plugin-proposal-class-properties", "@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-nullish-coalescing-operator",
[ [
"module-resolver", "module-resolver",
{ {

View File

@ -75,8 +75,6 @@ function jest() {
const jsonOut = out.substring(out.indexOf("{"), out.lastIndexOf("}") + 1); const jsonOut = out.substring(out.indexOf("{"), out.lastIndexOf("}") + 1);
const results = JSON.parse(jsonOut); const results = JSON.parse(jsonOut);
const failed = results.numFailedTests == 0;
// The individual failing tests are in jammed into the same message string :/ // The individual failing tests are in jammed into the same message string :/
const errors = [].concat( const errors = [].concat(
...results.testResults.map(r => ...results.testResults.map(r =>
@ -85,7 +83,7 @@ function jest() {
); );
logErrors("jest", errors); logErrors("jest", errors);
return failed; return errors.length == 0;
} }
function stylelint() { function stylelint() {

View File

@ -9175,7 +9175,11 @@ function getSpecifiers(specifiers) {
return []; return [];
} }
return specifiers.map(specifier => specifier.local && specifier.local.name); return specifiers.map(specifier => {
var _specifier$local;
return (_specifier$local = specifier.local) === null || _specifier$local === void 0 ? void 0 : _specifier$local.name;
});
} }
function isComputedExpression(expression) { function isComputedExpression(expression) {
@ -9218,10 +9222,14 @@ function getVariables(dec) {
// e.g. const [{a, b }] = 2 // e.g. const [{a, b }] = 2
return dec.id.elements.filter(element => element).map(element => ({ return dec.id.elements.filter(element => element).map(element => {
name: t.isAssignmentPattern(element) ? element.left.name : element.name || element.argument && element.argument.name, var _element$argument;
location: element.loc
})).filter(({ return {
name: t.isAssignmentPattern(element) ? element.left.name : element.name || ((_element$argument = element.argument) === null || _element$argument === void 0 ? void 0 : _element$argument.name),
location: element.loc
};
}).filter(({
name name
}) => name); }) => name);
} }
@ -15806,11 +15814,13 @@ function extractSymbols(sourceId) {
} }
function extendSnippet(name, expression, path, prevPath) { function extendSnippet(name, expression, path, prevPath) {
const computed = path && path.node.computed; var _path$node$property, _path$node$property$e;
const prevComputed = prevPath && prevPath.node.computed;
const computed = path === null || path === void 0 ? void 0 : path.node.computed;
const prevComputed = prevPath === null || prevPath === void 0 ? void 0 : prevPath.node.computed;
const prevArray = t.isArrayExpression(prevPath); const prevArray = t.isArrayExpression(prevPath);
const array = t.isArrayExpression(path); const array = t.isArrayExpression(path);
const value = path && path.node.property && path.node.property.extra && path.node.property.extra.raw || ""; const value = (path === null || path === void 0 ? void 0 : (_path$node$property = path.node.property) === null || _path$node$property === void 0 ? void 0 : (_path$node$property$e = _path$node$property.extra) === null || _path$node$property$e === void 0 ? void 0 : _path$node$property$e.raw) || "";
if (expression === "") { if (expression === "") {
if (computed) { if (computed) {
@ -15868,6 +15878,8 @@ function getMemberSnippet(node, expression = "") {
} }
function getObjectSnippet(path, prevPath, expression = "") { function getObjectSnippet(path, prevPath, expression = "") {
var _path$parentPath;
if (!path) { if (!path) {
return expression; return expression;
} }
@ -15875,11 +15887,13 @@ function getObjectSnippet(path, prevPath, expression = "") {
const name = path.node.key.name; const name = path.node.key.name;
const extendedExpression = extendSnippet(name, expression, path, prevPath); const extendedExpression = extendSnippet(name, expression, path, prevPath);
const nextPrevPath = path; const nextPrevPath = path;
const nextPath = path.parentPath && path.parentPath.parentPath; const nextPath = (_path$parentPath = path.parentPath) === null || _path$parentPath === void 0 ? void 0 : _path$parentPath.parentPath;
return getSnippet(nextPath, nextPrevPath, extendedExpression); return getSnippet(nextPath, nextPrevPath, extendedExpression);
} }
function getArraySnippet(path, prevPath, expression) { function getArraySnippet(path, prevPath, expression) {
var _path$parentPath2;
if (!prevPath.parentPath) { if (!prevPath.parentPath) {
throw new Error("Assertion failure - path should exist"); throw new Error("Assertion failure - path should exist");
} }
@ -15887,7 +15901,7 @@ function getArraySnippet(path, prevPath, expression) {
const index = `${prevPath.parentPath.containerIndex}`; const index = `${prevPath.parentPath.containerIndex}`;
const extendedExpression = extendSnippet(index, expression, path, prevPath); const extendedExpression = extendSnippet(index, expression, path, prevPath);
const nextPrevPath = path; const nextPrevPath = path;
const nextPath = path.parentPath && path.parentPath.parentPath; const nextPath = (_path$parentPath2 = path.parentPath) === null || _path$parentPath2 === void 0 ? void 0 : _path$parentPath2.parentPath;
return getSnippet(nextPath, nextPrevPath, extendedExpression); return getSnippet(nextPath, nextPrevPath, extendedExpression);
} }
@ -42469,8 +42483,6 @@ Object.defineProperty(exports, "__esModule", {
}); });
exports.default = void 0; exports.default = void 0;
var _get = _interopRequireDefault(__webpack_require__(161));
var _findIndex = _interopRequireDefault(__webpack_require__(354)); var _findIndex = _interopRequireDefault(__webpack_require__(354));
var _findLastIndex = _interopRequireDefault(__webpack_require__(371)); var _findLastIndex = _interopRequireDefault(__webpack_require__(371));
@ -42502,11 +42514,13 @@ function findSymbols(source) {
function getLocation(func) { function getLocation(func) {
var _func$identifier, _func$identifier$loc;
const location = { ...func.location const location = { ...func.location
}; // if the function has an identifier, start the block after it so the }; // if the function has an identifier, start the block after it so the
// identifier is included in the "scope" of its parent // identifier is included in the "scope" of its parent
const identifierEnd = (0, _get.default)(func, "identifier.loc.end"); const identifierEnd = func === null || func === void 0 ? void 0 : (_func$identifier = func.identifier) === null || _func$identifier === void 0 ? void 0 : (_func$identifier$loc = _func$identifier.loc) === null || _func$identifier$loc === void 0 ? void 0 : _func$identifier$loc.end;
if (identifierEnd) { if (identifierEnd) {
location.start = identifierEnd; location.start = identifierEnd;

View File

@ -122,10 +122,6 @@ declare module 'codemirror/addon/hint/javascript-hint' {
declare module.exports: any; declare module.exports: any;
} }
declare module 'codemirror/addon/hint/show-hint' {
declare module.exports: any;
}
declare module 'codemirror/addon/hint/sql-hint' { declare module 'codemirror/addon/hint/sql-hint' {
declare module.exports: any; declare module.exports: any;
} }
@ -246,14 +242,6 @@ declare module 'codemirror/addon/selection/selection-pointer' {
declare module.exports: any; declare module.exports: any;
} }
declare module 'codemirror/addon/tern/tern' {
declare module.exports: any;
}
declare module 'codemirror/addon/tern/worker' {
declare module.exports: any;
}
declare module 'codemirror/addon/wrap/hardwrap' { declare module 'codemirror/addon/wrap/hardwrap' {
declare module.exports: any; declare module.exports: any;
} }
@ -1090,9 +1078,6 @@ declare module 'codemirror/addon/hint/html-hint.js' {
declare module 'codemirror/addon/hint/javascript-hint.js' { declare module 'codemirror/addon/hint/javascript-hint.js' {
declare module.exports: $Exports<'codemirror/addon/hint/javascript-hint'>; declare module.exports: $Exports<'codemirror/addon/hint/javascript-hint'>;
} }
declare module 'codemirror/addon/hint/show-hint.js' {
declare module.exports: $Exports<'codemirror/addon/hint/show-hint'>;
}
declare module 'codemirror/addon/hint/sql-hint.js' { declare module 'codemirror/addon/hint/sql-hint.js' {
declare module.exports: $Exports<'codemirror/addon/hint/sql-hint'>; declare module.exports: $Exports<'codemirror/addon/hint/sql-hint'>;
} }
@ -1183,12 +1168,6 @@ declare module 'codemirror/addon/selection/mark-selection.js' {
declare module 'codemirror/addon/selection/selection-pointer.js' { declare module 'codemirror/addon/selection/selection-pointer.js' {
declare module.exports: $Exports<'codemirror/addon/selection/selection-pointer'>; declare module.exports: $Exports<'codemirror/addon/selection/selection-pointer'>;
} }
declare module 'codemirror/addon/tern/tern.js' {
declare module.exports: $Exports<'codemirror/addon/tern/tern'>;
}
declare module 'codemirror/addon/tern/worker.js' {
declare module.exports: $Exports<'codemirror/addon/tern/worker'>;
}
declare module 'codemirror/addon/wrap/hardwrap.js' { declare module 'codemirror/addon/wrap/hardwrap.js' {
declare module.exports: $Exports<'codemirror/addon/wrap/hardwrap'>; declare module.exports: $Exports<'codemirror/addon/wrap/hardwrap'>;
} }

View File

@ -40,5 +40,8 @@ module.exports = {
moduleNameMapper: { moduleNameMapper: {
"\\.css$": "<rootDir>/src/test/__mocks__/styleMock.js", "\\.css$": "<rootDir>/src/test/__mocks__/styleMock.js",
"\\.svg$": "<rootDir>/src/test/__mocks__/svgMock.js", "\\.svg$": "<rootDir>/src/test/__mocks__/svgMock.js",
"^Services": "<rootDir>/src/test/fixtures/Services",
// Map all require("devtools/...") to the real devtools root.
"^devtools\\/(.*)": "<rootDir>/../../$1",
}, },
}; };

View File

@ -102,6 +102,8 @@
"@babel/plugin-proposal-class-properties": "^7.5.5", "@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/plugin-transform-flow-strip-types": "^7.4.4", "@babel/plugin-transform-flow-strip-types": "^7.4.4",
"@babel/plugin-transform-modules-commonjs": "^7.5.0", "@babel/plugin-transform-modules-commonjs": "^7.5.0",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3",
"@babel/plugin-proposal-optional-chaining": "^7.8.3",
"@babel/preset-env": "^7.5.5", "@babel/preset-env": "^7.5.5",
"@babel/preset-react": "^7.0.0", "@babel/preset-react": "^7.0.0",
"@babel/register": "^7.0.0", "@babel/register": "^7.0.0",

View File

@ -55,7 +55,7 @@ function supportsObject(object, noGrip = false) {
} }
const type = getGripType(object, noGrip); const type = getGripType(object, noGrip);
return object.preview && (type === "HTMLDocument" || type === "XULDocument"); return object.preview && type === "HTMLDocument";
} }
// Exports from this module // Exports from this module

View File

@ -34,21 +34,4 @@ stubs.set("Location-less Document", {
}, },
}); });
stubs.set("XULDocument", {
type: "object",
actor: "server1.conn0.obj434",
class: "XULDocument",
extensible: true,
frozen: false,
sealed: false,
ownPropertyLength: 1,
preview: {
kind: "DOMNode",
nodeType: 9,
nodeName: "#document",
isConnected: true,
location: "chrome://browser/content/browser.xul",
},
});
module.exports = stubs; module.exports = stubs;

View File

@ -39,23 +39,3 @@ describe("Document", () => {
expect(renderedComponent.text()).toEqual("HTMLDocument"); expect(renderedComponent.text()).toEqual("HTMLDocument");
}); });
}); });
describe("XULDocument", () => {
const stub = stubs.get("XULDocument");
it("correctly selects Document Rep", () => {
expect(getRep(stub)).toBe(Document.rep);
});
it("renders with expected text content", () => {
const renderedComponent = shallow(
Document.rep({
object: stub,
})
);
expect(renderedComponent.text()).toEqual(
"XULDocument chrome://browser/content/browser.xul"
);
expectActorAttribute(renderedComponent, stub.actor);
});
});

View File

@ -27,8 +27,9 @@ async function getNodeFront(gripOrFront, toolbox) {
if ("actorID" in gripOrFront) { if ("actorID" in gripOrFront) {
return new Promise(resolve => resolve(gripOrFront)); return new Promise(resolve => resolve(gripOrFront));
} }
// Given a grip
return toolbox.walker.gripToNodeFront(gripOrFront); const inspectorFront = await toolbox.target.getFront("inspector");
return inspectorFront.getNodeFrontFromNodeGrip(gripOrFront);
} }
DebuggerPanel.prototype = { DebuggerPanel.prototype = {
@ -103,7 +104,6 @@ DebuggerPanel.prototype = {
}, },
openElementInInspector: async function(gripOrFront) { openElementInInspector: async function(gripOrFront) {
await this.toolbox.initInspector();
const onSelectInspector = this.toolbox.selectTool("inspector"); const onSelectInspector = this.toolbox.selectTool("inspector");
const onGripNodeToFront = getNodeFront(gripOrFront, this.toolbox); const onGripNodeToFront = getNodeFront(gripOrFront, this.toolbox);
@ -121,18 +121,18 @@ DebuggerPanel.prototype = {
}, },
highlightDomElement: async function(gripOrFront) { highlightDomElement: async function(gripOrFront) {
await this.toolbox.initInspector(); const nodeFront = await getNodeFront(gripOrFront, this.toolbox);
if (!this.toolbox.highlighter) { nodeFront.highlighterFront.highlight(nodeFront);
return null;
}
const front = await getNodeFront(gripOrFront, this.toolbox);
return this.toolbox.highlighter.highlight(front);
}, },
unHighlightDomElement: function() { unHighlightDomElement: async function(gripOrFront) {
return this.toolbox.highlighter try {
? this.toolbox.highlighter.unhighlight(false) const nodeFront = await getNodeFront(gripOrFront, this.toolbox);
: null; nodeFront.highlighterFront.unhighlight();
} catch (e) {
// This call might fail if called asynchrously after the toolbox is finished
// closing.
}
}, },
getFrames: function() { getFrames: function() {

View File

@ -42,7 +42,7 @@ async function findBreakpointPosition(
); );
const position = findPosition(positions, location); const position = findPosition(positions, location);
return position && position.generatedLocation; return position?.generatedLocation;
} }
async function findNewLocation( async function findNewLocation(

View File

@ -56,8 +56,7 @@ export function generateInlinePreview(cx: ThreadContext, frame: ?Frame) {
); );
let scopes: ?OriginalScope | Scope | null = let scopes: ?OriginalScope | Scope | null =
(originalFrameScopes && originalFrameScopes.scope) || originalFrameScopes?.scope || generatedFrameScopes?.scope;
(generatedFrameScopes && generatedFrameScopes.scope);
if (!scopes || !scopes.bindings) { if (!scopes || !scopes.bindings) {
return; return;
@ -144,8 +143,7 @@ function getBindingValues(
): Array<Preview> { ): Array<Preview> {
const previews = []; const previews = [];
const binding = const binding = originalAstScopes[curLevel]?.bindings[name];
originalAstScopes[curLevel] && originalAstScopes[curLevel].bindings[name];
if (!binding) { if (!binding) {
return previews; return previews;
} }
@ -211,13 +209,9 @@ function getExpressionNameAndValue(
const property: Object = properties.find( const property: Object = properties.find(
prop => prop.name === meta.property prop => prop.name === meta.property
); );
displayValue = property && property.contents.value; displayValue = property?.contents.value;
displayName += `.${meta.property}`; displayName += `.${meta.property}`;
} else if ( } else if (displayValue?.preview?.ownProperties) {
displayValue &&
displayValue.preview &&
displayValue.preview.ownProperties
) {
const { ownProperties } = displayValue.preview; const { ownProperties } = displayValue.preview;
Object.keys(ownProperties).forEach(prop => { Object.keys(ownProperties).forEach(prop => {
if (prop === meta.property) { if (prop === meta.property) {

View File

@ -24,7 +24,7 @@ import SourceMaps, { isGeneratedId } from "devtools-source-map";
function isFrameBlackboxed(state, frame) { function isFrameBlackboxed(state, frame) {
const source = getSource(state, frame.location.sourceId); const source = getSource(state, frame.location.sourceId);
return source && source.isBlackBoxed; return source?.isBlackBoxed;
} }
function getSelectedFrameId(state, thread, frames) { function getSelectedFrameId(state, thread, frames) {
@ -34,7 +34,7 @@ function getSelectedFrameId(state, thread, frames) {
} }
selectedFrame = frames.find(frame => !isFrameBlackboxed(state, frame)); selectedFrame = frames.find(frame => !isFrameBlackboxed(state, frame));
return selectedFrame && selectedFrame.id; return selectedFrame?.id;
} }
export function updateFrameLocation( export function updateFrameLocation(
@ -105,7 +105,7 @@ function isWasmOriginalSourceFrame(frame, getState: () => State): boolean {
frame.generatedLocation.sourceId frame.generatedLocation.sourceId
); );
return Boolean(generatedSource && generatedSource.isWasm); return Boolean(generatedSource?.isWasm);
} }
async function expandFrames( async function expandFrames(

View File

@ -247,8 +247,8 @@ describe("pause", () => {
}, },
}, },
}, },
mappings: { "1": null }, mappings: { "1": undefined },
original: { "1": { pending: false, scope: null } }, original: { "1": { pending: false, scope: undefined } },
}); });
expect( expect(

View File

@ -74,18 +74,32 @@ async function loadSource(
return result; return result;
} }
const actors = getSourceActorsForSource(state, source.id); // We only need the source text from one actor, but messages sent to retrieve
if (!actors.length) { // the source might fail if the actor has or is about to shut down. Keep
throw new Error("No source actor for loadSource"); // trying with different actors until one request succeeds.
let response;
const handledActors = new Set();
while (true) {
const actors = getSourceActorsForSource(state, source.id);
const actor = actors.find(({ actor: a }) => !handledActors.has(a));
if (!actor) {
throw new Error("Unknown source");
}
handledActors.add(actor.actor);
try {
telemetry.start(loadSourceHistogram, source);
response = await client.sourceContents(actor);
telemetry.finish(loadSourceHistogram, source);
break;
} catch (e) {
console.warn(`sourceContents failed: ${e}`);
}
} }
telemetry.start(loadSourceHistogram, source);
const response = await client.sourceContents(actors[0]);
telemetry.finish(loadSourceHistogram, source);
return { return {
text: response.source, text: (response: any).source,
contentType: response.contentType || "text/javascript", contentType: (response: any).contentType || "text/javascript",
}; };
} }

View File

@ -268,7 +268,7 @@ describe("loadSourceText", () => {
: null; : null;
expect( expect(
content && isRejected(content) && typeof content.value === "string" content && isRejected(content) && typeof content.value === "string"
? content.value.indexOf("unknown source") ? content.value.indexOf("Unknown source")
: -1 : -1
).not.toBe(-1); ).not.toBe(-1);
}); });

View File

@ -5,7 +5,13 @@
// @flow // @flow
import typeof SourceMaps from "devtools-source-map"; import typeof SourceMaps from "devtools-source-map";
import type { WorkerList, MainThread, Context, ThreadId } from "../../types"; import type {
WorkerList,
MainThread,
Context,
ThreadId,
SourceLocation,
} from "../../types";
import type { State } from "../../reducers/types"; import type { State } from "../../reducers/types";
import type { MatchedLocations } from "../../reducers/file-search"; import type { MatchedLocations } from "../../reducers/file-search";
import type { TreeNode } from "../../utils/sources-tree/types"; import type { TreeNode } from "../../utils/sources-tree/types";
@ -152,6 +158,13 @@ export type DebuggeeAction =
+type: "SELECT_THREAD", +type: "SELECT_THREAD",
+cx: Context, +cx: Context,
+thread: ThreadId, +thread: ThreadId,
|}
| {|
+type: "PREVIEW_PAUSED_LOCATION",
+location: SourceLocation,
|}
| {|
+type: "CLEAR_PREVIEW_PAUSED_LOCATION",
|}; |};
export type { export type {

View File

@ -28,7 +28,7 @@ function cloneAction(action: any) {
action = { ...action }; action = { ...action };
// ADD_TAB, ... // ADD_TAB, ...
if (action.source && action.source.text) { if (action.source?.text) {
const source = { ...action.source, text: "" }; const source = { ...action.source, text: "" };
action.source = source; action.source = source;
} }

View File

@ -9,15 +9,13 @@
* will appear in performance tooling under the User Timing API * will appear in performance tooling under the User Timing API
*/ */
const mark = const mark = window.performance?.mark
window.performance && window.performance.mark ? window.performance.mark.bind(window.performance)
? window.performance.mark.bind(window.performance) : a => {};
: a => {};
const measure = const measure = window.performance?.measure
window.performance && window.performance.measure ? window.performance.measure.bind(window.performance)
? window.performance.measure.bind(window.performance) : (a, b, c) => {};
: (a, b, c) => {};
export function timing(store: any) { export function timing(store: any) {
return (next: any) => (action: any) => { return (next: any) => (action: any) => {

View File

@ -107,7 +107,7 @@ function lookupThreadFront(thread: string) {
} }
function listWorkerThreadFronts() { function listWorkerThreadFronts() {
return (Object.values(workerTargets): any).map(target => target.threadFront); return (Object.values(workerTargets): any).map(target => target.threadFront).filter(t => !!t);
} }
function forEachThread(iteratee) { function forEachThread(iteratee) {
@ -452,10 +452,11 @@ async function getSourceActorBreakableLines({
thread, thread,
actor, actor,
}: SourceActor): Promise<Array<number>> { }: SourceActor): Promise<Array<number>> {
const sourceThreadFront = lookupThreadFront(thread); let sourceFront;
const sourceFront = sourceThreadFront.source({ actor });
let actorLines = []; let actorLines = [];
try { try {
const sourceThreadFront = lookupThreadFront(thread);
sourceFront = sourceThreadFront.source({ actor });
actorLines = await sourceFront.getBreakableLines(); actorLines = await sourceFront.getBreakableLines();
} catch (e) { } catch (e) {
// Handle backward compatibility // Handle backward compatibility
@ -463,10 +464,11 @@ async function getSourceActorBreakableLines({
e.message && e.message &&
e.message.match(/does not recognize the packet type getBreakableLines/) e.message.match(/does not recognize the packet type getBreakableLines/)
) { ) {
const pos = await sourceFront.getBreakpointPositionsCompressed(); const pos = await (sourceFront: any).getBreakpointPositionsCompressed();
actorLines = Object.keys(pos).map(line => Number(line)); actorLines = Object.keys(pos).map(line => Number(line));
} else if (!e.message || !e.message.match(/Connection closed/)) { } else {
throw e; // Other exceptions could be due to the target thread being shut down.
console.warn(`getSourceActorBreakableLines failed: ${e}`);
} }
} }

View File

@ -165,7 +165,6 @@ export type TabPayload = {
performanceActor: ActorId, performanceActor: ActorId,
performanceEntriesActor: ActorId, performanceEntriesActor: ActorId,
profilerActor: ActorId, profilerActor: ActorId,
promisesActor: ActorId,
reflowActor: ActorId, reflowActor: ActorId,
storageActor: ActorId, storageActor: ActorId,
styleEditorActor: ActorId, styleEditorActor: ActorId,

View File

@ -7,6 +7,9 @@
import { addThreadEventListeners } from "./events"; import { addThreadEventListeners } from "./events";
import type { TabTarget } from "./types"; import type { TabTarget } from "./types";
// $FlowIgnore
const { defaultThreadOptions } = require("devtools/client/shared/thread-utils");
export function supportsWorkers(tabTarget: TabTarget) { export function supportsWorkers(tabTarget: TabTarget) {
return tabTarget.isBrowsingContext || tabTarget.isContentProcess; return tabTarget.isBrowsingContext || tabTarget.isContentProcess;
} }
@ -32,7 +35,10 @@ export async function updateWorkerTargets({
if (workerTargets[threadActorID]) { if (workerTargets[threadActorID]) {
newWorkerTargets[threadActorID] = workerTargets[threadActorID]; newWorkerTargets[threadActorID] = workerTargets[threadActorID];
} else { } else {
const [, workerThread] = await workerTargetFront.attachThread(options); const [, workerThread] = await workerTargetFront.attachThread({
...defaultThreadOptions(),
...args.options,
});
workerThread.resume(); workerThread.resume();
addThreadEventListeners(workerThread); addThreadEventListeners(workerThread);

View File

@ -201,7 +201,7 @@ export class ConditionalPanel extends PureComponent<Props> {
getDefaultValue() { getDefaultValue() {
const { breakpoint, log } = this.props; const { breakpoint, log } = this.props;
const options = (breakpoint && breakpoint.options) || {}; const options = breakpoint?.options || {};
return log ? options.logValue : options.condition; return log ? options.logValue : options.condition;
} }

View File

@ -22,11 +22,11 @@ import {
getCurrentThread, getCurrentThread,
} from "../../selectors"; } from "../../selectors";
import type { Frame, Why, SourceWithContent } from "../../types"; import type { SourceLocation, Why, SourceWithContent } from "../../types";
type OwnProps = {||}; type OwnProps = {||};
type Props = { type Props = {
frame: ?Frame, location: ?SourceLocation,
why: ?Why, why: ?Why,
source: ?SourceWithContent, source: ?SourceWithContent,
}; };
@ -36,46 +36,47 @@ type TextClasses = {
lineClass: string, lineClass: string,
}; };
function isDocumentReady(source: ?SourceWithContent, frame: ?Frame) { function isDocumentReady(
return ( source: ?SourceWithContent,
frame && source && source.content && hasDocument(frame.location.sourceId) location: ?SourceLocation
); ) {
return location && source && source.content && hasDocument(location.sourceId);
} }
export class DebugLine extends PureComponent<Props> { export class DebugLine extends PureComponent<Props> {
debugExpression: null; debugExpression: null;
componentDidMount() { componentDidMount() {
const { why, frame, source } = this.props; const { why, location, source } = this.props;
this.setDebugLine(why, frame, source); this.setDebugLine(why, location, source);
} }
componentWillUnmount() { componentWillUnmount() {
const { why, frame, source } = this.props; const { why, location, source } = this.props;
this.clearDebugLine(why, frame, source); this.clearDebugLine(why, location, source);
} }
componentDidUpdate(prevProps: Props) { componentDidUpdate(prevProps: Props) {
const { why, frame, source } = this.props; const { why, location, source } = this.props;
startOperation(); startOperation();
this.clearDebugLine(prevProps.why, prevProps.frame, prevProps.source); this.clearDebugLine(prevProps.why, prevProps.location, prevProps.source);
this.setDebugLine(why, frame, source); this.setDebugLine(why, location, source);
endOperation(); endOperation();
} }
setDebugLine( setDebugLine(
why: ?Why, why: ?Why,
frame: ?Frame, location: ?SourceLocation,
source: ?SourceWithContent source: ?SourceWithContent
) { ) {
if (!frame || !isDocumentReady(source, frame)) { if (!location || !isDocumentReady(source, location)) {
return; return;
} }
const { sourceId } = frame.location; const { sourceId } = location;
const doc = getDocument(sourceId); const doc = getDocument(sourceId);
let { line, column } = toEditorPosition(frame.location); let { line, column } = toEditorPosition(location);
let { markTextClass, lineClass } = this.getTextClasses(why); let { markTextClass, lineClass } = this.getTextClasses(why);
doc.addLineClass(line, "line", lineClass); doc.addLineClass(line, "line", lineClass);
@ -97,8 +98,12 @@ export class DebugLine extends PureComponent<Props> {
); );
} }
clearDebugLine(why: ?Why, frame: ?Frame, source: ?SourceWithContent) { clearDebugLine(
if (!frame || !isDocumentReady(source, frame)) { why: ?Why,
location: ?SourceLocation,
source: ?SourceWithContent
) {
if (!location || !isDocumentReady(source, location)) {
return; return;
} }
@ -106,14 +111,14 @@ export class DebugLine extends PureComponent<Props> {
this.debugExpression.clear(); this.debugExpression.clear();
} }
const { line } = toEditorPosition(frame.location); const { line } = toEditorPosition(location);
const doc = getDocument(location.sourceId); const doc = getDocument(location.sourceId);
const { lineClass } = this.getTextClasses(why); const { lineClass } = this.getTextClasses(why);
doc.removeLineClass(line, "line", lineClass); doc.removeLineClass(line, "line", lineClass);
} }
getTextClasses(why: ?Why): TextClasses { getTextClasses(why: ?Why): TextClasses {
if (isException(why)) { if (why && isException(why)) {
return { return {
markTextClass: "debug-expression-error", markTextClass: "debug-expression-error",
lineClass: "new-debug-line-error", lineClass: "new-debug-line-error",
@ -130,9 +135,10 @@ export class DebugLine extends PureComponent<Props> {
const mapStateToProps = state => { const mapStateToProps = state => {
const frame = getVisibleSelectedFrame(state); const frame = getVisibleSelectedFrame(state);
const location = frame?.location;
return { return {
frame, location,
source: frame && getSourceWithContent(state, frame.location.sourceId), source: location && getSourceWithContent(state, location.sourceId),
why: getPauseReason(state, getCurrentThread(state)), why: getPauseReason(state, getCurrentThread(state)),
}; };
}; };

View File

@ -134,7 +134,7 @@ class SourceFooter extends PureComponent<Props, State> {
blackBoxButton() { blackBoxButton() {
const { cx, selectedSource, toggleBlackBox } = this.props; const { cx, selectedSource, toggleBlackBox } = this.props;
const sourceLoaded = selectedSource && selectedSource.content; const sourceLoaded = selectedSource?.content;
if (!selectedSource) { if (!selectedSource) {
return; return;

View File

@ -262,7 +262,7 @@ class SearchBar extends Component<Props, State> {
function SearchModBtn({ modVal, className, svgName, tooltip }) { function SearchModBtn({ modVal, className, svgName, tooltip }) {
const preppedClass = classnames(className, { const preppedClass = classnames(className, {
active: modifiers && modifiers[modVal], active: modifiers?.[modVal],
}); });
return ( return (
<button <button

View File

@ -437,7 +437,7 @@ class Editor extends PureComponent<Props, State> {
} }
// if user clicks gutter to set breakpoint on blackboxed source, un-blackbox the source. // if user clicks gutter to set breakpoint on blackboxed source, un-blackbox the source.
if (selectedSource && selectedSource.isBlackBoxed) { if (selectedSource?.isBlackBoxed) {
toggleBlackBox(cx, selectedSource); toggleBlackBox(cx, selectedSource);
} }
@ -659,7 +659,7 @@ class Editor extends PureComponent<Props, State> {
return ( return (
<div <div
className={classnames("editor-wrapper", { className={classnames("editor-wrapper", {
blackboxed: selectedSource && selectedSource.isBlackBoxed, blackboxed: selectedSource?.isBlackBoxed,
"skip-pausing": skipPausing, "skip-pausing": skipPausing,
})} })}
ref={c => (this.$editorWrapper = c)} ref={c => (this.$editorWrapper = c)}

View File

@ -41,13 +41,11 @@ function generateDefaults(editor, overrides) {
}; };
} }
function createFrame(line) { function createLocation(line) {
return { return {
location: { sourceId: "foo",
sourceId: "foo", line,
line, column: 2,
column: 2,
},
}; };
} }
@ -80,9 +78,9 @@ describe("DebugLine Component", () => {
}, },
}); });
const line = 2; const line = 2;
const frame = createFrame(line); const location = createLocation(line);
component.setProps({ ...props, frame }); component.setProps({ ...props, location });
expect(doc.removeLineClass.mock.calls).toEqual([]); expect(doc.removeLineClass.mock.calls).toEqual([]);
expect(doc.addLineClass.mock.calls).toEqual([ expect(doc.addLineClass.mock.calls).toEqual([
@ -107,10 +105,10 @@ describe("DebugLine Component", () => {
const firstLine = 2; const firstLine = 2;
const secondLine = 2; const secondLine = 2;
component.setProps({ ...props, frame: createFrame(firstLine) }); component.setProps({ ...props, location: createLocation(firstLine) });
component.setProps({ component.setProps({
...props, ...props,
frame: createFrame(secondLine), frame: createLocation(secondLine),
}); });
expect(doc.removeLineClass.mock.calls).toEqual([ expect(doc.removeLineClass.mock.calls).toEqual([
@ -143,9 +141,9 @@ describe("DebugLine Component", () => {
it("should not set the debug line", () => { it("should not set the debug line", () => {
const { component, props, doc } = render({ frame: null }); const { component, props, doc } = render({ frame: null });
const line = 2; const line = 2;
const frame = createFrame(line); const location = createLocation(line);
component.setProps({ ...props, frame }); component.setProps({ ...props, location });
expect(doc.removeLineClass).not.toHaveBeenCalled(); expect(doc.removeLineClass).not.toHaveBeenCalled();
}); });
}); });

View File

@ -129,7 +129,7 @@ class Breakpoint extends PureComponent<Props> {
const { source } = this.props; const { source } = this.props;
const { column, line } = this.selectedLocation; const { column, line } = this.selectedLocation;
const isWasm = source && source.isWasm; const isWasm = source?.isWasm;
const columnVal = features.columnBreakpoints && column ? `:${column}` : ""; const columnVal = features.columnBreakpoints && column ? `:${column}` : "";
const bpLocation = isWasm const bpLocation = isWasm
? `0x${line.toString(16).toUpperCase()}` ? `0x${line.toString(16).toUpperCase()}`

View File

@ -248,18 +248,14 @@ const mapStateToProps = state => {
} = getOriginalFrameScope( } = getOriginalFrameScope(
state, state,
cx.thread, cx.thread,
selectedSource && selectedSource.id, selectedSource?.id,
selectedFrame && selectedFrame.id selectedFrame?.id
) || { scope: null, pending: false }; ) || { scope: null, pending: false };
const { const {
scope: generatedFrameScopes, scope: generatedFrameScopes,
pending: generatedPending, pending: generatedPending,
} = getGeneratedFrameScope( } = getGeneratedFrameScope(state, cx.thread, selectedFrame?.id) || {
state,
cx.thread,
selectedFrame && selectedFrame.id
) || {
scope: null, scope: null,
pending: false, pending: false,
}; };

View File

@ -252,7 +252,7 @@ class SecondaryPanes extends Component<Props, State> {
if ( if (
!selectedFrame || !selectedFrame ||
isGeneratedId(selectedFrame.location.sourceId) || isGeneratedId(selectedFrame.location.sourceId) ||
(source && source.isPrettyPrinted) source?.isPrettyPrinted
) { ) {
return null; return null;
} }

View File

@ -84,7 +84,7 @@ class ManagedTree extends Component<Props, State> {
while (parents.length) { while (parents.length) {
const children = []; const children = [];
for (const parent of parents) { for (const parent of parents) {
if (parent.contents && parent.contents.length) { if (parent.contents?.length) {
for (const child of parent.contents) { for (const child of parent.contents) {
expandItem(child); expandItem(child);
children.push(child); children.push(child);

View File

@ -235,7 +235,7 @@ export function hasLogpoint(
location: ?SourceLocation location: ?SourceLocation
): ?string { ): ?string {
const breakpoint = getBreakpoint(state, location); const breakpoint = getBreakpoint(state, location);
return breakpoint && breakpoint.options.logValue; return breakpoint?.options.logValue;
} }
export default update; export default update;

View File

@ -3,7 +3,7 @@
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */ * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
// @flow // @flow
/* eslint complexity: ["error", 30]*/ /* eslint complexity: ["error", 35]*/
/** /**
* Pause reducer * Pause reducer
@ -230,13 +230,13 @@ function update(
...threadState().frameScopes.original, ...threadState().frameScopes.original,
[selectedFrameId]: { [selectedFrameId]: {
pending: status !== "done", pending: status !== "done",
scope: value && value.scope, scope: value?.scope,
}, },
}; };
const mappings = { const mappings = {
...threadState().frameScopes.mappings, ...threadState().frameScopes.mappings,
[selectedFrameId]: value && value.mappings, [selectedFrameId]: value?.mappings,
}; };
return updateThreadState({ return updateThreadState({
@ -381,7 +381,7 @@ function getPauseLocation(state, action) {
return null; return null;
} }
const frame = frames && frames[0]; const frame = frames?.[0];
if (!frame) { if (!frame) {
return previousLocation; return previousLocation;
} }
@ -635,7 +635,7 @@ export function getInlinePreviewExpression(
const previews = getThreadPauseState(state.pause, thread).inlinePreview[ const previews = getThreadPauseState(state.pause, thread).inlinePreview[
getGeneratedFrameId(frameId) getGeneratedFrameId(frameId)
]; ];
return previews && previews[line] && previews[line][expression]; return previews?.[line]?.[expression];
} }
// NOTE: currently only used for chrome // NOTE: currently only used for chrome

View File

@ -781,7 +781,7 @@ export function getSourceContent(
export function getSelectedSourceId(state: OuterState) { export function getSelectedSourceId(state: OuterState) {
const source = getSelectedSource((state: any)); const source = getSelectedSource((state: any));
return source && source.id; return source?.id;
} }
export function getProjectDirectoryRoot(state: OuterState): string { export function getProjectDirectoryRoot(state: OuterState): string {

View File

@ -12,7 +12,6 @@ import {
import { getCurrentThreadFrames } from "../reducers/pause"; import { getCurrentThreadFrames } from "../reducers/pause";
import { annotateFrames } from "../utils/pause/frames"; import { annotateFrames } from "../utils/pause/frames";
import { isOriginal } from "../utils/source"; import { isOriginal } from "../utils/source";
import { get } from "lodash";
import type { State, SourceResourceState } from "../reducers/types"; import type { State, SourceResourceState } from "../reducers/types";
import type { Frame, Source } from "../types"; import type { Frame, Source } from "../types";
import { createSelector } from "reselect"; import { createSelector } from "reselect";
@ -57,7 +56,7 @@ export function formatCallStackFrames(
const formattedFrames: Frame[] = frames const formattedFrames: Frame[] = frames
.filter(frame => getSourceForFrame(sources, frame)) .filter(frame => getSourceForFrame(sources, frame))
.map(frame => appendSource(sources, frame, selectedSource)) .map(frame => appendSource(sources, frame, selectedSource))
.filter(frame => !get(frame, "source.isBlackBoxed")); .filter(frame => !frame?.source?.isBlackBoxed);
return annotateFrames(formattedFrames); return annotateFrames(formattedFrames);
} }

View File

@ -70,7 +70,7 @@ function groupBreakpoints(breakpoints, selectedSource) {
function findBreakpoint(location, breakpointMap) { function findBreakpoint(location, breakpointMap) {
const { line, column } = location; const { line, column } = location;
const breakpoints = breakpointMap[line] && breakpointMap[line][column]; const breakpoints = breakpointMap[line]?.[column];
if (breakpoints) { if (breakpoints) {
return breakpoints[0]; return breakpoints[0];

View File

@ -2,11 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#scratchpad-sidebar > tabs { "use strict";
height: 0;
border: none;
}
#sp-toolbar { module.exports = {
border: none; appinfo: "",
} };

View File

@ -11,6 +11,8 @@ const { Provider } = require("react-redux");
import ToolboxProvider from "devtools/client/framework/store-provider"; import ToolboxProvider from "devtools/client/framework/store-provider";
import { isFirefoxPanel, isDevelopment, isTesting } from "devtools-environment"; import { isFirefoxPanel, isDevelopment, isTesting } from "devtools-environment";
import { AppConstants } from "devtools-modules";
import SourceMaps, { import SourceMaps, {
startSourceMapWorker, startSourceMapWorker,
stopSourceMapWorker, stopSourceMapWorker,
@ -64,9 +66,10 @@ export function bootstrapStore(
panel: Panel, panel: Panel,
initialState: Object initialState: Object
) { ) {
const debugJsModules = AppConstants.AppConstants.DEBUG_JS_MODULES == "1";
const createStore = configureStore({ const createStore = configureStore({
log: prefs.logging || isTesting(), log: prefs.logging || isTesting(),
timing: isDevelopment(), timing: debugJsModules || isDevelopment(),
makeThunkArgs: (args, state) => { makeThunkArgs: (args, state) => {
return { ...args, client, ...workers, panel }; return { ...args, client, ...workers, panel };
}, },

View File

@ -44,7 +44,7 @@ function bindSelectors(obj: Object): Object {
function getCM() { function getCM() {
const cm: any = document.querySelector(".CodeMirror"); const cm: any = document.querySelector(".CodeMirror");
return cm && cm.CodeMirror; return cm?.CodeMirror;
} }
function formatMappedLocation(mappedLocation) { function formatMappedLocation(mappedLocation) {

View File

@ -4,7 +4,7 @@
// @flow // @flow
import { get, findIndex } from "lodash"; import { findIndex } from "lodash";
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
import type { Frame } from "../../../types"; import type { Frame } from "../../../types";
@ -49,7 +49,7 @@ export function collapseFrames(frames: Frame[]): GroupedFrames {
let currentGroup = null; let currentGroup = null;
let prevItem = null; let prevItem = null;
for (const frame of frames) { for (const frame of frames) {
const prevLibrary = get(prevItem, "library"); const prevLibrary = prevItem?.library;
if (!currentGroup) { if (!currentGroup) {
currentGroup = [frame]; currentGroup = [frame];

View File

@ -67,10 +67,7 @@ const displayNameMap = {
function mapDisplayNames(frame, library) { function mapDisplayNames(frame, library) {
const { displayName } = frame; const { displayName } = frame;
return ( return displayNameMap[library]?.[displayName] || displayName;
(displayNameMap[library] && displayNameMap[library][displayName]) ||
displayName
);
} }
function getFrameDisplayName(frame: Frame): string { function getFrameDisplayName(frame: Frame): string {

View File

@ -4,10 +4,8 @@
// @flow // @flow
import { get } from "lodash";
import type { Frame } from "../../../types"; import type { Frame } from "../../../types";
export function getFrameUrl(frame: Frame) { export function getFrameUrl(frame: Frame) {
return get(frame, "source.url", "") || ""; return frame?.source?.url ?? "";
} }

View File

@ -260,7 +260,7 @@ async function mapImportReferenceToDescriptor({
for ( for (
let op = meta, index = 0; let op = meta, index = 0;
op && mappingContains(range, op) && desc && index < 2; op && mappingContains(range, op) && desc && index < 2;
index++, op = op && op.parent index++, op = op?.parent
) { ) {
// Calling could potentially trigger side-effects, which would not // Calling could potentially trigger side-effects, which would not
// be ideal for this case. // be ideal for this case.

View File

@ -178,7 +178,7 @@ function isReliableScope(scope: OriginalScope): boolean {
let unknownBindings = 0; let unknownBindings = 0;
for (let s = scope; s; s = s.parent) { for (let s = scope; s; s = s.parent) {
const vars = (s.bindings && s.bindings.variables) || {}; const vars = s.bindings?.variables || {};
for (const key of Object.keys(vars)) { for (const key of Object.keys(vars)) {
const binding = vars[key]; const binding = vars[key];
@ -452,7 +452,7 @@ async function findGeneratedBinding(
// because it can have multiple bindings, but we do want to make sure // because it can have multiple bindings, but we do want to make sure
// that all of the bindings that match the range are part of the same // that all of the bindings that match the range are part of the same
// import declaration. // import declaration.
if (declRange && declRange.singleDeclaration) { if (declRange?.singleDeclaration) {
const applicableDeclBindings = await loadApplicableBindings( const applicableDeclBindings = await loadApplicableBindings(
pos.declaration, pos.declaration,
pos.type pos.type

View File

@ -84,7 +84,7 @@ export function getScope(
} }
} }
if (vars && vars.length) { if (vars?.length) {
const title = getScopeTitle(type, scope) || ""; const title = getScopeTitle(type, scope) || "";
vars.sort((a, b) => a.name.localeCompare(b.name)); vars.sort((a, b) => a.name.localeCompare(b.name));
return { return {

View File

@ -45,11 +45,11 @@ export function getPauseReason(why?: ?Why): string | null {
} }
export function isException(why: Why) { export function isException(why: Why) {
return why && why.type && why.type === "exception"; return why?.type === "exception";
} }
export function isInterrupted(why: ?Why) { export function isInterrupted(why: ?Why) {
return why && why.type && why.type === "interrupted"; return why?.type === "interrupted";
} }
export function inDebuggerEval(why: ?Why) { export function inDebuggerEval(why: ?Why) {

View File

@ -5,6 +5,7 @@
// @flow // @flow
import { PrefsHelper, asyncStoreHelper } from "devtools-modules"; import { PrefsHelper, asyncStoreHelper } from "devtools-modules";
import { isDevelopment } from "devtools-environment"; import { isDevelopment } from "devtools-environment";
import Services from "devtools-services"; import Services from "devtools-services";
@ -138,7 +139,7 @@ export const features = new PrefsHelper("devtools.debugger.features", {
eventListenersBreakpoints: ["Bool", "event-listeners-breakpoints"], eventListenersBreakpoints: ["Bool", "event-listeners-breakpoints"],
domMutationBreakpoints: ["Bool", "dom-mutation-breakpoints"], domMutationBreakpoints: ["Bool", "dom-mutation-breakpoints"],
logPoints: ["Bool", "log-points"], logPoints: ["Bool", "log-points"],
showOverlayStepButtons: ["Bool", "overlay-step-buttons"], showOverlay: ["Bool", "overlay"],
inlinePreview: ["Bool", "inline-preview"], inlinePreview: ["Bool", "inline-preview"],
watchpoints: ["Bool", "watchpoints"], watchpoints: ["Bool", "watchpoints"],
}); });

View File

@ -18,7 +18,7 @@ export function isVisible() {
export function getLineNumberWidth(editor: Object) { export function getLineNumberWidth(editor: Object) {
const gutters = editor.display.gutters; const gutters = editor.display.gutters;
const lineNumbers = gutters.querySelector(".CodeMirror-linenumbers"); const lineNumbers = gutters.querySelector(".CodeMirror-linenumbers");
return lineNumbers && lineNumbers.clientWidth; return lineNumbers?.clientWidth;
} }
/** /**

View File

@ -5,7 +5,7 @@
// @flow // @flow
import type { SourceContent } from "../types"; import type { SourceContent } from "../types";
import { saveAs } from "devtools-modules"; import { DevToolsUtils } from "devtools-modules";
/** /**
* Utils for utils, by utils * Utils for utils, by utils
@ -62,5 +62,5 @@ export function downloadFile(content: SourceContent, fileName: string) {
} }
const data = new TextEncoder().encode(content.value); const data = new TextEncoder().encode(content.value);
saveAs(window, data, fileName); DevToolsUtils.saveAs(window, data, fileName);
} }

View File

@ -6,7 +6,6 @@
import type { AstLocation, AstPosition } from "./types"; import type { AstLocation, AstPosition } from "./types";
import get from "lodash/get";
import findIndex from "lodash/findIndex"; import findIndex from "lodash/findIndex";
import findLastIndex from "lodash/findLastIndex"; import findLastIndex from "lodash/findLastIndex";
@ -30,7 +29,7 @@ function getLocation(func) {
// if the function has an identifier, start the block after it so the // if the function has an identifier, start the block after it so the
// identifier is included in the "scope" of its parent // identifier is included in the "scope" of its parent
const identifierEnd = get(func, "identifier.loc.end"); const identifierEnd = func?.identifier?.loc?.end;
if (identifierEnd) { if (identifierEnd) {
location.start = identifierEnd; location.start = identifierEnd;
} }

View File

@ -313,16 +313,11 @@ function extendSnippet(
path?: { node: Node }, path?: { node: Node },
prevPath?: SimplePath prevPath?: SimplePath
) { ) {
const computed = path && path.node.computed; const computed = path?.node.computed;
const prevComputed = prevPath && prevPath.node.computed; const prevComputed = prevPath?.node.computed;
const prevArray = t.isArrayExpression(prevPath); const prevArray = t.isArrayExpression(prevPath);
const array = t.isArrayExpression(path); const array = t.isArrayExpression(path);
const value = const value = path?.node.property?.extra?.raw || "";
(path &&
path.node.property &&
path.node.property.extra &&
path.node.property.extra.raw) ||
"";
if (expression === "") { if (expression === "") {
if (computed) { if (computed) {
@ -462,7 +457,7 @@ function getSnippet(
} }
if (t.isObjectExpression(path)) { if (t.isObjectExpression(path)) {
const parentPath = prevPath && prevPath.parentPath; const parentPath = prevPath?.parentPath;
return getObjectSnippet(parentPath, prevPath, expression); return getObjectSnippet(parentPath, prevPath, expression);
} }

View File

@ -78,7 +78,7 @@ export function getSpecifiers(specifiers: any) {
return []; return [];
} }
return specifiers.map(specifier => specifier.local && specifier.local.name); return specifiers.map(specifier => specifier.local?.name);
} }
export function isComputedExpression(expression: string): boolean { export function isComputedExpression(expression: string): boolean {
@ -125,7 +125,7 @@ export function getVariables(dec: Node) {
.map(element => ({ .map(element => ({
name: t.isAssignmentPattern(element) name: t.isAssignmentPattern(element)
? element.left.name ? element.left.name
: element.name || (element.argument && element.argument.name), : element.name || element.argument?.name,
location: element.loc, location: element.loc,
})) }))
.filter(({ name }) => name); .filter(({ name }) => name);

View File

@ -151,11 +151,11 @@ skip-if = os == "win"
[browser_dbg-react-app.js] [browser_dbg-react-app.js]
skip-if = os == "win" skip-if = os == "win"
[browser_dbg-wasm-sourcemaps.js] [browser_dbg-wasm-sourcemaps.js]
skip-if = true
[browser_dbg-windowless-workers.js] [browser_dbg-windowless-workers.js]
[browser_dbg-windowless-workers-early-breakpoint.js] [browser_dbg-windowless-workers-early-breakpoint.js]
[browser_dbg-worker-exception.js]
[browser_dbg-worker-scopes.js] [browser_dbg-worker-scopes.js]
skip-if = (os == 'linux' && debug) || ccov #Bug 1456013 skip-if = (os == 'linux' && debug) || (os == 'linux' && asan) || ccov #Bug 1456013, Bug 1559547
[browser_dbg-event-handler.js] [browser_dbg-event-handler.js]
[browser_dbg-event-breakpoints.js] [browser_dbg-event-breakpoints.js]
[browser_dbg-eval-throw.js] [browser_dbg-eval-throw.js]

View File

@ -9,8 +9,9 @@ var gClient, gThreadFront;
var gNewChromeSource = promise.defer(); var gNewChromeSource = promise.defer();
var { DevToolsLoader } = ChromeUtils.import("resource://devtools/shared/Loader.jsm"); var { DevToolsLoader } = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
var customLoader = new DevToolsLoader(); var customLoader = new DevToolsLoader({
customLoader.invisibleToDebugger = true; invisibleToDebugger: true,
});
var { DebuggerServer } = customLoader.require("devtools/server/debugger-server"); var { DebuggerServer } = customLoader.require("devtools/server/debugger-server");
var { DebuggerClient } = require("devtools/shared/client/debugger-client"); var { DebuggerClient } = require("devtools/shared/client/debugger-client");

View File

@ -20,9 +20,8 @@ add_task(async function() {
// Ensure hovering over button highlights the node in content pane // Ensure hovering over button highlights the node in content pane
const view = inspectorNode.ownerDocument.defaultView; const view = inspectorNode.ownerDocument.defaultView;
const onNodeHighlight = toolbox.target const inspectorFront = await toolbox.target.getFront("inspector");
.once("inspector") const onNodeHighlight = inspectorFront.highlighter.once("node-highlight");
.then(inspector => inspector.highlighter.once("node-highlight"));
EventUtils.synthesizeMouseAtCenter( EventUtils.synthesizeMouseAtCenter(
inspectorNode, inspectorNode,
{ type: "mousemove" }, { type: "mousemove" },

View File

@ -7,26 +7,25 @@
*/ */
add_task(async function() { add_task(async function() {
const dbg = await initDebugger("doc-wasm-sourcemaps.html"); const dbg = await initDebugger("doc-wasm-sourcemaps.html");
// NOTE: wait for page load -- attempt to fight the intermittent failure:
// "A promise chain failed to handle a rejection: Debugger.Frame is not live"
await waitForSource(dbg, "doc-wasm-sourcemaps");
await waitForLoadedSources(dbg);
await reload(dbg); await reload(dbg);
// After reload() we are getting getSources notifiction for old sources,
// using the debugger statement to really stop are reloaded page.
await waitForPaused(dbg); await waitForPaused(dbg);
await resume(dbg);
await waitForLoadedSource(dbg, "doc-wasm-sourcemaps"); await waitForSources(dbg, "doc-wasm-sourcemaps.html", "fib.c");
assertPausedLocation(dbg);
await waitForSource(dbg, "fib.c");
// Set breakpoint and reload the page.
ok(true, "Original sources exist"); ok(true, "Original sources exist");
const mainSrc = findSource(dbg, "fib.c"); await selectSource(dbg, "fib.c");
await selectSource(dbg, mainSrc);
await addBreakpoint(dbg, "fib.c", 10); await addBreakpoint(dbg, "fib.c", 10);
reload(dbg);
// The same debugger statement as above, but using at for
// workaround to break at original source (see below) and not generated.
await waitForPaused(dbg);
await selectSource(dbg, "fib.c");
resume(dbg); resume(dbg);
await waitForPaused(dbg, "fib.c"); await waitForPaused(dbg, "fib.c");
@ -38,6 +37,6 @@ add_task(async function() {
is( is(
firstFrameLocation.includes("fib.c"), firstFrameLocation.includes("fib.c"),
true, true,
"It shall be to fib.c source" "It shall be fib.c source"
); );
}); });

View File

@ -0,0 +1,18 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
// Test that we can pause on exceptions in newly created workers.
add_task(async function() {
const dbg = await initDebugger("doc-worker-exception.html");
await togglePauseOnExceptions(dbg, true, false);
invokeInTab("startWorker");
invokeInTab("messageWorker");
await waitForPaused(dbg);
const source = findSource(dbg, "worker-exception.js");
assertPausedAtSourceAndLine(dbg, source.id, 2);
});

View File

@ -2,10 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */ * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
// This error shows up sometimes when running the test, and while this is a
// strange problem that shouldn't be happening it doesn't prevent the test from
// completing successfully.
PromiseTestUtils.whitelistRejectionsGlobally(/Current state is running/); PromiseTestUtils.whitelistRejectionsGlobally(/Current state is running/);
PromiseTestUtils.whitelistRejectionsGlobally(/Connection closed/);
function findNode(dbg, text) { function findNode(dbg, text) {
for (let index = 0; ; index++) { for (let index = 0; ; index++) {

View File

@ -0,0 +1,10 @@
<script>
var worker;
window.startWorker = () => {
worker = new Worker("worker-exception.js");
}
window.messageWorker = () => {
worker.postMessage({yo: 'yo'});
}
</script>

View File

@ -0,0 +1,3 @@
self.onmessage = () => {
throw new Error("OH NO!");
}

View File

@ -144,6 +144,11 @@
version "7.0.0" version "7.0.0"
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250"
"@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670"
integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==
"@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": "@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4":
version "7.5.5" version "7.5.5"
resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351"
@ -244,6 +249,14 @@
"@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-json-strings" "^7.2.0" "@babel/plugin-syntax-json-strings" "^7.2.0"
"@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2"
integrity sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw==
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0"
"@babel/plugin-proposal-object-rest-spread@^7.5.5": "@babel/plugin-proposal-object-rest-spread@^7.5.5":
version "7.5.5" version "7.5.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz#61939744f71ba76a3ae46b5eea18a54c16d22e58" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz#61939744f71ba76a3ae46b5eea18a54c16d22e58"
@ -258,6 +271,14 @@
"@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-optional-catch-binding" "^7.2.0" "@babel/plugin-syntax-optional-catch-binding" "^7.2.0"
"@babel/plugin-proposal-optional-chaining@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.8.3.tgz#ae10b3214cb25f7adb1f3bc87ba42ca10b7e2543"
integrity sha512-QIoIR9abkVn+seDE3OjA08jWcs3eZ9+wJCKSRgo3WdEU2csFYgdScb+8qHB3+WXsGJD55u+5hWCISI7ejXS+kg==
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-syntax-optional-chaining" "^7.8.0"
"@babel/plugin-proposal-unicode-property-regex@^7.4.4": "@babel/plugin-proposal-unicode-property-regex@^7.4.4":
version "7.4.4" version "7.4.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz#501ffd9826c0b91da22690720722ac7cb1ca9c78" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz#501ffd9826c0b91da22690720722ac7cb1ca9c78"
@ -296,6 +317,13 @@
dependencies: dependencies:
"@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9"
integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==
dependencies:
"@babel/helper-plugin-utils" "^7.8.0"
"@babel/plugin-syntax-object-rest-spread@^7.2.0": "@babel/plugin-syntax-object-rest-spread@^7.2.0":
version "7.2.0" version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e"
@ -308,6 +336,13 @@
dependencies: dependencies:
"@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-optional-chaining@^7.8.0":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a"
integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==
dependencies:
"@babel/helper-plugin-utils" "^7.8.0"
"@babel/plugin-transform-arrow-functions@^7.2.0": "@babel/plugin-transform-arrow-functions@^7.2.0":
version "7.2.0" version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550"
@ -2985,10 +3020,6 @@ ci-info@^1.0.0:
version "1.1.3" version "1.1.3"
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.3.tgz#710193264bb05c77b8c90d02f5aaf22216a667b2" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.3.tgz#710193264bb05c77b8c90d02f5aaf22216a667b2"
ci-info@^1.5.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497"
cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
version "1.0.4" version "1.0.4"
resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
@ -3349,7 +3380,7 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
cosmiconfig@5.0.6, cosmiconfig@^5.0.6: cosmiconfig@5.0.6:
version "5.0.6" version "5.0.6"
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.6.tgz#dca6cf680a0bd03589aff684700858c81abeeb39" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.6.tgz#dca6cf680a0bd03589aff684700858c81abeeb39"
dependencies: dependencies:
@ -4829,18 +4860,6 @@ execa@^0.8.0:
signal-exit "^3.0.0" signal-exit "^3.0.0"
strip-eof "^1.0.0" strip-eof "^1.0.0"
execa@^0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-0.9.0.tgz#adb7ce62cf985071f60580deb4a88b9e34712d01"
dependencies:
cross-spawn "^5.0.1"
get-stream "^3.0.0"
is-stream "^1.1.0"
npm-run-path "^2.0.0"
p-finally "^1.0.0"
signal-exit "^3.0.0"
strip-eof "^1.0.0"
execa@^1.0.0: execa@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
@ -6076,21 +6095,6 @@ https-proxy-agent@2.2.1:
agent-base "^4.1.0" agent-base "^4.1.0"
debug "^3.1.0" debug "^3.1.0"
husky@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/husky/-/husky-1.0.1.tgz#749bc6b3a14bdc9cab73d8cc827b92fcd691fac6"
dependencies:
cosmiconfig "^5.0.6"
execa "^0.9.0"
find-up "^3.0.0"
get-stdin "^6.0.0"
is-ci "^1.2.1"
pkg-dir "^3.0.0"
please-upgrade-node "^3.1.1"
read-pkg "^4.0.1"
run-node "^1.0.0"
slash "^2.0.0"
hyphenate-style-name@^1.0.1, hyphenate-style-name@^1.0.2: hyphenate-style-name@^1.0.1, hyphenate-style-name@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz#31160a36930adaf1fc04c6074f7eb41465d4ec4b" resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz#31160a36930adaf1fc04c6074f7eb41465d4ec4b"
@ -6363,12 +6367,6 @@ is-ci@^1.0.10:
dependencies: dependencies:
ci-info "^1.0.0" ci-info "^1.0.0"
is-ci@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c"
dependencies:
ci-info "^1.5.0"
is-data-descriptor@^0.1.4: is-data-descriptor@^0.1.4:
version "0.1.4" version "0.1.4"
resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
@ -9029,7 +9027,7 @@ pkg-up@^2.0.0:
dependencies: dependencies:
find-up "^2.1.0" find-up "^2.1.0"
please-upgrade-node@^3.0.2, please-upgrade-node@^3.1.1: please-upgrade-node@^3.0.2:
version "3.1.1" version "3.1.1"
resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz#ed320051dfcc5024fae696712c8288993595e8ac" resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz#ed320051dfcc5024fae696712c8288993595e8ac"
dependencies: dependencies:
@ -10075,14 +10073,6 @@ read-pkg@^3.0.0:
normalize-package-data "^2.3.2" normalize-package-data "^2.3.2"
path-type "^3.0.0" path-type "^3.0.0"
read-pkg@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-4.0.1.tgz#963625378f3e1c4d48c85872b5a6ec7d5d093237"
dependencies:
normalize-package-data "^2.3.2"
parse-json "^4.0.0"
pify "^3.0.0"
"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6: "readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6:
version "2.3.6" version "2.3.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
@ -11029,10 +11019,6 @@ run-async@^2.2.0:
dependencies: dependencies:
is-promise "^2.1.0" is-promise "^2.1.0"
run-node@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/run-node/-/run-node-1.0.0.tgz#46b50b946a2aa2d4947ae1d886e9856fd9cabe5e"
run-parallel@^1.1.4: run-parallel@^1.1.4:
version "1.1.9" version "1.1.9"
resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679"
@ -11314,10 +11300,6 @@ slash@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
slash@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
slice-ansi@0.0.4: slice-ansi@0.0.4:
version "0.0.4" version "0.0.4"
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"

View File

@ -58,11 +58,6 @@ loader.lazyGetter(
"StoragePanel", "StoragePanel",
() => require("devtools/client/storage/panel").StoragePanel () => require("devtools/client/storage/panel").StoragePanel
); );
loader.lazyGetter(
this,
"ScratchpadPanel",
() => require("devtools/client/scratchpad/panel").ScratchpadPanel
);
loader.lazyGetter( loader.lazyGetter(
this, this,
"DomPanel", "DomPanel",
@ -93,13 +88,7 @@ loader.lazyRequireGetter(
loader.lazyRequireGetter( loader.lazyRequireGetter(
this, this,
"ResponsiveUIManager", "ResponsiveUIManager",
"devtools/client/responsive/manager", "devtools/client/responsive/manager"
true
);
loader.lazyImporter(
this,
"ScratchpadManager",
"resource://devtools/client/scratchpad/scratchpad-manager.jsm"
); );
const { MultiLocalizationHelper } = require("devtools/shared/l10n"); const { MultiLocalizationHelper } = require("devtools/shared/l10n");
@ -154,8 +143,11 @@ Tools.inspector = {
inMenu: true, inMenu: true,
preventClosingOnKey: true, preventClosingOnKey: true,
// preventRaisingOnKey is used to keep the focus on the content window for shortcuts
// that trigger the element picker.
preventRaisingOnKey: true,
onkey: function(panel, toolbox) { onkey: function(panel, toolbox) {
toolbox.inspectorFront.nodePicker.togglePicker(); toolbox.nodePicker.togglePicker();
}, },
isTargetSupported: function(target) { isTargetSupported: function(target) {
@ -228,7 +220,7 @@ Tools.styleEditor = {
visibilityswitch: "devtools.styleeditor.enabled", visibilityswitch: "devtools.styleeditor.enabled",
accesskey: l10n("open.accesskey"), accesskey: l10n("open.accesskey"),
icon: "chrome://devtools/skin/images/tool-styleeditor.svg", icon: "chrome://devtools/skin/images/tool-styleeditor.svg",
url: "chrome://devtools/content/styleeditor/index.xul", url: "chrome://devtools/content/styleeditor/index.xhtml",
label: l10n("ToolboxStyleEditor.label"), label: l10n("ToolboxStyleEditor.label"),
panelLabel: l10n("ToolboxStyleEditor.panelLabel"), panelLabel: l10n("ToolboxStyleEditor.panelLabel"),
get tooltip() { get tooltip() {
@ -283,7 +275,7 @@ function switchPerformancePanel() {
return target.isLocalTab; return target.isLocalTab;
}; };
} else { } else {
Tools.performance.url = "chrome://devtools/content/performance/index.xul"; Tools.performance.url = "chrome://devtools/content/performance/index.xhtml";
Tools.performance.build = function(frame, target) { Tools.performance.build = function(frame, target) {
return new PerformancePanel(frame, target); return new PerformancePanel(frame, target);
}; };
@ -354,7 +346,7 @@ Tools.storage = {
accesskey: l10n("storage.accesskey"), accesskey: l10n("storage.accesskey"),
visibilityswitch: "devtools.storage.enabled", visibilityswitch: "devtools.storage.enabled",
icon: "chrome://devtools/skin/images/tool-storage.svg", icon: "chrome://devtools/skin/images/tool-storage.svg",
url: "chrome://devtools/content/storage/index.xul", url: "chrome://devtools/content/storage/index.xhtml",
label: l10n("storage.label"), label: l10n("storage.label"),
menuLabel: l10n("storage.menuLabel"), menuLabel: l10n("storage.menuLabel"),
panelLabel: l10n("storage.panelLabel"), panelLabel: l10n("storage.panelLabel"),
@ -378,24 +370,6 @@ Tools.storage = {
}, },
}; };
Tools.scratchpad = {
id: "scratchpad",
ordinal: 12,
visibilityswitch: "devtools.scratchpad.enabled",
icon: "chrome://devtools/skin/images/tool-scratchpad.svg",
url: "chrome://devtools/content/scratchpad/index.xul",
label: l10n("scratchpad.label"),
panelLabel: l10n("scratchpad.panelLabel"),
tooltip: l10n("scratchpad.tooltip"),
inMenu: false,
isTargetSupported: function(target) {
return target.hasActor("console");
},
build: function(iframeWindow, toolbox) {
return new ScratchpadPanel(iframeWindow, toolbox);
},
};
Tools.dom = { Tools.dom = {
id: "dom", id: "dom",
accesskey: l10n("dom.accesskey"), accesskey: l10n("dom.accesskey"),
@ -487,7 +461,6 @@ var defaultTools = [
Tools.performance, Tools.performance,
Tools.netMonitor, Tools.netMonitor,
Tools.storage, Tools.storage,
Tools.scratchpad,
Tools.memory, Tools.memory,
Tools.dom, Tools.dom,
#ifdef ACCESSIBILITY #ifdef ACCESSIBILITY
@ -531,14 +504,6 @@ exports.ToolboxButtons = [
return toolbox.isPaintFlashing; return toolbox.isPaintFlashing;
}, },
}, },
{
id: "command-button-scratchpad",
description: l10n("toolbox.buttons.scratchpad"),
isTargetSupported: target => target.isLocalTab,
onClick(event, toolbox) {
ScratchpadManager.openScratchpad();
},
},
{ {
id: "command-button-responsive", id: "command-button-responsive",
description: l10n( description: l10n(
@ -594,8 +559,8 @@ function createHighlightButton(highlighterName, id) {
description: l10n(`toolbox.buttons.${id}`), description: l10n(`toolbox.buttons.${id}`),
isTargetSupported: target => !target.chrome, isTargetSupported: target => !target.chrome,
async onClick(event, toolbox) { async onClick(event, toolbox) {
await toolbox.initInspector(); const inspectorFront = await toolbox.target.getFront("inspector");
const highlighter = await toolbox.inspectorFront.getOrCreateHighlighterByType( const highlighter = await inspectorFront.getOrCreateHighlighterByType(
highlighterName highlighterName
); );
if (highlighter.isShown()) { if (highlighter.isShown()) {
@ -609,11 +574,7 @@ function createHighlightButton(highlighterName, id) {
isChecked(toolbox) { isChecked(toolbox) {
// if the inspector doesn't exist, then the highlighter has not yet been connected // if the inspector doesn't exist, then the highlighter has not yet been connected
// to the front end. // to the front end.
// TODO: we are using target._inspector here, but we should be using const inspectorFront = toolbox.target.getCachedFront("inspector");
// target.getCachedFront. This is a temporary solution until the inspector no
// longer relies on the toolbox and can be destroyed the same way any other
// front would be. Related: #1487677
const inspectorFront = toolbox.target._inspector;
if (!inspectorFront) { if (!inspectorFront) {
// initialize the inspector front asyncronously. There is a potential for buggy // initialize the inspector front asyncronously. There is a potential for buggy
// behavior here, but we need to change how the buttons get data (have them // behavior here, but we need to change how the buttons get data (have them

View File

@ -77,33 +77,34 @@ class DomTree extends Component {
const toolbox = DomProvider.getToolbox(); const toolbox = DomProvider.getToolbox();
if (toolbox) { if (toolbox) {
onDOMNodeMouseOver = async (grip, options = {}) => { onDOMNodeMouseOver = async (grip, options = {}) => {
await toolbox.initInspector(); const inspectorFront = await toolbox.target.getFront("inspector");
if (!toolbox.highlighter) { const nodeFront = await inspectorFront.getNodeFrontFromNodeGrip(grip);
return null; const { highlighterFront } = nodeFront;
} return highlighterFront.highlight(nodeFront, options);
const nodeFront = await toolbox.walker.gripToNodeFront(grip);
return toolbox.highlighter.highlight(nodeFront, options);
}; };
onDOMNodeMouseOut = (forceHide = false) => { onDOMNodeMouseOut = async grip => {
return toolbox.highlighter const inspectorFront = await toolbox.target.getFront("inspector");
? toolbox.highlighter.unhighlight(forceHide) const nodeFront = await inspectorFront.getNodeFrontFromNodeGrip(grip);
: null; nodeFront.highlighterFront.unhighlight();
}; };
onInspectIconClick = async grip => { onInspectIconClick = async grip => {
await toolbox.initInspector();
const onSelectInspector = toolbox.selectTool( const onSelectInspector = toolbox.selectTool(
"inspector", "inspector",
"inspect_dom" "inspect_dom"
); );
const onGripNodeToFront = toolbox.walker.gripToNodeFront(grip); const onNodeFront = toolbox.target
const [front, inspector] = await Promise.all([ .getFront("inspector")
onGripNodeToFront, .then(inspectorFront =>
inspectorFront.getNodeFrontFromNodeGrip(grip)
);
const [nodeFront, inspectorPanel] = await Promise.all([
onNodeFront,
onSelectInspector, onSelectInspector,
]); ]);
const onInspectorUpdated = inspector.once("inspector-updated"); const onInspectorUpdated = inspectorPanel.once("inspector-updated");
const onNodeFrontSet = toolbox.selection.setNodeFront(front, { const onNodeFrontSet = toolbox.selection.setNodeFront(nodeFront, {
reason: "console", reason: "dom",
}); });
return Promise.all([onNodeFrontSet, onInspectorUpdated]); return Promise.all([onNodeFrontSet, onInspectorUpdated]);

View File

@ -87,19 +87,15 @@ DomPanel.prototype = {
}, },
destroy() { destroy() {
if (this._destroying) { if (this._destroyed) {
return this._destroying; return;
} }
this._destroyed = true;
this._destroying = new Promise(resolve => { this.target.off("navigate", this.onTabNavigated);
this.target.off("navigate", this.onTabNavigated); this._toolbox.off("select", this.onPanelVisibilityChange);
this._toolbox.off("select", this.onPanelVisibilityChange);
this.emit("destroyed"); this.emit("destroyed");
resolve();
});
return this._destroying;
}, },
// Events // Events

View File

@ -18,9 +18,8 @@ add_task(async function() {
let node = getRowByIndex(panel, 2).querySelector(".objectBox-node"); let node = getRowByIndex(panel, 2).querySelector(".objectBox-node");
// the inspector should be initialized first and then the node should // the inspector should be initialized first and then the node should
// highlight after the hover effect. // highlight after the hover effect.
let onNodeHighlight = toolbox.target const inspectorFront = await toolbox.target.getFront("inspector");
.once("inspector") let onNodeHighlight = inspectorFront.highlighter.once("node-highlight");
.then(inspector => inspector.highlighter.once("node-highlight"));
EventUtils.synthesizeMouseAtCenter( EventUtils.synthesizeMouseAtCenter(
node, node,
{ {
@ -32,7 +31,7 @@ add_task(async function() {
is(nodeFront.displayName, "h1", "The correct node was highlighted"); is(nodeFront.displayName, "h1", "The correct node was highlighted");
info("Unhighlight the node by moving away from the node"); info("Unhighlight the node by moving away from the node");
let onNodeUnhighlight = toolbox.highlighter.once("node-unhighlight"); let onNodeUnhighlight = inspectorFront.highlighter.once("node-unhighlight");
const btn = toolbox.doc.querySelector("#toolbox-meatball-menu-button"); const btn = toolbox.doc.querySelector("#toolbox-meatball-menu-button");
EventUtils.synthesizeMouseAtCenter( EventUtils.synthesizeMouseAtCenter(
btn, btn,
@ -57,7 +56,7 @@ add_task(async function() {
}, },
node.ownerDocument.defaultView node.ownerDocument.defaultView
); );
onNodeHighlight = toolbox.highlighter.once("node-highlight"); onNodeHighlight = inspectorFront.highlighter.once("node-highlight");
nodeFront = await onNodeHighlight; nodeFront = await onNodeHighlight;
is(nodeFront.displayName, "h2", "The correct node was highlighted"); is(nodeFront.displayName, "h2", "The correct node was highlighted");
@ -69,7 +68,7 @@ add_task(async function() {
}, },
btn.ownerDocument.defaultView btn.ownerDocument.defaultView
); );
onNodeUnhighlight = toolbox.highlighter.once("node-unhighlight"); onNodeUnhighlight = inspectorFront.highlighter.once("node-unhighlight");
await onNodeUnhighlight; await onNodeUnhighlight;
ok(true, "node-unhighlight event was fired when moving away from the node"); ok(true, "node-unhighlight event was fired when moving away from the node");
}); });

View File

@ -33,26 +33,29 @@ registerCleanupFunction(() => {
* @return a promise that resolves to the tab object when * @return a promise that resolves to the tab object when
* the url is loaded * the url is loaded
*/ */
function addTestTab(url) { async function addTestTab(url) {
info("Adding a new test tab with URL: '" + url + "'"); info("Adding a new test tab with URL: '" + url + "'");
return new Promise(resolve => { const tab = await addTab(url);
addTab(url).then(tab => {
// Load devtools/shared/test/frame-script-utils.js
loadFrameScriptUtils();
// Select the DOM panel and wait till it's initialized. // Load devtools/shared/test/frame-script-utils.js
initDOMPanel(tab).then(panel => { loadFrameScriptUtils();
waitForDispatch(panel, "FETCH_PROPERTIES").then(() => {
resolve({ // Select the DOM panel and wait till it's initialized.
tab: tab, const panel = await initDOMPanel(tab);
browser: tab.linkedBrowser,
panel: panel, // FETCH_PROPERTIES should be fired during the call to initDOMPanel
}); // But note that this behavior changed during a change in webconsole
}); // initialization. So this might be racy.
}); const doc = panel.panelWin.document;
}); const nodes = [...doc.querySelectorAll(".treeLabel")];
}); ok(nodes.length > 0, "The DOM panel is already populated");
return {
tab,
browser: tab.linkedBrowser,
panel,
};
} }
/** /**

View File

@ -116,8 +116,9 @@ BrowserToolboxProcess.prototype = {
// This allows us to safely use the tools against even the actors and // This allows us to safely use the tools against even the actors and
// DebuggingServer itself, especially since we can mark this loader as // DebuggingServer itself, especially since we can mark this loader as
// invisible to the debugger (unlike the usual loader settings). // invisible to the debugger (unlike the usual loader settings).
this.loader = new DevToolsLoader(); this.loader = new DevToolsLoader({
this.loader.invisibleToDebugger = true; invisibleToDebugger: true,
});
const { DebuggerServer } = this.loader.require( const { DebuggerServer } = this.loader.require(
"devtools/server/debugger-server" "devtools/server/debugger-server"
); );

View File

@ -10,15 +10,11 @@ const {
} = require("devtools/client/framework/reducers/dom-mutation-breakpoints"); } = require("devtools/client/framework/reducers/dom-mutation-breakpoints");
exports.registerWalkerListeners = registerWalkerListeners; exports.registerWalkerListeners = registerWalkerListeners;
function registerWalkerListeners(toolbox) { function registerWalkerListeners(store, walker) {
const { walker } = toolbox; walker.on("mutations", mutations => handleWalkerMutations(mutations, store));
walker.on("mutations", mutations =>
handleWalkerMutations(mutations, toolbox)
);
} }
function handleWalkerMutations(mutations, toolbox) { function handleWalkerMutations(mutations, store) {
// If we got BP updates for detach/unload, we want to drop those nodes from // If we got BP updates for detach/unload, we want to drop those nodes from
// the list of active DOM mutation breakpoints. We explicitly check these // the list of active DOM mutation breakpoints. We explicitly check these
// cases because BP updates could also happen due to explicitly API // cases because BP updates could also happen due to explicitly API
@ -27,7 +23,7 @@ function handleWalkerMutations(mutations, toolbox) {
mutation => mutation.type === "mutationBreakpoint" mutation => mutation.type === "mutationBreakpoint"
); );
if (mutationItems.length > 0) { if (mutationItems.length > 0) {
toolbox.store.dispatch(updateBreakpointsForMutations(mutationItems)); store.dispatch(updateBreakpointsForMutations(mutationItems));
} }
} }

View File

@ -45,7 +45,7 @@ function l10n(key) {
/** /**
* Create a xul:menuitem element * Create a xul:menuitem element
* *
* @param {XULDocument} doc * @param {HTMLDocument} doc
* The document to which menus are to be added. * The document to which menus are to be added.
* @param {String} id * @param {String} id
* Element id. * Element id.
@ -78,7 +78,7 @@ function createMenuItem({ doc, id, label, accesskey, isCheckbox }) {
* *
* @param {Object} toolDefinition * @param {Object} toolDefinition
* Tool definition of the tool to add a menu entry. * Tool definition of the tool to add a menu entry.
* @param {XULDocument} doc * @param {HTMLDocument} doc
* The document to which the tool menu item is to be added. * The document to which the tool menu item is to be added.
*/ */
function createToolMenuElements(toolDefinition, doc) { function createToolMenuElements(toolDefinition, doc) {
@ -143,7 +143,7 @@ function sendEntryPointTelemetry(window) {
* Create xul menuitem, key elements for a given tool. * Create xul menuitem, key elements for a given tool.
* And then insert them into browser DOM. * And then insert them into browser DOM.
* *
* @param {XULDocument} doc * @param {HTMLDocument} doc
* The document to which the tool is to be registered. * The document to which the tool is to be registered.
* @param {Object} toolDefinition * @param {Object} toolDefinition
* Tool definition of the tool to register. * Tool definition of the tool to register.
@ -156,7 +156,7 @@ function insertToolMenuElements(doc, toolDefinition, prevDef) {
let ref; let ref;
if (prevDef) { if (prevDef) {
const menuitem = doc.getElementById("menuitem_" + prevDef.id); const menuitem = doc.getElementById("menuitem_" + prevDef.id);
ref = menuitem && menuitem.nextSibling ? menuitem.nextSibling : null; ref = menuitem?.nextSibling ? menuitem.nextSibling : null;
} else { } else {
ref = doc.getElementById("menu_devtools_separator"); ref = doc.getElementById("menu_devtools_separator");
} }
@ -172,7 +172,7 @@ exports.insertToolMenuElements = insertToolMenuElements;
* *
* @param {string} toolId * @param {string} toolId
* Id of the tool to add a menu entry for * Id of the tool to add a menu entry for
* @param {XULDocument} doc * @param {HTMLDocument} doc
* The document to which the tool menu item is to be removed from * The document to which the tool menu item is to be removed from
*/ */
function removeToolFromMenu(toolId, doc) { function removeToolFromMenu(toolId, doc) {
@ -191,7 +191,7 @@ exports.removeToolFromMenu = removeToolFromMenu;
/** /**
* Add all tools to the developer tools menu of a window. * Add all tools to the developer tools menu of a window.
* *
* @param {XULDocument} doc * @param {HTMLDocument} doc
* The document to which the tool items are to be added. * The document to which the tool items are to be added.
*/ */
function addAllToolsToMenu(doc) { function addAllToolsToMenu(doc) {
@ -224,7 +224,7 @@ function addAllToolsToMenu(doc) {
/** /**
* Add global menus that are not panel specific. * Add global menus that are not panel specific.
* *
* @param {XULDocument} doc * @param {HTMLDocument} doc
* The document to which menus are to be added. * The document to which menus are to be added.
*/ */
function addTopLevelItems(doc) { function addTopLevelItems(doc) {
@ -266,7 +266,7 @@ function addTopLevelItems(doc) {
const menu = doc.getElementById("menuWebDeveloperPopup"); const menu = doc.getElementById("menuWebDeveloperPopup");
menu.appendChild(menuItems); menu.appendChild(menuItems);
// There is still "Page Source" menuitem hardcoded into browser.xul. Instead // There is still "Page Source" menuitem hardcoded into browser.xhtml. Instead
// of manually inserting everything around it, move it to the expected // of manually inserting everything around it, move it to the expected
// position. // position.
const pageSource = doc.getElementById("menu_pageSource"); const pageSource = doc.getElementById("menu_pageSource");
@ -277,7 +277,7 @@ function addTopLevelItems(doc) {
/** /**
* Remove global menus that are not panel specific. * Remove global menus that are not panel specific.
* *
* @param {XULDocument} doc * @param {HTMLDocument} doc
* The document to which menus are to be added. * The document to which menus are to be added.
*/ */
function removeTopLevelItems(doc) { function removeTopLevelItems(doc) {
@ -294,7 +294,7 @@ function removeTopLevelItems(doc) {
/** /**
* Add menus to a browser document * Add menus to a browser document
* *
* @param {XULDocument} doc * @param {HTMLDocument} doc
* The document to which menus are to be added. * The document to which menus are to be added.
*/ */
exports.addMenus = function(doc) { exports.addMenus = function(doc) {
@ -306,7 +306,7 @@ exports.addMenus = function(doc) {
/** /**
* Remove menus from a browser document * Remove menus from a browser document
* *
* @param {XULDocument} doc * @param {HTMLDocument} doc
* The document to which menus are to be removed. * The document to which menus are to be removed.
*/ */
exports.removeMenus = function(doc) { exports.removeMenus = function(doc) {

View File

@ -267,10 +267,11 @@ class ToolboxToolbar extends Component {
}`, }`,
ref: "frameMenuButton", ref: "frameMenuButton",
title: description, title: description,
onCloseButton: async () => { onCloseButton: () => {
// Only try to unhighlight if the highlighter has been started // Only try to unhighlight if the highlighter has been started
if (toolbox.highlighter) { const inspectorFront = toolbox.target.getCachedFront("inspector");
toolbox.highlighter.unhighlight(); if (inspectorFront) {
inspectorFront.highlighter.unhighlight();
} }
}, },
}, },

View File

@ -55,8 +55,7 @@ loader.lazyRequireGetter(
loader.lazyRequireGetter( loader.lazyRequireGetter(
this, this,
"ResponsiveUIManager", "ResponsiveUIManager",
"devtools/client/responsive/manager", "devtools/client/responsive/manager"
true
); );
loader.lazyRequireGetter( loader.lazyRequireGetter(
this, this,
@ -69,11 +68,6 @@ loader.lazyImporter(
"BrowserToolboxProcess", "BrowserToolboxProcess",
"resource://devtools/client/framework/ToolboxProcess.jsm" "resource://devtools/client/framework/ToolboxProcess.jsm"
); );
loader.lazyImporter(
this,
"ScratchpadManager",
"resource://devtools/client/scratchpad/scratchpad-manager.jsm"
);
const { LocalizationHelper } = require("devtools/shared/l10n"); const { LocalizationHelper } = require("devtools/shared/l10n");
const L10N = new LocalizationHelper( const L10N = new LocalizationHelper(
@ -105,7 +99,7 @@ var gDevToolsBrowser = (exports.gDevToolsBrowser = {
* of there * of there
*/ */
// used by browser-sets.inc, command // used by browser-sets.inc, command
async toggleToolboxCommand(gBrowser, startTime) { async toggleToolboxCommand(gBrowser) {
const target = await TargetFactory.forTab(gBrowser.selectedTab); const target = await TargetFactory.forTab(gBrowser.selectedTab);
const toolbox = gDevTools.getToolbox(target); const toolbox = gDevTools.getToolbox(target);
@ -113,11 +107,7 @@ var gDevToolsBrowser = (exports.gDevToolsBrowser = {
// - should close a docked toolbox // - should close a docked toolbox
// - should focus a windowed toolbox // - should focus a windowed toolbox
const isDocked = toolbox && toolbox.hostType != Toolbox.HostType.WINDOW; const isDocked = toolbox && toolbox.hostType != Toolbox.HostType.WINDOW;
if (isDocked) { isDocked ? gDevTools.closeToolbox(target) : gDevTools.showToolbox(target);
gDevTools.closeToolbox(target);
} else {
gDevTools.showToolbox(target, null, null, null, startTime);
}
}, },
/** /**
@ -253,7 +243,7 @@ var gDevToolsBrowser = (exports.gDevToolsBrowser = {
* Used when: - registering a new tool * Used when: - registering a new tool
* - new xul window, to add menu items * - new xul window, to add menu items
*/ */
async selectToolCommand(win, toolId, startTime) { async selectToolCommand(win, toolId) {
if (gDevToolsBrowser._isAboutDevtoolsToolbox(win)) { if (gDevToolsBrowser._isAboutDevtoolsToolbox(win)) {
const toolbox = gDevToolsBrowser._getAboutDevtoolsToolbox(win); const toolbox = gDevToolsBrowser._getAboutDevtoolsToolbox(win);
toolbox.selectTool(toolId, "key_shortcut"); toolbox.selectTool(toolId, "key_shortcut");
@ -275,15 +265,16 @@ var gDevToolsBrowser = (exports.gDevToolsBrowser = {
toolDefinition.preventClosingOnKey || toolDefinition.preventClosingOnKey ||
toolbox.hostType == Toolbox.HostType.WINDOW toolbox.hostType == Toolbox.HostType.WINDOW
) { ) {
toolbox.raise(); if (!toolDefinition.preventRaisingOnKey) {
toolbox.raise();
}
} else { } else {
toolbox.destroy(); toolbox.destroy();
} }
gDevTools.emit("select-tool-command", toolId); gDevTools.emit("select-tool-command", toolId);
} else { } else {
gDevTools gDevTools
.showToolbox(target, toolId, null, null, startTime) .showToolbox(target, toolId).then(newToolbox => {
.then(newToolbox => {
newToolbox.fireCustomKey(toolId); newToolbox.fireCustomKey(toolId);
gDevTools.emit("select-tool-command", toolId); gDevTools.emit("select-tool-command", toolId);
}); });
@ -300,13 +291,9 @@ var gDevToolsBrowser = (exports.gDevToolsBrowser = {
* from devtools-startup.js's KeyShortcuts array. The useful fields here * from devtools-startup.js's KeyShortcuts array. The useful fields here
* are: * are:
* - `toolId` used to identify a toolbox's panel like inspector or webconsole, * - `toolId` used to identify a toolbox's panel like inspector or webconsole,
* - `id` used to identify any other key shortcuts like scratchpad or * - `id` used to identify any other key shortcuts like about:debugging
* about:debugging
* @param {Number} startTime
* Optional, indicates the time at which the key event fired. This is a
* `Cu.now()` timing.
*/ */
async onKeyShortcut(window, key, startTime) { async onKeyShortcut(window, key) {
// Avoid to open devtools when the about:devtools-toolbox page is showing // Avoid to open devtools when the about:devtools-toolbox page is showing
// on the window now. // on the window now.
if ( if (
@ -318,14 +305,14 @@ var gDevToolsBrowser = (exports.gDevToolsBrowser = {
// If this is a toolbox's panel key shortcut, delegate to selectToolCommand // If this is a toolbox's panel key shortcut, delegate to selectToolCommand
if (key.toolId) { if (key.toolId) {
await gDevToolsBrowser.selectToolCommand(window, key.toolId, startTime); await gDevToolsBrowser.selectToolCommand(window, key.toolId);
return; return;
} }
// Otherwise implement all other key shortcuts individually here // Otherwise implement all other key shortcuts individually here
switch (key.id) { switch (key.id) {
case "toggleToolbox": case "toggleToolbox":
case "toggleToolboxF12": case "toggleToolboxF12":
await gDevToolsBrowser.toggleToolboxCommand(window.gBrowser, startTime); await gDevToolsBrowser.toggleToolboxCommand(window.gBrowser);
break; break;
case "browserToolbox": case "browserToolbox":
BrowserToolboxProcess.init(); BrowserToolboxProcess.init();
@ -341,16 +328,6 @@ var gDevToolsBrowser = (exports.gDevToolsBrowser = {
trigger: "shortcut", trigger: "shortcut",
}); });
break; break;
case "scratchpad":
ScratchpadManager.openScratchpad();
break;
case "inspectorMac":
await gDevToolsBrowser.selectToolCommand(
window,
"inspector",
startTime
);
break;
} }
}, },
@ -459,7 +436,7 @@ var gDevToolsBrowser = (exports.gDevToolsBrowser = {
/** /**
* Add this DevTools's presence to a browser window's document * Add this DevTools's presence to a browser window's document
* *
* @param {XULDocument} doc * @param {HTMLDocument} doc
* The document to which devtools should be hooked to. * The document to which devtools should be hooked to.
*/ */
_registerBrowserWindow(win) { _registerBrowserWindow(win) {
@ -819,7 +796,7 @@ Services.obs.addObserver(gDevToolsBrowser, "devtools:loader:destroy");
// Fake end of browser window load event for all already opened windows // Fake end of browser window load event for all already opened windows
// that is already fully loaded. // that is already fully loaded.
for (const win of Services.wm.getEnumerator(gDevTools.chromeWindowType)) { for (const win of Services.wm.getEnumerator(gDevTools.chromeWindowType)) {
if (win.gBrowserInit && win.gBrowserInit.delayedStartupFinished) { if (win.gBrowserInit?.delayedStartupFinished) {
gDevToolsBrowser._registerBrowserWindow(win); gDevToolsBrowser._registerBrowserWindow(win);
} }
} }

View File

@ -29,12 +29,6 @@ loader.lazyRequireGetter(
"devtools/client/webconsole/browser-console-manager", "devtools/client/webconsole/browser-console-manager",
true true
); );
loader.lazyRequireGetter(this, "Telemetry", "devtools/client/shared/telemetry");
loader.lazyImporter(
this,
"ScratchpadManager",
"resource://devtools/client/scratchpad/scratchpad-manager.jsm"
);
loader.lazyImporter( loader.lazyImporter(
this, this,
"BrowserToolboxProcess", "BrowserToolboxProcess",
@ -68,8 +62,6 @@ function DevTools() {
this._creatingToolboxes = new Map(); // Map<target, toolbox Promise> this._creatingToolboxes = new Map(); // Map<target, toolbox Promise>
EventEmitter.decorate(this); EventEmitter.decorate(this);
this._telemetry = new Telemetry();
this._telemetry.setEventRecordingEnabled(true);
// Listen for changes to the theme pref. // Listen for changes to the theme pref.
this._onThemeChanged = this._onThemeChanged.bind(this); this._onThemeChanged = this._onThemeChanged.bind(this);
@ -430,30 +422,12 @@ DevTools.prototype = {
saveDevToolsSession: function(state) { saveDevToolsSession: function(state) {
state.browserConsole = BrowserConsoleManager.getBrowserConsoleSessionState(); state.browserConsole = BrowserConsoleManager.getBrowserConsoleSessionState();
state.browserToolbox = BrowserToolboxProcess.getBrowserToolboxSessionState(); state.browserToolbox = BrowserToolboxProcess.getBrowserToolboxSessionState();
// Check if the module is loaded to avoid loading ScratchpadManager for no reason.
state.scratchpads = [];
if (
Cu.isModuleLoaded(
"resource://devtools/client/scratchpad/scratchpad-manager.jsm"
)
) {
state.scratchpads = ScratchpadManager.getSessionState();
}
}, },
/** /**
* Restore the devtools session state as provided by SessionStore. * Restore the devtools session state as provided by SessionStore.
*/ */
restoreDevToolsSession: function({ restoreDevToolsSession: function({ browserConsole, browserToolbox }) {
scratchpads,
browserConsole,
browserToolbox,
}) {
if (scratchpads) {
ScratchpadManager.restoreSession(scratchpads);
}
if (browserToolbox) { if (browserToolbox) {
BrowserToolboxProcess.init(); BrowserToolboxProcess.init();
} }
@ -463,12 +437,6 @@ DevTools.prototype = {
} }
}, },
/**
* Boolean, true, if we never opened a toolbox.
* Used to implement the telemetry tracking toolbox opening.
*/
_firstShowToolbox: true,
/** /**
* Show a Toolbox for a target (either by creating a new one, or if a toolbox * Show a Toolbox for a target (either by creating a new one, or if a toolbox
* already exists for the target, by bring to the front the existing one) * already exists for the target, by bring to the front the existing one)
@ -485,9 +453,6 @@ DevTools.prototype = {
* The type of host (bottom, window, left, right) * The type of host (bottom, window, left, right)
* @param {object} hostOptions * @param {object} hostOptions
* Options for host specifically * Options for host specifically
* @param {Number} startTime
* Optional, indicates the time at which the user event related to this toolbox
* opening started. This is a `Cu.now()` timing.
* @param {string} reason * @param {string} reason
* Reason the tool was opened * Reason the tool was opened
* *
@ -499,7 +464,6 @@ DevTools.prototype = {
toolId, toolId,
hostType, hostType,
hostOptions, hostOptions,
startTime,
reason = "toolbox_show" reason = "toolbox_show"
) { ) {
let toolbox = this._toolboxes.get(target); let toolbox = this._toolboxes.get(target);
@ -533,11 +497,6 @@ DevTools.prototype = {
this._creatingToolboxes.set(target, toolboxPromise); this._creatingToolboxes.set(target, toolboxPromise);
toolbox = await toolboxPromise; toolbox = await toolboxPromise;
this._creatingToolboxes.delete(target); this._creatingToolboxes.delete(target);
if (startTime) {
this.logToolboxOpenTime(toolbox, startTime);
}
this._firstShowToolbox = false;
} }
// We send the "enter" width here to ensure it is always sent *after* // We send the "enter" width here to ensure it is always sent *after*
@ -546,52 +505,9 @@ DevTools.prototype = {
const panelName = this.makeToolIdHumanReadable( const panelName = this.makeToolIdHumanReadable(
toolId || toolbox.defaultToolId toolId || toolbox.defaultToolId
); );
this._telemetry.addEventProperty(
toolbox,
"enter",
panelName,
null,
"width",
width
);
return toolbox; return toolbox;
}, },
/**
* Log telemetry related to toolbox opening.
* Two distinct probes are logged. One for cold startup, when we open the very first
* toolbox. This one includes devtools framework loading. And a second one for all
* subsequent toolbox opening, which should all be faster.
* These two probes are indexed by Tool ID.
*
* @param {String} toolbox
* Toolbox instance.
* @param {Number} startTime
* Indicates the time at which the user event related to the toolbox
* opening started. This is a `Cu.now()` timing.
*/
logToolboxOpenTime(toolbox, startTime) {
const toolId = toolbox.currentToolId || toolbox.defaultToolId;
const delay = Cu.now() - startTime;
const panelName = this.makeToolIdHumanReadable(toolId);
const telemetryKey = this._firstShowToolbox
? "DEVTOOLS_COLD_TOOLBOX_OPEN_DELAY_MS"
: "DEVTOOLS_WARM_TOOLBOX_OPEN_DELAY_MS";
this._telemetry.getKeyedHistogramById(telemetryKey).add(toolId, delay);
const browserWin = toolbox.win.top;
this._telemetry.addEventProperty(
browserWin,
"open",
"tools",
null,
"first_panel",
panelName
);
},
makeToolIdHumanReadable(toolId) { makeToolIdHumanReadable(toolId) {
if (/^[0-9a-fA-F]{40}_temporary-addon/.test(toolId)) { if (/^[0-9a-fA-F]{40}_temporary-addon/.test(toolId)) {
return "temporary-addon"; return "temporary-addon";
@ -711,60 +627,18 @@ DevTools.prototype = {
BrowserConsoleManager.openBrowserConsoleOrFocus(); BrowserConsoleManager.openBrowserConsoleOrFocus();
}, },
/**
* Evaluate the cross iframes query selectors
* @oaram {Object} walker
* @param {Array} selectors
* An array of CSS selectors to find the target accessible object.
* Several selectors can be needed if the element is nested in frames
* and not directly in the root document.
* @return {Promise} a promise that resolves when the node front is found for
* selection using inspector tools.
*/
async findNodeFront(walker, nodeSelectors) {
async function querySelectors(nodeFront) {
const selector = nodeSelectors.shift();
if (!selector) {
return nodeFront;
}
nodeFront = await walker.querySelector(nodeFront, selector);
if (nodeSelectors.length > 0) {
const { nodes } = await walker.children(nodeFront);
// If there are remaining selectors to process, they will target a document or a
// document-fragment under the current node. Whether the element is a frame or
// a web component, it can only contain one document/document-fragment, so just
// select the first one available.
nodeFront = nodes.find(node => {
const { nodeType } = node;
return (
nodeType === Node.DOCUMENT_FRAGMENT_NODE ||
nodeType === Node.DOCUMENT_NODE
);
});
}
return querySelectors(nodeFront);
}
const nodeFront = await walker.getRootNode();
return querySelectors(nodeFront);
},
/** /**
* Called from the DevToolsShim, used by nsContextMenu.js. * Called from the DevToolsShim, used by nsContextMenu.js.
* *
* @param {XULTab} tab * @param {XULTab} tab
* The browser tab on which inspect node was used. * The browser tab on which inspect node was used.
* @param {Array} selectors * @param {ElementIdentifier} domReference
* An array of CSS selectors to find the target node. Several selectors can be * Identifier generated by ContentDOMReference. It is a unique pair of
* needed if the element is nested in frames and not directly in the root * BrowsingContext ID and a numeric ID.
* document. The selectors are ordered starting with the root document and
* ending with the deepest nested frame.
* @param {Number} startTime
* Optional, indicates the time at which the user event related to this node
* inspection started. This is a `Cu.now()` timing.
* @return {Promise} a promise that resolves when the node is selected in the inspector * @return {Promise} a promise that resolves when the node is selected in the inspector
* markup view. * markup view.
*/ */
async inspectNode(tab, nodeSelectors, startTime) { async inspectNode(tab, domReference) {
const target = await TargetFactory.forTab(tab); const target = await TargetFactory.forTab(tab);
const toolbox = await gDevTools.showToolbox( const toolbox = await gDevTools.showToolbox(
@ -772,20 +646,18 @@ DevTools.prototype = {
"inspector", "inspector",
null, null,
null, null,
startTime,
"inspect_dom" "inspect_dom"
); );
const inspector = toolbox.getCurrentPanel(); const inspector = toolbox.getCurrentPanel();
// If the toolbox has been switched into a nested frame, we should first remove
// selectors according to the frame depth.
nodeSelectors.splice(0, toolbox.selectedFrameDepth);
// new-node-front tells us when the node has been selected, whether the // new-node-front tells us when the node has been selected, whether the
// browser is remote or not. // browser is remote or not.
const onNewNode = inspector.selection.once("new-node-front"); const onNewNode = inspector.selection.once("new-node-front");
const nodeFront = await this.findNodeFront(inspector.walker, nodeSelectors); const nodeFront = await inspector.walker.getNodeActorFromContentDomReference(
domReference
);
// Select the final node // Select the final node
inspector.selection.setNodeFront(nodeFront, { inspector.selection.setNodeFront(nodeFront, {
reason: "browser-context-menu", reason: "browser-context-menu",
@ -802,27 +674,25 @@ DevTools.prototype = {
* *
* @param {XULTab} tab * @param {XULTab} tab
* The browser tab on which inspect accessibility was used. * The browser tab on which inspect accessibility was used.
* @param {Array} selectors * @param {ElementIdentifier} domReference
* An array of CSS selectors to find the target accessible object. * Identifier generated by ContentDOMReference. It is a unique pair of
* Several selectors can be needed if the element is nested in frames * BrowsingContext ID and a numeric ID.
* and not directly in the root document.
* @param {Number} startTime
* Optional, indicates the time at which the user event related to this
* node inspection started. This is a `Cu.now()` timing.
* @return {Promise} a promise that resolves when the accessible object is * @return {Promise} a promise that resolves when the accessible object is
* selected in the accessibility inspector. * selected in the accessibility inspector.
*/ */
async inspectA11Y(tab, nodeSelectors, startTime) { async inspectA11Y(tab, domReference) {
const target = await TargetFactory.forTab(tab); const target = await TargetFactory.forTab(tab);
const toolbox = await gDevTools.showToolbox( const toolbox = await gDevTools.showToolbox(
target, target,
"accessibility", "accessibility",
null, null,
null, null
startTime );
const inspectorFront = await toolbox.target.getFront("inspector");
const nodeFront = await inspectorFront.walker.getNodeActorFromContentDomReference(
domReference
); );
const nodeFront = await this.findNodeFront(toolbox.walker, nodeSelectors);
// Select the accessible object in the panel and wait for the event that // Select the accessible object in the panel and wait for the event that
// tells us it has been done. // tells us it has been done.
const a11yPanel = toolbox.getCurrentPanel(); const a11yPanel = toolbox.getCurrentPanel();
@ -855,8 +725,8 @@ DevTools.prototype = {
removeThemeObserver(this._onThemeChanged); removeThemeObserver(this._onThemeChanged);
// Do not unregister devtools from the DevToolsShim if the destroy is caused by an // Do not unregister devtools from the DevToolsShim if the destroy is caused by an
// application shutdown. For instance SessionStore needs to save the Scratchpad // application shutdown. For instance SessionStore needs to save the Browser Toolbox
// manager state on shutdown. // state on shutdown.
if (!shuttingDown) { if (!shuttingDown) {
// Notify the DevToolsShim that DevTools are no longer available, particularly if // Notify the DevToolsShim that DevTools are no longer available, particularly if
// the destroy was caused by disabling/removing DevTools. // the destroy was caused by disabling/removing DevTools.

View File

@ -1,149 +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/. */
"use strict";
/**
* This JSM is here to keep some compatibility with existing add-ons.
* Please now use the modules:
* - devtools/client/framework/devtools for gDevTools
* - devtools/client/framework/devtools-browser for gDevToolsBrowser
*/
this.EXPORTED_SYMBOLS = ["gDevTools", "gDevToolsBrowser"];
/**
* Do not directly map to the commonjs modules so that callsites of
* gDevTools.jsm do not have to do anything to access to the very last version
* of the module. The `devtools` and `browser` getter are always going to
* retrieve the very last version of the modules.
*/
Object.defineProperty(this, "require", {
get() {
const { require } = ChromeUtils.import(
"resource://devtools/shared/Loader.jsm"
);
return require;
},
});
Object.defineProperty(this, "devtools", {
get() {
return require("devtools/client/framework/devtools").gDevTools;
},
});
Object.defineProperty(this, "browser", {
get() {
return require("devtools/client/framework/devtools-browser")
.gDevToolsBrowser;
},
});
/**
* gDevTools is a singleton that controls the Firefox Developer Tools.
*
* It is an instance of a DevTools class that holds a set of tools. It has the
* same lifetime as the browser.
*/
const gDevToolsMethods = [
// Used by: - b2g desktop.js
// - nsContextMenu
// - /devtools code
"showToolbox",
// Used by Addon SDK and /devtools
"closeToolbox",
"getToolbox",
// Used by Addon SDK, main.js and tests:
"registerTool",
"registerTheme",
"unregisterTool",
"unregisterTheme",
// Used by main.js and test
"getToolDefinitionArray",
"getThemeDefinitionArray",
// Used by WebExtensions devtools API
"getTheme",
// Used by theme-switching.js
"getThemeDefinition",
"emit",
// Used by /devtools
"on",
"off",
"once",
// Used by tests
"getToolDefinitionMap",
"getThemeDefinitionMap",
"getDefaultTools",
"getAdditionalTools",
"getToolDefinition",
];
this.gDevTools = {
// Used by tests
get _toolboxes() {
return devtools._toolboxes;
},
get _tools() {
return devtools._tools;
},
};
gDevToolsMethods.forEach(name => {
this.gDevTools[name] = (...args) => {
return devtools[name].apply(devtools, args);
};
});
/**
* gDevToolsBrowser exposes functions to connect the gDevTools instance with a
* Firefox instance.
*/
const gDevToolsBrowserMethods = [
// used by browser-sets.inc, command
"toggleToolboxCommand",
// Used by browser.js itself, by setting a oncommand string...
"selectToolCommand",
// Used by browser-sets.inc, command
"openAboutDebugging",
// Used by browser-sets.inc, command
"openConnectScreen",
// Used by browser-sets.inc, command
// itself, webide widget
"openWebIDE",
// Used by browser-sets.inc, command
"openContentProcessToolbox",
// Used by browser.js
"registerBrowserWindow",
// Used by devtools-browser.js for the Toggle Toolbox status
"hasToolboxOpened",
// Used by browser.js
"forgetBrowserWindow",
];
this.gDevToolsBrowser = {
// Used by webide.js
get isWebIDEInitialized() {
return browser.isWebIDEInitialized;
},
// Used by a test (should be removed)
get _trackedBrowserWindows() {
return browser._trackedBrowserWindows;
},
};
gDevToolsBrowserMethods.forEach(name => {
this.gDevToolsBrowser[name] = (...args) => {
return browser[name].apply(browser, args);
};
});

View File

@ -23,7 +23,6 @@ DevToolsModules(
'browser-menus.js', 'browser-menus.js',
'devtools-browser.js', 'devtools-browser.js',
'devtools.js', 'devtools.js',
'gDevTools.jsm',
'menu-item.js', 'menu-item.js',
'menu.js', 'menu.js',
'selection.js', 'selection.js',

View File

@ -4,16 +4,25 @@
"use strict"; "use strict";
const nodeConstants = require("devtools/shared/dom-node-constants"); const EventEmitter = require("devtools/shared/event-emitter");
var EventEmitter = require("devtools/shared/event-emitter");
loader.lazyRequireGetter(
this,
"nodeConstants",
"devtools/shared/dom-node-constants"
);
/** /**
* Selection is a singleton belonging to the Toolbox that manages the current selected
* NodeFront. In addition, it provides some helpers about the context of the selected
* node.
*
* API * API
* *
* new Selection(walker=null) * new Selection()
* destroy() * destroy()
* node (readonly) * nodeFront (readonly)
* setNode(node, origin="unknown") * setNodeFront(node, origin="unknown")
* *
* Helpers: * Helpers:
* *
@ -46,14 +55,11 @@ var EventEmitter = require("devtools/shared/event-emitter");
* "reparented" when the node (or one of its parents) is moved under * "reparented" when the node (or one of its parents) is moved under
* a different node * a different node
*/ */
function Selection() {
/**
* A Selection object. Hold a reference to a node.
* Includes some helpers, fire some helpful events.
*/
function Selection(walker) {
EventEmitter.decorate(this); EventEmitter.decorate(this);
// The WalkerFront is dynamic and is always set to the selected NodeFront's WalkerFront.
this._walker = null;
// A single node front can be represented twice on the client when the node is a slotted // A single node front can be represented twice on the client when the node is a slotted
// element. It will be displayed once as a direct child of the host element, and once as // element. It will be displayed once as a direct child of the host element, and once as
// a child of a slot in the "shadow DOM". The latter is called the slotted version. // a child of a slot in the "shadow DOM". The latter is called the slotted version.
@ -61,14 +67,9 @@ function Selection(walker) {
this._onMutations = this._onMutations.bind(this); this._onMutations = this._onMutations.bind(this);
this.setNodeFront = this.setNodeFront.bind(this); this.setNodeFront = this.setNodeFront.bind(this);
this.setWalker(walker);
} }
exports.Selection = Selection;
Selection.prototype = { Selection.prototype = {
_walker: null,
_onMutations: function(mutations) { _onMutations: function(mutations) {
let attributeChange = false; let attributeChange = false;
let pseudoChange = false; let pseudoChange = false;
@ -105,10 +106,10 @@ Selection.prototype = {
}, },
destroy: function() { destroy: function() {
this.setWalker(null); this.setWalker();
}, },
setWalker: function(walker) { setWalker: function(walker = null) {
if (this._walker) { if (this._walker) {
this._walker.off("mutations", this._onMutations); this._walker.off("mutations", this._onMutations);
} }
@ -151,11 +152,13 @@ Selection.prototype = {
this._isSlotted = isSlotted; this._isSlotted = isSlotted;
this._nodeFront = nodeFront; this._nodeFront = nodeFront;
this.emit("new-node-front", nodeFront, this.reason); if (nodeFront) {
}, this.setWalker(nodeFront.walkerFront);
} else {
this.setWalker();
}
get documentFront() { this.emit("new-node-front", nodeFront, this.reason);
return this._walker.document(this._nodeFront);
}, },
get nodeFront() { get nodeFront() {
@ -308,3 +311,5 @@ Selection.prototype = {
return this.isNode() && this.nodeFront.isShadowRoot; return this.isNode() && this.nodeFront.isShadowRoot;
}, },
}; };
module.exports = Selection;

View File

@ -91,13 +91,13 @@ async function _targetFromURL(client, id, type, chrome) {
throw ex; throw ex;
} }
} else if (type === "extension") { } else if (type === "extension") {
const addonFront = await client.mainRoot.getAddon({ id }); const addonDescriptor = await client.mainRoot.getAddon({ id });
if (!addonFront) { if (!addonDescriptor) {
throw new Error(`targetFromURL, extension with id '${id}' doesn't exist`); throw new Error(`targetFromURL, extension with id '${id}' doesn't exist`);
} }
front = await addonFront.connect(); front = await addonDescriptor.getTarget();
} else if (type === "worker") { } else if (type === "worker") {
front = await client.mainRoot.getWorker(id); front = await client.mainRoot.getWorker(id);

View File

@ -8,8 +8,9 @@ let tracker;
const { DevToolsLoader } = ChromeUtils.import( const { DevToolsLoader } = ChromeUtils.import(
"resource://devtools/shared/Loader.jsm" "resource://devtools/shared/Loader.jsm"
); );
const loader = new DevToolsLoader(); const loader = new DevToolsLoader({
loader.invisibleToDebugger = true; invisibleToDebugger: true,
});
const { allocationTracker } = loader.require( const { allocationTracker } = loader.require(
"chrome://mochitests/content/browser/devtools/shared/test-helpers/allocation-tracker" "chrome://mochitests/content/browser/devtools/shared/test-helpers/allocation-tracker"
); );

View File

@ -63,6 +63,7 @@ skip-if = os == 'win' || debug # Bug 1282269, 1448084
[browser_devtools_api.js] [browser_devtools_api.js]
[browser_devtools_api_destroy.js] [browser_devtools_api_destroy.js]
[browser_dynamic_tool_enabling.js] [browser_dynamic_tool_enabling.js]
[browser_front_parentFront.js]
[browser_ignore_toolbox_network_requests.js] [browser_ignore_toolbox_network_requests.js]
[browser_keybindings_01.js] [browser_keybindings_01.js]
[browser_keybindings_02.js] [browser_keybindings_02.js]
@ -145,7 +146,6 @@ run-if = e10s
[browser_toolbox_view_source_01.js] [browser_toolbox_view_source_01.js]
[browser_toolbox_view_source_02.js] [browser_toolbox_view_source_02.js]
[browser_toolbox_view_source_03.js] [browser_toolbox_view_source_03.js]
[browser_toolbox_view_source_04.js]
[browser_toolbox_window_reload_target.js] [browser_toolbox_window_reload_target.js]
[browser_toolbox_window_shortcuts.js] [browser_toolbox_window_shortcuts.js]
[browser_toolbox_window_title_changes.js] [browser_toolbox_window_title_changes.js]

View File

@ -0,0 +1,42 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test the Front's parentFront attribute returns the correct parent front.
const TEST_URL = `data:text/html;charset=utf-8,<div id="test"></div>`;
add_task(async function() {
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
const tab = await addTab(TEST_URL);
const target = await TargetFactory.forTab(tab);
await target.attach();
const inspectorFront = await target.getFront("inspector");
const walker = inspectorFront.walker;
const pageStyleFront = await inspectorFront.getPageStyle();
const nodeFront = await walker.querySelector(walker.rootNode, "#test");
is(
inspectorFront.parentFront,
target,
"Got the correct parentFront from the InspectorFront."
);
is(
walker.parentFront,
inspectorFront,
"Got the correct parentFront from the WalkerFront."
);
is(
pageStyleFront.parentFront,
inspectorFront,
"Got the correct parentFront from the PageStyleFront."
);
is(
nodeFront.parentFront,
walker,
"Got the correct parentFront from the NodeFront."
);
});

View File

@ -102,12 +102,12 @@ add_task(async function() {
async function inspectorShouldBeOpenAndHighlighting(inspector) { async function inspectorShouldBeOpenAndHighlighting(inspector) {
is(toolbox.currentToolId, "inspector", "Correct tool has been loaded"); is(toolbox.currentToolId, "inspector", "Correct tool has been loaded");
await toolbox.inspectorFront.nodePicker.once("picker-started"); await toolbox.nodePicker.once("picker-started");
ok(true, "picker-started event received, highlighter started"); ok(true, "picker-started event received, highlighter started");
inspector.synthesizeKey(); inspector.synthesizeKey();
await toolbox.inspectorFront.nodePicker.once("picker-stopped"); await toolbox.nodePicker.once("picker-stopped");
ok(true, "picker-stopped event received, highlighter stopped"); ok(true, "picker-stopped event received, highlighter stopped");
} }

Some files were not shown because too many files have changed in this diff Show More