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": [
"client/scratchpad/scratchpad-manager.jsm",
"client/scratchpad/scratchpad.js",
"client/shared/*.jsm",
],
"rules": {
@ -31,7 +29,6 @@ module.exports = {
}, {
"files": [
"client/framework/**",
"client/scratchpad/**",
"client/shared/*.jsm",
"client/shared/widgets/*.jsm",
],
@ -41,23 +38,13 @@ module.exports = {
}, {
"files": [
"client/framework/**",
"client/scratchpad/**",
],
"rules": {
"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": [
"client/framework/**",
"client/scratchpad/**",
"client/shared/*.jsm",
"client/shared/widgets/*.jsm",
],
@ -67,7 +54,6 @@ module.exports = {
}, {
"files": [
"client/framework/test/**",
"client/scratchpad/**",
],
"rules": {
"mozilla/var-only-at-top-level": "off",
@ -75,7 +61,6 @@ module.exports = {
}, {
"files": [
"client/framework/**",
"client/scratchpad/**",
"client/shared/widgets/*.jsm",
],
"rules": {
@ -84,7 +69,6 @@ module.exports = {
}, {
"files": [
"client/framework/**",
"client/scratchpad/**",
],
"rules": {
"strict": "off",

View File

@ -7,7 +7,7 @@
<meta charset="utf-8" />
<title>Debugging</title>
<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="stylesheet" href="chrome://devtools/content/aboutdebugging/aboutdebugging.css"/>
<script src="resource://devtools/client/aboutdebugging/initializer.js"></script>

View File

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

View File

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

View File

@ -58,9 +58,9 @@ function getRuntimeEventExtras(runtime) {
const { extra, runtimeDetails } = runtime;
// 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 runtimeName = (runtimeDetails && runtimeDetails.info.name) || "";
const runtimeName = runtimeDetails?.info.name || "";
return {
connection_type: runtime.type,
device_name: deviceName,
@ -125,8 +125,7 @@ function onRemoteRuntimesUpdated(action, store) {
const oldRuntime = oldRuntimes.find(
r => r.extra.deviceName === oldDeviceName
);
const isUnplugged =
newRuntime && newRuntime.isUnplugged && !oldRuntime.isUnplugged;
const isUnplugged = newRuntime?.isUnplugged && !oldRuntime.isUnplugged;
if (oldDeviceName && (!newRuntime || isUnplugged)) {
recordEvent("device_removed", {
connection_type: action.runtimeType,
@ -153,8 +152,7 @@ function onRemoteRuntimesUpdated(action, store) {
const oldRuntime = oldRuntimes.find(
r => r.extra.deviceName === newDeviceName
);
const isPlugged =
oldRuntime && oldRuntime.isUnplugged && !newRuntime.isUnplugged;
const isPlugged = oldRuntime?.isUnplugged && !newRuntime.isUnplugged;
if (newDeviceName && (!oldRuntime || isPlugged)) {
recordEvent("device_added", {

View File

@ -257,12 +257,6 @@ async function toolboxTestScript(toolbox, devtoolsTab) {
const waitForNavigated = toolbox.target.once("navigate");
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;
consoleWrapper.dispatchEvaluateExpression(
"myWebExtensionPopupAddonFunction()"

View File

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

View File

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

View File

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

View File

@ -4,7 +4,6 @@
:root {
--accessibility-font-size: 12px;
--accessibility-toolbar-height: 24px;
--accessibility-toolbar-height-tall: 35px;
--accessibility-toolbar-focus: var(--blue-50);
--accessibility-toolbar-focus-alpha30: rgba(10, 132, 255, 0.3);
@ -12,7 +11,12 @@
--accessibility-horizontal-padding: 5px;
--accessibility-horizontal-indent: 20px;
--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-tree-row-height: 21px;
--accessibility-unfocused-tree-focused-node-background: var(--grey-20);
@ -96,7 +100,7 @@ body {
}
.split-box.horz {
height: calc(100vh - var(--accessibility-toolbar-height));
height: var(--accessibility-main-height);
}
.mainFrame .devtools-button,
@ -369,7 +373,7 @@ body {
background: var(--theme-toolbar-background);
font: message-box;
font-size: var(--accessibility-font-size);
height: var(--accessibility-toolbar-height);
height: var(--theme-toolbar-height);
color: var(--theme-toolbar-color);
}
@ -452,14 +456,14 @@ body {
.split-box:not(.horz) .right-sidebar {
position: fixed;
width: inherit;
height: calc(100vh - (var(--accessibility-toolbar-height)));
height: var(--accessibility-main-height)
}
.right-sidebar ._header {
background-color: var(--theme-toolbar-background);
border-bottom: 1px solid var(--theme-splitter-color);
height: var(--accessibility-toolbar-height);
line-height: var(--accessibility-toolbar-height);
height: var(--theme-toolbar-height);
line-height: var(--theme-toolbar-height);
padding-inline-start: 14px;
padding-inline-end: var(--accessibility-arrow-horizontal-padding);
display: flex;
@ -683,7 +687,7 @@ body {
margin: 0;
font-weight: bold;
font-size: var(--accessibility-font-size);
line-height: var(--accessibility-toolbar-height);
line-height: var(--theme-toolbar-height);
}
.accessibility-color-contrast-annotation {

View File

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

View File

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

View File

@ -38,7 +38,7 @@ function accessibles(state = getInitialState(), action) {
}
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.toolbox = null;
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,
moduleNameMapper: {
// Custom name mappers for modules that require m-c specific API.
"^../utils/l10n": `${__dirname}/fixtures/l10n`,
"^devtools/client/shared/link": `${__dirname}/fixtures/stub`,
"^devtools/shared/plural-form": `${__dirname}/fixtures/plural-form`,
"^chrome": `${__dirname}/fixtures/Chrome`,
"^Services": `${__dirname}/fixtures/Services`,
"^devtools/client/shared/fluent-l10n/fluent-l10n$": `${__dirname}/fixtures/fluent-l10n`,
"^devtools/client/shared/unicode-url": `${__dirname}/fixtures/unicode-url`,
// Map all require("devtools/...") to the real devtools root.
"^devtools\\/(.*)": `${__dirname}/../../../../$1`,

View File

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

View File

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

View File

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

View File

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

View File

@ -122,10 +122,6 @@ declare module 'codemirror/addon/hint/javascript-hint' {
declare module.exports: any;
}
declare module 'codemirror/addon/hint/show-hint' {
declare module.exports: any;
}
declare module 'codemirror/addon/hint/sql-hint' {
declare module.exports: any;
}
@ -246,14 +242,6 @@ declare module 'codemirror/addon/selection/selection-pointer' {
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.exports: any;
}
@ -1090,9 +1078,6 @@ declare module 'codemirror/addon/hint/html-hint.js' {
declare module 'codemirror/addon/hint/javascript-hint.js' {
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.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.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.exports: $Exports<'codemirror/addon/wrap/hardwrap'>;
}

View File

@ -40,5 +40,8 @@ module.exports = {
moduleNameMapper: {
"\\.css$": "<rootDir>/src/test/__mocks__/styleMock.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-transform-flow-strip-types": "^7.4.4",
"@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-react": "^7.0.0",
"@babel/register": "^7.0.0",

View File

@ -55,7 +55,7 @@ function supportsObject(object, noGrip = false) {
}
const type = getGripType(object, noGrip);
return object.preview && (type === "HTMLDocument" || type === "XULDocument");
return object.preview && type === "HTMLDocument";
}
// 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;

View File

@ -39,23 +39,3 @@ describe("Document", () => {
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) {
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 = {
@ -103,7 +104,6 @@ DebuggerPanel.prototype = {
},
openElementInInspector: async function(gripOrFront) {
await this.toolbox.initInspector();
const onSelectInspector = this.toolbox.selectTool("inspector");
const onGripNodeToFront = getNodeFront(gripOrFront, this.toolbox);
@ -121,18 +121,18 @@ DebuggerPanel.prototype = {
},
highlightDomElement: async function(gripOrFront) {
await this.toolbox.initInspector();
if (!this.toolbox.highlighter) {
return null;
}
const front = await getNodeFront(gripOrFront, this.toolbox);
return this.toolbox.highlighter.highlight(front);
const nodeFront = await getNodeFront(gripOrFront, this.toolbox);
nodeFront.highlighterFront.highlight(nodeFront);
},
unHighlightDomElement: function() {
return this.toolbox.highlighter
? this.toolbox.highlighter.unhighlight(false)
: null;
unHighlightDomElement: async function(gripOrFront) {
try {
const nodeFront = await getNodeFront(gripOrFront, this.toolbox);
nodeFront.highlighterFront.unhighlight();
} catch (e) {
// This call might fail if called asynchrously after the toolbox is finished
// closing.
}
},
getFrames: function() {

View File

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

View File

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

View File

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

View File

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

View File

@ -74,18 +74,32 @@ async function loadSource(
return result;
}
// We only need the source text from one actor, but messages sent to retrieve
// the source might fail if the actor has or is about to shut down. Keep
// trying with different actors until one request succeeds.
let response;
const handledActors = new Set();
while (true) {
const actors = getSourceActorsForSource(state, source.id);
if (!actors.length) {
throw new Error("No source actor for loadSource");
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 {
text: response.source,
contentType: response.contentType || "text/javascript",
text: (response: any).source,
contentType: (response: any).contentType || "text/javascript",
};
}

View File

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

View File

@ -5,7 +5,13 @@
// @flow
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 { MatchedLocations } from "../../reducers/file-search";
import type { TreeNode } from "../../utils/sources-tree/types";
@ -152,6 +158,13 @@ export type DebuggeeAction =
+type: "SELECT_THREAD",
+cx: Context,
+thread: ThreadId,
|}
| {|
+type: "PREVIEW_PAUSED_LOCATION",
+location: SourceLocation,
|}
| {|
+type: "CLEAR_PREVIEW_PAUSED_LOCATION",
|};
export type {

View File

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

View File

@ -9,13 +9,11 @@
* will appear in performance tooling under the User Timing API
*/
const mark =
window.performance && window.performance.mark
const mark = window.performance?.mark
? window.performance.mark.bind(window.performance)
: a => {};
const measure =
window.performance && window.performance.measure
const measure = window.performance?.measure
? window.performance.measure.bind(window.performance)
: (a, b, c) => {};

View File

@ -107,7 +107,7 @@ function lookupThreadFront(thread: string) {
}
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) {
@ -452,10 +452,11 @@ async function getSourceActorBreakableLines({
thread,
actor,
}: SourceActor): Promise<Array<number>> {
const sourceThreadFront = lookupThreadFront(thread);
const sourceFront = sourceThreadFront.source({ actor });
let sourceFront;
let actorLines = [];
try {
const sourceThreadFront = lookupThreadFront(thread);
sourceFront = sourceThreadFront.source({ actor });
actorLines = await sourceFront.getBreakableLines();
} catch (e) {
// Handle backward compatibility
@ -463,10 +464,11 @@ async function getSourceActorBreakableLines({
e.message &&
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));
} else if (!e.message || !e.message.match(/Connection closed/)) {
throw e;
} else {
// 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,
performanceEntriesActor: ActorId,
profilerActor: ActorId,
promisesActor: ActorId,
reflowActor: ActorId,
storageActor: ActorId,
styleEditorActor: ActorId,

View File

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

View File

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

View File

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

View File

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

View File

@ -262,7 +262,7 @@ class SearchBar extends Component<Props, State> {
function SearchModBtn({ modVal, className, svgName, tooltip }) {
const preppedClass = classnames(className, {
active: modifiers && modifiers[modVal],
active: modifiers?.[modVal],
});
return (
<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 (selectedSource && selectedSource.isBlackBoxed) {
if (selectedSource?.isBlackBoxed) {
toggleBlackBox(cx, selectedSource);
}
@ -659,7 +659,7 @@ class Editor extends PureComponent<Props, State> {
return (
<div
className={classnames("editor-wrapper", {
blackboxed: selectedSource && selectedSource.isBlackBoxed,
blackboxed: selectedSource?.isBlackBoxed,
"skip-pausing": skipPausing,
})}
ref={c => (this.$editorWrapper = c)}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,11 +2,8 @@
* 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/. */
#scratchpad-sidebar > tabs {
height: 0;
border: none;
}
"use strict";
#sp-toolbar {
border: none;
}
module.exports = {
appinfo: "",
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -260,7 +260,7 @@ async function mapImportReferenceToDescriptor({
for (
let op = meta, index = 0;
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
// be ideal for this case.

View File

@ -178,7 +178,7 @@ function isReliableScope(scope: OriginalScope): boolean {
let unknownBindings = 0;
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)) {
const binding = vars[key];
@ -452,7 +452,7 @@ async function findGeneratedBinding(
// 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
// import declaration.
if (declRange && declRange.singleDeclaration) {
if (declRange?.singleDeclaration) {
const applicableDeclBindings = await loadApplicableBindings(
pos.declaration,
pos.type

View File

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

View File

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

View File

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

View File

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

View File

@ -5,7 +5,7 @@
// @flow
import type { SourceContent } from "../types";
import { saveAs } from "devtools-modules";
import { DevToolsUtils } from "devtools-modules";
/**
* Utils for utils, by utils
@ -62,5 +62,5 @@ export function downloadFile(content: SourceContent, fileName: string) {
}
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 get from "lodash/get";
import findIndex from "lodash/findIndex";
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
// identifier is included in the "scope" of its parent
const identifierEnd = get(func, "identifier.loc.end");
const identifierEnd = func?.identifier?.loc?.end;
if (identifierEnd) {
location.start = identifierEnd;
}

View File

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

View File

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

View File

@ -151,11 +151,11 @@ skip-if = os == "win"
[browser_dbg-react-app.js]
skip-if = os == "win"
[browser_dbg-wasm-sourcemaps.js]
skip-if = true
[browser_dbg-windowless-workers.js]
[browser_dbg-windowless-workers-early-breakpoint.js]
[browser_dbg-worker-exception.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-breakpoints.js]
[browser_dbg-eval-throw.js]

View File

@ -9,8 +9,9 @@ var gClient, gThreadFront;
var gNewChromeSource = promise.defer();
var { DevToolsLoader } = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
var customLoader = new DevToolsLoader();
customLoader.invisibleToDebugger = true;
var customLoader = new DevToolsLoader({
invisibleToDebugger: true,
});
var { DebuggerServer } = customLoader.require("devtools/server/debugger-server");
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
const view = inspectorNode.ownerDocument.defaultView;
const onNodeHighlight = toolbox.target
.once("inspector")
.then(inspector => inspector.highlighter.once("node-highlight"));
const inspectorFront = await toolbox.target.getFront("inspector");
const onNodeHighlight = inspectorFront.highlighter.once("node-highlight");
EventUtils.synthesizeMouseAtCenter(
inspectorNode,
{ type: "mousemove" },

View File

@ -7,26 +7,25 @@
*/
add_task(async function() {
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);
// After reload() we are getting getSources notifiction for old sources,
// using the debugger statement to really stop are reloaded page.
await waitForPaused(dbg);
await resume(dbg);
await waitForLoadedSource(dbg, "doc-wasm-sourcemaps");
assertPausedLocation(dbg);
await waitForSource(dbg, "fib.c");
await waitForSources(dbg, "doc-wasm-sourcemaps.html", "fib.c");
// Set breakpoint and reload the page.
ok(true, "Original sources exist");
const mainSrc = findSource(dbg, "fib.c");
await selectSource(dbg, mainSrc);
await selectSource(dbg, "fib.c");
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);
await waitForPaused(dbg, "fib.c");
@ -38,6 +37,6 @@ add_task(async function() {
is(
firstFrameLocation.includes("fib.c"),
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
* 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(/Connection closed/);
function findNode(dbg, text) {
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"
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":
version "7.5.5"
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/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":
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"
@ -258,6 +271,14 @@
"@babel/helper-plugin-utils" "^7.0.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":
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"
@ -296,6 +317,13 @@
dependencies:
"@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":
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"
@ -308,6 +336,13 @@
dependencies:
"@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":
version "7.2.0"
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"
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:
version "1.0.4"
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"
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"
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.6.tgz#dca6cf680a0bd03589aff684700858c81abeeb39"
dependencies:
@ -4829,18 +4860,6 @@ execa@^0.8.0:
signal-exit "^3.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:
version "1.0.0"
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"
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:
version "1.0.2"
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:
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:
version "0.1.4"
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:
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"
resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz#ed320051dfcc5024fae696712c8288993595e8ac"
dependencies:
@ -10075,14 +10073,6 @@ read-pkg@^3.0.0:
normalize-package-data "^2.3.2"
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:
version "2.3.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
@ -11029,10 +11019,6 @@ run-async@^2.2.0:
dependencies:
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:
version "1.1.9"
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"
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:
version "0.0.4"
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"

View File

@ -58,11 +58,6 @@ loader.lazyGetter(
"StoragePanel",
() => require("devtools/client/storage/panel").StoragePanel
);
loader.lazyGetter(
this,
"ScratchpadPanel",
() => require("devtools/client/scratchpad/panel").ScratchpadPanel
);
loader.lazyGetter(
this,
"DomPanel",
@ -93,13 +88,7 @@ loader.lazyRequireGetter(
loader.lazyRequireGetter(
this,
"ResponsiveUIManager",
"devtools/client/responsive/manager",
true
);
loader.lazyImporter(
this,
"ScratchpadManager",
"resource://devtools/client/scratchpad/scratchpad-manager.jsm"
"devtools/client/responsive/manager"
);
const { MultiLocalizationHelper } = require("devtools/shared/l10n");
@ -154,8 +143,11 @@ Tools.inspector = {
inMenu: 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) {
toolbox.inspectorFront.nodePicker.togglePicker();
toolbox.nodePicker.togglePicker();
},
isTargetSupported: function(target) {
@ -228,7 +220,7 @@ Tools.styleEditor = {
visibilityswitch: "devtools.styleeditor.enabled",
accesskey: l10n("open.accesskey"),
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"),
panelLabel: l10n("ToolboxStyleEditor.panelLabel"),
get tooltip() {
@ -283,7 +275,7 @@ function switchPerformancePanel() {
return target.isLocalTab;
};
} 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) {
return new PerformancePanel(frame, target);
};
@ -354,7 +346,7 @@ Tools.storage = {
accesskey: l10n("storage.accesskey"),
visibilityswitch: "devtools.storage.enabled",
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"),
menuLabel: l10n("storage.menuLabel"),
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 = {
id: "dom",
accesskey: l10n("dom.accesskey"),
@ -487,7 +461,6 @@ var defaultTools = [
Tools.performance,
Tools.netMonitor,
Tools.storage,
Tools.scratchpad,
Tools.memory,
Tools.dom,
#ifdef ACCESSIBILITY
@ -531,14 +504,6 @@ exports.ToolboxButtons = [
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",
description: l10n(
@ -594,8 +559,8 @@ function createHighlightButton(highlighterName, id) {
description: l10n(`toolbox.buttons.${id}`),
isTargetSupported: target => !target.chrome,
async onClick(event, toolbox) {
await toolbox.initInspector();
const highlighter = await toolbox.inspectorFront.getOrCreateHighlighterByType(
const inspectorFront = await toolbox.target.getFront("inspector");
const highlighter = await inspectorFront.getOrCreateHighlighterByType(
highlighterName
);
if (highlighter.isShown()) {
@ -609,11 +574,7 @@ function createHighlightButton(highlighterName, id) {
isChecked(toolbox) {
// if the inspector doesn't exist, then the highlighter has not yet been connected
// to the front end.
// TODO: we are using target._inspector here, but we should be using
// 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;
const inspectorFront = toolbox.target.getCachedFront("inspector");
if (!inspectorFront) {
// 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

View File

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

View File

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

View File

@ -18,9 +18,8 @@ add_task(async function() {
let node = getRowByIndex(panel, 2).querySelector(".objectBox-node");
// the inspector should be initialized first and then the node should
// highlight after the hover effect.
let onNodeHighlight = toolbox.target
.once("inspector")
.then(inspector => inspector.highlighter.once("node-highlight"));
const inspectorFront = await toolbox.target.getFront("inspector");
let onNodeHighlight = inspectorFront.highlighter.once("node-highlight");
EventUtils.synthesizeMouseAtCenter(
node,
{
@ -32,7 +31,7 @@ add_task(async function() {
is(nodeFront.displayName, "h1", "The correct node was highlighted");
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");
EventUtils.synthesizeMouseAtCenter(
btn,
@ -57,7 +56,7 @@ add_task(async function() {
},
node.ownerDocument.defaultView
);
onNodeHighlight = toolbox.highlighter.once("node-highlight");
onNodeHighlight = inspectorFront.highlighter.once("node-highlight");
nodeFront = await onNodeHighlight;
is(nodeFront.displayName, "h2", "The correct node was highlighted");
@ -69,7 +68,7 @@ add_task(async function() {
},
btn.ownerDocument.defaultView
);
onNodeUnhighlight = toolbox.highlighter.once("node-unhighlight");
onNodeUnhighlight = inspectorFront.highlighter.once("node-unhighlight");
await onNodeUnhighlight;
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
* the url is loaded
*/
function addTestTab(url) {
async function addTestTab(url) {
info("Adding a new test tab with URL: '" + url + "'");
return new Promise(resolve => {
addTab(url).then(tab => {
const tab = await addTab(url);
// Load devtools/shared/test/frame-script-utils.js
loadFrameScriptUtils();
// Select the DOM panel and wait till it's initialized.
initDOMPanel(tab).then(panel => {
waitForDispatch(panel, "FETCH_PROPERTIES").then(() => {
resolve({
tab: tab,
const panel = await initDOMPanel(tab);
// 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: panel,
});
});
});
});
});
panel,
};
}
/**

View File

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

View File

@ -10,15 +10,11 @@ const {
} = require("devtools/client/framework/reducers/dom-mutation-breakpoints");
exports.registerWalkerListeners = registerWalkerListeners;
function registerWalkerListeners(toolbox) {
const { walker } = toolbox;
walker.on("mutations", mutations =>
handleWalkerMutations(mutations, toolbox)
);
function registerWalkerListeners(store, walker) {
walker.on("mutations", mutations => handleWalkerMutations(mutations, store));
}
function handleWalkerMutations(mutations, toolbox) {
function handleWalkerMutations(mutations, store) {
// 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
// cases because BP updates could also happen due to explicitly API
@ -27,7 +23,7 @@ function handleWalkerMutations(mutations, toolbox) {
mutation => mutation.type === "mutationBreakpoint"
);
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
*
* @param {XULDocument} doc
* @param {HTMLDocument} doc
* The document to which menus are to be added.
* @param {String} id
* Element id.
@ -78,7 +78,7 @@ function createMenuItem({ doc, id, label, accesskey, isCheckbox }) {
*
* @param {Object} toolDefinition
* 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.
*/
function createToolMenuElements(toolDefinition, doc) {
@ -143,7 +143,7 @@ function sendEntryPointTelemetry(window) {
* Create xul menuitem, key elements for a given tool.
* And then insert them into browser DOM.
*
* @param {XULDocument} doc
* @param {HTMLDocument} doc
* The document to which the tool is to be registered.
* @param {Object} toolDefinition
* Tool definition of the tool to register.
@ -156,7 +156,7 @@ function insertToolMenuElements(doc, toolDefinition, prevDef) {
let ref;
if (prevDef) {
const menuitem = doc.getElementById("menuitem_" + prevDef.id);
ref = menuitem && menuitem.nextSibling ? menuitem.nextSibling : null;
ref = menuitem?.nextSibling ? menuitem.nextSibling : null;
} else {
ref = doc.getElementById("menu_devtools_separator");
}
@ -172,7 +172,7 @@ exports.insertToolMenuElements = insertToolMenuElements;
*
* @param {string} toolId
* 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
*/
function removeToolFromMenu(toolId, doc) {
@ -191,7 +191,7 @@ exports.removeToolFromMenu = removeToolFromMenu;
/**
* 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.
*/
function addAllToolsToMenu(doc) {
@ -224,7 +224,7 @@ function addAllToolsToMenu(doc) {
/**
* Add global menus that are not panel specific.
*
* @param {XULDocument} doc
* @param {HTMLDocument} doc
* The document to which menus are to be added.
*/
function addTopLevelItems(doc) {
@ -266,7 +266,7 @@ function addTopLevelItems(doc) {
const menu = doc.getElementById("menuWebDeveloperPopup");
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
// position.
const pageSource = doc.getElementById("menu_pageSource");
@ -277,7 +277,7 @@ function addTopLevelItems(doc) {
/**
* Remove global menus that are not panel specific.
*
* @param {XULDocument} doc
* @param {HTMLDocument} doc
* The document to which menus are to be added.
*/
function removeTopLevelItems(doc) {
@ -294,7 +294,7 @@ function removeTopLevelItems(doc) {
/**
* Add menus to a browser document
*
* @param {XULDocument} doc
* @param {HTMLDocument} doc
* The document to which menus are to be added.
*/
exports.addMenus = function(doc) {
@ -306,7 +306,7 @@ exports.addMenus = function(doc) {
/**
* Remove menus from a browser document
*
* @param {XULDocument} doc
* @param {HTMLDocument} doc
* The document to which menus are to be removed.
*/
exports.removeMenus = function(doc) {

View File

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

View File

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

View File

@ -29,12 +29,6 @@ loader.lazyRequireGetter(
"devtools/client/webconsole/browser-console-manager",
true
);
loader.lazyRequireGetter(this, "Telemetry", "devtools/client/shared/telemetry");
loader.lazyImporter(
this,
"ScratchpadManager",
"resource://devtools/client/scratchpad/scratchpad-manager.jsm"
);
loader.lazyImporter(
this,
"BrowserToolboxProcess",
@ -68,8 +62,6 @@ function DevTools() {
this._creatingToolboxes = new Map(); // Map<target, toolbox Promise>
EventEmitter.decorate(this);
this._telemetry = new Telemetry();
this._telemetry.setEventRecordingEnabled(true);
// Listen for changes to the theme pref.
this._onThemeChanged = this._onThemeChanged.bind(this);
@ -430,30 +422,12 @@ DevTools.prototype = {
saveDevToolsSession: function(state) {
state.browserConsole = BrowserConsoleManager.getBrowserConsoleSessionState();
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.
*/
restoreDevToolsSession: function({
scratchpads,
browserConsole,
browserToolbox,
}) {
if (scratchpads) {
ScratchpadManager.restoreSession(scratchpads);
}
restoreDevToolsSession: function({ browserConsole, browserToolbox }) {
if (browserToolbox) {
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
* 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)
* @param {object} hostOptions
* 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
* Reason the tool was opened
*
@ -499,7 +464,6 @@ DevTools.prototype = {
toolId,
hostType,
hostOptions,
startTime,
reason = "toolbox_show"
) {
let toolbox = this._toolboxes.get(target);
@ -533,11 +497,6 @@ DevTools.prototype = {
this._creatingToolboxes.set(target, toolboxPromise);
toolbox = await toolboxPromise;
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*
@ -546,52 +505,9 @@ DevTools.prototype = {
const panelName = this.makeToolIdHumanReadable(
toolId || toolbox.defaultToolId
);
this._telemetry.addEventProperty(
toolbox,
"enter",
panelName,
null,
"width",
width
);
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) {
if (/^[0-9a-fA-F]{40}_temporary-addon/.test(toolId)) {
return "temporary-addon";
@ -711,60 +627,18 @@ DevTools.prototype = {
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.
*
* @param {XULTab} tab
* The browser tab on which inspect node was used.
* @param {Array} selectors
* An array of CSS selectors to find the target node. Several selectors can be
* needed if the element is nested in frames and not directly in the root
* 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.
* @param {ElementIdentifier} domReference
* Identifier generated by ContentDOMReference. It is a unique pair of
* BrowsingContext ID and a numeric ID.
* @return {Promise} a promise that resolves when the node is selected in the inspector
* markup view.
*/
async inspectNode(tab, nodeSelectors, startTime) {
async inspectNode(tab, domReference) {
const target = await TargetFactory.forTab(tab);
const toolbox = await gDevTools.showToolbox(
@ -772,20 +646,18 @@ DevTools.prototype = {
"inspector",
null,
null,
startTime,
"inspect_dom"
);
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
// browser is remote or not.
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
inspector.selection.setNodeFront(nodeFront, {
reason: "browser-context-menu",
@ -802,27 +674,25 @@ DevTools.prototype = {
*
* @param {XULTab} tab
* The browser tab on which inspect accessibility was used.
* @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.
* @param {Number} startTime
* Optional, indicates the time at which the user event related to this
* node inspection started. This is a `Cu.now()` timing.
* @param {ElementIdentifier} domReference
* Identifier generated by ContentDOMReference. It is a unique pair of
* BrowsingContext ID and a numeric ID.
* @return {Promise} a promise that resolves when the accessible object is
* selected in the accessibility inspector.
*/
async inspectA11Y(tab, nodeSelectors, startTime) {
async inspectA11Y(tab, domReference) {
const target = await TargetFactory.forTab(tab);
const toolbox = await gDevTools.showToolbox(
target,
"accessibility",
null,
null,
startTime
null
);
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
// tells us it has been done.
const a11yPanel = toolbox.getCurrentPanel();
@ -855,8 +725,8 @@ DevTools.prototype = {
removeThemeObserver(this._onThemeChanged);
// Do not unregister devtools from the DevToolsShim if the destroy is caused by an
// application shutdown. For instance SessionStore needs to save the Scratchpad
// manager state on shutdown.
// application shutdown. For instance SessionStore needs to save the Browser Toolbox
// state on shutdown.
if (!shuttingDown) {
// Notify the DevToolsShim that DevTools are no longer available, particularly if
// 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',
'devtools-browser.js',
'devtools.js',
'gDevTools.jsm',
'menu-item.js',
'menu.js',
'selection.js',

View File

@ -4,16 +4,25 @@
"use strict";
const nodeConstants = require("devtools/shared/dom-node-constants");
var EventEmitter = require("devtools/shared/event-emitter");
const 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
*
* new Selection(walker=null)
* new Selection()
* destroy()
* node (readonly)
* setNode(node, origin="unknown")
* nodeFront (readonly)
* setNodeFront(node, origin="unknown")
*
* Helpers:
*
@ -46,14 +55,11 @@ var EventEmitter = require("devtools/shared/event-emitter");
* "reparented" when the node (or one of its parents) is moved under
* a different node
*/
/**
* A Selection object. Hold a reference to a node.
* Includes some helpers, fire some helpful events.
*/
function Selection(walker) {
function Selection() {
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
// 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.
@ -61,14 +67,9 @@ function Selection(walker) {
this._onMutations = this._onMutations.bind(this);
this.setNodeFront = this.setNodeFront.bind(this);
this.setWalker(walker);
}
exports.Selection = Selection;
Selection.prototype = {
_walker: null,
_onMutations: function(mutations) {
let attributeChange = false;
let pseudoChange = false;
@ -105,10 +106,10 @@ Selection.prototype = {
},
destroy: function() {
this.setWalker(null);
this.setWalker();
},
setWalker: function(walker) {
setWalker: function(walker = null) {
if (this._walker) {
this._walker.off("mutations", this._onMutations);
}
@ -151,11 +152,13 @@ Selection.prototype = {
this._isSlotted = isSlotted;
this._nodeFront = nodeFront;
this.emit("new-node-front", nodeFront, this.reason);
},
if (nodeFront) {
this.setWalker(nodeFront.walkerFront);
} else {
this.setWalker();
}
get documentFront() {
return this._walker.document(this._nodeFront);
this.emit("new-node-front", nodeFront, this.reason);
},
get nodeFront() {
@ -308,3 +311,5 @@ Selection.prototype = {
return this.isNode() && this.nodeFront.isShadowRoot;
},
};
module.exports = Selection;

View File

@ -91,13 +91,13 @@ async function _targetFromURL(client, id, type, chrome) {
throw ex;
}
} 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`);
}
front = await addonFront.connect();
front = await addonDescriptor.getTarget();
} else if (type === "worker") {
front = await client.mainRoot.getWorker(id);

View File

@ -8,8 +8,9 @@ let tracker;
const { DevToolsLoader } = ChromeUtils.import(
"resource://devtools/shared/Loader.jsm"
);
const loader = new DevToolsLoader();
loader.invisibleToDebugger = true;
const loader = new DevToolsLoader({
invisibleToDebugger: true,
});
const { allocationTracker } = loader.require(
"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_destroy.js]
[browser_dynamic_tool_enabling.js]
[browser_front_parentFront.js]
[browser_ignore_toolbox_network_requests.js]
[browser_keybindings_01.js]
[browser_keybindings_02.js]
@ -145,7 +146,6 @@ run-if = e10s
[browser_toolbox_view_source_01.js]
[browser_toolbox_view_source_02.js]
[browser_toolbox_view_source_03.js]
[browser_toolbox_view_source_04.js]
[browser_toolbox_window_reload_target.js]
[browser_toolbox_window_shortcuts.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) {
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");
inspector.synthesizeKey();
await toolbox.inspectorFront.nodePicker.once("picker-stopped");
await toolbox.nodePicker.once("picker-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