From a22ab804cedf78953c962ad45b03b7006889b427 Mon Sep 17 00:00:00 2001 From: Orual Date: Tue, 24 Feb 2026 00:33:52 -0500 Subject: [PATCH] fix: address final code review feedback (type safety, XSS, dead deps) --- .deciduous/deciduous.db | Bin 0 -> 147456 bytes dfgraph/frontend/package-lock.json | 51 ++++++-------------- dfgraph/frontend/package.json | 7 +-- dfgraph/frontend/src/cytoscape-dagre.d.ts | 1 - dfgraph/frontend/src/cytoscape-plugins.d.ts | 15 ++++++ dfgraph/frontend/src/cytoscape-svg.d.ts | 1 - dfgraph/frontend/src/export.ts | 24 ++++----- dfgraph/frontend/src/layout.ts | 26 +++++----- dfgraph/frontend/src/main.ts | 40 +++++++++++---- dfgraph/frontend/src/style.ts | 26 ++++++---- dfgraph/frontend/src/types.ts | 28 +++++------ dfgraph/pipeline.py | 3 +- 12 files changed, 122 insertions(+), 100 deletions(-) create mode 100644 .deciduous/deciduous.db delete mode 100644 dfgraph/frontend/src/cytoscape-dagre.d.ts create mode 100644 dfgraph/frontend/src/cytoscape-plugins.d.ts diff --git a/.deciduous/deciduous.db b/.deciduous/deciduous.db new file mode 100644 index 0000000000000000000000000000000000000000..3d9e1c1b2466a7ec8216938273f50347315d60f2 GIT binary patch literal 147456 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®Q`iO;Q6?jq4Pr7HT%xFtUS; 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 literal 0 HcmV?d00001 diff --git a/dfgraph/frontend/package-lock.json b/dfgraph/frontend/package-lock.json index 63f7a21..9bcd5a9 100644 --- a/dfgraph/frontend/package-lock.json +++ b/dfgraph/frontend/package-lock.json @@ -9,13 +9,13 @@ "version": "0.1.0", "dependencies": { "cytoscape": "^3.30.0", - "cytoscape-dagre": "^2.5.0", "cytoscape-elk": "^2.3.0", "cytoscape-svg": "^0.4.0" }, "devDependencies": { "@types/cytoscape": "^3.21.0", - "esbuild": "^0.24.0" + "esbuild": "^0.24.0", + "typescript": "^5.7.0" } }, "node_modules/@esbuild/aix-ppc64": { @@ -460,18 +460,6 @@ "node": ">=0.10" } }, - "node_modules/cytoscape-dagre": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/cytoscape-dagre/-/cytoscape-dagre-2.5.0.tgz", - "integrity": "sha512-VG2Knemmshop4kh5fpLO27rYcyUaaDkRw+6PiX4bstpB+QFt0p2oauMrsjVbUamGWQ6YNavh7x2em2uZlzV44g==", - "license": "MIT", - "dependencies": { - "dagre": "^0.8.5" - }, - "peerDependencies": { - "cytoscape": "^3.2.22" - } - }, "node_modules/cytoscape-elk": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/cytoscape-elk/-/cytoscape-elk-2.3.0.tgz", @@ -493,16 +481,6 @@ "cytoscape": "^3.2.0" } }, - "node_modules/dagre": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz", - "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==", - "license": "MIT", - "dependencies": { - "graphlib": "^2.1.8", - "lodash": "^4.17.15" - } - }, "node_modules/elkjs": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.3.tgz", @@ -550,20 +528,19 @@ "@esbuild/win32-x64": "0.24.2" } }, - "node_modules/graphlib": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", - "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", - "license": "MIT", - "dependencies": { - "lodash": "^4.17.15" + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" } - }, - "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", - "license": "MIT" } } } diff --git a/dfgraph/frontend/package.json b/dfgraph/frontend/package.json index 20384bc..137daa5 100644 --- a/dfgraph/frontend/package.json +++ b/dfgraph/frontend/package.json @@ -5,16 +5,17 @@ "type": "module", "scripts": { "build": "esbuild src/main.ts --bundle --outfile=dist/bundle.js --format=esm --target=es2020", - "watch": "esbuild src/main.ts --bundle --outfile=dist/bundle.js --format=esm --target=es2020 --watch" + "watch": "esbuild src/main.ts --bundle --outfile=dist/bundle.js --format=esm --target=es2020 --watch", + "typecheck": "tsc --noEmit" }, "dependencies": { "cytoscape": "^3.30.0", - "cytoscape-dagre": "^2.5.0", "cytoscape-elk": "^2.3.0", "cytoscape-svg": "^0.4.0" }, "devDependencies": { "@types/cytoscape": "^3.21.0", - "esbuild": "^0.24.0" + "esbuild": "^0.24.0", + "typescript": "^5.7.0" } } diff --git a/dfgraph/frontend/src/cytoscape-dagre.d.ts b/dfgraph/frontend/src/cytoscape-dagre.d.ts deleted file mode 100644 index ee3ab5d..0000000 --- a/dfgraph/frontend/src/cytoscape-dagre.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module 'cytoscape-dagre'; diff --git a/dfgraph/frontend/src/cytoscape-plugins.d.ts b/dfgraph/frontend/src/cytoscape-plugins.d.ts new file mode 100644 index 0000000..c0c0980 --- /dev/null +++ b/dfgraph/frontend/src/cytoscape-plugins.d.ts @@ -0,0 +1,15 @@ +import "cytoscape"; + +declare module "cytoscape" { + interface Core { + svg(options?: { full?: boolean; scale?: number; bg?: string }): string; + png(options?: { + full?: boolean; + output?: "base64uri" | "base64" | "blob" | "blob-promise"; + scale?: number; + bg?: string; + maxWidth?: number; + maxHeight?: number; + }): string | Blob | Promise; + } +} diff --git a/dfgraph/frontend/src/cytoscape-svg.d.ts b/dfgraph/frontend/src/cytoscape-svg.d.ts index e4ed35c..ac81b2f 100644 --- a/dfgraph/frontend/src/cytoscape-svg.d.ts +++ b/dfgraph/frontend/src/cytoscape-svg.d.ts @@ -1,5 +1,4 @@ declare module "cytoscape-svg" { - import cytoscape from "cytoscape"; const ext: cytoscape.Ext; export default ext; } diff --git a/dfgraph/frontend/src/export.ts b/dfgraph/frontend/src/export.ts index a35f538..488040c 100644 --- a/dfgraph/frontend/src/export.ts +++ b/dfgraph/frontend/src/export.ts @@ -12,30 +12,26 @@ function downloadBlob(blob: Blob, filename: string): void { } export function exportSvg(cy: cytoscape.Core): void { - const svgContent: string = (cy as any).svg({ full: true }); + const svgContent = cy.svg({ full: true }); const blob = new Blob([svgContent], { type: "image/svg+xml" }); downloadBlob(blob, "dfgraph.svg"); } -export function exportPng(cy: cytoscape.Core): void { - const pngPromise: Promise = (cy as any).png({ +export async function exportPng(cy: cytoscape.Core): Promise { + const blob = await (cy.png({ full: true, output: "blob-promise", scale: 2, - }); - pngPromise.then((blob: Blob) => { - downloadBlob(blob, "dfgraph.png"); - }); + }) as Promise); + downloadBlob(blob, "dfgraph.png"); } -export function copyPng(cy: cytoscape.Core): void { - const pngPromise: Promise = (cy as any).png({ +export async function copyPng(cy: cytoscape.Core): Promise { + const blob = await (cy.png({ full: true, output: "blob-promise", scale: 2, - }); - pngPromise.then((blob: Blob) => { - const item = new ClipboardItem({ "image/png": blob }); - navigator.clipboard.write([item]); - }); + }) as Promise); + const item = new ClipboardItem({ "image/png": blob }); + await navigator.clipboard.write([item]); } diff --git a/dfgraph/frontend/src/layout.ts b/dfgraph/frontend/src/layout.ts index de96ba4..bab351b 100644 --- a/dfgraph/frontend/src/layout.ts +++ b/dfgraph/frontend/src/layout.ts @@ -1,4 +1,6 @@ -export function logicalLayout(): object { +import cytoscape from "cytoscape"; + +export function logicalLayout(): cytoscape.LayoutOptions { return { name: "elk", elk: { @@ -15,25 +17,27 @@ export function logicalLayout(): object { "elk.layered.nodePlacement.strategy": "NETWORK_SIMPLEX", }, animate: false, - }; + } as cytoscape.LayoutOptions; } -export function physicalLayout(): object { +export function physicalLayout(): cytoscape.LayoutOptions { return { name: "elk", elk: { algorithm: "layered", "elk.direction": "DOWN", - "elk.spacing.nodeNode": 35, - "elk.layered.spacing.nodeNodeBetweenLayers": 40, - "elk.spacing.edgeNode": 20, - "elk.spacing.edgeNodeBetweenLayers": 15, - "elk.spacing.edgeEdge": 10, - "elk.spacing.edgeEdgeBetweenLayers": 10, - "elk.edgeRouting": "ORTHOGONAL", + "elk.hierarchyHandling": "INCLUDE_CHILDREN", + "elk.spacing.nodeNode": 40, + "elk.layered.spacing.nodeNodeBetweenLayers": 50, + "elk.spacing.edgeNode": 25, + "elk.spacing.edgeNodeBetweenLayers": 20, + "elk.spacing.edgeEdge": 12, + "elk.spacing.edgeEdgeBetweenLayers": 12, + "elk.edgeRouting": "POLYLINE", + "elk.padding": "[top=20,left=20,bottom=20,right=20]", "elk.layered.crossingMinimization.strategy": "LAYER_SWEEP", "elk.layered.nodePlacement.strategy": "NETWORK_SIMPLEX", }, animate: false, - }; + } as cytoscape.LayoutOptions; } diff --git a/dfgraph/frontend/src/main.ts b/dfgraph/frontend/src/main.ts index 3a461ca..a2b9f6e 100644 --- a/dfgraph/frontend/src/main.ts +++ b/dfgraph/frontend/src/main.ts @@ -151,18 +151,24 @@ function buildPhysicalElements(update: GraphUpdate): cytoscape.ElementDefinition targetLabel: edge.port, sourceLabel: "", }, - classes: (isCrossPe ? "cross-pe" : "intra-pe") + (edge.has_error ? " error" : ""), + classes: "physical " + (isCrossPe ? "cross-pe" : "intra-pe") + (edge.has_error ? " error" : ""), }); } return elements; } +function getRequiredElement(id: string): HTMLElement { + const element = document.getElementById(id); + if (!element) throw new Error(`Required element with id "${id}" not found`); + return element; +} + function updateErrorPanel(update: GraphUpdate): void { - const panel = document.getElementById("error-panel")!; - const list = document.getElementById("error-list")!; - const count = document.getElementById("error-count")!; - const overlay = document.getElementById("parse-error-overlay")!; + const panel = getRequiredElement("error-panel"); + const list = getRequiredElement("error-list"); + const count = getRequiredElement("error-count"); + const overlay = getRequiredElement("parse-error-overlay"); // Handle parse error (AC5.5) if (update.parse_error) { @@ -186,9 +192,22 @@ function updateErrorPanel(update: GraphUpdate): void { for (const error of update.errors) { const li = document.createElement("li"); li.className = "error-item"; - li.innerHTML = `L${error.line}:${error.column}` - + `[${error.category}]` - + error.message; + + // Create line:column span + const lineSpan = document.createElement("span"); + lineSpan.className = "error-line"; + lineSpan.textContent = `L${error.line}:${error.column}`; + li.appendChild(lineSpan); + + // Create category span + const categorySpan = document.createElement("span"); + categorySpan.className = "error-category"; + categorySpan.textContent = `[${error.category}]`; + li.appendChild(categorySpan); + + // Create message text node (safe from XSS) + const messageNode = document.createTextNode(error.message); + li.appendChild(messageNode); if (error.suggestions.length > 0) { for (const suggestion of error.suggestions) { @@ -293,7 +312,6 @@ function renderPhysical(update: GraphUpdate): void { }); const layout = cy.layout(physicalLayout()); layout.on("layoutstop", () => { - routeEdges(); cy.fit(undefined, 40); }); layout.run(); @@ -355,6 +373,10 @@ function connect(): void { } }; + ws.onerror = (event: Event) => { + console.error("WebSocket error:", event); + }; + ws.onclose = () => { setTimeout(connect, 2000); }; diff --git a/dfgraph/frontend/src/style.ts b/dfgraph/frontend/src/style.ts index 9c1f8c7..af66eea 100644 --- a/dfgraph/frontend/src/style.ts +++ b/dfgraph/frontend/src/style.ts @@ -1,6 +1,6 @@ import cytoscape from "cytoscape"; -export const stylesheet: cytoscape.Stylesheet[] = [ +export const stylesheet: cytoscape.StylesheetStyle[] = [ { selector: "node", style: { @@ -31,7 +31,8 @@ export const stylesheet: cytoscape.Stylesheet[] = [ "border-style": "dashed", "border-width": 1, "border-color": "#888", - "background-color": "rgba(200, 200, 200, 0.06)", + "background-color": "#c8c8c8", + "background-opacity": 0.06, padding: "20px", "text-valign": "top", "text-halign": "center", @@ -86,31 +87,38 @@ export const stylesheet: cytoscape.Stylesheet[] = [ width: "label", height: "label", "border-width": 1.5, - "border-color": "#5c6bc0", - "background-color": "rgba(92, 107, 192, 0.04)", + "border-color": "#7986cb", + "background-color": "#e8eaf6", + "background-opacity": 0.5, padding: "16px", "text-valign": "top", "text-halign": "center", label: "data(label)", "font-size": 9, "font-weight": "bold", - color: "#5c6bc0", + color: "#3949ab", }, }, { selector: "edge.cross-pe", style: { width: 1.5, - "line-color": "#5c6bc0", - "target-arrow-color": "#5c6bc0", + "line-color": "#e57373", + "target-arrow-color": "#e57373", }, }, { selector: "edge.intra-pe", style: { width: 0.75, - "line-color": "#999", - "target-arrow-color": "#999", + "line-color": "#616161", + "target-arrow-color": "#616161", + }, + }, + { + selector: "edge.physical", + style: { + "curve-style": "bezier", }, }, ]; diff --git a/dfgraph/frontend/src/types.ts b/dfgraph/frontend/src/types.ts index f05fdb9..9ba40e4 100644 --- a/dfgraph/frontend/src/types.ts +++ b/dfgraph/frontend/src/types.ts @@ -1,4 +1,4 @@ -export interface GraphNode { +export type GraphNode = { id: string; opcode: string; category: string; @@ -9,45 +9,45 @@ export interface GraphNode { ctx: number | null; has_error: boolean; loc: SourceLoc; -} +}; -export interface SourceLoc { +export type SourceLoc = { line: number; column: number; end_line: number | null; end_column: number | null; -} +}; -export interface AddrInfo { +export type AddrInfo = { offset: number; port: string; pe: number | null; -} +}; -export interface GraphEdge { +export type GraphEdge = { source: string; target: string; port: string; source_port: string | null; has_error: boolean; addr?: AddrInfo; -} +}; -export interface GraphRegion { +export type GraphRegion = { tag: string; kind: string; node_ids: string[]; -} +}; -export interface GraphError { +export type GraphError = { line: number; column: number; category: string; message: string; suggestions: string[]; -} +}; -export interface GraphUpdate { +export type GraphUpdate = { type: "graph_update"; stage: string; nodes: GraphNode[]; @@ -60,4 +60,4 @@ export interface GraphUpdate { pe_count: number; sm_count: number; }; -} +}; diff --git a/dfgraph/pipeline.py b/dfgraph/pipeline.py index fe358da..4bdaf94 100644 --- a/dfgraph/pipeline.py +++ b/dfgraph/pipeline.py @@ -11,6 +11,7 @@ from enum import Enum from typing import Optional from lark import Lark +from lark.exceptions import UnexpectedInput from pathlib import Path from asm.ir import IRGraph @@ -85,7 +86,7 @@ def run_progressive(source: str) -> PipelineResult: # Stage 1: Parse try: tree = _get_parser().parse(source) - except Exception as exc: + except UnexpectedInput as exc: return PipelineResult( graph=None, stage=PipelineStage.PARSE_ERROR, -- 2.51.2