Skip to content

Fix/Replace Temporary removeBugNodes Function with Proper Solution#944

Open
subhamkumarr wants to merge 6 commits intoCircuitVerse:mainfrom
subhamkumarr:fix/replace-removeBugNodes-function
Open

Fix/Replace Temporary removeBugNodes Function with Proper Solution#944
subhamkumarr wants to merge 6 commits intoCircuitVerse:mainfrom
subhamkumarr:fix/replace-removeBugNodes-function

Conversation

@subhamkumarr
Copy link

@subhamkumarr subhamkumarr commented Feb 15, 2026

Problem

The removeBugNodes() function was a temporary workaround that "shouldn't ideally exist" (as documented in the code). It was used to clean up incorrectly created nodes after loading, masking the root cause of the issue.

Solution

  • ✅ Removed the removeBugNodes() function entirely
  • ✅ Replaced with targeted cleanup that only removes orphaned nodes
  • ✅ Fixed root cause: properly identifies input/output nodes with wrong parents
  • ✅ More efficient: uses reverse iteration instead of resetting loop counter
  • ✅ Clearer logic: only removes nodes that are clearly orphaned

Changes Made

Before:

  • removeBugNodes() function with inefficient loop that reset counter
  • Removed nodes based on unclear condition (type !== 2 && parent.objectType === 'CircuitElement')
  • Temporary workaround that masked the real issue

After:

  • Targeted cleanup that removes only orphaned input/output nodes
  • Nodes with scope.root as parent (wrong) are identified and removed
  • Clear comments explaining the logic
  • More efficient reverse iteration

Technical Details

Root Cause:

  • loadNode() creates all nodes with scope.root as parent
  • When modules load, they create new nodes with correct CircuitElement parents
  • replace() swaps them, but some nodes never get replaced (orphaned)
  • These orphaned nodes remain with scope.root as parent (wrong for input/output nodes)

Fix:

  • After loading modules, identify orphaned input/output nodes (type 0, 1) with scope.root as parent
  • Remove only these orphaned nodes
  • Intermediate nodes (type 2) correctly belong to scope.root, so they're not affected

Files Changed

  • src/simulator/src/data/load.js
  • v1/src/simulator/src/data/load.js

Testing

  • ✅ Applied fix to both v0 and v1 versions
  • ✅ No linting errors
  • ✅ Logic is clearer and more maintainable

Fixes #943

Summary by CodeRabbit

  • Bug Fixes
    • Reduced crashes and excessive redraws when rapidly adjusting clock timer/enable/light-mode controls by debouncing updates.
  • Improvements
    • More robust circuit loading that ensures intermediate and input/output nodes are created and cleaned up correctly, reducing initialization errors.
  • Behavior Changes
    • Input controls now update the displayed value and emit change events without directly mutating parent-bound props, which may affect parent state synchronization.

- Add debouncing (300ms) for changeClockTime and changeClockEnable
- Skip heavy canvas updates (scheduleUpdate, updateCanvasSet, wireToBeCheckedSet) for clock properties
- Clock changes now only update clock interval/state, not entire canvas
- Fixes continuous resetup() calls that caused crashes
- Applied to both v0 and v1 versions

Fixes: Clock timer and clock enable crash issue in Project Properties Panel
- Remove direct prop mutation (props.propertyValue = value)
- Props are readonly in Vue 3, causing console warnings
- Input value is already updated and change event is triggered
- Fixes Vue warnings: 'Set operation on key propertyValue failed: target is readonly'
- Remove removeBugNodes() function that was a temporary workaround
- Replace with targeted cleanup that only removes orphaned nodes
- Fix root cause: input/output nodes with scope.root parent are now properly identified and removed
- Use reverse iteration for safer array modification
- Applied to both v0 and v1 versions

The new approach:
- Only removes input/output nodes (type 0, 1) that have scope.root as parent
- These nodes should have been replaced with nodes having proper CircuitElement parents
- More efficient and clearer than the original loop-based approach

