|
2 | 2 | import hljs from 'highlight.js'; |
3 | 3 | import { toast } from 'svelte-sonner'; |
4 | 4 | import { getContext, onMount, tick, onDestroy } from 'svelte'; |
5 | | - import { config } from '$lib/stores'; |
| 5 | + import { config, pyodideWorker as pyodideWorkerStore } from '$lib/stores'; |
6 | 6 |
|
7 | 7 | import PyodideWorker from '$lib/workers/pyodide.worker?worker'; |
8 | 8 | import { executeCode } from '$lib/apis/utils'; |
|
47 | 47 | export let editorClassName = ''; |
48 | 48 | export let stickyButtonsClassName = 'top-0'; |
49 | 49 |
|
50 | | - let pyodideWorker = null; |
| 50 | + let localPyodideWorker = null; |
51 | 51 |
|
52 | 52 | let _code = ''; |
53 | 53 | $: if (code) { |
|
237 | 237 |
|
238 | 238 | console.log(packages); |
239 | 239 |
|
240 | | - pyodideWorker = new PyodideWorker(); |
| 240 | + // Reuse the shared Pyodide worker when code interpreter is active, |
| 241 | + // so files written here are immediately visible in PyodideFileNav. |
| 242 | + // Otherwise fall back to a throwaway worker. |
| 243 | + const sharedWorker = $pyodideWorkerStore; |
| 244 | + const isShared = !!sharedWorker; |
| 245 | + const worker = sharedWorker ?? new PyodideWorker(); |
241 | 246 |
|
242 | | - pyodideWorker.postMessage({ |
| 247 | + if (!isShared) { |
| 248 | + localPyodideWorker = worker; |
| 249 | + } |
| 250 | +
|
| 251 | + worker.postMessage({ |
243 | 252 | id: id, |
244 | 253 | code: code, |
245 | 254 | packages: packages |
246 | 255 | }); |
247 | 256 |
|
248 | | - setTimeout(() => { |
| 257 | + const timeoutId = setTimeout(() => { |
249 | 258 | if (executing) { |
250 | 259 | executing = false; |
251 | 260 | stderr = 'Execution Time Limit Exceeded'; |
252 | | - pyodideWorker.terminate(); |
| 261 | + if (!isShared) { |
| 262 | + worker.terminate(); |
| 263 | + localPyodideWorker = null; |
| 264 | + } |
253 | 265 | } |
254 | 266 | }, 60000); |
255 | 267 |
|
256 | | - pyodideWorker.onmessage = (event) => { |
| 268 | + const handler = (event) => { |
| 269 | + // Ignore messages from other requests on the shared worker |
| 270 | + if (event.data?.id !== id) return; |
| 271 | +
|
257 | 272 | console.log('pyodideWorker.onmessage', event); |
258 | | - const { id, ...data } = event.data; |
| 273 | + const { id: _id, ...data } = event.data; |
259 | 274 |
|
260 | | - console.log(id, data); |
| 275 | + console.log(_id, data); |
261 | 276 |
|
262 | 277 | if (data['stdout']) { |
263 | 278 | stdout = data['stdout']; |
|
320 | 335 | data['stderr'] && (stderr = data['stderr']); |
321 | 336 | data['result'] && (result = data['result']); |
322 | 337 |
|
| 338 | + clearTimeout(timeoutId); |
| 339 | + worker.removeEventListener('message', handler); |
323 | 340 | executing = false; |
| 341 | +
|
| 342 | + // Signal PyodideFileNav to auto-refresh after execution |
| 343 | + window.dispatchEvent(new Event('pyodide:files')); |
324 | 344 | }; |
325 | 345 |
|
326 | | - pyodideWorker.onerror = (event) => { |
| 346 | + worker.addEventListener('message', handler); |
| 347 | +
|
| 348 | + worker.onerror = (event) => { |
327 | 349 | console.log('pyodideWorker.onerror', event); |
| 350 | + clearTimeout(timeoutId); |
| 351 | + worker.removeEventListener('message', handler); |
328 | 352 | executing = false; |
329 | 353 | }; |
330 | 354 | }; |
|
412 | 436 | }); |
413 | 437 |
|
414 | 438 | onDestroy(() => { |
415 | | - if (pyodideWorker) { |
416 | | - pyodideWorker.terminate(); |
| 439 | + if (localPyodideWorker) { |
| 440 | + localPyodideWorker.terminate(); |
| 441 | + localPyodideWorker = null; |
417 | 442 | } |
418 | 443 | }); |
419 | 444 | </script> |
|
0 commit comments