diff --git a/devtools/client/debugger/images/moz.build b/devtools/client/debugger/images/moz.build index d362551ff07a..bc6f2d406dd5 100644 --- a/devtools/client/debugger/images/moz.build +++ b/devtools/client/debugger/images/moz.build @@ -46,5 +46,6 @@ DevToolsModules( 'stepOver.svg', 'tab.svg', 'whole-word-match.svg', + 'window.svg', 'worker.svg', ) diff --git a/devtools/client/debugger/images/window.svg b/devtools/client/debugger/images/window.svg new file mode 100644 index 000000000000..3dc00bddd14a --- /dev/null +++ b/devtools/client/debugger/images/window.svg @@ -0,0 +1,4 @@ + + \ No newline at end of file diff --git a/devtools/client/debugger/src/actions/navigation.js b/devtools/client/debugger/src/actions/navigation.js index cfc0559e7577..1a066e727074 100644 --- a/devtools/client/debugger/src/actions/navigation.js +++ b/devtools/client/debugger/src/actions/navigation.js @@ -58,7 +58,7 @@ export function connect(url: string, actor: string, canRewind: boolean) { dispatch( ({ type: "CONNECT", - mainThread: { url, actor, type: -1 }, + mainThread: { url, actor, type: -1, name: "" }, canRewind }: Action) ); diff --git a/devtools/client/debugger/src/actions/source-tree.js b/devtools/client/debugger/src/actions/source-tree.js index 410acbc91a35..b2cfa0c44b2c 100644 --- a/devtools/client/debugger/src/actions/source-tree.js +++ b/devtools/client/debugger/src/actions/source-tree.js @@ -3,27 +3,12 @@ * file, You can obtain one at . */ // @flow -import type { Action, FocusItem, ThunkArgs } from "./types"; -import type { Context } from "../types"; +import type { TreeNode } from "../utils/sources-tree/types"; -export function setExpandedState(thread: string, expanded: Set) { - return ({ dispatch, getState }: ThunkArgs) => { - dispatch( - ({ - type: "SET_EXPANDED_STATE", - thread, - expanded - }: Action) - ); - }; +export function setExpandedState(expanded: Set) { + return { type: "SET_EXPANDED_STATE", expanded }; } -export function focusItem(cx: Context, item: FocusItem) { - return ({ dispatch, getState }: ThunkArgs) => { - dispatch({ - type: "SET_FOCUSED_SOURCE_ITEM", - cx, - item - }); - }; +export function focusItem(item: TreeNode) { + return { type: "SET_FOCUSED_SOURCE_ITEM", item }; } diff --git a/devtools/client/debugger/src/actions/sources/tests/blackbox.spec.js b/devtools/client/debugger/src/actions/sources/tests/blackbox.spec.js index 0cdb62a9fb1b..d722711a87d6 100644 --- a/devtools/client/debugger/src/actions/sources/tests/blackbox.spec.js +++ b/devtools/client/debugger/src/actions/sources/tests/blackbox.spec.js @@ -30,16 +30,10 @@ describe("blackbox", () => { throw new Error("foo should exist"); } - const { thread } = selectors.getSourceActorsForSource( - getState(), - foo1Source.id - )[0]; - const displayedSources = selectors.getDisplayedSourcesForThread( - getState(), - thread + const displayedSources = selectors.getDisplayedSources(getState()); + expect(displayedSources.FakeThread[fooSource.id].isBlackBoxed).toEqual( + true ); - - expect(displayedSources[fooSource.id].isBlackBoxed).toEqual(true); expect(fooSource.isBlackBoxed).toEqual(true); }); }); diff --git a/devtools/client/debugger/src/actions/tests/setProjectDirectoryRoot.spec.js b/devtools/client/debugger/src/actions/tests/setProjectDirectoryRoot.spec.js index ac32677dea95..2801432b7e25 100644 --- a/devtools/client/debugger/src/actions/tests/setProjectDirectoryRoot.spec.js +++ b/devtools/client/debugger/src/actions/tests/setProjectDirectoryRoot.spec.js @@ -11,8 +11,6 @@ import { makeSource } from "../../utils/test-head"; -import type { Source } from "../../types"; - const { getProjectDirectoryRoot, getDisplayedSources } = selectors; describe("setProjectDirectoryRoot", () => { @@ -54,14 +52,15 @@ describe("setProjectDirectoryRoot", () => { dispatch(actions.setProjectDirectoryRoot(cx, "localhost:8000/examples/js")); const filteredSourcesByThread = getDisplayedSources(getState()); - const filteredSources = Object.values(filteredSourcesByThread)[0]; - const firstSource: Source = (Object.values(filteredSources)[0]: any); + const filteredSources = (Object.values( + filteredSourcesByThread.FakeThread + ): any)[0]; - expect(firstSource.url).toEqual( + expect(filteredSources.url).toEqual( "http://localhost:8000/examples/js/scopes.js" ); - expect(firstSource.relativeUrl).toEqual("scopes.js"); + expect(filteredSources.relativeUrl).toEqual("scopes.js"); }); it("should update the child directory ", () => { diff --git a/devtools/client/debugger/src/actions/tests/source-tree.spec.js b/devtools/client/debugger/src/actions/tests/source-tree.spec.js index a52f5cb40cc3..fcbd56da33f5 100644 --- a/devtools/client/debugger/src/actions/tests/source-tree.spec.js +++ b/devtools/client/debugger/src/actions/tests/source-tree.spec.js @@ -12,8 +12,8 @@ describe("source tree", () => { const { dispatch, getState } = createStore(); const expandedState = new Set(["foo", "bar"]); - expect(getExpandedState(getState(), "FakeThread")).toEqual(undefined); - dispatch(actions.setExpandedState("FakeThread", expandedState)); - expect(getExpandedState(getState(), "FakeThread")).toEqual(expandedState); + expect(getExpandedState(getState())).toEqual(new Set([])); + dispatch(actions.setExpandedState(expandedState)); + expect(getExpandedState(getState())).toEqual(expandedState); }); }); diff --git a/devtools/client/debugger/src/actions/types/index.js b/devtools/client/debugger/src/actions/types/index.js index a778c8bbc6ce..6d6f13c6ffcc 100644 --- a/devtools/client/debugger/src/actions/types/index.js +++ b/devtools/client/debugger/src/actions/types/index.js @@ -71,10 +71,7 @@ type NavigateAction = | {| +type: "CONNECT", +mainThread: MainThread, +canRewind: boolean |} | {| +type: "NAVIGATE", +mainThread: MainThread |}; -export type FocusItem = { - thread: string, - item: TreeNode -}; +export type FocusItem = TreeNode; export type SourceTreeAction = | {| +type: "SET_EXPANDED_STATE", +thread: string, +expanded: any |} diff --git a/devtools/client/debugger/src/client/firefox/create.js b/devtools/client/debugger/src/client/firefox/create.js index 19df8ec6d57d..693d56027fce 100644 --- a/devtools/client/debugger/src/client/firefox/create.js +++ b/devtools/client/debugger/src/client/firefox/create.js @@ -77,6 +77,7 @@ export function createWorker(actor: string, url: string) { actor, url, // Ci.nsIWorkerDebugger.TYPE_DEDICATED - type: 0 + type: 0, + name: "" }; } diff --git a/devtools/client/debugger/src/components/PrimaryPanes/SourcesTree.js b/devtools/client/debugger/src/components/PrimaryPanes/SourcesTree.js index b2bb5533e317..34409f3e0e9e 100644 --- a/devtools/client/debugger/src/components/PrimaryPanes/SourcesTree.js +++ b/devtools/client/debugger/src/components/PrimaryPanes/SourcesTree.js @@ -16,10 +16,8 @@ import { getDebuggeeUrl, getExpandedState, getProjectDirectoryRoot, - getDisplayedSourcesForThread, + getDisplayedSources, getFocusedSourceItem, - getWorkerByThread, - getWorkerCount, getContext } from "../../selectors"; @@ -29,7 +27,6 @@ import { getGeneratedSourceByURL } from "../../reducers/sources"; import actions from "../../actions"; // Components -import AccessibleImage from "../shared/AccessibleImage"; import SourcesTreeItem from "./SourcesTreeItem"; import ManagedTree from "../shared/ManagedTree"; @@ -42,25 +39,25 @@ import { nodeHasChildren, updateTree } from "../../utils/sources-tree"; +import { parse } from "../../utils/url"; import { getRawSourceURL } from "../../utils/source"; -import { getDisplayName } from "../../utils/workers"; -import { features } from "../../utils/prefs"; - import type { TreeNode, TreeDirectory, ParentMap } from "../../utils/sources-tree/types"; -import type { Worker, Source, Context } from "../../types"; -import type { SourcesMap, State as AppState } from "../../reducers/types"; +import type { Source, Context, Thread } from "../../types"; +import type { + SourcesMapByThread, + State as AppState +} from "../../reducers/types"; import type { Item } from "../shared/ManagedTree"; type Props = { cx: Context, - thread: string, - worker: Worker, - sources: SourcesMap, + threads: Thread[], + sources: SourcesMapByThread, sourceCount: number, shownSource?: Source, selectedSource?: Source, @@ -70,8 +67,7 @@ type Props = { selectSource: typeof actions.selectSource, setExpandedState: typeof actions.setExpandedState, focusItem: typeof actions.focusItem, - focused: TreeNode, - workerCount: number + focused: TreeNode }; type State = { @@ -84,17 +80,24 @@ type State = { type SetExpanded = (item: TreeNode, expanded: boolean, altKey: boolean) => void; -class SourcesTree extends Component { - mounted: boolean; +function shouldAutoExpand(depth, item, debuggeeUrl) { + if (depth !== 1) { + return false; + } + const { host } = parse(debuggeeUrl); + return item.name === host; +} + +class SourcesTree extends Component { constructor(props: Props) { super(props); - const { debuggeeUrl, sources, projectRoot } = this.props; + const { debuggeeUrl, sources, threads } = this.props; this.state = createTree({ - projectRoot, debuggeeUrl, - sources + sources, + threads }); } @@ -104,21 +107,24 @@ class SourcesTree extends Component { debuggeeUrl, sources, shownSource, - selectedSource + selectedSource, + threads } = this.props; const { uncollapsedTree, sourceTree } = this.state; if ( projectRoot != nextProps.projectRoot || debuggeeUrl != nextProps.debuggeeUrl || + threads != nextProps.threads || nextProps.sourceCount === 0 ) { // early recreate tree because of changes - // to project root, debugee url or lack of sources + // to project root, debuggee url or lack of sources return this.setState( createTree({ sources: nextProps.sources, - debuggeeUrl: nextProps.debuggeeUrl + debuggeeUrl: nextProps.debuggeeUrl, + threads: nextProps.threads }) ); } @@ -145,6 +151,7 @@ class SourcesTree extends Component { this.setState( updateTree({ newSources: nextProps.sources, + threads: nextProps.threads, prevSources: sources, debuggeeUrl, uncollapsedTree, @@ -161,7 +168,7 @@ class SourcesTree extends Component { }; onFocus = (item: TreeNode) => { - this.props.focusItem(this.props.cx, { thread: this.props.thread, item }); + this.props.focusItem(item); }; onActivate = (item: TreeNode) => { @@ -170,16 +177,11 @@ class SourcesTree extends Component { // NOTE: we get the source from sources because item.contents is cached getSource(item: TreeNode): ?Source { - const source = getSourceFromNode(item); - if (source) { - return this.props.sources[source.id]; - } - - return null; + return getSourceFromNode(item); } getPath = (item: TreeNode): string => { - const path = `${item.path}/${item.name}`; + const { path } = item; const source = this.getSource(item); if (!source || isDirectory(item)) { @@ -187,15 +189,16 @@ class SourcesTree extends Component { } const blackBoxedPart = source.isBlackBoxed ? ":blackboxed" : ""; + return `${path}/${source.id}/${blackBoxedPart}`; }; onExpand = (item: Item, expandedState: Set) => { - this.props.setExpandedState(this.props.thread, expandedState); + this.props.setExpandedState(expandedState); }; onCollapse = (item: Item, expandedState: Set) => { - this.props.setExpandedState(this.props.thread, expandedState); + this.props.setExpandedState(expandedState); }; isEmpty() { @@ -230,6 +233,10 @@ class SourcesTree extends Component { return sourceTree.contents; }; + getChildren = (item: $Shape) => { + return nodeHasChildren(item) ? item.contents : []; + }; + renderItem = ( item: TreeNode, depth: number, @@ -238,13 +245,15 @@ class SourcesTree extends Component { expanded: boolean, { setExpanded }: { setExpanded: SetExpanded } ) => { - const { debuggeeUrl, projectRoot } = this.props; + const { debuggeeUrl, projectRoot, threads } = this.props; return ( { renderTree() { const { expanded, focused } = this.props; + const { highlightItems, listItems, parentMap } = this.state; const treeProps = { autoExpandAll: false, - autoExpandDepth: expanded ? 0 : 1, + autoExpandDepth: 1, expanded, focused, - getChildren: (item: $Shape) => - nodeHasChildren(item) ? item.contents : [], + getChildren: this.getChildren, getParent: (item: $Shape) => parentMap.get(item), getPath: this.getPath, getRoots: this.getRoots, @@ -286,14 +295,13 @@ class SourcesTree extends Component { } renderPane(...children) { - const { projectRoot, thread } = this.props; + const { projectRoot } = this.props; return (
{children} @@ -301,39 +309,8 @@ class SourcesTree extends Component { ); } - renderThreadHeader() { - const { worker, workerCount } = this.props; - - if (!features.windowlessWorkers || workerCount == 0) { - return null; - } - - if (worker) { - return ( -
- - {getDisplayName(worker)} -
- ); - } - - return ( -
- - {L10N.getStr("mainThread")} -
- ); - } - render() { - const { worker } = this.props; - - if (!features.windowlessWorkers && worker) { - return null; - } - return this.renderPane( - this.renderThreadHeader(), this.isEmpty() ? ( this.renderEmptyElement(L10N.getStr("noSourcesText")) ) : ( @@ -347,15 +324,13 @@ class SourcesTree extends Component { function getSourceForTree( state: AppState, - displayedSources: SourcesMap, - source: ?Source, - thread + displayedSources: SourcesMapByThread, + source: ?Source ): ?Source { if (!source) { return null; } - source = displayedSources[source.id]; if (!source || !source.isPrettyPrinted) { return source; } @@ -366,27 +341,19 @@ function getSourceForTree( const mapStateToProps = (state, props) => { const selectedSource = getSelectedSource(state); const shownSource = getShownSource(state); - const focused = getFocusedSourceItem(state); - const thread = props.thread; - const displayedSources = getDisplayedSourcesForThread(state, thread); + const displayedSources = getDisplayedSources(state); return { + threads: props.threads, cx: getContext(state), - shownSource: getSourceForTree(state, displayedSources, shownSource, thread), - selectedSource: getSourceForTree( - state, - displayedSources, - selectedSource, - thread - ), + shownSource: getSourceForTree(state, displayedSources, shownSource), + selectedSource: getSourceForTree(state, displayedSources, selectedSource), debuggeeUrl: getDebuggeeUrl(state), - expanded: getExpandedState(state, props.thread), - focused: focused && focused.thread == props.thread ? focused.item : null, + expanded: getExpandedState(state), + focused: getFocusedSourceItem(state), projectRoot: getProjectDirectoryRoot(state), sources: displayedSources, - sourceCount: Object.values(displayedSources).length, - worker: getWorkerByThread(state, thread), - workerCount: getWorkerCount(state) + sourceCount: Object.values(displayedSources).length }; }; diff --git a/devtools/client/debugger/src/components/PrimaryPanes/SourcesTreeItem.js b/devtools/client/debugger/src/components/PrimaryPanes/SourcesTreeItem.js index 4f9719f07e0c..68a5b2dc2e01 100644 --- a/devtools/client/debugger/src/components/PrimaryPanes/SourcesTreeItem.js +++ b/devtools/client/debugger/src/components/PrimaryPanes/SourcesTreeItem.js @@ -11,12 +11,14 @@ import { showMenu } from "devtools-contextmenu"; import SourceIcon from "../shared/SourceIcon"; import AccessibleImage from "../shared/AccessibleImage"; +import { getDisplayName, isWorker } from "../../utils/workers"; import { getGeneratedSourceByURL, getHasSiblingOfSameName, hasPrettySource as checkHasPrettySource, - getContext + getContext, + getMainThread } from "../../selectors"; import actions from "../../actions"; @@ -31,9 +33,10 @@ import { copyToTheClipboard } from "../../utils/clipboard"; import { features } from "../../utils/prefs"; import type { TreeNode } from "../../utils/sources-tree/types"; -import type { Source, Context } from "../../types"; +import type { Source, Context, MainThread, Thread } from "../../types"; type Props = { + autoExpand: ?boolean, cx: Context, debuggeeUrl: string, projectRoot: string, @@ -42,6 +45,8 @@ type Props = { depth: number, focused: boolean, expanded: boolean, + threads: Thread[], + mainThread: MainThread, hasMatchingGeneratedSource: boolean, hasSiblingOfSameName: boolean, hasPrettySource: boolean, @@ -65,47 +70,17 @@ type MenuOption = { type ContextMenu = Array; class SourceTreeItem extends Component { - getIcon(item: TreeNode, depth: number) { - const { debuggeeUrl, projectRoot, source, hasPrettySource } = this.props; - - if (item.path === "webpack://") { - return ; - } else if (item.path === "ng://") { - return ; - } else if (isUrlExtension(item.path) && depth === 0) { - return ; + componentDidMount() { + const { autoExpand, item } = this.props; + if (autoExpand) { + this.props.setExpanded(item, true, false); } - - if (depth === 0 && projectRoot === "") { - return ( - - ); - } - - if (isDirectory(item)) { - return ; - } - - if (hasPrettySource) { - return ; - } - - if (source) { - return ; - } - - return null; } onClick = (e: MouseEvent) => { const { item, focusItem, selectItem } = this.props; focusItem(item); - if (!isDirectory(item)) { selectItem(item); } @@ -208,8 +183,69 @@ class SourceTreeItem extends Component { ); } - renderItemName() { - const { item } = this.props; + renderIcon(item: TreeNode, depth: number) { + const { + debuggeeUrl, + projectRoot, + source, + hasPrettySource, + threads + } = this.props; + + if (item.name === "webpack://") { + return ; + } else if (item.name === "ng://") { + return ; + } else if (isUrlExtension(item.path) && depth === 1) { + return ; + } + + // Threads level + if (depth === 0 && projectRoot === "") { + const thread = threads.find(thrd => thrd.actor == item.name); + + if (thread) { + const icon = thread === this.props.mainThread ? "window" : "worker"; + return ( + + ); + } + } + + if (isDirectory(item)) { + // Domain level + if (depth === 1) { + return ; + } + return ; + } + + if (hasPrettySource) { + return ; + } + + if (source) { + return ; + } + + return null; + } + + renderItemName(depth) { + const { item, threads } = this.props; + + if (depth === 0) { + const thread = threads.find(({ actor }) => actor == item.name); + if (thread) { + return isWorker(thread) + ? getDisplayName((thread: any)) + : L10N.getStr("mainThread"); + } + } switch (item.name) { case "ng://": @@ -253,10 +289,9 @@ class SourceTreeItem extends Component { onContextMenu={e => this.onContextMenu(e, item)} > {this.renderItemArrow()} - {this.getIcon(item, depth)} + {this.renderIcon(item, depth)} - {" "} - {this.renderItemName()} + {this.renderItemName(depth)} {query} {suffix}
@@ -276,6 +311,7 @@ const mapStateToProps = (state, props) => { const { source } = props; return { cx: getContext(state), + mainThread: getMainThread(state), hasMatchingGeneratedSource: getHasMatchingGeneratedSource(state, source), hasSiblingOfSameName: getHasSiblingOfSameName(state, source), hasPrettySource: source ? checkHasPrettySource(state, source.id) : false diff --git a/devtools/client/debugger/src/components/PrimaryPanes/index.js b/devtools/client/debugger/src/components/PrimaryPanes/index.js index 8046d7dc93ee..fd6c2374e4b7 100644 --- a/devtools/client/debugger/src/components/PrimaryPanes/index.js +++ b/devtools/client/debugger/src/components/PrimaryPanes/index.js @@ -127,9 +127,7 @@ class PrimaryPanes extends Component { } renderThreadSources() { - return this.props.threads.map(({ actor }) => ( - - )); + return ; } render() { diff --git a/devtools/client/debugger/src/components/PrimaryPanes/tests/SourcesTree.spec.js b/devtools/client/debugger/src/components/PrimaryPanes/tests/SourcesTree.spec.js index 4492cd104ed3..64b1d102ba9e 100644 --- a/devtools/client/debugger/src/components/PrimaryPanes/tests/SourcesTree.spec.js +++ b/devtools/client/debugger/src/components/PrimaryPanes/tests/SourcesTree.spec.js @@ -83,8 +83,10 @@ describe("SourcesTree", () => { const newSource = createMockSource( "server1.conn13.child1/43", "http://mdn.com/four.js", - true + true, + "" ); + const newThreadSources = { ...props.sources.FakeThread, "server1.conn13.child1/43": newSource @@ -92,15 +94,12 @@ describe("SourcesTree", () => { await component.setProps({ ...props, - sources: { - ...props.sources, - ...newThreadSources - } + sources: newThreadSources }); expect( - component.state("uncollapsedTree").contents[0].contents - ).toHaveLength(6); + component.state("uncollapsedTree").contents[0].contents[0].contents + ).toHaveLength(5); }); it("updates sources if sources are emptied", async () => { @@ -120,15 +119,17 @@ describe("SourcesTree", () => { it("recreates tree if projectRoot is changed", async () => { const { component, props, defaultState } = render(); const sources = { - "server1.conn13.child1/41": createMockSource( - "server1.conn13.child1/41", - "http://mozilla.com/three.js" - ) + FakeThread: { + "server1.conn13.child1/41": createMockSource( + "server1.conn13.child1/41", + "http://mozilla.com/three.js" + ) + } }; - expect(defaultState.uncollapsedTree.contents[0].contents).toHaveLength( - 5 - ); + expect( + defaultState.uncollapsedTree.contents[0].contents[0].contents + ).toHaveLength(5); await component.setProps({ ...props, @@ -141,18 +142,22 @@ describe("SourcesTree", () => { ).toHaveLength(1); }); - it("recreates tree if debugeeUrl is changed", async () => { + it("recreates tree if debuggeeUrl is changed", async () => { const { component, props, defaultState } = render(); const sources = { - "server1.conn13.child1/41": createMockSource( - "server1.conn13.child1/41", - "http://mdn.com/three.js" - ) + FakeThread: { + "server1.conn13.child1/41": createMockSource( + "server1.conn13.child1/41", + "http://mdn.com/three.js", + true, + "" + ) + } }; - expect(defaultState.uncollapsedTree.contents[0].contents).toHaveLength( - 5 - ); + expect( + defaultState.uncollapsedTree.contents[0].contents[0].contents + ).toHaveLength(5); await component.setProps({ ...props, @@ -166,6 +171,56 @@ describe("SourcesTree", () => { }); }); + describe("updates threads", () => { + it("adds sources to the correct thread", async () => { + const { component, props } = render(); + const newSource = createMockSource( + "server1.conn13.child1/43", + "http://mdn.com/four.js", + true, + "" + ); + + const newThreadSources = { + FakeThread1: { + "server1.conn13.child1/43": newSource + } + }; + + expect(component.state("uncollapsedTree").contents[0].name).toEqual( + "FakeThread" + ); + expect( + component.state("uncollapsedTree").contents[0].contents[0].contents + ).toHaveLength(5); + expect(component.state("uncollapsedTree").contents[1]).toEqual( + undefined + ); + + await component.setProps({ + ...props, + sources: { + ...props.sources, + ...newThreadSources + } + }); + + expect(component.state("uncollapsedTree").contents[0].name).toEqual( + "FakeThread" + ); + expect( + component.state("uncollapsedTree").contents[0].contents[0].contents + ).toHaveLength(5); + + expect(component.state("uncollapsedTree").contents[1].name).toEqual( + "FakeThread1" + ); + expect( + component.state("uncollapsedTree").contents[1].contents[0].contents + ).toHaveLength(1); + }); + }); + describe("updates highlighted items", () => { it("updates highlightItems if selectedSource changes", async () => { const { component, props } = render(); @@ -173,8 +228,7 @@ describe("SourcesTree", () => { "server1.conn13.child1/41", "http://mdn.com/three.js", false, - null, - "FakeThread" + null ); await component.setProps({ ...props, @@ -247,10 +301,7 @@ describe("SourcesTree", () => { .find("ManagedTree") .props() .onExpand({}, expandedState); - expect(props.setExpandedState).toHaveBeenCalledWith( - "FakeThread", - expandedState - ); + expect(props.setExpandedState).toHaveBeenCalledWith(expandedState); }); it("onCollapse", async () => { @@ -260,10 +311,7 @@ describe("SourcesTree", () => { .find("ManagedTree") .props() .onCollapse({}, expandedState); - expect(props.setExpandedState).toHaveBeenCalledWith( - "FakeThread", - expandedState - ); + expect(props.setExpandedState).toHaveBeenCalledWith(expandedState); }); it("getParent", async () => { @@ -274,8 +322,8 @@ describe("SourcesTree", () => { .props() .getParent(item); - expect(parent.path).toEqual("mdn.com"); - expect(parent.contents).toHaveLength(5); + expect(parent.path).toEqual("FakeThread"); + expect(parent.contents[0].contents).toHaveLength(5); }); }); @@ -283,31 +331,7 @@ describe("SourcesTree", () => { it("should return path for item", async () => { const { instance } = render(); const path = instance.getPath(createMockItem()); - expect(path).toEqual( - "http://mdn.com/one.js/one.js/server1.conn13.child1/39/" - ); - }); - - it("should return path for blackboxedboxed item", async () => { - const item = createMockItem( - "http://mdn.com/blackboxed.js", - "blackboxed.js", - { id: "server1.conn13.child1/59" } - ); - - const sources = { - "server1.conn13.child1/59": createMockSource( - "server1.conn13.child1/59", - "http://mdn.com/blackboxed.js", - true - ) - }; - - const { instance } = render({ sources }); - const path = instance.getPath(item); - expect(path).toEqual( - "http://mdn.com/blackboxed.js/blackboxed.js/server1.conn13.child1/59/:blackboxed" - ); + expect(path).toEqual("http://mdn.com/one.js/server1.conn13.child1/39/"); }); it("should return path for generated item", async () => { @@ -318,7 +342,7 @@ describe("SourcesTree", () => { }) ); expect(pathOriginal).toEqual( - "http://mdn.com/four.js/four.js/server1.conn13.child1/42/originalSource-sha/" + "http://mdn.com/four.js/server1.conn13.child1/42/originalSource-sha/" ); const pathGenerated = instance.getPath( @@ -327,7 +351,7 @@ describe("SourcesTree", () => { }) ); expect(pathGenerated).toEqual( - "http://mdn.com/four.js/four.js/server1.conn13.child1/42/" + "http://mdn.com/four.js/server1.conn13.child1/42/" ); }); }); @@ -335,32 +359,42 @@ describe("SourcesTree", () => { function generateDefaults(overrides: Object) { const defaultSources = { - "server1.conn13.child1/39": createMockSource( - "server1.conn13.child1/39", - "http://mdn.com/one.js" - ), - "server1.conn13.child1/40": createMockSource( - "server1.conn13.child1/40", - "http://mdn.com/two.js" - ), - "server1.conn13.child1/41": createMockSource( - "server1.conn13.child1/41", - "http://mdn.com/three.js" - ), - "server1.conn13.child1/42/originalSource-sha": createMockSource( - "server1.conn13.child1/42/originalSource-sha", - "http://mdn.com/four.js" - ), - "server1.conn13.child1/42": createMockSource( - "server1.conn13.child1/42", - "http://mdn.com/four.js", - false, - "data:application/json?charset=utf?dsffewrsf" - ) + FakeThread: { + "server1.conn13.child1/39": createMockSource( + "server1.conn13.child1/39", + "http://mdn.com/one.js", + false, + null + ), + "server1.conn13.child1/40": createMockSource( + "server1.conn13.child1/40", + "http://mdn.com/two.js", + false, + null + ), + "server1.conn13.child1/41": createMockSource( + "server1.conn13.child1/41", + "http://mdn.com/three.js", + false, + null + ), + "server1.conn13.child1/42/originalSource-sha": createMockSource( + "server1.conn13.child1/42/originalSource-sha", + "http://mdn.com/four.js", + false, + null + ), + "server1.conn13.child1/42": createMockSource( + "server1.conn13.child1/42", + "http://mdn.com/four.js", + false, + "data:application/json?charset=utf?dsffewrsf" + ) + } }; + return { cx: mockcx, - thread: "FakeThread", autoExpandAll: true, selectSource: jest.fn(), setExpandedState: jest.fn(), @@ -370,6 +404,16 @@ function generateDefaults(overrides: Object) { setProjectDirectoryRoot: jest.fn(), focusItem: jest.fn(), projectRoot: "", + threads: [ + { + name: "FakeThread", + actor: "FakeThread" + }, + { + name: "FakeThread1", + actor: "FakeThread1" + } + ], ...overrides }; } @@ -386,13 +430,7 @@ function render(overrides = {}) { return { component, props, defaultState, instance }; } -function createMockSource( - id, - url, - isBlackBoxed = false, - sourceMapURL = null, - thread = "" -) { +function createMockSource(id, url, isBlackBoxed = false, sourceMapURL = null) { return { ...makeMockSource(url, id), isBlackBoxed, diff --git a/devtools/client/debugger/src/components/PrimaryPanes/tests/SourcesTreeItem.spec.js b/devtools/client/debugger/src/components/PrimaryPanes/tests/SourcesTreeItem.spec.js index 88733a302315..15b0a527dc9b 100644 --- a/devtools/client/debugger/src/components/PrimaryPanes/tests/SourcesTreeItem.spec.js +++ b/devtools/client/debugger/src/components/PrimaryPanes/tests/SourcesTreeItem.spec.js @@ -375,6 +375,7 @@ function generateDefaults(overrides) { selectItem: jest.fn(), focusItem: jest.fn(), setExpanded: jest.fn(), + threads: [{ name: "Main Thread" }], ...overrides }; } @@ -389,7 +390,11 @@ function render(overrides = {}) { return { component, props, defaultState, instance }; } -function createMockDirectory(path = "folder/", name = "folder", contents = []) { +function createMockDirectory( + path = "domain/subfolder", + name = "folder", + contents = [] +) { return { type: "directory", name, diff --git a/devtools/client/debugger/src/components/PrimaryPanes/tests/__snapshots__/PrimaryPanes.spec.js.snap b/devtools/client/debugger/src/components/PrimaryPanes/tests/__snapshots__/PrimaryPanes.spec.js.snap index aa905a73fda0..d07959bd25f9 100644 --- a/devtools/client/debugger/src/components/PrimaryPanes/tests/__snapshots__/PrimaryPanes.spec.js.snap +++ b/devtools/client/debugger/src/components/PrimaryPanes/tests/__snapshots__/PrimaryPanes.spec.js.snap @@ -57,6 +57,9 @@ exports[`PrimaryPanes with custom root renders custom root source list 1`] = ` + + -
- - - Main Thread - -
-
- - - Main Thread - -
-
- - - Main Thread - -
-
- - - Main Thread - -
-
- - - Main Thread - -
, "_forcedUpdate": false, @@ -198,6 +210,11 @@ Object { "relativeUrl": "http://mdn.com/one.js", "url": "http://mdn.com/one.js", }, + "threads": Array [ + Object { + "name": "Main Thread", + }, + ], "toggleBlackBox": [MockFunction], }, } @@ -285,6 +302,11 @@ Object { "relativeUrl": "http://mdn.com/one.js", "url": "http://mdn.com/one.js", }, + "threads": Array [ + Object { + "name": "Main Thread", + }, + ], "toggleBlackBox": [MockFunction], }, "refs": Object {}, @@ -334,6 +356,13 @@ Object { "url": "http://mdn.com/one.js", } } + threads={ + Array [ + Object { + "name": "Main Thread", + }, + ] + } toggleBlackBox={[MockFunction]} />, "_forcedUpdate": false, @@ -417,6 +446,11 @@ Object { "relativeUrl": "http://mdn.com/one.js", "url": "http://mdn.com/one.js", }, + "threads": Array [ + Object { + "name": "Main Thread", + }, + ], "toggleBlackBox": [MockFunction], }, } @@ -433,8 +467,20 @@ Object { - , "_forcedUpdate": false, @@ -549,8 +607,20 @@ Object { - , "_forcedUpdate": false, @@ -715,7 +802,7 @@ Object { className="arrow" /> , "_forcedUpdate": false, @@ -872,7 +976,7 @@ Object { className="arrow" /> @@ -932,7 +1041,7 @@ Object { className="arrow expanded" /> , "_forcedUpdate": false, @@ -1008,7 +1129,7 @@ Object { className="arrow expanded" /> , "_forcedUpdate": false, @@ -1193,6 +1331,11 @@ Object { "relativeUrl": "http://mdn.com/one.js", "url": "http://mdn.com/one.js", }, + "threads": Array [ + Object { + "name": "Main Thread", + }, + ], "toggleBlackBox": [MockFunction], }, } @@ -1202,7 +1345,7 @@ exports[`SourceTreeItem renderItem should show icon for folder with arrow 1`] = Object { "component":
@@ -1234,7 +1377,7 @@ Object { "item": Object { "contents": Array [], "name": "folder", - "path": "folder/", + "path": "domain/subfolder", "type": "directory", }, "projectRoot": "", @@ -1242,6 +1385,11 @@ Object { "setExpanded": [MockFunction], "setProjectDirectoryRoot": [MockFunction], "source": null, + "threads": Array [ + Object { + "name": "Main Thread", + }, + ], "toggleBlackBox": [MockFunction], }, "refs": Object {}, @@ -1259,7 +1407,7 @@ Object { Object { "contents": Array [], "name": "folder", - "path": "folder/", + "path": "domain/subfolder", "type": "directory", } } @@ -1268,6 +1416,13 @@ Object { setExpanded={[MockFunction]} setProjectDirectoryRoot={[MockFunction]} source={null} + threads={ + Array [ + Object { + "name": "Main Thread", + }, + ] + } toggleBlackBox={[MockFunction]} />, "_forcedUpdate": false, @@ -1305,7 +1460,7 @@ Object { "item": Object { "contents": Array [], "name": "folder", - "path": "folder/", + "path": "domain/subfolder", "type": "directory", }, "projectRoot": "", @@ -1313,6 +1468,11 @@ Object { "setExpanded": [MockFunction], "setProjectDirectoryRoot": [MockFunction], "source": null, + "threads": Array [ + Object { + "name": "Main Thread", + }, + ], "toggleBlackBox": [MockFunction], }, } @@ -1322,7 +1482,7 @@ exports[`SourceTreeItem renderItem should show icon for folder with expanded arr Object { "component":
@@ -1330,7 +1490,7 @@ Object { className="arrow expanded" /> , "_forcedUpdate": false, @@ -1406,7 +1578,7 @@ Object { className="arrow expanded" /> , "_forcedUpdate": false, @@ -1552,7 +1741,7 @@ Object { className="arrow" /> , "_forcedUpdate": false, @@ -1746,6 +1952,11 @@ Object { "relativeUrl": "http://mdn.com/one.js", "url": "http://mdn.com/one.js", }, + "threads": Array [ + Object { + "name": "Main Thread", + }, + ], "toggleBlackBox": [MockFunction], }, } @@ -1827,6 +2038,11 @@ Object { "relativeUrl": "http://mdn.com/one.js", "url": "http://mdn.com/one.js", }, + "threads": Array [ + Object { + "name": "Main Thread", + }, + ], "toggleBlackBox": [MockFunction], }, "refs": Object {}, @@ -1875,6 +2091,13 @@ Object { "url": "http://mdn.com/one.js", } } + threads={ + Array [ + Object { + "name": "Main Thread", + }, + ] + } toggleBlackBox={[MockFunction]} />, "_forcedUpdate": false, @@ -1952,6 +2175,11 @@ Object { "relativeUrl": "http://mdn.com/one.js", "url": "http://mdn.com/one.js", }, + "threads": Array [ + Object { + "name": "Main Thread", + }, + ], "toggleBlackBox": [MockFunction], }, } @@ -2034,6 +2262,11 @@ Object { "relativeUrl": "http://mdn.com/one.js", "url": "http://mdn.com/one.js", }, + "threads": Array [ + Object { + "name": "Main Thread", + }, + ], "toggleBlackBox": [MockFunction], }, "refs": Object {}, @@ -2083,6 +2316,13 @@ Object { "url": "http://mdn.com/one.js", } } + threads={ + Array [ + Object { + "name": "Main Thread", + }, + ] + } toggleBlackBox={[MockFunction]} />, "_forcedUpdate": false, @@ -2161,6 +2401,11 @@ Object { "relativeUrl": "http://mdn.com/one.js", "url": "http://mdn.com/one.js", }, + "threads": Array [ + Object { + "name": "Main Thread", + }, + ], "toggleBlackBox": [MockFunction], }, } @@ -2242,6 +2487,11 @@ Object { "relativeUrl": "http://mdn.com/one.js", "url": "http://mdn.com/one.js", }, + "threads": Array [ + Object { + "name": "Main Thread", + }, + ], "toggleBlackBox": [MockFunction], }, "refs": Object {}, @@ -2290,6 +2540,13 @@ Object { "url": "http://mdn.com/one.js", } } + threads={ + Array [ + Object { + "name": "Main Thread", + }, + ] + } toggleBlackBox={[MockFunction]} />, "_forcedUpdate": false, @@ -2367,6 +2624,11 @@ Object { "relativeUrl": "http://mdn.com/one.js", "url": "http://mdn.com/one.js", }, + "threads": Array [ + Object { + "name": "Main Thread", + }, + ], "toggleBlackBox": [MockFunction], }, } diff --git a/devtools/client/debugger/src/components/QuickOpenModal.js b/devtools/client/debugger/src/components/QuickOpenModal.js index 76501100a2d5..bd98b9e59c06 100644 --- a/devtools/client/debugger/src/components/QuickOpenModal.js +++ b/devtools/client/debugger/src/components/QuickOpenModal.js @@ -430,11 +430,12 @@ export class QuickOpenModal extends Component { /* istanbul ignore next: ignoring testing of redux connection stuff */ function mapStateToProps(state) { const selectedSource = getSelectedSource(state); + const displayedSources = getDisplayedSourcesList(state); return { cx: getContext(state), enabled: getQuickOpenEnabled(state), - sources: formatSources(getDisplayedSourcesList(state), getTabs(state)), + sources: formatSources(displayedSources, getTabs(state)), selectedSource, selectedContentLoaded: selectedSource ? !!getSourceContent(state, selectedSource.id) diff --git a/devtools/client/debugger/src/components/SecondaryPanes/Worker.js b/devtools/client/debugger/src/components/SecondaryPanes/Worker.js index 3910c821804b..397e46b48931 100644 --- a/devtools/client/debugger/src/components/SecondaryPanes/Worker.js +++ b/devtools/client/debugger/src/components/SecondaryPanes/Worker.js @@ -44,7 +44,7 @@ export class Worker extends Component { onClick={this.onSelectThread} >
- +
{label}
{isPaused ? ( diff --git a/devtools/client/debugger/src/components/shared/AccessibleImage.css b/devtools/client/debugger/src/components/shared/AccessibleImage.css index 308f238c7114..c463f3b57e8e 100644 --- a/devtools/client/debugger/src/components/shared/AccessibleImage.css +++ b/devtools/client/debugger/src/components/shared/AccessibleImage.css @@ -80,6 +80,11 @@ html[dir="rtl"] .img.arrow { mask-size: 12px 12px; } +.img.window { + mask-image: url(resource://devtools/client/debugger/images/window.svg); + mask-size: 12px 12px; +} + .img.file { mask-image: url(resource://devtools/client/debugger/images/file-small.svg); mask-size: 12px 12px; diff --git a/devtools/client/debugger/src/reducers/debuggee.js b/devtools/client/debugger/src/reducers/debuggee.js index f3df260a662c..110ee943a147 100644 --- a/devtools/client/debugger/src/reducers/debuggee.js +++ b/devtools/client/debugger/src/reducers/debuggee.js @@ -10,9 +10,12 @@ */ import { sortBy } from "lodash"; +import { createSelector } from "reselect"; + import { getDisplayName } from "../utils/workers"; -import type { MainThread, WorkerList } from "../types"; +import type { Selector } from "./types"; +import type { MainThread, WorkerList, Thread } from "../types"; import type { Action } from "../actions/types"; export type DebuggeeState = { @@ -21,7 +24,10 @@ export type DebuggeeState = { }; export function initialDebuggeeState(): DebuggeeState { - return { workers: [], mainThread: { actor: "", url: "", type: -1 } }; + return { + workers: [], + mainThread: { actor: "", url: "", type: -1, name: "" } + }; } export default function debuggee( @@ -32,13 +38,10 @@ export default function debuggee( case "CONNECT": return { ...state, - mainThread: action.mainThread + mainThread: { ...action.mainThread, name: L10N.getStr("mainThread") } }; case "INSERT_WORKERS": - return { - ...state, - workers: [...state.workers, ...action.workers] - }; + return insertWorkers(state, action.workers); case "REMOVE_WORKERS": const { workers } = action; return { @@ -55,6 +58,18 @@ export default function debuggee( } } +function insertWorkers(state, workers) { + const formatedWorkers = workers.map(worker => ({ + ...worker, + name: getDisplayName(worker) + })); + + return { + ...state, + workers: [...state.workers, ...formatedWorkers] + }; +} + export const getWorkers = (state: OuterState) => state.debuggee.workers; export const getWorkerCount = (state: OuterState) => getWorkers(state).length; @@ -71,8 +86,10 @@ export function getDebuggeeUrl(state: OuterState): string { return getMainThread(state).url; } -export function getThreads(state: OuterState) { - return [getMainThread(state), ...sortBy(getWorkers(state), getDisplayName)]; -} +export const getThreads: Selector = createSelector( + getMainThread, + getWorkers, + (mainThread, workers) => [mainThread, ...sortBy(workers, getDisplayName)] +); type OuterState = { debuggee: DebuggeeState }; diff --git a/devtools/client/debugger/src/reducers/source-tree.js b/devtools/client/debugger/src/reducers/source-tree.js index 764df5fa2d90..4a0f69e3e0e4 100644 --- a/devtools/client/debugger/src/reducers/source-tree.js +++ b/devtools/client/debugger/src/reducers/source-tree.js @@ -9,15 +9,17 @@ * @module reducers/source-tree */ -import type { SourceTreeAction } from "../actions/types"; +import type { SourceTreeAction, FocusItem } from "../actions/types"; export type SourceTreeState = { - expanded: { [string]: Set } + expanded: Set, + focusedItem: ?FocusItem }; export function InitialState(): SourceTreeState { return { - expanded: {} + expanded: new Set(), + focusedItem: null }; } @@ -28,6 +30,9 @@ export default function update( switch (action.type) { case "SET_EXPANDED_STATE": return updateExpanded(state, action); + + case "SET_FOCUSED_SOURCE_ITEM": + return { ...state, focusedItem: action.item }; } return state; @@ -36,7 +41,7 @@ export default function update( function updateExpanded(state, action) { return { ...state, - expanded: { ...state.expanded, [action.thread]: new Set(action.expanded) } + expanded: new Set(action.expanded) }; } @@ -44,6 +49,10 @@ type OuterState = { sourceTree: SourceTreeState }; -export function getExpandedState(state: OuterState, thread: string) { - return state.sourceTree.expanded[thread]; +export function getExpandedState(state: OuterState) { + return state.sourceTree.expanded; +} + +export function getFocusedSourceItem(state: OuterState): ?FocusItem { + return state.sourceTree.focusedItem; } diff --git a/devtools/client/debugger/src/reducers/sources.js b/devtools/client/debugger/src/reducers/sources.js index 2b6d1301aa27..fecc8a729373 100644 --- a/devtools/client/debugger/src/reducers/sources.js +++ b/devtools/client/debugger/src/reducers/sources.js @@ -68,8 +68,9 @@ export type SourcesMap = { [SourceId]: Source }; type SourcesContentMap = { [SourceId]: AsyncValue | null }; -export type BreakpointPositionsMap = { [SourceId]: BreakpointPositions }; export type SourcesMapByThread = { [ThreadId]: SourcesMap }; + +export type BreakpointPositionsMap = { [SourceId]: BreakpointPositions }; type SourceActorMap = { [SourceId]: Array }; type UrlsMap = { [string]: SourceId[] }; @@ -852,9 +853,10 @@ const getDisplayedSourceIDs: GetDisplayedSourceIDsSelector = createSelector( return sourceIDsByThread; } ); + type GetDisplayedSourcesSelector = ( OuterState & SourceActorOuterState -) => { [ThreadId]: { [SourceId]: Source } }; +) => SourcesMapByThread; export const getDisplayedSources: GetDisplayedSourcesSelector = createSelector( state => state.sources.sources, getDisplayedSourceIDs, @@ -874,17 +876,6 @@ export const getDisplayedSources: GetDisplayedSourcesSelector = createSelector( } ); -export function getDisplayedSourcesForThread( - state: OuterState & SourceActorOuterState, - thread: string -): SourcesMap { - return getDisplayedSources(state)[thread] || {}; -} - -export function getFocusedSourceItem(state: OuterState): ?FocusItem { - return state.sources.focusedItem; -} - export function getSourceActorsForSource( state: OuterState & SourceActorOuterState, id: SourceId diff --git a/devtools/client/debugger/src/reducers/tests/sources.spec.js b/devtools/client/debugger/src/reducers/tests/sources.spec.js index 92f44c96c4ab..7a03fe96344b 100644 --- a/devtools/client/debugger/src/reducers/tests/sources.spec.js +++ b/devtools/client/debugger/src/reducers/tests/sources.spec.js @@ -81,7 +81,6 @@ describe("sources selectors", () => { sources: update(state, { type: "ADD_SOURCES", cx: mockcx, - // coercing to a Source for the purpose of this test sources: ((mockedSources: any): Source[]) }), sourceActors: undefined @@ -94,9 +93,8 @@ describe("sources selectors", () => { sources: update(state.sources, insertAction), sourceActors: updateSourceActors(state.sourceActors, insertAction) }; - const selectedDisplayedSources = getDisplayedSources(state); - const threadSources = selectedDisplayedSources.foo; - expect(Object.values(threadSources)).toHaveLength(3); + const threadSources = getDisplayedSources(state); + expect(Object.values(threadSources.foo)).toHaveLength(3); }); it("should omit all extensions when chrome preference enabled", () => { @@ -106,7 +104,6 @@ describe("sources selectors", () => { sources: update(state, { type: "ADD_SOURCES", cx: mockcx, - // coercing to a Source for the purpose of this test sources: ((mockedSources: any): Source[]) }), sourceActors: undefined @@ -121,8 +118,7 @@ describe("sources selectors", () => { sources: update(state.sources, insertAction), sourceActors: updateSourceActors(state.sourceActors, insertAction) }; - const selectedDisplayedSources = getDisplayedSources(state); - const threadSources = selectedDisplayedSources.foo; - expect(Object.values(threadSources)).toHaveLength(1); + const threadSources = getDisplayedSources(state); + expect(Object.values(threadSources.foo)).toHaveLength(1); }); }); diff --git a/devtools/client/debugger/src/types.js b/devtools/client/debugger/src/types.js index 8c1da9d8fa5a..7e8bda074087 100644 --- a/devtools/client/debugger/src/types.js +++ b/devtools/client/debugger/src/types.js @@ -447,13 +447,15 @@ export type Scope = {| export type MainThread = { +actor: ThreadId, +url: string, - +type: number + +type: number, + +name: string }; export type Worker = { +actor: ThreadId, +url: string, - +type: number + +type: number, + +name: string }; export type Thread = MainThread & Worker; diff --git a/devtools/client/debugger/src/utils/source.js b/devtools/client/debugger/src/utils/source.js index 8c2298d2ed72..bd89b7db6c4d 100644 --- a/devtools/client/debugger/src/utils/source.js +++ b/devtools/client/debugger/src/utils/source.js @@ -491,7 +491,7 @@ export function getSourceQueryString(source: ?Source) { } export function isUrlExtension(url: string) { - return /^(chrome|moz)-extension:\//.test(url); + return /\/?(chrome|moz)-extension:\//.test(url); } export function getPlainUrl(url: string): string { diff --git a/devtools/client/debugger/src/utils/sources-tree/addToTree.js b/devtools/client/debugger/src/utils/sources-tree/addToTree.js index d4c01a67bad2..a9c2ff037c37 100644 --- a/devtools/client/debugger/src/utils/sources-tree/addToTree.js +++ b/devtools/client/debugger/src/utils/sources-tree/addToTree.js @@ -90,15 +90,25 @@ function traverseTree( url: ParsedURL, tree: TreeDirectory, debuggeeHost: ?string, - source: Source + source: Source, + thread: string ): TreeNode { const parts = url.path.split("/").filter(p => p !== ""); parts.unshift(url.group); + if (thread) { + parts.unshift(thread); + } let path = ""; return parts.reduce((subTree, part, index) => { - path = path ? `${path}/${part}` : part; - const debuggeeHostIfRoot = index === 0 ? debuggeeHost : null; + if (index == 0 && thread) { + path = thread; + } else { + path = `${path}/${part}`; + } + + const debuggeeHostIfRoot = index === 1 ? debuggeeHost : null; + return findOrCreateNode( parts, subTree, @@ -165,7 +175,8 @@ function addSourceToNode( export function addToTree( tree: TreeDirectory, source: Source, - debuggeeHost: ?string + debuggeeHost: ?string, + thread: string ) { const url = getURL(source, debuggeeHost); @@ -173,7 +184,7 @@ export function addToTree( return; } - const finalNode = traverseTree(url, tree, debuggeeHost, source); + const finalNode = traverseTree(url, tree, debuggeeHost, source, thread); // $FlowIgnore finalNode.contents = addSourceToNode(finalNode, url, source); diff --git a/devtools/client/debugger/src/utils/sources-tree/collapseTree.js b/devtools/client/debugger/src/utils/sources-tree/collapseTree.js index 4ff81613267e..57d3e898496d 100644 --- a/devtools/client/debugger/src/utils/sources-tree/collapseTree.js +++ b/devtools/client/debugger/src/utils/sources-tree/collapseTree.js @@ -18,8 +18,9 @@ function _collapseTree(node: TreeNode, depth: number): TreeNode { console.log(`Expected array at: ${node.path}`); } - // Node is not a root/domain node, and only contains 1 item. - if (depth > 1 && node.contents.length === 1) { + // Node is not a (1) thread and (2) root/domain node, + // and only contains 1 item. + if (depth > 2 && node.contents.length === 1) { const next = node.contents[0]; // Do not collapse if the next node is a leaf node. if (next.type === "directory") { diff --git a/devtools/client/debugger/src/utils/sources-tree/createTree.js b/devtools/client/debugger/src/utils/sources-tree/createTree.js deleted file mode 100644 index 7eed7b6cdf1f..000000000000 --- a/devtools/client/debugger/src/utils/sources-tree/createTree.js +++ /dev/null @@ -1,36 +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 . */ - -// @flow - -import { addToTree } from "./addToTree"; -import { collapseTree } from "./collapseTree"; -import { createDirectoryNode, createParentMap } from "./utils"; -import { getDomain } from "./treeOrder"; - -import type { SourcesMap } from "../../reducers/types"; -import type { TreeDirectory } from "./types"; - -type Params = { - sources: SourcesMap, - debuggeeUrl: string -}; - -export function createTree({ sources, debuggeeUrl }: Params) { - const uncollapsedTree = createDirectoryNode("root", "", []); - const debuggeeHost = getDomain(debuggeeUrl); - - for (const sourceId in sources) { - const source = sources[sourceId]; - addToTree(uncollapsedTree, source, debuggeeHost); - } - - const sourceTree = collapseTree((uncollapsedTree: TreeDirectory)); - - return { - uncollapsedTree, - sourceTree, - parentMap: createParentMap(sourceTree) - }; -} diff --git a/devtools/client/debugger/src/utils/sources-tree/index.js b/devtools/client/debugger/src/utils/sources-tree/index.js index 335e2fd61f5a..102e73a70ace 100644 --- a/devtools/client/debugger/src/utils/sources-tree/index.js +++ b/devtools/client/debugger/src/utils/sources-tree/index.js @@ -11,11 +11,10 @@ export { addToTree } from "./addToTree"; export { collapseTree } from "./collapseTree"; -export { createTree } from "./createTree"; export { formatTree } from "./formatTree"; export { getDirectories } from "./getDirectories"; export { getFilenameFromPath, getURL } from "./getURL"; -export { sortEntireTree, sortTree } from "./sortTree"; -export { updateTree } from "./updateTree"; +export { sortTree } from "./sortTree"; +export { createTree, updateTree } from "./updateTree"; export * from "./utils"; diff --git a/devtools/client/debugger/src/utils/sources-tree/moz.build b/devtools/client/debugger/src/utils/sources-tree/moz.build index 4550973c166b..0288b56d311a 100644 --- a/devtools/client/debugger/src/utils/sources-tree/moz.build +++ b/devtools/client/debugger/src/utils/sources-tree/moz.build @@ -10,7 +10,6 @@ DIRS += [ CompiledModules( 'addToTree.js', 'collapseTree.js', - 'createTree.js', 'formatTree.js', 'getDirectories.js', 'getURL.js', diff --git a/devtools/client/debugger/src/utils/sources-tree/sortTree.js b/devtools/client/debugger/src/utils/sources-tree/sortTree.js index 77eff3aba324..5bf8f0e92201 100644 --- a/devtools/client/debugger/src/utils/sources-tree/sortTree.js +++ b/devtools/client/debugger/src/utils/sources-tree/sortTree.js @@ -8,25 +8,6 @@ import { nodeHasChildren, isExactUrlMatch } from "./utils"; import type { TreeDirectory } from "./types"; -/** - * Look at the nodes in the source tree, and determine the index of where to - * insert a new node. The ordering is index -> folder -> file. - * @memberof utils/sources-tree - * @static - */ -export function sortEntireTree( - tree: TreeDirectory, - debuggeeUrl: string = "" -): TreeDirectory { - if (nodeHasChildren(tree)) { - const contents = sortTree(tree, debuggeeUrl).map((subtree: any) => - sortEntireTree(subtree) - ); - return { ...tree, contents }; - } - return tree; -} - /** * Look at the nodes in the source tree, and determine the index of where to * insert a new node. The ordering is index -> folder -> file. diff --git a/devtools/client/debugger/src/utils/sources-tree/tests/__snapshots__/addToTree.spec.js.snap b/devtools/client/debugger/src/utils/sources-tree/tests/__snapshots__/addToTree.spec.js.snap index e31a7543420c..7059aced63f5 100644 --- a/devtools/client/debugger/src/utils/sources-tree/tests/__snapshots__/addToTree.spec.js.snap +++ b/devtools/client/debugger/src/utils/sources-tree/tests/__snapshots__/addToTree.spec.js.snap @@ -2,77 +2,90 @@ exports[`sources-tree addToTree can add a file to an intermediate directory 1`] = ` " - root path= - - unpkg.com path=unpkg.com - - codemirror@5.1 path=unpkg.com/codemirror@5.1 - - mode path=unpkg.com/codemirror@5.1/mode - - xml path=unpkg.com/codemirror@5.1/mode/xml - - xml.js path=unpkg.com/codemirror@5.1/mode/xml/xml.js source_id=server1.conn13.child1/39 - - codemirror@5.1 path=unpkg.com/codemirror@5.1 source_id=server1.conn13.child1/37 + - FakeThread path=FakeThread + - unpkg.com path=FakeThread/unpkg.com + - codemirror@5.1 path=FakeThread/unpkg.com/codemirror@5.1 + - mode path=FakeThread/unpkg.com/codemirror@5.1/mode + - xml path=FakeThread/unpkg.com/codemirror@5.1/mode/xml + - xml.js path=FakeThread/unpkg.com/codemirror@5.1/mode/xml/xml.js source_id=server1.conn13.child1/39 + - codemirror@5.1 path=FakeThread/unpkg.com/codemirror@5.1 source_id=server1.conn13.child1/37 " `; exports[`sources-tree addToTree correctly parses file sources 1`] = ` " - root path= - - file:// path=file:// - - a path=file:///a - - b.js path=file:///a/b.js source_id=actor1 + - FakeThread path=FakeThread + - file:// path=FakeThread/file:// + - a path=FakeThread/file:///a + - b.js path=FakeThread/file:///a/b.js source_id=actor1 " `; exports[`sources-tree addToTree does not attempt to add two of the same directory 1`] = ` " - root path= - - davidwalsh.name path=davidwalsh.name - - (index) path=https://davidwalsh.name/ source_id=server1.conn13.child1/37 - - wp-content path=davidwalsh.name/wp-content - - prism.js path=davidwalsh.name/wp-content/prism.js source_id=server1.conn13.child1/39 + - FakeThread path=FakeThread + - davidwalsh.name path=FakeThread/davidwalsh.name + - (index) path=https://davidwalsh.name/ source_id=server1.conn13.child1/37 + - wp-content path=FakeThread/davidwalsh.name/wp-content + - prism.js path=FakeThread/davidwalsh.name/wp-content/prism.js source_id=server1.conn13.child1/39 " `; exports[`sources-tree addToTree does not attempt to add two of the same file 1`] = ` " - root path= - - davidwalsh.name path=davidwalsh.name - - (index) path=https://davidwalsh.name/ source_id=server1.conn13.child1/37 + - FakeThread path=FakeThread + - davidwalsh.name path=FakeThread/davidwalsh.name + - (index) path=https://davidwalsh.name/ source_id=server1.conn13.child1/39 + - util.js path=FakeThread/davidwalsh.name/util.js source_id=server1.conn13.child1/37 + - FakeThread2 path=FakeThread2 + - davidwalsh.name path=FakeThread2/davidwalsh.name + - util.js path=FakeThread2/davidwalsh.name/util.js source_id=server1.conn13.child1/37 " `; exports[`sources-tree addToTree does not mangle encoded URLs 1`] = ` " - root path= - - example.com path=example.com - - foo path=example.com/foo - - B9724220.131821496;dc_ver=42.111;sz=468x60;u_sd=2;dc_adk=2020465299;ord=a53rpc;dc_rfl=1,https%3A%2F%2Fdavidwalsh.name%2F$0;xdt=1 path=example.com/foo/B9724220.131821496;dc_ver=42.111;sz=468x60;u_sd=2;dc_adk=2020465299;ord=a53rpc;dc_rfl=1,https%3A%2F%2Fdavidwalsh.name%2F$0;xdt=1 source_id=actor1 + - FakeThread path=FakeThread + - example.com path=FakeThread/example.com + - foo path=FakeThread/example.com/foo + - B9724220.131821496;dc_ver=42.111;sz=468x60;u_sd=2;dc_adk=2020465299;ord=a53rpc;dc_rfl=1,https%3A%2F%2Fdavidwalsh.name%2F$0;xdt=1 path=FakeThread/example.com/foo/B9724220.131821496;dc_ver=42.111;sz=468x60;u_sd=2;dc_adk=2020465299;ord=a53rpc;dc_rfl=1,https%3A%2F%2Fdavidwalsh.name%2F$0;xdt=1 source_id=actor1 " `; exports[`sources-tree addToTree excludes javascript: URLs from the tree 1`] = ` " - root path= - - example.com path=example.com - - source1.js path=example.com/source1.js source_id=actor2 + - FakeThread path=FakeThread + - example.com path=FakeThread/example.com + - source1.js path=FakeThread/example.com/source1.js source_id=actor2 " `; exports[`sources-tree addToTree name does not include query params 1`] = ` " - root path= - - example.com path=example.com - - foo path=example.com/foo - - name.js path=example.com/foo/name.js source_id=actor1 + - FakeThread path=FakeThread + - example.com path=FakeThread/example.com + - foo path=FakeThread/example.com/foo + - name.js path=FakeThread/example.com/foo/name.js source_id=actor1 " `; exports[`sources-tree addToTree replaces a file with a directory 1`] = ` " - root path= - - unpkg.com path=unpkg.com - - codemirror@5.1 path=unpkg.com/codemirror@5.1 - - mode path=unpkg.com/codemirror@5.1/mode - - xml path=unpkg.com/codemirror@5.1/mode/xml - - xml.js path=unpkg.com/codemirror@5.1/mode/xml/xml.js source_id=server1.conn13.child1/39 - - codemirror@5.1 path=unpkg.com/codemirror@5.1 source_id=server1.conn13.child1/37 + - FakeThread path=FakeThread + - unpkg.com path=FakeThread/unpkg.com + - codemirror@5.1 path=FakeThread/unpkg.com/codemirror@5.1 + - mode path=FakeThread/unpkg.com/codemirror@5.1/mode + - xml path=FakeThread/unpkg.com/codemirror@5.1/mode/xml + - xml.js path=FakeThread/unpkg.com/codemirror@5.1/mode/xml/xml.js source_id=server1.conn13.child1/39 + - codemirror@5.1 path=FakeThread/unpkg.com/codemirror@5.1 source_id=server1.conn13.child1/37 " `; exports[`sources-tree addToTree supports data URLs 1`] = ` " - root path= - - (no domain) path=(no domain) - - data:text/html, path=data:text/html, source_id=server1.conn13.child1/39 + - FakeThread path=FakeThread + - (no domain) path=FakeThread/(no domain) + - data:text/html, path=data:text/html, source_id=server1.conn13.child1/39 " `; diff --git a/devtools/client/debugger/src/utils/sources-tree/tests/__snapshots__/collapseTree.spec.js.snap b/devtools/client/debugger/src/utils/sources-tree/tests/__snapshots__/collapseTree.spec.js.snap index bdad26c16fc0..529874f8bdc6 100644 --- a/devtools/client/debugger/src/utils/sources-tree/tests/__snapshots__/collapseTree.spec.js.snap +++ b/devtools/client/debugger/src/utils/sources-tree/tests/__snapshots__/collapseTree.spec.js.snap @@ -2,37 +2,41 @@ exports[`sources tree collapseTree can collapse a single source 1`] = ` " - root path= - - example.com path=example.com - - a/b path=example.com/a/b - - c.js path=example.com/a/b/c.js source_id=actor1 + - Main Thread path=Main Thread + - example.com path=Main Thread/example.com + - a/b path=Main Thread/example.com/a/b + - c.js path=Main Thread/example.com/a/b/c.js source_id=actor1 " `; exports[`sources tree collapseTree correctly merges in a collapsed source with a deeper level 1`] = ` " - root path= - - example.com path=example.com - - a/b path=example.com/a/b - - c/d path=example.com/a/b/c/d - - e.js path=example.com/a/b/c/d/e.js source_id=actor2 - - c.js path=example.com/a/b/c.js source_id=actor1 + - Main Thread path=Main Thread + - example.com path=Main Thread/example.com + - a/b path=Main Thread/example.com/a/b + - c/d path=Main Thread/example.com/a/b/c/d + - e.js path=Main Thread/example.com/a/b/c/d/e.js source_id=actor2 + - c.js path=Main Thread/example.com/a/b/c.js source_id=actor1 " `; exports[`sources tree collapseTree correctly merges in a collapsed source with a shallower level 1`] = ` " - root path= - - example.com path=example.com - - a/b path=example.com/a/b - - c.js path=example.com/a/b/c.js source_id=actor1 - - x.js path=example.com/a/b/x.js source_id=actor3 + - Main Thread path=Main Thread + - example.com path=Main Thread/example.com + - a/b path=Main Thread/example.com/a/b + - c.js path=Main Thread/example.com/a/b/c.js source_id=actor1 + - x.js path=Main Thread/example.com/a/b/x.js source_id=actor3 " `; exports[`sources tree collapseTree correctly merges in a collapsed source with the same level 1`] = ` " - root path= - - example.com path=example.com - - a/b path=example.com/a/b - - c/d path=example.com/a/b/c/d - - e.js path=example.com/a/b/c/d/e.js source_id=actor2 - - c.js path=example.com/a/b/c.js source_id=actor1 + - Main Thread path=Main Thread + - example.com path=Main Thread/example.com + - a/b path=Main Thread/example.com/a/b + - c/d path=Main Thread/example.com/a/b/c/d + - e.js path=Main Thread/example.com/a/b/c/d/e.js source_id=actor2 + - c.js path=Main Thread/example.com/a/b/c.js source_id=actor1 " `; diff --git a/devtools/client/debugger/src/utils/sources-tree/tests/__snapshots__/sortTree.spec.js.snap b/devtools/client/debugger/src/utils/sources-tree/tests/__snapshots__/sortTree.spec.js.snap deleted file mode 100644 index e8120f8cb3d9..000000000000 --- a/devtools/client/debugger/src/utils/sources-tree/tests/__snapshots__/sortTree.spec.js.snap +++ /dev/null @@ -1,73 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`sources-tree sortEntireTree alphabetically sorts children 1`] = ` -" - root path= - - example.com path=example.com - - foo path=example.com/foo - - a_source3.js path=example.com/foo/a_source3.js source_id=actor3 - - b_source2.js path=example.com/foo/b_source2.js source_id=actor2 - - source1.js path=example.com/source1.js source_id=actor1 -" -`; - -exports[`sources-tree sortEntireTree puts folder at the top of the sort 1`] = ` -" - root path= - - example.com path=example.com - - folder path=example.com/folder - - b path=example.com/folder/b - - b.js path=example.com/folder/b/b.js source_id=actor2 - - c path=example.com/folder/c - - (index) path=http://example.com/folder/c/ source_id=actor3 - - a.js path=example.com/folder/a.js source_id=actor1 -" -`; - -exports[`sources-tree sortEntireTree puts root debugee url at the top of the sort 1`] = ` -" - root path= - - example.com path=example.com - - b.js path=example.com/b.js source_id=actor2 - - api.example.com path=api.example.com - - a.js path=api.example.com/a.js source_id=actor1 - - demo.com path=demo.com - - c.js path=demo.com/c.js source_id=actor3 -" -`; - -exports[`sources-tree sortEntireTree puts root debugee url at the top of the sort 2`] = ` -" - root path= - - demo.com path=demo.com - - c.js path=demo.com/c.js source_id=actor3 - - api.example.com path=api.example.com - - a.js path=api.example.com/a.js source_id=actor1 - - example.com path=example.com - - b.js path=example.com/b.js source_id=actor2 -" -`; - -exports[`sources-tree sortEntireTree sorts folders first 1`] = ` -" - root path= - - example.com path=example.com - - (index) path=http://example.com source_id=actor4 - - b.js path=example.com/b.js - - b_source.js path=example.com/b.js/b_source.js source_id=actor2 - - d path=example.com/d - - d_source.js path=example.com/d/d_source.js source_id=actor5 - - a.js path=example.com/a.js source_id=actor1 - - b2 path=example.com/b2 source_id=actor6 - - c.js path=example.com/c.js source_id=actor3 -" -`; - -exports[`sources-tree sortEntireTree sorts folders first 2`] = ` -" - root path= - - example.com path=example.com - - (index) path=http://example.com source_id=actor4 - - b.js path=example.com/b.js - - b_source.js path=example.com/b.js/b_source.js source_id=actor2 - - d path=example.com/d - - d_source.js path=example.com/d/d_source.js source_id=actor5 - - a.js path=example.com/a.js source_id=actor1 - - b2 path=example.com/b2 source_id=actor6 - - c.js path=example.com/c.js source_id=actor3 -" -`; diff --git a/devtools/client/debugger/src/utils/sources-tree/tests/__snapshots__/updateTree.spec.js.snap b/devtools/client/debugger/src/utils/sources-tree/tests/__snapshots__/updateTree.spec.js.snap index f2c2e0ee07bc..1de925f0864a 100644 --- a/devtools/client/debugger/src/utils/sources-tree/tests/__snapshots__/updateTree.spec.js.snap +++ b/devtools/client/debugger/src/utils/sources-tree/tests/__snapshots__/updateTree.spec.js.snap @@ -8,38 +8,45 @@ exports[`calls updateTree.js adds one source 1`] = ` \\"contents\\": [ { \\"type\\": \\"directory\\", - \\"name\\": \\"davidwalsh.name\\", - \\"path\\": \\"davidwalsh.name\\", + \\"name\\": \\"FakeThread\\", + \\"path\\": \\"FakeThread\\", \\"contents\\": [ { - \\"type\\": \\"source\\", - \\"name\\": \\"(index)\\", - \\"path\\": \\"https://davidwalsh.name/\\", - \\"contents\\": { - \\"id\\": \\"server1.conn13.child1/39\\", - \\"url\\": \\"https://davidwalsh.name/\\", - \\"isBlackBoxed\\": false, - \\"isPrettyPrinted\\": false, - \\"relativeUrl\\": \\"https://davidwalsh.name/\\", - \\"introductionUrl\\": null, - \\"isWasm\\": false, - \\"isExtension\\": false - } - }, - { - \\"type\\": \\"source\\", - \\"name\\": \\"source1.js\\", - \\"path\\": \\"davidwalsh.name/source1.js\\", - \\"contents\\": { - \\"id\\": \\"server1.conn13.child1/37\\", - \\"url\\": \\"https://davidwalsh.name/source1.js\\", - \\"isBlackBoxed\\": false, - \\"isPrettyPrinted\\": false, - \\"relativeUrl\\": \\"https://davidwalsh.name/source1.js\\", - \\"introductionUrl\\": null, - \\"isWasm\\": false, - \\"isExtension\\": false - } + \\"type\\": \\"directory\\", + \\"name\\": \\"davidwalsh.name\\", + \\"path\\": \\"FakeThread/davidwalsh.name\\", + \\"contents\\": [ + { + \\"type\\": \\"source\\", + \\"name\\": \\"(index)\\", + \\"path\\": \\"https://davidwalsh.name/\\", + \\"contents\\": { + \\"id\\": \\"server1.conn13.child1/39\\", + \\"url\\": \\"https://davidwalsh.name/\\", + \\"isBlackBoxed\\": false, + \\"isPrettyPrinted\\": false, + \\"relativeUrl\\": \\"https://davidwalsh.name/\\", + \\"introductionUrl\\": null, + \\"isWasm\\": false, + \\"isExtension\\": false + } + }, + { + \\"type\\": \\"source\\", + \\"name\\": \\"source1.js\\", + \\"path\\": \\"FakeThread/davidwalsh.name/source1.js\\", + \\"contents\\": { + \\"id\\": \\"server1.conn13.child1/37\\", + \\"url\\": \\"https://davidwalsh.name/source1.js\\", + \\"isBlackBoxed\\": false, + \\"isPrettyPrinted\\": false, + \\"relativeUrl\\": \\"https://davidwalsh.name/source1.js\\", + \\"introductionUrl\\": null, + \\"isWasm\\": false, + \\"isExtension\\": false + } + } + ] } ] } @@ -55,53 +62,60 @@ exports[`calls updateTree.js adds two sources 1`] = ` \\"contents\\": [ { \\"type\\": \\"directory\\", - \\"name\\": \\"davidwalsh.name\\", - \\"path\\": \\"davidwalsh.name\\", + \\"name\\": \\"FakeThread\\", + \\"path\\": \\"FakeThread\\", \\"contents\\": [ { - \\"type\\": \\"source\\", - \\"name\\": \\"(index)\\", - \\"path\\": \\"https://davidwalsh.name/\\", - \\"contents\\": { - \\"id\\": \\"server1.conn13.child1/39\\", - \\"url\\": \\"https://davidwalsh.name/\\", - \\"isBlackBoxed\\": false, - \\"isPrettyPrinted\\": false, - \\"relativeUrl\\": \\"https://davidwalsh.name/\\", - \\"introductionUrl\\": null, - \\"isWasm\\": false, - \\"isExtension\\": false - } - }, - { - \\"type\\": \\"source\\", - \\"name\\": \\"source1.js\\", - \\"path\\": \\"davidwalsh.name/source1.js\\", - \\"contents\\": { - \\"id\\": \\"server1.conn13.child1/37\\", - \\"url\\": \\"https://davidwalsh.name/source1.js\\", - \\"isBlackBoxed\\": false, - \\"isPrettyPrinted\\": false, - \\"relativeUrl\\": \\"https://davidwalsh.name/source1.js\\", - \\"introductionUrl\\": null, - \\"isWasm\\": false, - \\"isExtension\\": false - } - }, - { - \\"type\\": \\"source\\", - \\"name\\": \\"source2.js\\", - \\"path\\": \\"davidwalsh.name/source2.js\\", - \\"contents\\": { - \\"id\\": \\"server1.conn13.child1/40\\", - \\"url\\": \\"https://davidwalsh.name/source2.js\\", - \\"isBlackBoxed\\": false, - \\"isPrettyPrinted\\": false, - \\"relativeUrl\\": \\"https://davidwalsh.name/source2.js\\", - \\"introductionUrl\\": null, - \\"isWasm\\": false, - \\"isExtension\\": false - } + \\"type\\": \\"directory\\", + \\"name\\": \\"davidwalsh.name\\", + \\"path\\": \\"FakeThread/davidwalsh.name\\", + \\"contents\\": [ + { + \\"type\\": \\"source\\", + \\"name\\": \\"(index)\\", + \\"path\\": \\"https://davidwalsh.name/\\", + \\"contents\\": { + \\"id\\": \\"server1.conn13.child1/39\\", + \\"url\\": \\"https://davidwalsh.name/\\", + \\"isBlackBoxed\\": false, + \\"isPrettyPrinted\\": false, + \\"relativeUrl\\": \\"https://davidwalsh.name/\\", + \\"introductionUrl\\": null, + \\"isWasm\\": false, + \\"isExtension\\": false + } + }, + { + \\"type\\": \\"source\\", + \\"name\\": \\"source1.js\\", + \\"path\\": \\"FakeThread/davidwalsh.name/source1.js\\", + \\"contents\\": { + \\"id\\": \\"server1.conn13.child1/37\\", + \\"url\\": \\"https://davidwalsh.name/source1.js\\", + \\"isBlackBoxed\\": false, + \\"isPrettyPrinted\\": false, + \\"relativeUrl\\": \\"https://davidwalsh.name/source1.js\\", + \\"introductionUrl\\": null, + \\"isWasm\\": false, + \\"isExtension\\": false + } + }, + { + \\"type\\": \\"source\\", + \\"name\\": \\"source2.js\\", + \\"path\\": \\"FakeThread/davidwalsh.name/source2.js\\", + \\"contents\\": { + \\"id\\": \\"server1.conn13.child1/40\\", + \\"url\\": \\"https://davidwalsh.name/source2.js\\", + \\"isBlackBoxed\\": false, + \\"isPrettyPrinted\\": false, + \\"relativeUrl\\": \\"https://davidwalsh.name/source2.js\\", + \\"introductionUrl\\": null, + \\"isWasm\\": false, + \\"isExtension\\": false + } + } + ] } ] } @@ -117,38 +131,30 @@ exports[`calls updateTree.js shows all the sources 1`] = ` \\"contents\\": [ { \\"type\\": \\"directory\\", - \\"name\\": \\"davidwalsh.name\\", - \\"path\\": \\"davidwalsh.name\\", + \\"name\\": \\"FakeThread\\", + \\"path\\": \\"FakeThread\\", \\"contents\\": [ { - \\"type\\": \\"source\\", - \\"name\\": \\"(index)\\", - \\"path\\": \\"https://davidwalsh.name/\\", - \\"contents\\": { - \\"id\\": \\"server1.conn13.child1/39\\", - \\"url\\": \\"https://davidwalsh.name/\\", - \\"isBlackBoxed\\": false, - \\"isPrettyPrinted\\": false, - \\"relativeUrl\\": \\"https://davidwalsh.name/\\", - \\"introductionUrl\\": null, - \\"isWasm\\": false, - \\"isExtension\\": false - } - }, - { - \\"type\\": \\"source\\", - \\"name\\": \\"source1.js\\", - \\"path\\": \\"davidwalsh.name/source1.js\\", - \\"contents\\": { - \\"id\\": \\"server1.conn13.child1/37\\", - \\"url\\": \\"https://davidwalsh.name/source1.js\\", - \\"isBlackBoxed\\": false, - \\"isPrettyPrinted\\": false, - \\"relativeUrl\\": \\"https://davidwalsh.name/source1.js\\", - \\"introductionUrl\\": null, - \\"isWasm\\": false, - \\"isExtension\\": false - } + \\"type\\": \\"directory\\", + \\"name\\": \\"davidwalsh.name\\", + \\"path\\": \\"FakeThread/davidwalsh.name\\", + \\"contents\\": [ + { + \\"type\\": \\"source\\", + \\"name\\": \\"(index)\\", + \\"path\\": \\"https://davidwalsh.name/\\", + \\"contents\\": { + \\"id\\": \\"server1.conn13.child1/39\\", + \\"url\\": \\"https://davidwalsh.name/\\", + \\"isBlackBoxed\\": false, + \\"isPrettyPrinted\\": false, + \\"relativeUrl\\": \\"https://davidwalsh.name/\\", + \\"introductionUrl\\": null, + \\"isWasm\\": false, + \\"isExtension\\": false + } + } + ] } ] } diff --git a/devtools/client/debugger/src/utils/sources-tree/tests/addToTree.spec.js b/devtools/client/debugger/src/utils/sources-tree/tests/addToTree.spec.js index 37daf84da674..ea5cccb41f90 100644 --- a/devtools/client/debugger/src/utils/sources-tree/tests/addToTree.spec.js +++ b/devtools/client/debugger/src/utils/sources-tree/tests/addToTree.spec.js @@ -17,7 +17,7 @@ import { nodeHasChildren } from "../index"; -type RawSource = {| url: string, id: string |}; +type RawSource = {| url: string, id: string, actors?: any |}; function createSourcesMap(sources: RawSource[]) { const sourcesMap = sources.reduce((map, source) => { @@ -63,10 +63,10 @@ describe("sources-tree", () => { ); const tree = createDirectoryNode("root", "", []); - addToTree(tree, source1, "http://example.com/"); + addToTree(tree, source1, "http://example.com/", "FakeThread"); expect(tree.contents).toHaveLength(1); - const base = tree.contents[0]; + const base = tree.contents[0].contents[0]; expect(base.name).toBe("example.com"); expect(base.contents).toHaveLength(1); @@ -89,8 +89,8 @@ describe("sources-tree", () => { const tree = createDirectoryNode("root", "", []); - addToTree(tree, source1, "http://example.com/"); - const childNode = getChildNode(tree, 0, 0, 0); + addToTree(tree, source1, "http://example.com/", "FakeThread"); + const childNode = getChildNode(tree, 0, 0, 0, 0); expect(childNode.name).toEqual(sourceName); expect(formatTree(tree)).toMatchSnapshot(); }); @@ -105,7 +105,7 @@ describe("sources-tree", () => { const tree = createDirectoryNode("root", "", []); - addToTree(tree, source1, "http://example.com/"); + addToTree(tree, source1, "http://example.com/", "FakeThread"); expect(formatTree(tree)).toMatchSnapshot(); }); @@ -121,14 +121,22 @@ describe("sources-tree", () => { } ]; - const sourceMap = createSourcesMap(sources); + const sourceMap = { FakeThread: createSourcesMap(sources) }; const tree = createTree({ sources: sourceMap, debuggeeUrl: "", - projectRoot: "" + threads: [ + { + actor: "FakeThread", + name: "FakeThread", + url: "https://davidwalsh.name", + type: 1 + } + ] }).sourceTree; - // expect(tree.contents).toHaveLength(1); - const subtree = tree.contents[0]; + + expect(tree.contents[0].contents).toHaveLength(1); + const subtree = tree.contents[0].contents[0]; expect(subtree.contents).toHaveLength(2); expect(formatTree(tree)).toMatchSnapshot(); }); @@ -141,11 +149,18 @@ describe("sources-tree", () => { } ]; - const sourceMap = createSourcesMap(sources); + const sourceMap = { FakeThread: createSourcesMap(sources) }; const tree = createTree({ sources: sourceMap, debuggeeUrl: "", - projectRoot: "" + threads: [ + { + actor: "FakeThread", + url: "https://davidwalsh.name", + type: 1, + name: "FakeThread" + } + ] }).sourceTree; expect(formatTree(tree)).toMatchSnapshot(); }); @@ -158,19 +173,39 @@ describe("sources-tree", () => { }, { id: "server1.conn13.child1/37", - url: "https://davidwalsh.name/" + url: "https://davidwalsh.name/util.js" } ]; - const sourceMap = createSourcesMap(sources); + const sourceMap = { + FakeThread: createSourcesMap(sources), + FakeThread2: createSourcesMap([sources[1]]) + }; + const tree = createTree({ sources: sourceMap, - debuggeeUrl: "", - projectRoot: "" + debuggeeUrl: "https://davidwalsh.name", + threads: [ + { + actor: "FakeThread", + name: "FakeThread", + url: "https://davidwalsh.name", + type: 1 + }, + { + actor: "FakeThread2", + name: "FakeThread2", + url: "https://davidwalsh.name/WorkerA.js", + type: 2 + } + ] }).sourceTree; - expect(tree.contents).toHaveLength(1); - const subtree = tree.contents[0]; - expect(subtree.contents).toHaveLength(1); + + expect(tree.contents[0].contents).toHaveLength(1); + const subtree = tree.contents[0].contents[0]; + expect(subtree.contents).toHaveLength(2); + const subtree2 = tree.contents[1].contents[0]; + expect(subtree2.contents).toHaveLength(1); expect(formatTree(tree)).toMatchSnapshot(); }); @@ -186,11 +221,11 @@ describe("sources-tree", () => { ); const tree = createDirectoryNode("root", "", []); - addToTree(tree, source1, "http://example.com/"); - addToTree(tree, source2, "http://example.com/"); - addToTree(tree, source3, "http://example.com/"); + addToTree(tree, source1, "http://example.com/", "FakeThread"); + addToTree(tree, source2, "http://example.com/", "FakeThread"); + addToTree(tree, source3, "http://example.com/", "FakeThread"); - const base = tree.contents[0]; + const base = tree.contents[0].contents[0]; expect(tree.contents).toHaveLength(1); const source1Node = base.contents[0]; @@ -202,10 +237,10 @@ describe("sources-tree", () => { const source = makeMockSource("file:///a/b.js", "actor1"); const tree = createDirectoryNode("root", "", []); - addToTree(tree, source, "file:///a/index.html"); + addToTree(tree, source, "file:///a/index.html", "FakeThread"); expect(tree.contents).toHaveLength(1); - const base = tree.contents[0]; + const base = tree.contents[0].contents[0]; expect(base.name).toBe("file://"); expect(base.contents).toHaveLength(1); @@ -232,7 +267,9 @@ describe("sources-tree", () => { const sources = createSourcesList(testData); const tree = createDirectoryNode("root", "", []); - sources.forEach(source => addToTree(tree, source, "https://unpkg.com/")); + sources.forEach(source => + addToTree(tree, source, "https://unpkg.com/", "FakeThread") + ); expect(formatTree(tree)).toMatchSnapshot(); }); @@ -251,7 +288,9 @@ describe("sources-tree", () => { const sources = createSourcesList(testData); const tree = createDirectoryNode("root", "", []); - sources.forEach(source => addToTree(tree, source, "https://unpkg.com/")); + sources.forEach(source => + addToTree(tree, source, "https://unpkg.com/", "FakeThread") + ); expect(formatTree(tree)).toMatchSnapshot(); }); @@ -284,7 +323,7 @@ describe("sources-tree", () => { const domain = "http://localhost:4242"; const sources = createSourcesList(testData); const tree = createDirectoryNode("root", "", []); - sources.forEach(source => addToTree(tree, source, domain)); + sources.forEach(source => addToTree(tree, source, domain, "FakeThread")); expect(formatTree(tree)).toMatchSnapshot(); }); }); diff --git a/devtools/client/debugger/src/utils/sources-tree/tests/collapseTree.spec.js b/devtools/client/debugger/src/utils/sources-tree/tests/collapseTree.spec.js index 5a9dbcf3e285..ad7dce2985a3 100644 --- a/devtools/client/debugger/src/utils/sources-tree/tests/collapseTree.spec.js +++ b/devtools/client/debugger/src/utils/sources-tree/tests/collapseTree.spec.js @@ -8,7 +8,6 @@ import { makeMockSource } from "../../../utils/test-mockup"; import { collapseTree, - sortEntireTree, formatTree, addToTree, createDirectoryNode @@ -22,11 +21,11 @@ describe("sources tree", () => { describe("collapseTree", () => { it("can collapse a single source", () => { const fullTree = createDirectoryNode("root", "", []); - addToTree(fullTree, abcSource, "http://example.com/"); + addToTree(fullTree, abcSource, "http://example.com/", "Main Thread"); expect(fullTree.contents).toHaveLength(1); const tree = collapseTree(fullTree); - const host = tree.contents[0]; + const host = tree.contents[0].contents[0]; expect(host.name).toBe("example.com"); expect(host.contents).toHaveLength(1); @@ -36,20 +35,17 @@ describe("sources tree", () => { const abcNode = abFolder.contents[0]; expect(abcNode.name).toBe("c.js"); - expect(abcNode.path).toBe("example.com/a/b/c.js"); + expect(abcNode.path).toBe("Main Thread/example.com/a/b/c.js"); expect(formatTree(tree)).toMatchSnapshot(); }); it("correctly merges in a collapsed source with a deeper level", () => { const fullTree = createDirectoryNode("root", "", []); - addToTree(fullTree, abcSource, "http://example.com/"); - addToTree(fullTree, abcdeSource, "http://example.com/"); + addToTree(fullTree, abcSource, "http://example.com/", "Main Thread"); + addToTree(fullTree, abcdeSource, "http://example.com/", "Main Thread"); const tree = collapseTree(fullTree); - sortEntireTree(tree); - expect(tree.contents).toHaveLength(1); - - const host = tree.contents[0]; + const host = tree.contents[0].contents[0]; expect(host.name).toBe("example.com"); expect(host.contents).toHaveLength(1); @@ -59,24 +55,24 @@ describe("sources tree", () => { const [cdFolder, abcNode] = abFolder.contents; expect(abcNode.name).toBe("c.js"); - expect(abcNode.path).toBe("example.com/a/b/c.js"); + expect(abcNode.path).toBe("Main Thread/example.com/a/b/c.js"); expect(cdFolder.name).toBe("c/d"); const [abcdeNode] = cdFolder.contents; expect(abcdeNode.name).toBe("e.js"); - expect(abcdeNode.path).toBe("example.com/a/b/c/d/e.js"); + expect(abcdeNode.path).toBe("Main Thread/example.com/a/b/c/d/e.js"); expect(formatTree(tree)).toMatchSnapshot(); }); it("correctly merges in a collapsed source with a shallower level", () => { const fullTree = createDirectoryNode("root", "", []); - addToTree(fullTree, abcSource, "http://example.com/"); - addToTree(fullTree, abxSource, "http://example.com/"); + addToTree(fullTree, abcSource, "http://example.com/", "Main Thread"); + addToTree(fullTree, abxSource, "http://example.com/", "Main Thread"); const tree = collapseTree(fullTree); expect(tree.contents).toHaveLength(1); - const host = tree.contents[0]; + const host = tree.contents[0].contents[0]; expect(host.name).toBe("example.com"); expect(host.contents).toHaveLength(1); @@ -86,21 +82,21 @@ describe("sources tree", () => { const [abcNode, abxNode] = abFolder.contents; expect(abcNode.name).toBe("c.js"); - expect(abcNode.path).toBe("example.com/a/b/c.js"); + expect(abcNode.path).toBe("Main Thread/example.com/a/b/c.js"); expect(abxNode.name).toBe("x.js"); - expect(abxNode.path).toBe("example.com/a/b/x.js"); + expect(abxNode.path).toBe("Main Thread/example.com/a/b/x.js"); expect(formatTree(tree)).toMatchSnapshot(); }); it("correctly merges in a collapsed source with the same level", () => { const fullTree = createDirectoryNode("root", "", []); - addToTree(fullTree, abcdeSource, "http://example.com/"); - addToTree(fullTree, abcSource, "http://example.com/"); + addToTree(fullTree, abcdeSource, "http://example.com/", "Main Thread"); + addToTree(fullTree, abcSource, "http://example.com/", "Main Thread"); const tree = collapseTree(fullTree); expect(tree.contents).toHaveLength(1); - const host = tree.contents[0]; + const host = tree.contents[0].contents[0]; expect(host.name).toBe("example.com"); expect(host.contents).toHaveLength(1); @@ -110,12 +106,12 @@ describe("sources tree", () => { const [cdFolder, abcNode] = abFolder.contents; expect(abcNode.name).toBe("c.js"); - expect(abcNode.path).toBe("example.com/a/b/c.js"); + expect(abcNode.path).toBe("Main Thread/example.com/a/b/c.js"); expect(cdFolder.name).toBe("c/d"); const [abcdeNode] = cdFolder.contents; expect(abcdeNode.name).toBe("e.js"); - expect(abcdeNode.path).toBe("example.com/a/b/c/d/e.js"); + expect(abcdeNode.path).toBe("Main Thread/example.com/a/b/c/d/e.js"); expect(formatTree(tree)).toMatchSnapshot(); }); }); diff --git a/devtools/client/debugger/src/utils/sources-tree/tests/getDirectories.spec.js b/devtools/client/debugger/src/utils/sources-tree/tests/getDirectories.spec.js index ccc499eae2ee..c3c472fe42d1 100644 --- a/devtools/client/debugger/src/utils/sources-tree/tests/getDirectories.spec.js +++ b/devtools/client/debugger/src/utils/sources-tree/tests/getDirectories.spec.js @@ -14,11 +14,13 @@ function formatDirectories(source, tree) { } function createSources(urls) { - return urls.reduce((sources, url, index) => { - const id = `a${index}`; - sources[id] = makeMockSource(url, id); - return sources; - }, {}); + return { + FakeThread: urls.reduce((sources, url, index) => { + const id = `a${index}`; + sources[id] = makeMockSource(url, id); + return sources; + }, {}) + }; } describe("getDirectories", () => { @@ -29,14 +31,36 @@ describe("getDirectories", () => { "http://b/c.js" ]); + const threads = [ + { + actor: "FakeThread", + url: "http://a", + type: 1, + name: "FakeThread" + } + ]; + const debuggeeUrl = "http://a/"; const { sourceTree } = createTree({ sources, debuggeeUrl, - projectRoot: "" + threads }); - expect(formatDirectories(sources.a0, sourceTree)).toEqual(["a/b.js", "a"]); - expect(formatDirectories(sources.a1, sourceTree)).toEqual(["a/c.js", "a"]); - expect(formatDirectories(sources.a2, sourceTree)).toEqual(["b/c.js", "b"]); + + expect(formatDirectories(sources.FakeThread.a0, sourceTree)).toEqual([ + "FakeThread/a/b.js", + "FakeThread/a", + "FakeThread" + ]); + expect(formatDirectories(sources.FakeThread.a1, sourceTree)).toEqual([ + "FakeThread/a/c.js", + "FakeThread/a", + "FakeThread" + ]); + expect(formatDirectories(sources.FakeThread.a2, sourceTree)).toEqual([ + "FakeThread/b/c.js", + "FakeThread/b", + "FakeThread" + ]); }); }); diff --git a/devtools/client/debugger/src/utils/sources-tree/tests/sortTree.spec.js b/devtools/client/debugger/src/utils/sources-tree/tests/sortTree.spec.js deleted file mode 100644 index 99cf1c5970e6..000000000000 --- a/devtools/client/debugger/src/utils/sources-tree/tests/sortTree.spec.js +++ /dev/null @@ -1,153 +0,0 @@ -/* eslint max-nested-callbacks: ["error", 4]*/ -/* 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 . */ - -// @flow - -import { makeMockSource } from "../../../utils/test-mockup"; - -import { - addToTree, - sortEntireTree, - createDirectoryNode, - formatTree -} from "../index"; - -describe("sources-tree", () => { - describe("sortEntireTree", () => { - it("alphabetically sorts children", () => { - const source1 = makeMockSource("http://example.com/source1.js", "actor1"); - const source2 = makeMockSource( - "http://example.com/foo/b_source2.js", - "actor2" - ); - const source3 = makeMockSource( - "http://example.com/foo/a_source3.js", - "actor3" - ); - const _tree = createDirectoryNode("root", "", []); - - addToTree(_tree, source1, "http://example.com/"); - addToTree(_tree, source2, "http://example.com/"); - addToTree(_tree, source3, "http://example.com/"); - const tree = sortEntireTree(_tree); - - const base = tree.contents[0]; - const fooNode = base.contents[0]; - expect(fooNode.name).toBe("foo"); - expect(fooNode.contents).toHaveLength(2); - - const source1Node = base.contents[1]; - expect(source1Node.name).toBe("source1.js"); - - // source2 should be after source1 alphabetically - const source2Node = fooNode.contents[1]; - const source3Node = fooNode.contents[0]; - expect(source2Node.name).toBe("b_source2.js"); - expect(source3Node.name).toBe("a_source3.js"); - expect(formatTree(tree)).toMatchSnapshot(); - }); - - it("sorts folders first", () => { - const sources = [ - makeMockSource("http://example.com/a.js", "actor1"), - makeMockSource("http://example.com/b.js/b_source.js", "actor2"), - makeMockSource("http://example.com/c.js", "actor3"), - makeMockSource("http://example.com", "actor4"), - makeMockSource("http://example.com/d/d_source.js", "actor5"), - makeMockSource("http://example.com/b2", "actor6") - ]; - - const _tree = createDirectoryNode("root", "", []); - sources.forEach(source => - addToTree(_tree, source, "http://example.com/") - ); - const tree = sortEntireTree(_tree); - const domain = tree.contents[0]; - - const [ - indexNode, - bFolderNode, - dFolderNode, - aFileNode, - b2FileNode, - cFileNode - ] = domain.contents; - - expect(formatTree(tree)).toMatchSnapshot(); - expect(indexNode.name).toBe("(index)"); - expect(bFolderNode.name).toBe("b.js"); - expect(bFolderNode.contents).toHaveLength(1); - expect(bFolderNode.contents[0].name).toBe("b_source.js"); - - expect(b2FileNode.name).toBe("b2"); - - expect(dFolderNode.name).toBe("d"); - expect(dFolderNode.contents).toHaveLength(1); - expect(dFolderNode.contents[0].name).toBe("d_source.js"); - - expect(aFileNode.name).toBe("a.js"); - - expect(cFileNode.name).toBe("c.js"); - expect(formatTree(tree)).toMatchSnapshot(); - }); - - it("puts folder at the top of the sort", () => { - const sources = [ - makeMockSource("http://example.com/folder/a.js", "actor1"), - makeMockSource("http://example.com/folder/b/b.js", "actor2"), - makeMockSource("http://example.com/folder/c/", "actor3") - ]; - - const _tree = createDirectoryNode("root", "", []); - sources.forEach(source => - addToTree(_tree, source, "http://example.com/") - ); - const tree = sortEntireTree(_tree); - const [ - bFolderNode, - cFolderNode, - aFileNode - ] = tree.contents[0].contents[0].contents; - - expect(bFolderNode.name).toBe("b"); - expect(bFolderNode.contents).toHaveLength(1); - expect(bFolderNode.contents[0].name).toBe("b.js"); - - expect(cFolderNode.name).toBe("c"); - expect(cFolderNode.contents).toHaveLength(1); - expect(cFolderNode.contents[0].name).toBe("(index)"); - - expect(aFileNode.name).toBe("a.js"); - expect(formatTree(tree)).toMatchSnapshot(); - }); - - it("puts root debugee url at the top of the sort", () => { - const sources = [ - makeMockSource("http://api.example.com/a.js", "actor1"), - makeMockSource("http://example.com/b.js", "actor2"), - makeMockSource("http://demo.com/c.js", "actor3") - ]; - - const rootA = "http://example.com/path/to/file.html"; - const rootB = "https://www.demo.com/index.html"; - const _treeA = createDirectoryNode("root", "", []); - const _treeB = createDirectoryNode("root", "", []); - sources.forEach(source => { - addToTree(_treeA, source, rootA); - addToTree(_treeB, source, rootB); - }); - const treeA = sortEntireTree(_treeA, rootA); - const treeB = sortEntireTree(_treeB, rootB); - - expect(treeA.contents[0].contents[0].name).toBe("b.js"); - expect(treeA.contents[1].contents[0].name).toBe("a.js"); - - expect(treeB.contents[0].contents[0].name).toBe("c.js"); - expect(treeB.contents[1].contents[0].name).toBe("a.js"); - expect(formatTree(treeA)).toMatchSnapshot(); - expect(formatTree(treeB)).toMatchSnapshot(); - }); - }); -}); diff --git a/devtools/client/debugger/src/utils/sources-tree/tests/updateTree.spec.js b/devtools/client/debugger/src/utils/sources-tree/tests/updateTree.spec.js index bd09adcac8f5..386b177fc866 100644 --- a/devtools/client/debugger/src/utils/sources-tree/tests/updateTree.spec.js +++ b/devtools/client/debugger/src/utils/sources-tree/tests/updateTree.spec.js @@ -7,7 +7,7 @@ import { makeMockSource } from "../../../utils/test-mockup"; import { updateTree, createTree } from "../index"; -type RawSource = {| url: string, id: string |}; +type RawSource = {| url: string, id: string, actors?: any |}; function createSourcesMap(sources: RawSource[]) { const sourcesMap = sources.reduce((map, source) => { @@ -15,7 +15,7 @@ function createSourcesMap(sources: RawSource[]) { return map; }, {}); - return sourcesMap; + return { FakeThread: sourcesMap }; } function formatTree(tree) { @@ -37,25 +37,32 @@ const sources = [ } ]; +const threads = [ + { + actor: "FakeThread", + url: "https://davidwalsh.name", + type: 1, + name: "FakeThread" + } +]; + const debuggeeUrl = "blah"; describe("calls updateTree.js", () => { it("adds one source", () => { const prevSources = createSourcesMap([sources[0]]); - const { sourceTree, uncollapsedTree } = createTree({ debuggeeUrl, sources: prevSources, - projectRoot: "" + threads }); - const newTree = updateTree({ debuggeeUrl, prevSources, newSources: createSourcesMap([sources[0], sources[1]]), uncollapsedTree, sourceTree, - projectRoot: "" + threads }); expect(formatTree(newTree)).toMatchSnapshot(); @@ -67,7 +74,7 @@ describe("calls updateTree.js", () => { const { sourceTree, uncollapsedTree } = createTree({ debuggeeUrl, sources: prevSources, - projectRoot: "" + threads }); const newTree = updateTree({ @@ -76,7 +83,8 @@ describe("calls updateTree.js", () => { newSources: createSourcesMap([sources[0], sources[1], sources[2]]), uncollapsedTree, sourceTree, - projectRoot: "" + projectRoot: "", + threads }); expect(formatTree(newTree)).toMatchSnapshot(); @@ -90,7 +98,7 @@ describe("calls updateTree.js", () => { const { sourceTree, uncollapsedTree } = createTree({ debuggeeUrl, sources: prevSources, - projectRoot: "" + threads }); const newTree = updateTree({ @@ -99,7 +107,8 @@ describe("calls updateTree.js", () => { newSources: createSourcesMap([sources[1]]), uncollapsedTree, sourceTree, - projectRoot: "" + projectRoot: "", + threads }); expect(formatTree(newTree)).toMatchSnapshot(); diff --git a/devtools/client/debugger/src/utils/sources-tree/tests/utils.spec.js b/devtools/client/debugger/src/utils/sources-tree/tests/utils.spec.js index 4169d922a6c1..a6e6129e781d 100644 --- a/devtools/client/debugger/src/utils/sources-tree/tests/utils.spec.js +++ b/devtools/client/debugger/src/utils/sources-tree/tests/utils.spec.js @@ -13,7 +13,6 @@ import { isExactUrlMatch, isDirectory, addToTree, - sortEntireTree, isNotJavaScript } from "../index"; @@ -47,9 +46,10 @@ describe("sources tree", () => { ]; const tree = createDirectoryNode("root", "", []); - sources.forEach(source => addToTree(tree, source, "http://example.com/")); - sortEntireTree(tree); - const [bFolderNode, aFileNode] = tree.contents[0].contents; + sources.forEach(source => + addToTree(tree, source, "http://example.com/", "Main Thread") + ); + const [bFolderNode, aFileNode] = tree.contents[0].contents[0].contents; const [cFolderNode] = bFolderNode.contents; const [dFileNode] = cFolderNode.contents; diff --git a/devtools/client/debugger/src/utils/sources-tree/updateTree.js b/devtools/client/debugger/src/utils/sources-tree/updateTree.js index c211ad038fa2..1085abdccd08 100644 --- a/devtools/client/debugger/src/utils/sources-tree/updateTree.js +++ b/devtools/client/debugger/src/utils/sources-tree/updateTree.js @@ -6,42 +6,82 @@ import { addToTree } from "./addToTree"; import { collapseTree } from "./collapseTree"; -import { createParentMap } from "./utils"; -import { difference } from "lodash"; +import { createDirectoryNode, createParentMap } from "./utils"; import { getDomain } from "./treeOrder"; -import type { SourcesMap } from "../../reducers/types"; + +import type { SourcesMapByThread } from "../../reducers/types"; +import type { Thread, Source } from "../../types"; import type { TreeDirectory } from "./types"; -function newSourcesSet(newSources, prevSources) { - const newSourceIds = difference( - Object.keys(newSources), - Object.keys(prevSources) - ); - const uniqSources = newSourceIds.map(id => newSources[id]); - return uniqSources; +function getSourcesToAdd(newSources, prevSources): Source[] { + const sourcesToAdd = []; + + for (const sourceId in newSources) { + const newSource = newSources[sourceId]; + const prevSource = prevSources ? prevSources[sourceId] : null; + if (!prevSource) { + sourcesToAdd.push(newSource); + } + } + + return sourcesToAdd; } -type Params = { - newSources: SourcesMap, - prevSources: SourcesMap, +type UpdateTreeParams = { + newSources: SourcesMapByThread, + prevSources: SourcesMapByThread, uncollapsedTree: TreeDirectory, - sourceTree: TreeDirectory, - debuggeeUrl: string + debuggeeUrl: string, + threads: Thread[] }; +type CreateTreeParams = { + sources: SourcesMapByThread, + debuggeeUrl: string, + threads: Thread[] +}; + +export function createTree({ + debuggeeUrl, + sources, + threads +}: CreateTreeParams) { + const uncollapsedTree = createDirectoryNode("root", "", []); + + return updateTree({ + debuggeeUrl, + newSources: sources, + prevSources: {}, + threads, + uncollapsedTree + }); +} + export function updateTree({ newSources, prevSources, debuggeeUrl, uncollapsedTree, - sourceTree -}: Params) { - const newSet = newSourcesSet(newSources, prevSources); + threads +}: UpdateTreeParams) { const debuggeeHost = getDomain(debuggeeUrl); + const contexts = (Object.keys(newSources): any); - for (const source of newSet) { - addToTree(uncollapsedTree, source, debuggeeHost); - } + contexts.forEach(context => { + const thread = threads.find(t => t.actor === context); + if (!thread) { + return; + } + + const sourcesToAdd = getSourcesToAdd( + (Object.values(newSources[context]): any), + prevSources[context] ? (Object.values(prevSources[context]): any) : null + ); + + for (const source of sourcesToAdd) { + addToTree(uncollapsedTree, source, debuggeeHost, thread.actor); + } + }); const newSourceTree = collapseTree(uncollapsedTree); diff --git a/devtools/client/debugger/src/utils/sources-tree/utils.js b/devtools/client/debugger/src/utils/sources-tree/utils.js index d032a1bd8c89..4cf3dbe47e23 100644 --- a/devtools/client/debugger/src/utils/sources-tree/utils.js +++ b/devtools/client/debugger/src/utils/sources-tree/utils.js @@ -13,7 +13,7 @@ import { getURL } from "./getURL"; const IGNORED_URLS = ["debugger eval code", "XStringBundle"]; export function nodeHasChildren(item: TreeNode): boolean { - return Array.isArray(item.contents) && item.type === "directory"; + return Array.isArray(item.contents) && item.type == "directory"; } export function isExactUrlMatch(pathPart: string, debuggeeUrl: string) { diff --git a/devtools/client/debugger/test/mochitest/browser_dbg-asm.js b/devtools/client/debugger/test/mochitest/browser_dbg-asm.js index 84308de6f930..751710e75ebc 100644 --- a/devtools/client/debugger/test/mochitest/browser_dbg-asm.js +++ b/devtools/client/debugger/test/mochitest/browser_dbg-asm.js @@ -10,7 +10,7 @@ add_task(async function() { await waitForSources(dbg, "doc-asm.html", "asm.js"); // Make sure sources appear. - is(findAllElements(dbg, "sourceNodes").length, 2); + is(findAllElements(dbg, "sourceNodes").length, 3); await selectSource(dbg, "asm.js"); diff --git a/devtools/client/debugger/test/mochitest/browser_dbg-content-script-sources.js b/devtools/client/debugger/test/mochitest/browser_dbg-content-script-sources.js index df5d8fc3b680..23bf2d0ecfb6 100644 --- a/devtools/client/debugger/test/mochitest/browser_dbg-content-script-sources.js +++ b/devtools/client/debugger/test/mochitest/browser_dbg-content-script-sources.js @@ -49,6 +49,9 @@ add_task(async function() { const extension = await installAndStartExtension(); let dbg = await initDebugger("doc-content-script-sources.html"); + await clickElement(dbg, "sourceDirectoryLabel", 2); + + await selectContentScriptSources(dbg); await closeTab(dbg, "content_script.js"); @@ -57,6 +60,9 @@ add_task(async function() { await dbg.toolbox.destroy(); const toolbox = await openToolboxForTab(gBrowser.selectedTab, "jsdebugger"); dbg = createDebuggerContext(toolbox); + + await clickElement(dbg, "sourceDirectoryLabel", 2); + await selectContentScriptSources(dbg); await addBreakpoint(dbg, "content_script.js", 2); diff --git a/devtools/client/debugger/test/mochitest/browser_dbg-sourcemaps.js b/devtools/client/debugger/test/mochitest/browser_dbg-sourcemaps.js index 3acb76d39285..5aa9c8b41a3b 100644 --- a/devtools/client/debugger/test/mochitest/browser_dbg-sourcemaps.js +++ b/devtools/client/debugger/test/mochitest/browser_dbg-sourcemaps.js @@ -66,8 +66,8 @@ add_task(async function() { const bundleSrc = findSource(dbg, "bundle.js"); // Check that the original sources appear in the source tree - await clickElement(dbg, "sourceDirectoryLabel", 3); - await assertSourceCount(dbg, 8); + await clickElement(dbg, "sourceDirectoryLabel", 4); + await assertSourceCount(dbg, 9); await selectSource(dbg, bundleSrc); diff --git a/devtools/client/debugger/test/mochitest/browser_dbg-sources-arrow-keys.js b/devtools/client/debugger/test/mochitest/browser_dbg-sources-arrow-keys.js index 286e618f191a..2f3decdab5dc 100644 --- a/devtools/client/debugger/test/mochitest/browser_dbg-sources-arrow-keys.js +++ b/devtools/client/debugger/test/mochitest/browser_dbg-sources-arrow-keys.js @@ -5,8 +5,8 @@ add_task(async function() { const dbg = await initDebugger("doc-sources.html", "simple1", "simple2", "nested-source", "long.js"); - await clickElement(dbg, "sourceDirectoryLabel", 2); - await assertSourceCount(dbg, 7); + await clickElement(dbg, "sourceDirectoryLabel", 3); + await assertSourceCount(dbg, 8); // Right key on open dir await pressKey(dbg, "Right"); @@ -15,12 +15,12 @@ add_task(async function() { // Right key on closed dir await pressKey(dbg, "Right"); await assertSourceCount(dbg, 8); - await assertNodeIsFocused(dbg, 3); + await assertNodeIsFocused(dbg, 4); // Left key on a open dir await pressKey(dbg, "Left"); - await assertSourceCount(dbg, 7); - await assertNodeIsFocused(dbg, 3); + await assertSourceCount(dbg, 8); + await assertNodeIsFocused(dbg, 4); // Down key on a closed dir await pressKey(dbg, "Down"); @@ -28,32 +28,33 @@ add_task(async function() { // Right key on a source await pressKey(dbg, "Right"); - await assertNodeIsFocused(dbg, 5); + await assertNodeIsFocused(dbg, 4); // Down key on a source + await waitForSourceCount(dbg, 9); await pressKey(dbg, "Down"); - await assertNodeIsFocused(dbg, 6); + await assertNodeIsFocused(dbg, 5); // Go to bottom of tree and press down key await pressKey(dbg, "Down"); await pressKey(dbg, "Down"); - await assertNodeIsFocused(dbg, 7); + await assertNodeIsFocused(dbg, 6); // Up key on a source await pressKey(dbg, "Up"); - await assertNodeIsFocused(dbg, 6); + await assertNodeIsFocused(dbg, 5); // Left key on a source await pressKey(dbg, "Left"); - await assertNodeIsFocused(dbg, 2); + await assertNodeIsFocused(dbg, 4); // Left key on a closed dir await pressKey(dbg, "Left"); - await assertSourceCount(dbg, 2); + await assertSourceCount(dbg, 8); await pressKey(dbg, "Left"); - await assertNodeIsFocused(dbg, 1); + await assertNodeIsFocused(dbg, 3); // Up Key at the top of the source tree await pressKey(dbg, "Up"); - await assertNodeIsFocused(dbg, 1); + await assertNodeIsFocused(dbg, 2); }); diff --git a/devtools/client/debugger/test/mochitest/browser_dbg-sources.js b/devtools/client/debugger/test/mochitest/browser_dbg-sources.js index f6d73bb0b4c5..93941b5afe86 100644 --- a/devtools/client/debugger/test/mochitest/browser_dbg-sources.js +++ b/devtools/client/debugger/test/mochitest/browser_dbg-sources.js @@ -18,15 +18,15 @@ add_task(async function() { } = dbg; // Expand nodes and make sure more sources appear. - await assertSourceCount(dbg, 2); - await clickElement(dbg, "sourceDirectoryLabel", 2); - - await assertSourceCount(dbg, 7); + await assertSourceCount(dbg, 3); await clickElement(dbg, "sourceDirectoryLabel", 3); + await assertSourceCount(dbg, 8); + await clickElement(dbg, "sourceDirectoryLabel", 4); + await assertSourceCount(dbg, 9); const selected = waitForDispatch(dbg, "SET_SELECTED_LOCATION"); - await clickElement(dbg, "sourceNode", 4); + await clickElement(dbg, "sourceNode", 5); await selected; await waitForSelectedSource(dbg); @@ -34,12 +34,12 @@ add_task(async function() { await waitForElementWithSelector(dbg, ".sources-list .focused"); const focusedNode = findElementWithSelector(dbg, ".sources-list .focused"); - const fourthNode = findElement(dbg, "sourceNode", 4); + const fourthNode = findElement(dbg, "sourceNode", 5); const selectedSource = getSelectedSource().url; ok(fourthNode.classList.contains("focused"), "4th node is focused"); ok(selectedSource.includes("nested-source.js"), "nested-source is selected"); - await assertNodeIsFocused(dbg, 4); + await assertNodeIsFocused(dbg, 5); await waitForSelectedSource(dbg, "nested-source"); // Make sure new sources appear in the list. @@ -49,10 +49,10 @@ add_task(async function() { content.document.body.appendChild(script); }); - await waitForSourceCount(dbg, 9); - await assertNodeIsFocused(dbg, 4); + await waitForSourceCount(dbg, 10); + await assertNodeIsFocused(dbg, 5); is( - getSourceNodeLabel(dbg, 7), + getSourceNodeLabel(dbg, 8), "math.min.js", "math.min.js - The dynamic script exists" ); diff --git a/devtools/client/framework/test/test_browser_toolbox_debugger.js b/devtools/client/framework/test/test_browser_toolbox_debugger.js index f06f56988677..3512b1dbd2e8 100644 --- a/devtools/client/framework/test/test_browser_toolbox_debugger.js +++ b/devtools/client/framework/test/test_browser_toolbox_debugger.js @@ -15,12 +15,11 @@ info(`START: ${new Error().lineNumber}`); const document = window.document; await waitForSources(dbg, testUrl); -// yield waitForSourceCount(dbg, 6); info("Loaded, selecting the test script to debug"); // First expand the domain const domain = [...document.querySelectorAll(".tree-node")].find(node => { - return node.textContent.trim() == "mozilla.org"; + return node.querySelector(".label").textContent.trim() == "mozilla.org"; }); const arrow = domain.querySelector(".arrow"); arrow.click();