Fixes CircuitVerse#943
@netlify
Copy link

netlify bot commented Feb 15, 2026

Deploy Preview for circuitverse ready!

Name Link
🔨 Latest commit 3f993aa
🔍 Latest deploy log https://app.netlify.com/projects/circuitverse/deploys/6992992779c3ca0008ccbaf6
😎 Deploy Preview https://deploy-preview-944--circuitverse.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 35 (🔴 down 11 from production)
Accessibility: 73 (🟢 up 7 from production)
Best Practices: 92 (no change from production)
SEO: 82 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 15, 2026

Walkthrough

Adds debounce handling for clock-related properties in ux.js (DEBOUNCE_DELAY ≈ 300ms) to postpone heavy canvas updates for changeClockTime and changeClockEnable; removes the temporary removeBugNodes helper from simulator load logic and instead loads nodes/connections/modules then performs an in-place reverse-order cleanup of orphaned input/output nodes (parent == scope.root) before wiring; updates InputGroups.vue so increase/decrease update only the DOM input and dispatch a change event (no direct assignment to the public prop); adjusts comments in ProjectProperty.vue.

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Merge Conflict Detection ⚠️ Warning ❌ Merge conflicts detected (145 files):

⚔️ .github/workflows/Tauri-Release.yml (content)
⚔️ package-lock.json (content)
⚔️ package.json (content)
⚔️ src-tauri/Cargo.toml (content)
⚔️ src-tauri/tauri.conf.json (content)
⚔️ src/assets/constants/theme.ts (content)
⚔️ src/components/Navbar/QuickButton/QuickButton.ts (content)
⚔️ src/components/Panels/ElementsPanel/ElementsPanel.ts (content)
⚔️ src/components/Panels/PropertiesPanel/ModuleProperty/ProjectProperty/ProjectProperty.vue (content)
⚔️ src/components/Panels/PropertiesPanel/PropertiesPanel.ts (content)
⚔️ src/components/Panels/Shared/InputGroups.vue (content)
⚔️ src/components/Panels/TimingDiagramPanel/TimingDiagramPanel.ts (content)
⚔️ src/env.d.ts (content)
⚔️ src/globalVariables.ts (content)
⚔️ src/locales/i18n.ts (content)
⚔️ src/main.ts (content)
⚔️ src/plugins/vuetify.ts (content)
⚔️ src/plugins/webfontloader.ts (content)
⚔️ src/router/index.ts (content)
⚔️ src/shims-vuetify.d.ts (content)
⚔️ src/simulator/spec/vitestSetup.ts (content)
⚔️ src/simulator/src/app.ts (content)
⚔️ src/simulator/src/backgroundArea.ts (content)
⚔️ src/simulator/src/circuit.ts (content)
⚔️ src/simulator/src/contention.ts (content)
⚔️ src/simulator/src/data/load.js (content)
⚔️ src/simulator/src/data/project.ts (content)
⚔️ src/simulator/src/data/redo.ts (content)
⚔️ src/simulator/src/data/saveImage.ts (content)
⚔️ src/simulator/src/data/undo.ts (content)
⚔️ src/simulator/src/drag.ts (content)
⚔️ src/simulator/src/eventQueue.ts (content)
⚔️ src/simulator/src/hotkey_binder/defaultKeys.ts (content)
⚔️ src/simulator/src/hotkey_binder/model/actions.ts (content)
⚔️ src/simulator/src/hotkey_binder/model/addShortcut.ts (content)
⚔️ src/simulator/src/hotkey_binder/model/model.types.ts (content)
⚔️ src/simulator/src/hotkey_binder/model/shortcuts.plugin.ts (content)
⚔️ src/simulator/src/hotkey_binder/model/utils.ts (content)
⚔️ src/simulator/src/interface/backgroundArea.ts (content)
⚔️ src/simulator/src/interface/simulationArea.ts (content)
⚔️ src/simulator/src/layout/layoutBuffer.ts (content)
⚔️ src/simulator/src/layout/layoutNode.ts (content)
⚔️ src/simulator/src/layoutMode.ts (content)
⚔️ src/simulator/src/metadata.ts (content)
⚔️ src/simulator/src/modules/OrGate.ts (content)
⚔️ src/simulator/src/quinMcCluskey.ts (content)
⚔️ src/simulator/src/sequential.ts (content)
⚔️ src/simulator/src/simulationArea.ts (content)
⚔️ src/simulator/src/testbench.ts (content)
⚔️ src/simulator/src/themer/customThemeAbstraction.ts (content)
⚔️ src/simulator/src/themer/themeCardSvg.ts (content)
⚔️ src/simulator/src/themer/themer.ts (content)
⚔️ src/simulator/src/themer/themer.types.ts (content)
⚔️ src/simulator/src/themer/themes.ts (content)
⚔️ src/simulator/src/tutorials.ts (content)
⚔️ src/simulator/src/types/app.types.ts (content)
⚔️ src/simulator/src/utils.ts (content)
⚔️ src/simulator/src/ux.js (content)
⚔️ src/simulator/src/wire.ts (content)
⚔️ src/store/SimulatorStore/SimulatorStore.ts (content)
⚔️ src/store/SimulatorStore/actions.ts (content)
⚔️ src/store/SimulatorStore/getters.ts (content)
⚔️ src/store/SimulatorStore/state.ts (content)
⚔️ src/store/authStore.ts (content)
⚔️ src/store/extractStore.ts (content)
⚔️ src/store/layoutStore.ts (content)
⚔️ src/store/projectStore.ts (content)
⚔️ src/store/promptStore.ts (content)
⚔️ src/store/propertiesPanelStore.ts (content)
⚔️ src/store/simulatorMobileStore.ts (content)
⚔️ src/store/testBenchStore.ts (content)
⚔️ src/store/timingDiagramPanelStore.ts (content)
⚔️ src/store/verilogStore.ts (content)
⚔️ v1/src/assets/constants/theme.ts (content)
⚔️ v1/src/components/Navbar/QuickButton/QuickButton.ts (content)
⚔️ v1/src/components/Panels/ElementsPanel/ElementsPanel.ts (content)
⚔️ v1/src/components/Panels/PropertiesPanel/ModuleProperty/ProjectProperty/ProjectProperty.vue (content)
⚔️ v1/src/components/Panels/PropertiesPanel/PropertiesPanel.ts (content)
⚔️ v1/src/components/Panels/Shared/InputGroups.vue (content)
⚔️ v1/src/components/Panels/TimingDiagramPanel/TimingDiagramPanel.ts (content)
⚔️ v1/src/env.d.ts (content)
⚔️ v1/src/globalVariables.ts (content)
⚔️ v1/src/locales/i18n.ts (content)
⚔️ v1/src/main.ts (content)
⚔️ v1/src/plugins/vuetify.ts (content)
⚔️ v1/src/plugins/webfontloader.ts (content)
⚔️ v1/src/router/index.ts (content)
⚔️ v1/src/shims-vuetify.d.ts (content)
⚔️ v1/src/simulator/spec/vitestSetup.ts (content)
⚔️ v1/src/simulator/src/app.ts (content)
⚔️ v1/src/simulator/src/backgroundArea.ts (content)
⚔️ v1/src/simulator/src/circuit.ts (content)
⚔️ v1/src/simulator/src/contention.ts (content)
⚔️ v1/src/simulator/src/data/load.js (content)
⚔️ v1/src/simulator/src/data/project.ts (content)
⚔️ v1/src/simulator/src/data/redo.ts (content)
⚔️ v1/src/simulator/src/data/saveImage.ts (content)
⚔️ v1/src/simulator/src/data/undo.ts (content)
⚔️ v1/src/simulator/src/drag.ts (content)
⚔️ v1/src/simulator/src/eventQueue.ts (content)
⚔️ v1/src/simulator/src/hotkey_binder/defaultKeys.ts (content)
⚔️ v1/src/simulator/src/hotkey_binder/model/actions.ts (content)
⚔️ v1/src/simulator/src/hotkey_binder/model/addShortcut.ts (content)
⚔️ v1/src/simulator/src/hotkey_binder/model/model.types.ts (content)
⚔️ v1/src/simulator/src/hotkey_binder/model/shortcuts.plugin.ts (content)
⚔️ v1/src/simulator/src/hotkey_binder/model/utils.ts (content)
⚔️ v1/src/simulator/src/interface/backgroundArea.ts (content)
⚔️ v1/src/simulator/src/interface/simulationArea.ts (content)
⚔️ v1/src/simulator/src/layout/layoutBuffer.ts (content)
⚔️ v1/src/simulator/src/layout/layoutNode.ts (content)
⚔️ v1/src/simulator/src/layoutMode.ts (content)
⚔️ v1/src/simulator/src/metadata.ts (content)
⚔️ v1/src/simulator/src/modules/OrGate.ts (content)
⚔️ v1/src/simulator/src/quinMcCluskey.ts (content)
⚔️ v1/src/simulator/src/sequential.ts (content)
⚔️ v1/src/simulator/src/simulationArea.ts (content)
⚔️ v1/src/simulator/src/testbench.ts (content)
⚔️ v1/src/simulator/src/themer/customThemeAbstraction.ts (content)
⚔️ v1/src/simulator/src/themer/themeCardSvg.ts (content)
⚔️ v1/src/simulator/src/themer/themer.ts (content)
⚔️ v1/src/simulator/src/themer/themer.types.ts (content)
⚔️ v1/src/simulator/src/themer/themes.ts (content)
⚔️ v1/src/simulator/src/tutorials.ts (content)
⚔️ v1/src/simulator/src/types/app.types.ts (content)
⚔️ v1/src/simulator/src/utils.ts (content)
⚔️ v1/src/simulator/src/ux.js (content)
⚔️ v1/src/simulator/src/wire.ts (content)
⚔️ v1/src/store/SimulatorStore/SimulatorStore.ts (content)
⚔️ v1/src/store/SimulatorStore/actions.ts (content)
⚔️ v1/src/store/SimulatorStore/getters.ts (content)
⚔️ v1/src/store/SimulatorStore/state.ts (content)
⚔️ v1/src/store/authStore.ts (content)
⚔️ v1/src/store/extractStore.ts (content)
⚔️ v1/src/store/layoutStore.ts (content)
⚔️ v1/src/store/projectStore.ts (content)
⚔️ v1/src/store/promptStore.ts (content)
⚔️ v1/src/store/propertiesPanelStore.ts (content)
⚔️ v1/src/store/simulatorMobileStore.ts (content)
⚔️ v1/src/store/testBenchStore.ts (content)
⚔️ v1/src/store/timingDiagramPanelStore.ts (content)
⚔️ version/config.ts (content)
⚔️ version/main.ts (content)
⚔️ version/versionLoader.ts (content)
⚔️ vite.config.ts (content)
⚔️ vitest.workspace.ts (content)

