Bug 1514339 - Update Debugger [Frontend v109] Provide initial implementation of opening DOM nodes in inspector (#7455). r=davidwalsh

This commit is contained in:
Jason Laster 2018-12-14 14:48:06 -05:00
parent fc57fc30d0
commit 63dc85db91
10 changed files with 122 additions and 47 deletions

View File

@ -35,7 +35,22 @@ DebuggerPanel.prototype = {
toolboxActions: {
// Open a link in a new browser tab.
openLink: this.openLink.bind(this),
openWorkerToolbox: this.openWorkerToolbox.bind(this)
openWorkerToolbox: this.openWorkerToolbox.bind(this),
openElementInInspector: async function(grip) {
await this.toolbox.initInspector();
const onSelectInspector = this.toolbox.selectTool("inspector");
const onGripNodeToFront = this.toolbox.walker.gripToNodeFront(grip);
const [
front,
inspector,
] = await Promise.all([onGripNodeToFront, onSelectInspector]);
const onInspectorUpdated = inspector.once("inspector-updated");
const onNodeFrontSet = this.toolbox.selection
.setNodeFront(front, { reason: "debugger" });
return Promise.all([onNodeFrontSet, onInspectorUpdated]);
}.bind(this)
}
});

View File

@ -8,7 +8,7 @@ const { isDevelopment } = require("devtools-environment");
const { getSelectedFrameId } = require("../selectors");
import type { ThunkArgs } from "./types";
import type { Worker } from "../types";
import type { Worker, Grip } from "../types";
/**
* @memberof actions/toolbox
@ -47,3 +47,13 @@ export function evaluateInConsole(inputString: string) {
);
};
}
export function openElementInInspectorCommand(grip: Grip) {
return async ({ openElementInInspector }: ThunkArgs) => {
if (isDevelopment()) {
alert(`Opening node in Inspector: ${grip.class}`);
} else {
return openElementInInspector(grip);
}
};
}

View File

@ -34,6 +34,7 @@ import "./Popup.css";
import type { EditorRange } from "../../../utils/editor/types";
import type { Coords } from "../../shared/Popover";
import type { Grip } from "../../../types";
type PopupValue = Object | null;
type Props = {
@ -49,7 +50,8 @@ type Props = {
editorRef: ?HTMLDivElement,
selectSourceURL: (string, Object) => void,
openLink: string => void,
extra: Object
extra: Object,
openElementInInspector: (grip: Grip) => void
};
type State = {
@ -268,7 +270,7 @@ export class Popup extends Component<Props, State> {
}
renderObjectInspector(roots: Array<Object>) {
const { openLink } = this.props;
const { openLink, openElementInInspector } = this.props;
return (
<ObjectInspector
@ -278,6 +280,8 @@ export class Popup extends Component<Props, State> {
focusable={false}
openLink={openLink}
createObjectClient={grip => createObjectClient(grip)}
onDOMNodeClick={grip => openElementInInspector(grip)}
onInspectIconClick={grip => openElementInInspector(grip)}
/>
);
}
@ -344,7 +348,8 @@ export class Popup extends Component<Props, State> {
}
const mapStateToProps = state => ({
popupObjectProperties: getAllPopupObjectProperties(state)
popupObjectProperties: getAllPopupObjectProperties(state),
openElementInInspector: actions.openElementInInspectorCommand
});
const {

View File

@ -22,7 +22,7 @@ import { CloseButton } from "../shared/Button";
import { debounce } from "lodash";
import type { List } from "immutable";
import type { Expression } from "../../types";
import type { Expression, Grip } from "../../types";
import "./Expressions.css";
@ -48,7 +48,8 @@ type Props = {
evaluateExpressions: () => void,
updateExpression: (input: string, expression: Expression) => void,
deleteExpression: (expression: Expression) => void,
openLink: (url: string) => void
openLink: (url: string) => void,
openElementInInspector: (grip: Grip) => void
};
class Expressions extends Component<Props, State> {
@ -206,7 +207,7 @@ class Expressions extends Component<Props, State> {
};
renderExpression = (expression: Expression, index: number) => {
const { expressionError, openLink } = this.props;
const { expressionError, openLink, openElementInInspector } = this.props;
const { editing, editIndex } = this.state;
const { input, updating } = expression;
const isEditingExpr = editing && editIndex === index;
@ -243,6 +244,8 @@ class Expressions extends Component<Props, State> {
focusable={false}
openLink={openLink}
createObjectClient={grip => createObjectClient(grip)}
onDOMNodeClick={grip => openElementInInspector(grip)}
onInspectIconClick={grip => openElementInInspector(grip)}
/>
<div className="expression-container__close-btn">
<CloseButton
@ -374,6 +377,7 @@ export default connect(
evaluateExpressions: actions.evaluateExpressions,
updateExpression: actions.updateExpression,
deleteExpression: actions.deleteExpression,
openLink: actions.openLink
openLink: actions.openLink,
openElementInInspector: actions.openElementInInspectorCommand
}
)(Expressions);

View File

@ -13,7 +13,7 @@ import { getSelectedFrame, getAllPopupObjectProperties } from "../../selectors";
import { objectInspector } from "devtools-reps";
import { isReactComponent } from "../../utils/preview";
import type { Frame } from "../../types";
import type { Frame, Grip } from "../../types";
const {
component: ObjectInspector,
@ -27,7 +27,8 @@ const {
type Props = {
selectedFrame: Frame,
popupObjectProperties: Object,
setPopupObjectProperties: (Object, Object) => void
setPopupObjectProperties: (Object, Object) => void,
openElementInInspector: (grip: Grip) => void
};
class FrameworkComponent extends PureComponent<Props> {
@ -44,7 +45,11 @@ class FrameworkComponent extends PureComponent<Props> {
}
renderReactComponent() {
const { selectedFrame, popupObjectProperties } = this.props;
const {
selectedFrame,
popupObjectProperties,
openElementInInspector
} = this.props;
const expression = "this;";
const value = selectedFrame.this;
const root = {
@ -75,6 +80,8 @@ class FrameworkComponent extends PureComponent<Props> {
focusable={false}
dimTopLevelWindow={true}
createObjectClient={grip => createObjectClient(grip)}
onDOMNodeClick={grip => openElementInInspector(grip)}
onInspectIconClick={grip => openElementInInspector(grip)}
/>
</div>
);
@ -92,7 +99,8 @@ class FrameworkComponent extends PureComponent<Props> {
const mapStateToProps = state => ({
selectedFrame: getSelectedFrame(state),
popupObjectProperties: getAllPopupObjectProperties(state)
popupObjectProperties: getAllPopupObjectProperties(state),
openElementInInspector: actions.openElementInInspectorCommand
});
export default connect(

View File

@ -19,7 +19,7 @@ import {
import { getScopes } from "../../utils/pause/scopes";
import { objectInspector } from "devtools-reps";
import type { Pause, Why } from "../../types";
import type { Pause, Why, Grip } from "../../types";
import type { NamedValue } from "../../utils/pause/scopes/types";
import "./Scopes.css";
@ -33,7 +33,8 @@ type Props = {
originalFrameScopes: Object | null,
isLoading: boolean,
why: Why,
openLink: string => void
openLink: string => void,
openElementInInspector: (grip: Grip) => void
};
type State = {
@ -96,7 +97,12 @@ class Scopes extends PureComponent<Props, State> {
}
render() {
const { isPaused, isLoading, openLink } = this.props;
const {
isPaused,
isLoading,
openLink,
openElementInInspector
} = this.props;
const { originalScopes, generatedScopes, showOriginal } = this.state;
const scopes = (showOriginal && originalScopes) || generatedScopes;
@ -113,6 +119,8 @@ class Scopes extends PureComponent<Props, State> {
dimTopLevelWindow={true}
openLink={openLink}
createObjectClient={grip => createObjectClient(grip)}
onDOMNodeClick={grip => openElementInInspector(grip)}
onInspectIconClick={grip => openElementInInspector(grip)}
/>
{originalScopes ? (
<div className="scope-type-toggle">
@ -184,6 +192,7 @@ const mapStateToProps = state => {
export default connect(
mapStateToProps,
{
openLink: actions.openLink
openLink: actions.openLink,
openElementInInspector: actions.openElementInInspectorCommand
}
)(Scopes);

View File

@ -697,6 +697,7 @@ skip-if = (os == "win" && ccov) # Bug 1424154
[browser_dbg-expressions-error.js]
[browser_dbg-iframes.js]
[browser_dbg-inline-cache.js]
[browser_dbg-inspector-integration.js]
[browser_dbg-keyboard-navigation.js]
[browser_dbg-keyboard-shortcuts.js]
skip-if = os == "linux" # bug 1351952

View File

@ -9,11 +9,6 @@
* 4. expanding properties when not paused
*/
const expressionSelectors = {
plusIcon: ".watch-expressions-pane button.plus",
input: "input.input-expression"
};
function getLabel(dbg, index) {
return findElement(dbg, "expressionNode", index).innerText;
}
@ -32,31 +27,6 @@ function assertEmptyValue(dbg, index) {
is(value, null);
}
async function addExpression(dbg, input) {
info("Adding an expression");
const plusIcon = findElementWithSelector(dbg, expressionSelectors.plusIcon);
if (plusIcon) {
plusIcon.click();
}
findElementWithSelector(dbg, expressionSelectors.input).focus();
type(dbg, input);
pressKey(dbg, "Enter");
await waitForDispatch(dbg, "EVALUATE_EXPRESSION");
}
async function editExpression(dbg, input) {
info("Updating the expression");
dblClickElement(dbg, "expressionNode", 1);
// Position cursor reliably at the end of the text.
pressKey(dbg, "End");
type(dbg, input);
const evaluated = waitForDispatch(dbg, "EVALUATE_EXPRESSIONS");
pressKey(dbg, "Enter");
await evaluated;
}
add_task(async function() {
const dbg = await initDebugger("doc-script-switching.html");

View File

@ -0,0 +1,27 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that clicking the DOM node button in any ObjectInspect
// opens the Inspector panel
function waitForInspectorPanelChange(dbg) {
const { toolbox } = dbg;
return new Promise(resolve => {
toolbox.getPanelWhenReady("inspector").then(() => {
ok(toolbox.inspector, "Inspector is shown.");
resolve(toolbox.inspector);
});
});
}
add_task(async function() {
const dbg = await initDebugger("doc-script-switching.html");
await addExpression(dbg, "window.document.body.firstChild");
await waitForElementWithSelector(dbg, "button.open-inspector");
findElementWithSelector(dbg, "button.open-inspector").click();
await waitForInspectorPanelChange(dbg);
});

View File

@ -1032,6 +1032,7 @@ const selectors = {
`.expressions-list .expression-container:nth-child(${i}) .close`,
expressionInput: ".expressions-list input.input-expression",
expressionNodes: ".expressions-list .tree-node",
expressionPlus: ".watch-expressions-pane button.plus",
scopesHeader: ".scopes-pane ._header",
breakpointItem: i => `.breakpoints-list div:nth-of-type(${i})`,
breakpointItems: `.breakpoints-list .breakpoint`,
@ -1388,3 +1389,28 @@ async function assertNodeIsFocused(dbg, index) {
const node = findElement(dbg, "sourceNode", index);
ok(node.classList.contains("focused"), `node ${index} is focused`);
}
async function addExpression(dbg, input) {
info("Adding an expression");
const plusIcon = findElementWithSelector(dbg, selectors.expressionPlus);
if (plusIcon) {
plusIcon.click();
}
findElementWithSelector(dbg, selectors.expressionInput).focus();
type(dbg, input);
pressKey(dbg, "Enter");
await waitForDispatch(dbg, "EVALUATE_EXPRESSION");
}
async function editExpression(dbg, input) {
info("Updating the expression");
dblClickElement(dbg, "expressionNode", 1);
// Position cursor reliably at the end of the text.
pressKey(dbg, "End");
type(dbg, input);
const evaluated = waitForDispatch(dbg, "EVALUATE_EXPRESSIONS");
pressKey(dbg, "Enter");
await evaluated;
}