Skip to content

Commit

Permalink
Dependency graph UI POC (#10551)
Browse files Browse the repository at this point in the history
  • Loading branch information
bhackett1024 authored Jun 13, 2024
1 parent 8a8df2e commit db9b68c
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 1 deletion.
9 changes: 8 additions & 1 deletion packages/shared/client/ReplayClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ import throttle from "lodash/throttle";
import uniqueId from "lodash/uniqueId";

// eslint-disable-next-line no-restricted-imports
import { addEventListener, client, initSocket, removeEventListener } from "protocol/socket";
import { addEventListener, client, initSocket, removeEventListener, sendMessage } from "protocol/socket";
import { assert, compareNumericStrings, defer, waitForTime } from "protocol/utils";
import { initProtocolMessagesStore } from "replay-next/components/protocol/ProtocolMessagesStore";
import { insert } from "replay-next/src/utils/array";
Expand All @@ -92,6 +92,7 @@ import {
ReplayClientInterface,
SourceLocationRange,
TimeStampedPointWithPaintHash,
DependencyChainStep,
} from "./types";

export const MAX_POINTS_TO_FIND = 10_000;
Expand Down Expand Up @@ -1207,6 +1208,12 @@ export class ReplayClient implements ReplayClientInterface {
return this.focusWindow;
}

async getDependencies(point: ExecutionPoint): Promise<DependencyChainStep[]> {
const sessionId = await this.waitForSession();
const result = await sendMessage("Session.experimentalCommand", { name: "analyzeDependencies", params: { point } }, sessionId);
return result.rval.dependencies;
}

_dispatchEvent(type: ReplayClientEvents, ...args: any[]): void {
const handlers = this._eventHandlers.get(type);
if (handlers) {
Expand Down
7 changes: 7 additions & 0 deletions packages/shared/client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,12 @@ export interface TimeStampedPointWithPaintHash extends TimeStampedPoint {

export type AnnotationListener = (annotation: Annotation) => void;

export interface DependencyChainStep {
code: string;
time?: number;
point?: string;
}

export interface ReplayClientInterface {
get loadedRegions(): LoadedRegions | null;
addEventListener(type: ReplayClientEvents, handler: Function): void;
Expand Down Expand Up @@ -311,5 +317,6 @@ export interface ReplayClientInterface {
}) => void,
onSourceContentsChunk: ({ chunk, sourceId }: { chunk: string; sourceId: SourceId }) => void
): Promise<void>;
getDependencies(point: ExecutionPoint): Promise<DependencyChainStep[]>;
waitForSession(): Promise<string>;
}
53 changes: 53 additions & 0 deletions src/ui/components/LoadDependenciesButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import classnames from "classnames";
import { useContext } from "react";

import { useMostRecentLoadedPause } from "replay-next/src/hooks/useMostRecentLoadedPause";
import { pauseIdCache } from "replay-next/src/suspense/PauseCache";
import { TerminalContext } from "replay-next/src/contexts/TerminalContext";
import { replayClient } from "shared/client/ReplayClientContext";

let gNextPointId = 1;

export function LoadDependenciesButton() {
const { point, time, pauseId } = useMostRecentLoadedPause() ?? {};
const { addMessage } = useContext(TerminalContext);

const title = "Load dependencies at this point";

const onClick = async () => {
if (!point || !time || !pauseId) {
console.log(`Missing pause point`);
return;
}

const steps = await replayClient.getDependencies(point);

const pointId = gNextPointId++;

for (const { code, point: stepPoint, time: stepTime } of steps) {
if (stepPoint && stepTime) {
const pauseId = await pauseIdCache.readAsync(
replayClient,
stepPoint,
stepTime
);
addMessage({
expression: `"P${pointId}: ${code}"`,
frameId: null,
pauseId,
point: stepPoint,
time: stepTime,
});
}
}
};

return (
<button
className={classnames("devtools-button toolbar-panel-button tab")}
id="command-button-load-dependencies"
onClick={onClick}
title={title}
/>
);
}
2 changes: 2 additions & 0 deletions src/ui/components/SecondaryToolbox/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { trackEvent } from "ui/utils/telemetry";
import { selectors } from "../../reducers";
import NetworkMonitor from "../NetworkMonitor";
import { NodePicker } from "../NodePicker";
import { LoadDependenciesButton } from "../LoadDependenciesButton";
import { Redacted } from "../Redacted";
import ReplayLogo from "../shared/ReplayLogo";
import WaitForReduxSlice from "../WaitForReduxSlice";
Expand Down Expand Up @@ -228,6 +229,7 @@ export default function SecondaryToolbox() {
<header className="secondary-toolbox-header">
<div className="panel-buttons theme-tab-font-size flex flex-row items-center overflow-hidden">
{supportsRepaintingGraphics && <NodePicker />}
<LoadDependenciesButton />
<PanelButton panel="console">Console</PanelButton>
{supportsElementsInspector && <PanelButton panel="inspector">Elements</PanelButton>}
{showDebuggerTab && (
Expand Down

0 comments on commit db9b68c

Please sign in to comment.