These conflicts must be resolved before merging into main.
Resolve conflicts locally and push changes to this branch.
Out of Scope Changes check ❓ Inconclusive Changes to debouncing in ux.js and property updates in InputGroups.vue appear tangential to the removeBugNodes fix stated in the title and primary objective. Clarify why debounce timing and property value handling changes are included; these may be related to fixing clock timer crashes mentioned in comments but seem out of scope for the removeBugNodes replacement.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: replacing the temporary removeBugNodes function with a proper solution, which is the primary objective of this PR.
Linked Issues check ✅ Passed The PR addresses all key coding requirements from issue #943: removes the removeBugNodes function, implements proper orphaned node cleanup inline, fixes the root cause, improves efficiency with reverse iteration, and applies the fix to both v0 and v1 code paths.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
⚔️ Resolve merge conflicts (beta)
  • Auto-commit resolved conflicts to branch fix/replace-removeBugNodes-function
  • Post resolved changes as copyable diffs in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@subhamkumarr
Copy link
Author

@Nihal4777
could you review and merge this

- Fix deprecation comment to accurately reflect current code behavior
- Remove incorrect statement about 'only intermediate nodes loaded before modules'
- Add real-world impact examples explaining consequences of orphaned nodes:
  * Simulation errors from improperly connected nodes
  * Memory leaks from nodes not being garbage collected
  * Circuit loading failures or incorrect behavior
  * Example: Missing connections when loading saved circuits

