File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 11<script lang =" ts" >
2+ import { onDestroy } from ' svelte' ;
23 import { fly } from ' svelte/transition' ;
34 import { cubicOut } from ' svelte/easing' ;
45 import { untrack } from ' svelte' ;
115116 }
116117 });
117118
119+ // Track active resize cleanup for component destroy
120+ let activeCleanup: (() => void ) | null = null ;
121+
118122 function startResize(edge : ' left' | ' right' | ' top' | ' bottom' ) {
119123 return (event : MouseEvent ) => {
120124 event .preventDefault ();
146150 }
147151 }
148152
149- function onMouseUp() {
150- isResizing = false ;
151- resizeEdge = null ;
153+ function cleanup() {
152154 document .removeEventListener (' mousemove' , onMouseMove );
153155 document .removeEventListener (' mouseup' , onMouseUp );
154156 document .body .classList .remove (' resizing-ew' , ' resizing-ns' );
157+ activeCleanup = null ;
155158 }
156159
160+ function onMouseUp() {
161+ isResizing = false ;
162+ resizeEdge = null ;
163+ cleanup ();
164+ }
165+
166+ activeCleanup = cleanup ;
157167 document .addEventListener (' mousemove' , onMouseMove );
158168 document .addEventListener (' mouseup' , onMouseUp );
159169 document .body .classList .add ((edge === ' left' || edge === ' right' ) ? ' resizing-ew' : ' resizing-ns' );
160170 };
161171 }
172+
173+ onDestroy (() => {
174+ activeCleanup ?.();
175+ });
162176 </script >
163177
164178<!-- svelte-ignore a11y_no_static_element_interactions, a11y_no_noninteractive_element_interactions -->
Original file line number Diff line number Diff line change 11<script lang =" ts" >
2+ import { onDestroy } from ' svelte' ;
23 import { fade , scale } from ' svelte/transition' ;
34 import { cubicOut } from ' svelte/easing' ;
45 import { graphStore } from ' $lib/stores/graph' ;
2425 let nodeId = $state <string | null >(null );
2526 let node = $state <NodeInstance | null >(null );
2627
27- nodeDialogStore .subscribe ((id ) => {
28+ const unsubscribeDialog = nodeDialogStore .subscribe ((id ) => {
2829 nodeId = id ;
2930 if (id ) {
3031 node = graphStore .getNode (id ) || null ;
3435 });
3536
3637 // Keep node updated when params change
37- graphStore .nodesArray .subscribe ((nodes ) => {
38+ const unsubscribeNodes = graphStore .nodesArray .subscribe ((nodes ) => {
3839 if (nodeId ) {
3940 node = nodes .find (n => n .id === nodeId ) || null ;
4041 }
4142 });
4243
44+ onDestroy (() => {
45+ unsubscribeDialog ();
46+ unsubscribeNodes ();
47+ });
48+
4349 // Get type definition
4450 const typeDef = $derived (node ? nodeRegistry .get (node .type ) : null );
4551
Original file line number Diff line number Diff line change 2424 let copied = $state (false );
2525
2626 // Subscribe to theme changes
27- themeStore .subscribe ((theme ) => {
27+ const unsubscribeTheme = themeStore .subscribe ((theme ) => {
2828 currentTheme = theme ;
2929 if (editorView && cmModules && editorContainer ) {
3030 recreateEditor ();
115115 }
116116
117117 onDestroy (() => {
118+ unsubscribeTheme ();
118119 destroyEditor ();
119120 });
120121 </script >
Original file line number Diff line number Diff line change 11<script lang =" ts" >
2+ import { onDestroy } from ' svelte' ;
23 import { fade , scale } from ' svelte/transition' ;
34 import { cubicOut } from ' svelte/easing' ;
45 import { get } from ' svelte/store' ;
2223 let eventId = $state <string | null >(null );
2324 let event = $state <EventInstance | null >(null );
2425
25- eventDialogStore .subscribe ((id ) => {
26+ const unsubscribeDialog = eventDialogStore .subscribe ((id ) => {
2627 eventId = id ;
2728 if (id ) {
2829 event = eventStore .getEvent (id ) || null ;
3233 });
3334
3435 // Keep event updated when params change
35- eventStore .eventsArray .subscribe ((events ) => {
36+ const unsubscribeEvents = eventStore .eventsArray .subscribe ((events ) => {
3637 if (eventId ) {
3738 event = events .find (e => e .id === eventId ) || null ;
3839 }
3940 });
4041
42+ onDestroy (() => {
43+ unsubscribeDialog ();
44+ unsubscribeEvents ();
45+ });
46+
4147 // Get type definition
4248 const typeDef = $derived (event ? eventRegistry .get (event .type ) : null );
4349
Original file line number Diff line number Diff line change 2727 let currentTheme = $state <Theme >(' dark' );
2828
2929 // Subscribe to theme changes
30- themeStore .subscribe ((theme ) => {
30+ const unsubscribeTheme = themeStore .subscribe ((theme ) => {
3131 currentTheme = theme ;
3232 if (editorView && cmModules && editorContainer ) {
3333 recreateEditor ();
125125 }
126126
127127 onDestroy (() => {
128+ unsubscribeTheme ();
128129 destroyEditor ();
129130 });
130131 </script >
Original file line number Diff line number Diff line change 11<script lang =" ts" >
2+ import { onDestroy } from ' svelte' ;
23 import { fade , scale } from ' svelte/transition' ;
34 import { cubicOut } from ' svelte/easing' ;
45 import Icon from ' $lib/components/icons/Icon.svelte' ;
3738 settings = s ;
3839 });
3940
41+ onDestroy (() => {
42+ unsubscribe ();
43+ });
44+
4045 function handleKeydown(event : KeyboardEvent ) {
4146 if (event .key === ' Escape' ) {
4247 onClose ();
Original file line number Diff line number Diff line change 11<script lang =" ts" >
2+ import { onDestroy } from ' svelte' ;
23 import { fade , scale } from ' svelte/transition' ;
34 import { cubicOut } from ' svelte/easing' ;
45 import { graphStore , type SearchableNode } from ' $lib/stores/graph' ;
2122 let currentPath = $state <string []>([]);
2223
2324 // Subscribe to current path for prioritizing current view
24- graphStore .currentPath .subscribe ((path ) => {
25+ const unsubscribePath = graphStore .currentPath .subscribe ((path ) => {
2526 currentPath = path ;
2627 });
2728
29+ onDestroy (() => {
30+ unsubscribePath ();
31+ });
32+
2833 // Refresh node list when dialog opens
2934 $effect (() => {
3035 if (open ) {
Original file line number Diff line number Diff line change 705705 // Prevent concurrent simulation runs (synchronous check for rapid key presses)
706706 if (simRunning || isRunStarting || pyodideLoading ) return ;
707707
708+ // Set flag before any async operations to prevent race conditions
709+ isRunStarting = true ;
710+
708711 // Auto-initialize if not ready
709712 if (! pyodideReady ) {
710713 try {
711714 await initPyodide ();
712715 } catch (error ) {
713716 console .error (' Failed to initialize Pyodide:' , error );
717+ isRunStarting = false ;
714718 return ;
715719 }
716720 }
717721
718- // Set flag synchronously to prevent race conditions during validation
719- isRunStarting = true ;
720-
721722 try {
722723 // Run simulation
723724 const { nodes, connections } = graphStore .toJSON ();
You can’t perform that action at this time.
0 commit comments