-
Notifications
You must be signed in to change notification settings - Fork 172
Convert backupCircuit.js to TypeScript #672
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Convert backupCircuit.js to TypeScript #672
Conversation
✅ Deploy Preview for circuitverse ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
WalkthroughConverts the backup circuit module from JavaScript to TypeScript by migrating Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/simulator/src/data/backupCircuit.js(0 hunks)src/simulator/src/data/backupCircuit.ts(1 hunks)
💤 Files with no reviewable changes (1)
- src/simulator/src/data/backupCircuit.js
🧰 Additional context used
🧬 Code graph analysis (1)
src/simulator/src/data/backupCircuit.ts (4)
src/simulator/src/circuit.ts (1)
Scope(294-515)src/simulator/src/restrictedElementDiv.js (1)
globalScope(4-4)src/simulator/src/metadata.ts (2)
updateOrder(67-72)moduleList(66-66)src/simulator/src/data/project.ts (1)
projectSavedSet(85-87)
🔇 Additional comments (4)
src/simulator/src/data/backupCircuit.ts (4)
1-4: LGTM!The imports are correct and the eslint directive is appropriate for this module.
42-44: LGTM!The helper function is simple and correctly typed.
52-58: LGTM!The function correctly uses optional chaining to safely check for the existence of backup data.
108-122: LGTM!The function correctly prevents duplicate backups and updates the timestamp. The logic is sound.
| interface Scope { | ||
| SubCircuit: SubCircuitLike[]; | ||
| allNodes: NodeLike[]; | ||
| nodes: NodeLike[]; | ||
| layout: Record<string, any>; | ||
| verilogMetadata: Record<string, any>; | ||
| testbenchData: Record<string, any>; | ||
| id: number; | ||
| name: string; | ||
| restrictedCircuitElementsUsed: Record<string, any>; | ||
| backups: string[]; | ||
| history: string[]; | ||
| timeStamp: number; | ||
| [key: string]: any; // For dynamic moduleList entries | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Fix type mismatches with the actual Scope class.
The Scope interface has several type inconsistencies with the actual Scope class defined in circuit.ts:
- Line 26:
idshould benumber | string(not justnumber) - Line 28:
restrictedCircuitElementsUsedshould beany[](notRecord<string, any>) - Lines 20-22:
SubCircuit,allNodes, andnodesshould be optional properties marked with?, as they are in the actual Scope class - Line 25:
testbenchDatais not defined in the Scope class fromcircuit.ts
Apply this diff to align the interface with the actual Scope class:
interface Scope {
- SubCircuit: SubCircuitLike[];
- allNodes: NodeLike[];
- nodes: NodeLike[];
+ SubCircuit?: SubCircuitLike[];
+ allNodes?: NodeLike[];
+ nodes?: NodeLike[];
layout: Record<string, any>;
verilogMetadata: Record<string, any>;
- testbenchData: Record<string, any>;
- id: number;
+ testbenchData?: Record<string, any>;
+ id: number | string;
name: string;
- restrictedCircuitElementsUsed: Record<string, any>;
+ restrictedCircuitElementsUsed: any[];
backups: string[];
history: string[];
timeStamp: number;
[key: string]: any;
}Please verify whether testbenchData exists on the Scope class or is dynamically added. Run this script to check:
🏁 Script executed:
#!/bin/bash
# Search for testbenchData usage in the Scope class definition
rg -nP --type=ts -C5 'testbenchData' 'src/simulator/src/circuit.ts'
# Also check where testbenchData is assigned or accessed
rg -nP --type=ts -A3 -B3 '\.testbenchData\s*[=:]'Length of output: 5108
🏁 Script executed:
#!/bin/bash
# Find the actual Scope class/type definition in circuit.ts
rg -nP --type=ts -A20 'class Scope|interface Scope|type Scope' 'src/simulator/src/circuit.ts' | head -60
# Search for restrictedCircuitElementsUsed to see its actual type
rg -nP --type=ts -B2 -A2 'restrictedCircuitElementsUsed\s*[:=]' 'src/simulator/src/circuit.ts'
# Check id property definition
rg -nP --type=ts -B2 -A2 'this\.id\s*[:=]|id\s*[:=]\s*[0-9]|id\s*[:=]\s*string' 'src/simulator/src/circuit.ts' | head -40Length of output: 2101
🏁 Script executed:
#!/bin/bash
# Check if SubCircuit is used elsewhere or if it's CircuitElement
rg -nP --type=ts -B3 -A3 'SubCircuit' 'src/simulator/src/data/backupCircuit.ts'
# Check how the Scope interface is actually used in backupCircuit.ts
rg -nP --type=ts -B5 -A5 'interface Scope' 'src/simulator/src/data/backupCircuit.ts'
# See the full context of backupCircuit.ts
cat 'src/simulator/src/data/backupCircuit.ts' | head -100Length of output: 3424
Fix critical type mismatches and incompatibility with the actual Scope class.
The Scope interface has several serious type inconsistencies with the actual Scope class in circuit.ts:
- Line 20:
SubCircuitproperty doesn't exist in the Scope class—it hasCircuitElementinstead. ThebackUp()function (lines 67, 95) will fail at runtime trying to accessscope.SubCircuit. - Line 26:
idshould benumber | string(not justnumber) - Line 28:
restrictedCircuitElementsUsedshould beany[](notRecord<string, any>) - Lines 21–22:
allNodesandnodesshould be optional (marked with?)
The testbenchData property (line 25) is intentionally included and actively used in the backup logic (line 73, 85), so it should remain.
Apply this diff:
interface Scope {
- SubCircuit: SubCircuitLike[];
+ CircuitElement?: SubCircuitLike[];
allNodes?: NodeLike[];
nodes?: NodeLike[];
layout: Record<string, any>;
verilogMetadata: Record<string, any>;
testbenchData: Record<string, any>;
- id: number;
+ id: number | string;
name: string;
- restrictedCircuitElementsUsed: Record<string, any>;
+ restrictedCircuitElementsUsed: any[];
backups: string[];
history: string[];
timeStamp: number;
[key: string]: any;
}Then update the backUp() function loops (lines 67, 95) to iterate over scope.CircuitElement instead of scope.SubCircuit.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/simulator/src/data/backupCircuit.ts around lines 19 to 33, the Scope
interface does not match the real Scope class: change SubCircuit to
CircuitElement: SubCircuit: SubCircuitLike[] -> remove and add CircuitElement?:
CircuitElementLike[] (or CircuitElement: CircuitElementLike[] if required by
class), make allNodes? and nodes? optional (add ?), change id: number -> id:
number | string, change restrictedCircuitElementsUsed: Record<string, any> ->
restrictedCircuitElementsUsed: any[], keep testbenchData as-is. Then update the
backUp() function loops at lines ~67 and ~95 to iterate over
scope.CircuitElement instead of scope.SubCircuit so runtime access matches the
actual class.
| for (const sub of scope.SubCircuit) { | ||
| sub.removeConnections(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add guard for optional SubCircuit property.
Since SubCircuit is an optional property on the Scope class, attempting to iterate over it without checking if it exists will cause a runtime error.
Apply this diff to add a safe guard:
// Disconnect subcircuits before saving
- for (const sub of scope.SubCircuit) {
- sub.removeConnections();
+ if (scope.SubCircuit) {
+ for (const sub of scope.SubCircuit) {
+ sub.removeConnections();
+ }
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| for (const sub of scope.SubCircuit) { | |
| sub.removeConnections(); | |
| } | |
| // Disconnect subcircuits before saving | |
| if (scope.SubCircuit) { | |
| for (const sub of scope.SubCircuit) { | |
| sub.removeConnections(); | |
| } | |
| } |
🤖 Prompt for AI Agents
In src/simulator/src/data/backupCircuit.ts around lines 67 to 69, the code
iterates over scope.SubCircuit which is optional on Scope; add a guard to check
that scope.SubCircuit exists and is iterable before looping (e.g., if
(scope.SubCircuit && Array.isArray(scope.SubCircuit)) or if
(scope.SubCircuit?.length) ), and only then call sub.removeConnections() for
each element; keep the existing behavior otherwise.
| const data: Record<string, any> = { | ||
| layout: scope.layout, | ||
| verilogMetadata: scope.verilogMetadata, | ||
| allNodes: scope.allNodes.map(extract), | ||
| testbenchData: scope.testbenchData, | ||
| id: scope.id, | ||
| name: scope.name, | ||
| }; | ||
|
|
||
| // Save all module objects dynamically | ||
| for (const moduleName of moduleList) { | ||
| if (scope[moduleName]?.length) { | ||
| data[moduleName] = scope[moduleName].map(extract); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add guards for optional properties.
The code accesses optional properties without checking if they exist:
- Line 74:
allNodesis optional and could be undefined - Line 75:
testbenchDatamight not exist on the Scope
Apply this diff to add safe guards:
const data: Record<string, any> = {
layout: scope.layout,
verilogMetadata: scope.verilogMetadata,
- allNodes: scope.allNodes.map(extract),
- testbenchData: scope.testbenchData,
+ allNodes: scope.allNodes?.map(extract) || [],
+ testbenchData: scope.testbenchData || {},
id: scope.id,
name: scope.name,
};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const data: Record<string, any> = { | |
| layout: scope.layout, | |
| verilogMetadata: scope.verilogMetadata, | |
| allNodes: scope.allNodes.map(extract), | |
| testbenchData: scope.testbenchData, | |
| id: scope.id, | |
| name: scope.name, | |
| }; | |
| // Save all module objects dynamically | |
| for (const moduleName of moduleList) { | |
| if (scope[moduleName]?.length) { | |
| data[moduleName] = scope[moduleName].map(extract); | |
| } | |
| } | |
| const data: Record<string, any> = { | |
| layout: scope.layout, | |
| verilogMetadata: scope.verilogMetadata, | |
| allNodes: scope.allNodes?.map(extract) || [], | |
| testbenchData: scope.testbenchData || {}, | |
| id: scope.id, | |
| name: scope.name, | |
| }; | |
| // Save all module objects dynamically | |
| for (const moduleName of moduleList) { | |
| if (scope[moduleName]?.length) { | |
| data[moduleName] = scope[moduleName].map(extract); | |
| } | |
| } |
🤖 Prompt for AI Agents
In src/simulator/src/data/backupCircuit.ts around lines 71 to 85, the code maps
scope.allNodes and reads scope.testbenchData without guarding for undefined;
update the construction of data so optional properties are safely handled—use
default empty array when mapping (e.g., treat allNodes as an empty array if
undefined) and set testbenchData to a safe default (null/undefined or an empty
object) when absent; keep the existing dynamic module loop but ensure each
scope[moduleName] access is also guarded (only map when it exists and is an
array).
| data.nodes = scope.nodes.map(node => | ||
| scope.allNodes.indexOf(node) | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add guards for optional nodes property.
The nodes property is optional on the Scope class. Attempting to map over it without checking will cause a runtime error.
Apply this diff:
// Save intermediate nodes (wire nodes)
- data.nodes = scope.nodes.map(node =>
- scope.allNodes.indexOf(node)
- );
+ data.nodes = scope.nodes?.map(node =>
+ scope.allNodes?.indexOf(node) ?? -1
+ ) || [];📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| data.nodes = scope.nodes.map(node => | |
| scope.allNodes.indexOf(node) | |
| ); | |
| data.nodes = scope.nodes?.map(node => | |
| scope.allNodes?.indexOf(node) ?? -1 | |
| ) || []; |
🤖 Prompt for AI Agents
In src/simulator/src/data/backupCircuit.ts around lines 90 to 92, the code maps
scope.nodes without guarding for scope.nodes being optional; update this to
first check whether scope.nodes is present before mapping (e.g., set data.nodes
to an empty array or undefined when scope.nodes is missing), and only call
scope.nodes.map when scope.nodes is defined to avoid runtime errors.
| for (const sub of scope.SubCircuit) { | ||
| sub.makeConnections(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add guard for optional SubCircuit property.
Same issue as the disconnection code—need to check if SubCircuit exists before iterating.
Apply this diff:
// Reconnect subcircuits after saving
- for (const sub of scope.SubCircuit) {
- sub.makeConnections();
+ if (scope.SubCircuit) {
+ for (const sub of scope.SubCircuit) {
+ sub.makeConnections();
+ }
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| for (const sub of scope.SubCircuit) { | |
| sub.makeConnections(); | |
| } | |
| // Reconnect subcircuits after saving | |
| if (scope.SubCircuit) { | |
| for (const sub of scope.SubCircuit) { | |
| sub.makeConnections(); | |
| } | |
| } |
🤖 Prompt for AI Agents
In src/simulator/src/data/backupCircuit.ts around lines 95 to 97, the loop
assumes scope.SubCircuit always exists; add a guard to check that SubCircuit is
defined (and is iterable) before iterating and calling sub.makeConnections(),
e.g. return early or wrap the for loop in an if (scope.SubCircuit) / if
(Array.isArray(scope.SubCircuit)) check so you don't iterate over undefined.

Fixes #661
Describe the changes you have made in this PR -
Converted backupCircuit.js file to TypeScript (backupCircuit.ts)
Added proper type definitions for Scope and related functions
Improved code readability and type safety
No functional logic has been changed — only migration from JS → TS
Summary by CodeRabbit