Addresses CodeRabbit review feedback
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/simulator/src/data/load.js`:
- Around line 126-156: The two-pass approach is broken because node.delete()
mutates/reassigns scope.allNodes (via .filter()), making the collected indices
stale; instead, remove orphaned nodes inline during a single reverse iteration:
loop for (let i = scope.allNodes.length - 1; i >= 0; i--) inspect
scope.allNodes[i] (check node.type !== 2 and node.parent === scope.root) and if
true call scope.allNodes[i].delete() immediately (do not push indices to
nodesToRemove). This keeps higher-index deletions from invalidating lower-index
checks and uses the existing reverse iteration to preserve correctness while
referencing scope.allNodes and node.delete().
🧹 Nitpick comments (4)
src/simulator/src/data/load.js (2)

86-91: Remove the dangling @deprecated JSDoc comment.

This JSDoc block isn't attached to any function — the function it documented (removeBugNodes) has been deleted. A floating JSDoc comment is confusing and serves no purpose. Remove it entirely, or if you want to leave a historical note, use a plain // comment.

Proposed fix
-/**
- * `@deprecated` This function has been removed as the root cause has been fixed.
- * Nodes are now loaded correctly and orphaned nodes are cleaned up properly.
- * The removeBugNodes() workaround is no longer needed.
- * `@category` data
- */

127-139: Comment block is disproportionately long for 8 lines of code.

The 13-line comment (including "real-world impact" examples) reads more like a commit message or issue description than an inline code comment. Consider trimming to 2–3 lines explaining the what and why; the broader context belongs in the commit message or PR description.

v1/src/simulator/src/data/load.js (2)

86-90: Same dangling @deprecated JSDoc as in the v0 file — remove it here too.

See the comment on src/simulator/src/data/load.js lines 86–91.


125-154: Same cleanup logic and verbose comments as in v0 — same feedback applies.

The orphan cleanup block is identical to the v0 version. The same concerns apply: verify node.delete() behavior, simplify to inline deletion during reverse iteration, and trim the comment block.

Additionally, maintaining two near-identical copies of this file (v0 and v1) is a maintenance burden. Consider whether these can share a common implementation.

Critical fix: node.delete() reassigns scope.allNodes with filter(),
creating a new array. Collecting indices first makes them stale after
the first deletion, causing incorrect nodes to be deleted or skipped.

Solution: Delete inline during reverse iteration. Since we iterate
backwards, deleting higher indices first keeps lower indices valid
across filter operations.

Fixes CodeRabbit critical issue: index staling bug in two-pass deletion
Reduce verbose comments to essential information only
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/simulator/src/data/load.js (1)

87-91: Orphaned @deprecated JSDoc block — consider converting to a plain comment.

This JSDoc block with @deprecated isn't attached to any function declaration, so documentation generators won't associate it with anything meaningful. A regular // comment would be more appropriate here.

Suggested change
-/**
- * `@deprecated` This function has been removed as the root cause has been fixed.
- * Nodes are now loaded correctly and orphaned nodes are cleaned up properly.
- * The removeBugNodes() workaround is no longer needed.
- * `@category` data
- */
+// Note: The removeBugNodes() workaround has been removed.
+// Orphaned nodes are now cleaned up inline in loadScope().

@naman79820
Copy link
Contributor

Hii @subhamkumarr Can you please follow pr template. Thankss :))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replace Temporary removeBugNodes Function with Proper Solution

2 participants