зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1588803-Show sources after setting directory root r=davidwalsh
1.Show sources and thread name after a thread is set to root 2.Show sources under chrome:// 3.Show extension name and icon if an extension directory is set to root {F1665109} I'm building a better understanding of sources, sourcesTree and their utils. There could be better solutions than the ones I thought of. I'll appreciate feedback or discussions! Differential Revision: https://phabricator.services.mozilla.com/D50438 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
ac5aff0e5b
Коммит
0815c788fc
|
@ -194,13 +194,16 @@ export function clearProjectDirectoryRoot(cx: Context) {
|
|||
|
||||
export function setProjectDirectoryRoot(cx: Context, newRoot: string) {
|
||||
return ({ dispatch, getState }: ThunkArgs) => {
|
||||
// Remove the thread actor ID from the root path
|
||||
const threadActor = startsWithThreadActor(getState(), newRoot);
|
||||
|
||||
let curRoot = getProjectDirectoryRoot(getState());
|
||||
|
||||
// Remove the thread actor ID from the root path
|
||||
if (threadActor) {
|
||||
newRoot = newRoot.slice(threadActor.length + 1);
|
||||
curRoot = curRoot.slice(threadActor.length + 1);
|
||||
}
|
||||
|
||||
const curRoot = getProjectDirectoryRoot(getState());
|
||||
if (newRoot && curRoot) {
|
||||
const newRootArr = newRoot.replace(/\/+/g, "/").split("/");
|
||||
const curRootArr = curRoot
|
||||
|
|
|
@ -28,6 +28,7 @@ import {
|
|||
isOriginal as isOriginalSource,
|
||||
getSourceQueryString,
|
||||
isUrlExtension,
|
||||
isExtensionDirectoryPath,
|
||||
shouldBlackbox,
|
||||
} from "../../utils/source";
|
||||
import { isDirectory, getPathWithoutThread } from "../../utils/sources-tree";
|
||||
|
@ -241,7 +242,7 @@ class SourceTreeItem extends Component<Props, State> {
|
|||
return <AccessibleImage className="webpack" />;
|
||||
} else if (item.name === "ng://") {
|
||||
return <AccessibleImage className="angular" />;
|
||||
} else if (isUrlExtension(item.path) && depth === 1) {
|
||||
} else if (isExtensionDirectoryPath(item.path)) {
|
||||
return <AccessibleImage className="extension" />;
|
||||
}
|
||||
|
||||
|
@ -263,7 +264,10 @@ class SourceTreeItem extends Component<Props, State> {
|
|||
|
||||
if (isDirectory(item)) {
|
||||
// Domain level
|
||||
if (depth === 1 && projectRoot === "") {
|
||||
if (
|
||||
(depth === 1 && projectRoot === "") ||
|
||||
(depth === 0 && threads.find(thrd => thrd.actor === projectRoot))
|
||||
) {
|
||||
return <AccessibleImage className="globe-small" />;
|
||||
}
|
||||
return <AccessibleImage className="folder" />;
|
||||
|
@ -379,7 +383,7 @@ function getSourceContentValue(state, source: Source) {
|
|||
}
|
||||
|
||||
function isExtensionDirectory(depth, extensionName) {
|
||||
return extensionName && depth === 1;
|
||||
return extensionName && (depth === 1 || depth === 0);
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, props: OwnProps) => {
|
||||
|
|
|
@ -10,13 +10,14 @@ import { Tab, Tabs, TabList, TabPanels } from "react-aria-components/src/tabs";
|
|||
|
||||
import actions from "../../actions";
|
||||
import {
|
||||
getDisplayedSources,
|
||||
getActiveSearch,
|
||||
getProjectDirectoryRoot,
|
||||
getSelectedPrimaryPaneTab,
|
||||
getAllThreads,
|
||||
getContext,
|
||||
getExtensionNameBySourceUrl,
|
||||
} from "../../selectors";
|
||||
import { isExtensionDirectoryPath } from "../../utils/source";
|
||||
import { features, prefs } from "../../utils/prefs";
|
||||
import { connect } from "../../utils/connect";
|
||||
import { formatKeyShortcut } from "../../utils/text";
|
||||
|
@ -25,7 +26,6 @@ import Outline from "./Outline";
|
|||
import SourcesTree from "./SourcesTree";
|
||||
import AccessibleImage from "../shared/AccessibleImage";
|
||||
|
||||
import type { SourcesMapByThread } from "../../reducers/types";
|
||||
import type { SelectedPrimaryPaneTabType } from "../../selectors";
|
||||
import type { Thread, Context } from "../../types";
|
||||
|
||||
|
@ -41,9 +41,9 @@ type OwnProps = {|
|
|||
type Props = {
|
||||
cx: Context,
|
||||
selectedTab: SelectedPrimaryPaneTabType,
|
||||
sources: SourcesMapByThread,
|
||||
horizontal: boolean,
|
||||
projectRoot: string,
|
||||
rootExtensionName: ?string,
|
||||
sourceSearchOn: boolean,
|
||||
setPrimaryPaneTab: typeof actions.setPrimaryPaneTab,
|
||||
setActiveSearch: typeof actions.setActiveSearch,
|
||||
|
@ -79,6 +79,26 @@ class PrimaryPanes extends Component<Props, State> {
|
|||
}
|
||||
};
|
||||
|
||||
getRootLabel = (projectRoot: string) => {
|
||||
const { threads, rootExtensionName } = this.props;
|
||||
const targetThread = threads.find(thread => thread.actor === projectRoot);
|
||||
|
||||
if (targetThread) {
|
||||
return targetThread.name;
|
||||
} else if (rootExtensionName) {
|
||||
return rootExtensionName;
|
||||
} else if (projectRoot.endsWith("://")) {
|
||||
if (projectRoot === "ng://") {
|
||||
return "Angular";
|
||||
} else if (projectRoot === "webpack://") {
|
||||
return "Webpack";
|
||||
}
|
||||
return `${unescape(projectRoot)}`;
|
||||
}
|
||||
|
||||
return projectRoot.split("/").pop();
|
||||
};
|
||||
|
||||
renderOutlineTabs() {
|
||||
if (!features.outline) {
|
||||
return;
|
||||
|
@ -112,7 +132,7 @@ class PrimaryPanes extends Component<Props, State> {
|
|||
return null;
|
||||
}
|
||||
|
||||
const rootLabel = projectRoot.split("/").pop();
|
||||
const rootLabel = this.getRootLabel(projectRoot);
|
||||
|
||||
return (
|
||||
<div key="root" className="sources-clear-root-container">
|
||||
|
@ -166,14 +186,21 @@ class PrimaryPanes extends Component<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
cx: getContext(state),
|
||||
selectedTab: getSelectedPrimaryPaneTab(state),
|
||||
sources: getDisplayedSources(state),
|
||||
sourceSearchOn: getActiveSearch(state) === "source",
|
||||
threads: getAllThreads(state),
|
||||
projectRoot: getProjectDirectoryRoot(state),
|
||||
});
|
||||
const mapStateToProps = state => {
|
||||
const newProjectRoot = getProjectDirectoryRoot(state);
|
||||
const extensionAsRoot = isExtensionDirectoryPath(newProjectRoot);
|
||||
|
||||
return {
|
||||
cx: getContext(state),
|
||||
selectedTab: getSelectedPrimaryPaneTab(state),
|
||||
sourceSearchOn: getActiveSearch(state) === "source",
|
||||
threads: getAllThreads(state),
|
||||
projectRoot: newProjectRoot,
|
||||
rootExtensionName: extensionAsRoot
|
||||
? getExtensionNameBySourceUrl(state, newProjectRoot)
|
||||
: null,
|
||||
};
|
||||
};
|
||||
|
||||
const connector = connect<Props, OwnProps, _, _, _, _>(
|
||||
mapStateToProps,
|
||||
|
|
|
@ -46,6 +46,23 @@ describe("PrimaryPanes", () => {
|
|||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe("with a thread set to root", () => {
|
||||
it("uses the thread name as root label", () => {
|
||||
const { component } = render({
|
||||
projectRoot: "FakeThread",
|
||||
threads: [
|
||||
{
|
||||
actor: "FakeThread",
|
||||
name: "Main Thread",
|
||||
type: "mainThread",
|
||||
url: "http://a",
|
||||
},
|
||||
],
|
||||
});
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function generateDefaults(overrides) {
|
||||
|
|
|
@ -282,7 +282,36 @@ describe("SourceTreeItem", () => {
|
|||
"moz-extension://e37c3c08-beac-a04b-8032-c4f699a1a856",
|
||||
"moz-extension://e37c3c08-beac-a04b-8032-c4f699a1a856"
|
||||
);
|
||||
const node = render({ item, depth: 0 });
|
||||
const node = render({ item, depth: 1 });
|
||||
expect(node).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should show icon for moz-extension item when a thread is set to root", async () => {
|
||||
const item = createMockDirectory(
|
||||
"moz-extension://e37c3c08-beac-a04b-8032-c4f699a1a856",
|
||||
"moz-extension://e37c3c08-beac-a04b-8032-c4f699a1a856"
|
||||
);
|
||||
const node = render({
|
||||
item,
|
||||
depth: 0,
|
||||
projectRoot: "server1.conn13.child1/thread19",
|
||||
threads: [
|
||||
{ name: "Main Thread", actor: "server1.conn13.child1/thread19" },
|
||||
],
|
||||
});
|
||||
expect(node).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should show icon for domain item when a thread is set to root", async () => {
|
||||
const item = createMockDirectory();
|
||||
const node = render({
|
||||
item,
|
||||
depth: 0,
|
||||
projectRoot: "server1.conn13.child1/thread19",
|
||||
threads: [
|
||||
{ name: "Main Thread", actor: "server1.conn13.child1/thread19" },
|
||||
],
|
||||
});
|
||||
expect(node).toMatchSnapshot();
|
||||
});
|
||||
|
||||
|
|
|
@ -137,3 +137,81 @@ exports[`PrimaryPanes with custom root renders empty custom root source list 1`]
|
|||
</TabPanels>
|
||||
</Tabs>
|
||||
`;
|
||||
|
||||
exports[`PrimaryPanes with a thread set to root uses the thread name as root label 1`] = `
|
||||
<Tabs
|
||||
activeIndex={1}
|
||||
className="sources-panel"
|
||||
onActivateTab={[Function]}
|
||||
>
|
||||
<TabList
|
||||
activeIndex={0}
|
||||
className="source-outline-tabs"
|
||||
onActivateTab={[Function]}
|
||||
vertical={false}
|
||||
>
|
||||
<Tab
|
||||
active={false}
|
||||
className="tab sources-tab"
|
||||
key="sources-tab"
|
||||
>
|
||||
Sources
|
||||
</Tab>
|
||||
<Tab
|
||||
active={false}
|
||||
className="tab outline-tab"
|
||||
key="outline-tab"
|
||||
>
|
||||
Outline
|
||||
</Tab>
|
||||
</TabList>
|
||||
<TabPanels
|
||||
activeIndex={0}
|
||||
className="source-outline-panel has-root"
|
||||
hasFocusableContent={true}
|
||||
>
|
||||
<div
|
||||
className="threads-list"
|
||||
>
|
||||
<div
|
||||
className="sources-clear-root-container"
|
||||
key="root"
|
||||
>
|
||||
<button
|
||||
className="sources-clear-root"
|
||||
onClick={[Function]}
|
||||
title="Remove directory root"
|
||||
>
|
||||
<AccessibleImage
|
||||
className="home"
|
||||
/>
|
||||
<AccessibleImage
|
||||
className="breadcrumb"
|
||||
/>
|
||||
<span
|
||||
className="sources-clear-root-label"
|
||||
>
|
||||
Main Thread
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<Connect(SourcesTree)
|
||||
threads={
|
||||
Array [
|
||||
Object {
|
||||
"actor": "FakeThread",
|
||||
"name": "Main Thread",
|
||||
"type": "mainThread",
|
||||
"url": "http://a",
|
||||
},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<Connect(Outline)
|
||||
alphabetizeOutline={false}
|
||||
onAlphabetizeClick={[Function]}
|
||||
/>
|
||||
</TabPanels>
|
||||
</Tabs>
|
||||
`;
|
||||
|
|
|
@ -1700,7 +1700,7 @@ Object {
|
|||
className="arrow"
|
||||
/>
|
||||
<AccessibleImage
|
||||
className="folder"
|
||||
className="extension"
|
||||
/>
|
||||
<span
|
||||
className="label"
|
||||
|
@ -1719,7 +1719,7 @@ Object {
|
|||
"props": Object {
|
||||
"clearProjectDirectoryRoot": [MockFunction],
|
||||
"debuggeeUrl": "http://mdn.com",
|
||||
"depth": 0,
|
||||
"depth": 1,
|
||||
"expanded": false,
|
||||
"focusItem": [MockFunction],
|
||||
"item": Object {
|
||||
|
@ -1761,7 +1761,7 @@ Object {
|
|||
"_element": <SourceTreeItem
|
||||
clearProjectDirectoryRoot={[MockFunction]}
|
||||
debuggeeUrl="http://mdn.com"
|
||||
depth={0}
|
||||
depth={1}
|
||||
expanded={false}
|
||||
focusItem={[MockFunction]}
|
||||
item={
|
||||
|
@ -1812,7 +1812,7 @@ Object {
|
|||
className="arrow"
|
||||
/>
|
||||
<AccessibleImage
|
||||
className="folder"
|
||||
className="extension"
|
||||
/>
|
||||
<span
|
||||
className="label"
|
||||
|
@ -1830,7 +1830,7 @@ Object {
|
|||
"props": Object {
|
||||
"clearProjectDirectoryRoot": [MockFunction],
|
||||
"debuggeeUrl": "http://mdn.com",
|
||||
"depth": 0,
|
||||
"depth": 1,
|
||||
"expanded": false,
|
||||
"focusItem": [MockFunction],
|
||||
"item": Object {
|
||||
|
@ -1865,6 +1865,368 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`SourceTreeItem renderItem should show icon for moz-extension item when a thread is set to root 1`] = `
|
||||
Object {
|
||||
"component": <div
|
||||
className="node"
|
||||
key="moz-extension://e37c3c08-beac-a04b-8032-c4f699a1a856"
|
||||
onClick={[Function]}
|
||||
onContextMenu={[Function]}
|
||||
title=""
|
||||
>
|
||||
<AccessibleImage
|
||||
className="arrow"
|
||||
/>
|
||||
<AccessibleImage
|
||||
className="extension"
|
||||
/>
|
||||
<span
|
||||
className="label"
|
||||
>
|
||||
moz-extension://e37c3c08-beac-a04b-8032-c4f699a1a856
|
||||
|
||||
</span>
|
||||
</div>,
|
||||
"defaultState": null,
|
||||
"instance": SourceTreeItem {
|
||||
"addCollapseExpandAllOptions": [Function],
|
||||
"context": Object {},
|
||||
"handleDownloadFile": [Function],
|
||||
"onClick": [Function],
|
||||
"onContextMenu": [Function],
|
||||
"props": Object {
|
||||
"clearProjectDirectoryRoot": [MockFunction],
|
||||
"debuggeeUrl": "http://mdn.com",
|
||||
"depth": 0,
|
||||
"expanded": false,
|
||||
"focusItem": [MockFunction],
|
||||
"item": Object {
|
||||
"contents": Array [],
|
||||
"name": "moz-extension://e37c3c08-beac-a04b-8032-c4f699a1a856",
|
||||
"path": "moz-extension://e37c3c08-beac-a04b-8032-c4f699a1a856",
|
||||
"type": "directory",
|
||||
},
|
||||
"projectRoot": "server1.conn13.child1/thread19",
|
||||
"selectItem": [MockFunction],
|
||||
"setExpanded": [MockFunction],
|
||||
"setProjectDirectoryRoot": [MockFunction],
|
||||
"source": Object {
|
||||
"extensionName": null,
|
||||
"id": "server1.conn13.child1/39",
|
||||
"introductionType": undefined,
|
||||
"introductionUrl": null,
|
||||
"isBlackBoxed": false,
|
||||
"isExtension": false,
|
||||
"isPrettyPrinted": false,
|
||||
"isWasm": false,
|
||||
"relativeUrl": "http://mdn.com/one.js",
|
||||
"url": "http://mdn.com/one.js",
|
||||
},
|
||||
"threads": Array [
|
||||
Object {
|
||||
"actor": "server1.conn13.child1/thread19",
|
||||
"name": "Main Thread",
|
||||
},
|
||||
],
|
||||
"toggleBlackBox": [MockFunction],
|
||||
},
|
||||
"refs": Object {},
|
||||
"setState": [Function],
|
||||
"state": null,
|
||||
"updater": Updater {
|
||||
"_callbacks": Array [],
|
||||
"_renderer": ReactShallowRenderer {
|
||||
"_context": Object {},
|
||||
"_element": <SourceTreeItem
|
||||
clearProjectDirectoryRoot={[MockFunction]}
|
||||
debuggeeUrl="http://mdn.com"
|
||||
depth={0}
|
||||
expanded={false}
|
||||
focusItem={[MockFunction]}
|
||||
item={
|
||||
Object {
|
||||
"contents": Array [],
|
||||
"name": "moz-extension://e37c3c08-beac-a04b-8032-c4f699a1a856",
|
||||
"path": "moz-extension://e37c3c08-beac-a04b-8032-c4f699a1a856",
|
||||
"type": "directory",
|
||||
}
|
||||
}
|
||||
projectRoot="server1.conn13.child1/thread19"
|
||||
selectItem={[MockFunction]}
|
||||
setExpanded={[MockFunction]}
|
||||
setProjectDirectoryRoot={[MockFunction]}
|
||||
source={
|
||||
Object {
|
||||
"extensionName": null,
|
||||
"id": "server1.conn13.child1/39",
|
||||
"introductionType": undefined,
|
||||
"introductionUrl": null,
|
||||
"isBlackBoxed": false,
|
||||
"isExtension": false,
|
||||
"isPrettyPrinted": false,
|
||||
"isWasm": false,
|
||||
"relativeUrl": "http://mdn.com/one.js",
|
||||
"url": "http://mdn.com/one.js",
|
||||
}
|
||||
}
|
||||
threads={
|
||||
Array [
|
||||
Object {
|
||||
"actor": "server1.conn13.child1/thread19",
|
||||
"name": "Main Thread",
|
||||
},
|
||||
]
|
||||
}
|
||||
toggleBlackBox={[MockFunction]}
|
||||
/>,
|
||||
"_forcedUpdate": false,
|
||||
"_instance": [Circular],
|
||||
"_newState": null,
|
||||
"_rendered": <div
|
||||
className="node"
|
||||
onClick={[Function]}
|
||||
onContextMenu={[Function]}
|
||||
title=""
|
||||
>
|
||||
<AccessibleImage
|
||||
className="arrow"
|
||||
/>
|
||||
<AccessibleImage
|
||||
className="extension"
|
||||
/>
|
||||
<span
|
||||
className="label"
|
||||
>
|
||||
moz-extension://e37c3c08-beac-a04b-8032-c4f699a1a856
|
||||
|
||||
</span>
|
||||
</div>,
|
||||
"_rendering": false,
|
||||
"_updater": [Circular],
|
||||
},
|
||||
},
|
||||
Symbol(enzyme.__setState__): [Function],
|
||||
},
|
||||
"props": Object {
|
||||
"clearProjectDirectoryRoot": [MockFunction],
|
||||
"debuggeeUrl": "http://mdn.com",
|
||||
"depth": 0,
|
||||
"expanded": false,
|
||||
"focusItem": [MockFunction],
|
||||
"item": Object {
|
||||
"contents": Array [],
|
||||
"name": "moz-extension://e37c3c08-beac-a04b-8032-c4f699a1a856",
|
||||
"path": "moz-extension://e37c3c08-beac-a04b-8032-c4f699a1a856",
|
||||
"type": "directory",
|
||||
},
|
||||
"projectRoot": "server1.conn13.child1/thread19",
|
||||
"selectItem": [MockFunction],
|
||||
"setExpanded": [MockFunction],
|
||||
"setProjectDirectoryRoot": [MockFunction],
|
||||
"source": Object {
|
||||
"extensionName": null,
|
||||
"id": "server1.conn13.child1/39",
|
||||
"introductionType": undefined,
|
||||
"introductionUrl": null,
|
||||
"isBlackBoxed": false,
|
||||
"isExtension": false,
|
||||
"isPrettyPrinted": false,
|
||||
"isWasm": false,
|
||||
"relativeUrl": "http://mdn.com/one.js",
|
||||
"url": "http://mdn.com/one.js",
|
||||
},
|
||||
"threads": Array [
|
||||
Object {
|
||||
"actor": "server1.conn13.child1/thread19",
|
||||
"name": "Main Thread",
|
||||
},
|
||||
],
|
||||
"toggleBlackBox": [MockFunction],
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`SourceTreeItem renderItem should show icon for domain item when a thread is set to root 1`] = `
|
||||
Object {
|
||||
"component": <div
|
||||
className="node"
|
||||
key="domain/subfolder"
|
||||
onClick={[Function]}
|
||||
onContextMenu={[Function]}
|
||||
title=""
|
||||
>
|
||||
<AccessibleImage
|
||||
className="arrow"
|
||||
/>
|
||||
<AccessibleImage
|
||||
className="globe-small"
|
||||
/>
|
||||
<span
|
||||
className="label"
|
||||
>
|
||||
folder
|
||||
|
||||
</span>
|
||||
</div>,
|
||||
"defaultState": null,
|
||||
"instance": SourceTreeItem {
|
||||
"addCollapseExpandAllOptions": [Function],
|
||||
"context": Object {},
|
||||
"handleDownloadFile": [Function],
|
||||
"onClick": [Function],
|
||||
"onContextMenu": [Function],
|
||||
"props": Object {
|
||||
"clearProjectDirectoryRoot": [MockFunction],
|
||||
"debuggeeUrl": "http://mdn.com",
|
||||
"depth": 0,
|
||||
"expanded": false,
|
||||
"focusItem": [MockFunction],
|
||||
"item": Object {
|
||||
"contents": Array [],
|
||||
"name": "folder",
|
||||
"path": "domain/subfolder",
|
||||
"type": "directory",
|
||||
},
|
||||
"projectRoot": "server1.conn13.child1/thread19",
|
||||
"selectItem": [MockFunction],
|
||||
"setExpanded": [MockFunction],
|
||||
"setProjectDirectoryRoot": [MockFunction],
|
||||
"source": Object {
|
||||
"extensionName": null,
|
||||
"id": "server1.conn13.child1/39",
|
||||
"introductionType": undefined,
|
||||
"introductionUrl": null,
|
||||
"isBlackBoxed": false,
|
||||
"isExtension": false,
|
||||
"isPrettyPrinted": false,
|
||||
"isWasm": false,
|
||||
"relativeUrl": "http://mdn.com/one.js",
|
||||
"url": "http://mdn.com/one.js",
|
||||
},
|
||||
"threads": Array [
|
||||
Object {
|
||||
"actor": "server1.conn13.child1/thread19",
|
||||
"name": "Main Thread",
|
||||
},
|
||||
],
|
||||
"toggleBlackBox": [MockFunction],
|
||||
},
|
||||
"refs": Object {},
|
||||
"setState": [Function],
|
||||
"state": null,
|
||||
"updater": Updater {
|
||||
"_callbacks": Array [],
|
||||
"_renderer": ReactShallowRenderer {
|
||||
"_context": Object {},
|
||||
"_element": <SourceTreeItem
|
||||
clearProjectDirectoryRoot={[MockFunction]}
|
||||
debuggeeUrl="http://mdn.com"
|
||||
depth={0}
|
||||
expanded={false}
|
||||
focusItem={[MockFunction]}
|
||||
item={
|
||||
Object {
|
||||
"contents": Array [],
|
||||
"name": "folder",
|
||||
"path": "domain/subfolder",
|
||||
"type": "directory",
|
||||
}
|
||||
}
|
||||
projectRoot="server1.conn13.child1/thread19"
|
||||
selectItem={[MockFunction]}
|
||||
setExpanded={[MockFunction]}
|
||||
setProjectDirectoryRoot={[MockFunction]}
|
||||
source={
|
||||
Object {
|
||||
"extensionName": null,
|
||||
"id": "server1.conn13.child1/39",
|
||||
"introductionType": undefined,
|
||||
"introductionUrl": null,
|
||||
"isBlackBoxed": false,
|
||||
"isExtension": false,
|
||||
"isPrettyPrinted": false,
|
||||
"isWasm": false,
|
||||
"relativeUrl": "http://mdn.com/one.js",
|
||||
"url": "http://mdn.com/one.js",
|
||||
}
|
||||
}
|
||||
threads={
|
||||
Array [
|
||||
Object {
|
||||
"actor": "server1.conn13.child1/thread19",
|
||||
"name": "Main Thread",
|
||||
},
|
||||
]
|
||||
}
|
||||
toggleBlackBox={[MockFunction]}
|
||||
/>,
|
||||
"_forcedUpdate": false,
|
||||
"_instance": [Circular],
|
||||
"_newState": null,
|
||||
"_rendered": <div
|
||||
className="node"
|
||||
onClick={[Function]}
|
||||
onContextMenu={[Function]}
|
||||
title=""
|
||||
>
|
||||
<AccessibleImage
|
||||
className="arrow"
|
||||
/>
|
||||
<AccessibleImage
|
||||
className="globe-small"
|
||||
/>
|
||||
<span
|
||||
className="label"
|
||||
>
|
||||
folder
|
||||
|
||||
</span>
|
||||
</div>,
|
||||
"_rendering": false,
|
||||
"_updater": [Circular],
|
||||
},
|
||||
},
|
||||
Symbol(enzyme.__setState__): [Function],
|
||||
},
|
||||
"props": Object {
|
||||
"clearProjectDirectoryRoot": [MockFunction],
|
||||
"debuggeeUrl": "http://mdn.com",
|
||||
"depth": 0,
|
||||
"expanded": false,
|
||||
"focusItem": [MockFunction],
|
||||
"item": Object {
|
||||
"contents": Array [],
|
||||
"name": "folder",
|
||||
"path": "domain/subfolder",
|
||||
"type": "directory",
|
||||
},
|
||||
"projectRoot": "server1.conn13.child1/thread19",
|
||||
"selectItem": [MockFunction],
|
||||
"setExpanded": [MockFunction],
|
||||
"setProjectDirectoryRoot": [MockFunction],
|
||||
"source": Object {
|
||||
"extensionName": null,
|
||||
"id": "server1.conn13.child1/39",
|
||||
"introductionType": undefined,
|
||||
"introductionUrl": null,
|
||||
"isBlackBoxed": false,
|
||||
"isExtension": false,
|
||||
"isPrettyPrinted": false,
|
||||
"isWasm": false,
|
||||
"relativeUrl": "http://mdn.com/one.js",
|
||||
"url": "http://mdn.com/one.js",
|
||||
},
|
||||
"threads": Array [
|
||||
Object {
|
||||
"actor": "server1.conn13.child1/thread19",
|
||||
"name": "Main Thread",
|
||||
},
|
||||
],
|
||||
"toggleBlackBox": [MockFunction],
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`SourceTreeItem renderItem should show icon for webpack item 1`] = `
|
||||
Object {
|
||||
"component": <div
|
||||
|
|
|
@ -60,6 +60,7 @@ import {
|
|||
type SourceActorId,
|
||||
type SourceActorOuterState,
|
||||
} from "./source-actors";
|
||||
import { getThreads, getMainThread } from "./threads";
|
||||
import type {
|
||||
Source,
|
||||
SourceId,
|
||||
|
@ -796,6 +797,7 @@ const queryAllDisplayedSources: ReduceQuery<
|
|||
projectDirectoryRoot: string,
|
||||
chromeAndExtensionsEnabled: boolean,
|
||||
debuggeeIsWebExtension: boolean,
|
||||
threadActors: Array<ThreadId>,
|
||||
|},
|
||||
Array<SourceId>
|
||||
> = makeReduceQuery(
|
||||
|
@ -807,11 +809,12 @@ const queryAllDisplayedSources: ReduceQuery<
|
|||
projectDirectoryRoot,
|
||||
chromeAndExtensionsEnabled,
|
||||
debuggeeIsWebExtension,
|
||||
threadActors,
|
||||
}
|
||||
) => ({
|
||||
id: resource.id,
|
||||
displayed:
|
||||
underRoot(resource, projectDirectoryRoot) &&
|
||||
underRoot(resource, projectDirectoryRoot, threadActors) &&
|
||||
(!resource.isExtension ||
|
||||
chromeAndExtensionsEnabled ||
|
||||
debuggeeIsWebExtension),
|
||||
|
@ -833,6 +836,10 @@ function getAllDisplayedSources(
|
|||
projectDirectoryRoot: state.sources.projectDirectoryRoot,
|
||||
chromeAndExtensionsEnabled: state.sources.chromeAndExtenstionsEnabled,
|
||||
debuggeeIsWebExtension: state.threads.isWebExtension,
|
||||
threadActors: [
|
||||
getMainThread(state).actor,
|
||||
...getThreads(state).map(t => t.actor),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ import type {
|
|||
SourceActor,
|
||||
SourceContent,
|
||||
SourceLocation,
|
||||
ThreadId,
|
||||
} from "../types";
|
||||
import { isFulfilled, type AsyncValue } from "./async-value";
|
||||
import type { Symbols } from "../reducers/types";
|
||||
|
@ -483,7 +484,23 @@ export function getRelativeUrl(source: Source, root: string) {
|
|||
return url.slice(url.indexOf(root) + root.length + 1);
|
||||
}
|
||||
|
||||
export function underRoot(source: Source, root: string) {
|
||||
export function underRoot(
|
||||
source: Source,
|
||||
root: string,
|
||||
threadActors: Array<ThreadId>
|
||||
) {
|
||||
// source.url doesn't include thread actor ID, so remove the thread actor ID from the root
|
||||
threadActors.forEach(threadActor => {
|
||||
if (root.includes(threadActor)) {
|
||||
root = root.slice(threadActor.length + 1);
|
||||
}
|
||||
});
|
||||
|
||||
if (source.url && source.url.includes("chrome://")) {
|
||||
const { group, path } = getURL(source);
|
||||
return (group + path).includes(root);
|
||||
}
|
||||
|
||||
return source.url && source.url.includes(root);
|
||||
}
|
||||
|
||||
|
@ -509,6 +526,17 @@ export function isUrlExtension(url: string) {
|
|||
return url.includes("moz-extension:") || url.includes("chrome-extension");
|
||||
}
|
||||
|
||||
export function isExtensionDirectoryPath(url: string) {
|
||||
if (isUrlExtension(url)) {
|
||||
const urlArr = url.replace(/\/+/g, "/").split("/");
|
||||
let extensionIndex = urlArr.indexOf("moz-extension:");
|
||||
if (extensionIndex === -1) {
|
||||
extensionIndex = urlArr.indexOf("chrome-extension:");
|
||||
}
|
||||
return !urlArr[extensionIndex + 2];
|
||||
}
|
||||
}
|
||||
|
||||
export function getPlainUrl(url: string): string {
|
||||
const queryStart = url.indexOf("?");
|
||||
return queryStart !== -1 ? url.slice(0, queryStart) : url;
|
||||
|
|
|
@ -13,7 +13,9 @@ import {
|
|||
getSourceLineCount,
|
||||
isThirdParty,
|
||||
isJavaScript,
|
||||
underRoot,
|
||||
isUrlExtension,
|
||||
isExtensionDirectoryPath,
|
||||
} from "../source.js";
|
||||
|
||||
import {
|
||||
|
@ -504,6 +506,35 @@ describe("sources", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("underRoot", () => {
|
||||
const threadActors = ["server0.conn1.child1/thread19"];
|
||||
|
||||
it("should detect normal source urls", () => {
|
||||
const source = makeMockSource(
|
||||
"resource://activity-stream/vendor/react.js"
|
||||
);
|
||||
expect(
|
||||
underRoot(source, "resource://activity-stream", threadActors)
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("should detect source urls under chrome:// as root", () => {
|
||||
const source = makeMockSource(
|
||||
"chrome://browser/content/contentSearchUI.js"
|
||||
);
|
||||
expect(underRoot(source, "chrome://", threadActors)).toBe(true);
|
||||
});
|
||||
|
||||
it("should detect source urls if root is a thread actor Id", () => {
|
||||
const source = makeMockSource(
|
||||
"resource://activity-stream/vendor/react-dom.js"
|
||||
);
|
||||
expect(
|
||||
underRoot(source, "server0.conn1.child1/thread19", threadActors)
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isUrlExtension", () => {
|
||||
it("should detect mozilla extenstion", () => {
|
||||
expect(isUrlExtension("moz-extension://id/js/content.js")).toBe(true);
|
||||
|
@ -515,4 +546,18 @@ describe("sources", () => {
|
|||
expect(isUrlExtension("https://example.org/init.js")).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isExtensionDirectoryPath", () => {
|
||||
it("should detect mozilla extenstion directory", () => {
|
||||
expect(isExtensionDirectoryPath("moz-extension://id")).toBe(true);
|
||||
});
|
||||
it("should detect chrome extenstion directory", () => {
|
||||
expect(isExtensionDirectoryPath("chrome-extension://id")).toBe(true);
|
||||
});
|
||||
it("should return false for child file within the extenstion directory", () => {
|
||||
expect(isExtensionDirectoryPath("moz-extension://id/js/content.js")).toBe(
|
||||
false
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче