Skip to content
This repository was archived by the owner on Jan 11, 2023. It is now read-only.

Commit 6c58893

Browse files
mmcotejasonLaster
authored andcommitted
[Preview] React Component pane (#5801)
1 parent 1207e75 commit 6c58893

File tree

9 files changed

+157
-8
lines changed

9 files changed

+157
-8
lines changed

assets/panel/prefs.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ pref("devtools.debugger.ui.variables-searchbox-visible", false);
2929
pref("devtools.debugger.ui.framework-grouping-on", true);
3030
pref("devtools.debugger.call-stack-visible", true);
3131
pref("devtools.debugger.scopes-visible", true);
32+
pref("devtools.debugger.component-visible", true);
3233
pref("devtools.debugger.workers-visible", true);
3334
pref("devtools.debugger.breakpoints-visible", true);
3435
pref("devtools.debugger.expressions-visible", true);

src/actions/pause/fetchScopes.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import { getSelectedFrame, getGeneratedFrameScope } from "../../selectors";
88
import { mapScopes } from "./mapScopes";
9+
import { getExtra } from "../preview";
910
import { PROMISE } from "../utils/middleware/promise";
1011

1112
import type { ThunkArgs } from "../types";
@@ -17,9 +18,12 @@ export function fetchScopes() {
1718
return;
1819
}
1920

21+
const extra = await dispatch(getExtra("this;", frame.this, frame));
22+
2023
const scopes = dispatch({
2124
type: "ADD_SCOPES",
2225
frame,
26+
extra,
2327
[PROMISE]: client.getFrameScopes(frame)
2428
});
2529

src/actions/preview.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { getMappedExpression } from "./expressions";
2424
import { isEqual } from "lodash";
2525

2626
import type { ThunkArgs } from "./types";
27-
import type { Range, Position } from "../types";
27+
import type { Frame, Range, Position } from "../types";
2828

2929
async function getReactProps(evaluate) {
3030
const reactDisplayName = await evaluate(
@@ -90,6 +90,20 @@ function isInvalidTarget(target: HTMLElement) {
9090
return invalidTarget || invalidToken || invaildType;
9191
}
9292

93+
export function getExtra(
94+
expression: string,
95+
result: Object,
96+
selectedFrame: Frame
97+
) {
98+
return async ({ dispatch, getState, client, sourceMaps }: ThunkArgs) => {
99+
const extra = await getExtraProps(expression, result, expr =>
100+
client.evaluateInFrame(selectedFrame.id, expr)
101+
);
102+
103+
return extra;
104+
};
105+
}
106+
93107
export function updatePreview(target: HTMLElement, editor: any) {
94108
return ({ dispatch, getState, client, sourceMaps }: ThunkArgs) => {
95109
const tokenPos = getTokenLocation(editor.codeMirror, target);
@@ -185,8 +199,8 @@ export function setPreview(
185199
return;
186200
}
187201

188-
const extra = await getExtraProps(expression, result, expr =>
189-
client.evaluateInFrame(selectedFrame.id, expr)
202+
const extra = await dispatch(
203+
getExtra(expression, result, selectedFrame)
190204
);
191205

192206
return {

src/actions/types.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ type PauseAction =
313313
| {
314314
type: "ADD_SCOPES",
315315
frame: Frame,
316+
extra: any,
316317
status: AsyncStatus,
317318
value: Scope
318319
};

src/components/Editor/Preview/index.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ type Props = {
3131
editorRef: ?HTMLDivElement,
3232
selectedSource: SourceRecord,
3333
selectedLocation: SelectedLocation,
34-
selectedFrame: any,
3534
clearPreview: () => void,
3635
preview: PreviewType,
3736
selectedFrameVisible: boolean,
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
4+
5+
// @flow
6+
import React, { PureComponent } from "react";
7+
import { bindActionCreators } from "redux";
8+
import { connect } from "react-redux";
9+
import actions from "../../actions";
10+
11+
import { createObjectClient } from "../../client/firefox";
12+
13+
import { getSelectedFrame, getAllPopupObjectProperties } from "../../selectors";
14+
15+
import { ObjectInspector, ObjectInspectorUtils } from "devtools-reps";
16+
import { isReactComponent } from "../../utils/preview";
17+
18+
import type { Frame } from "../../types";
19+
20+
const { createNode, getChildren } = ObjectInspectorUtils.node;
21+
const { loadItemProperties } = ObjectInspectorUtils.loadProperties;
22+
23+
type Props = {
24+
setPopupObjectProperties: (Object, Object) => void,
25+
selectedFrame: Frame,
26+
popupObjectProperties: Object
27+
};
28+
29+
class FrameworkComponent extends PureComponent<Props> {
30+
async componentWillMount() {
31+
const expression = "this;";
32+
const { selectedFrame, setPopupObjectProperties } = this.props;
33+
const value = selectedFrame.this;
34+
35+
const root = createNode(null, expression, expression, { value });
36+
const properties = await loadItemProperties(root, createObjectClient);
37+
if (properties) {
38+
setPopupObjectProperties(value, properties);
39+
}
40+
}
41+
42+
renderReactComponent() {
43+
const { selectedFrame, popupObjectProperties } = this.props;
44+
const expression = "this;";
45+
const value = selectedFrame.this;
46+
const root = {
47+
name: expression,
48+
path: expression,
49+
contents: { value }
50+
};
51+
52+
const loadedRootProperties = popupObjectProperties[value.actor];
53+
54+
let roots = getChildren({
55+
item: root,
56+
loadedProperties: new Map([[root.path, loadedRootProperties]])
57+
});
58+
59+
roots = roots.filter(r => ["state", "props"].includes(r.name));
60+
61+
return (
62+
<div className="pane framework-component">
63+
<ObjectInspector
64+
roots={roots}
65+
autoExpandAll={false}
66+
autoExpandDepth={0}
67+
disableWrap={true}
68+
disabledFocus={true}
69+
dimTopLevelWindow={true}
70+
createObjectClient={grip => createObjectClient(grip)}
71+
/>
72+
</div>
73+
);
74+
}
75+
76+
render() {
77+
const { selectedFrame } = this.props;
78+
if (isReactComponent(selectedFrame.this)) {
79+
return this.renderReactComponent();
80+
}
81+
82+
return null;
83+
}
84+
}
85+
86+
export default connect(
87+
state => {
88+
return {
89+
selectedFrame: getSelectedFrame(state),
90+
popupObjectProperties: getAllPopupObjectProperties(state)
91+
};
92+
},
93+
dispatch => bindActionCreators(actions, dispatch)
94+
)(FrameworkComponent);

src/components/SecondaryPanes/index.js

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ import {
1818
getIsWaitingOnBreak,
1919
getShouldPauseOnExceptions,
2020
getShouldIgnoreCaughtExceptions,
21-
getWorkers
21+
getWorkers,
22+
getExtra
2223
} from "../../selectors";
2324

2425
import Svg from "../shared/Svg";
@@ -34,6 +35,7 @@ import Accordion from "../shared/Accordion";
3435
import CommandBar from "./CommandBar";
3536
import UtilsBar from "./UtilsBar";
3637
import renderBreakpointsDropdown from "./BreakpointsDropdown";
38+
import FrameworkComponent from "./FrameworkComponent";
3739

3840
import _chromeScopes from "./ChromeScopes";
3941
import _Scopes from "./Scopes";
@@ -67,6 +69,7 @@ function debugBtn(onClick, type, className, tooltip) {
6769
}
6870

6971
type Props = {
72+
extra: Object,
7073
evaluateExpressions: Function,
7174
hasFrames: boolean,
7275
horizontal: boolean,
@@ -151,6 +154,20 @@ class SecondaryPanes extends Component<Props> {
151154
};
152155
}
153156

157+
getComponentItem() {
158+
const { extra: { react } } = this.props;
159+
160+
return {
161+
header: react.displayName,
162+
className: "component-pane",
163+
component: <FrameworkComponent />,
164+
opened: prefs.componentVisible,
165+
onToggle: opened => {
166+
prefs.componentVisible = opened;
167+
}
168+
};
169+
}
170+
154171
getWatchItem(): AccordionPaneItem {
155172
return {
156173
header: L10N.getStr("watchExpressions.header"),
@@ -224,7 +241,7 @@ class SecondaryPanes extends Component<Props> {
224241
}
225242

226243
getStartItems() {
227-
const { workers } = this.props;
244+
const { extra, workers } = this.props;
228245

229246
const items: Array<AccordionPaneItem> = [];
230247
if (this.props.horizontal) {
@@ -239,7 +256,12 @@ class SecondaryPanes extends Component<Props> {
239256

240257
if (this.props.hasFrames) {
241258
items.push(this.getCallStackItem());
259+
242260
if (this.props.horizontal) {
261+
if (extra && extra.react) {
262+
items.push(this.getComponentItem());
263+
}
264+
243265
items.push(this.getScopeItem());
244266
}
245267
}
@@ -260,7 +282,7 @@ class SecondaryPanes extends Component<Props> {
260282
}
261283

262284
getEndItems() {
263-
const { workers } = this.props;
285+
const { extra, workers } = this.props;
264286

265287
let items: Array<AccordionPaneItem> = [];
266288

@@ -274,6 +296,10 @@ class SecondaryPanes extends Component<Props> {
274296

275297
items.push(this.getWatchItem());
276298

299+
if (extra && extra.react) {
300+
items.push(this.getComponentItem());
301+
}
302+
277303
if (this.props.hasFrames) {
278304
items = [...items, this.getScopeItem()];
279305
}
@@ -332,6 +358,7 @@ SecondaryPanes.contextTypes = {
332358

333359
export default connect(
334360
state => ({
361+
extra: getExtra(state),
335362
hasFrames: !!getTopFrame(state),
336363
breakpoints: getBreakpoints(state),
337364
breakpointsDisabled: getBreakpointsDisabled(state),

src/reducers/pause.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export type Command =
3232
| "expression";
3333

3434
export type PauseState = {
35+
extra: ?Object,
3536
why: ?Why,
3637
isWaitingOnBreak: boolean,
3738
frames: ?(any[]),
@@ -68,6 +69,7 @@ export type PauseState = {
6869
};
6970

7071
export const createPauseState = (): PauseState => ({
72+
extra: {},
7173
why: null,
7274
isWaitingOnBreak: false,
7375
frames: undefined,
@@ -129,7 +131,7 @@ function update(
129131
}
130132

131133
case "ADD_SCOPES": {
132-
const { frame, status, value } = action;
134+
const { frame, extra, status, value } = action;
133135
const selectedFrameId = frame.id;
134136

135137
const generated = {
@@ -141,6 +143,7 @@ function update(
141143
};
142144
return {
143145
...state,
146+
extra: extra,
144147
frameScopes: {
145148
...state.frameScopes,
146149
generated
@@ -330,6 +333,10 @@ export function getCanRewind(state: OuterState) {
330333
return state.pause.canRewind;
331334
}
332335

336+
export function getExtra(state: OuterState) {
337+
return state.pause.extra;
338+
}
339+
333340
export function getFrames(state: OuterState) {
334341
return state.pause.frames;
335342
}

src/utils/prefs.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ if (isDevelopment()) {
1919
pref("devtools.debugger.ignore-caught-exceptions", false);
2020
pref("devtools.debugger.call-stack-visible", true);
2121
pref("devtools.debugger.scopes-visible", true);
22+
pref("devtools.debugger.component-visible", true);
2223
pref("devtools.debugger.workers-visible", true);
2324
pref("devtools.debugger.expressions-visible", true);
2425
pref("devtools.debugger.breakpoints-visible", true);
@@ -61,6 +62,7 @@ export const prefs = new PrefsHelper("devtools", {
6162
ignoreCaughtExceptions: ["Bool", "debugger.ignore-caught-exceptions"],
6263
callStackVisible: ["Bool", "debugger.call-stack-visible"],
6364
scopesVisible: ["Bool", "debugger.scopes-visible"],
65+
componentVisible: ["Bool", "debugger.component-visible"],
6466
workersVisible: ["Bool", "debugger.workers-visible"],
6567
breakpointsVisible: ["Bool", "debugger.breakpoints-visible"],
6668
expressionsVisible: ["Bool", "debugger.expressions-visible"],

0 commit comments

Comments
 (0)