refac
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
import hljs from 'highlight.js';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import { getContext, onMount, tick, onDestroy } from 'svelte';
|
||||
import { config } from '$lib/stores';
|
||||
import { config, pyodideWorker as pyodideWorkerStore } from '$lib/stores';
|
||||
|
||||
import PyodideWorker from '$lib/workers/pyodide.worker?worker';
|
||||
import { executeCode } from '$lib/apis/utils';
|
||||
@@ -47,7 +47,7 @@
|
||||
export let editorClassName = '';
|
||||
export let stickyButtonsClassName = 'top-0';
|
||||
|
||||
let pyodideWorker = null;
|
||||
let localPyodideWorker = null;
|
||||
|
||||
let _code = '';
|
||||
$: if (code) {
|
||||
@@ -237,27 +237,42 @@
|
||||
|
||||
console.log(packages);
|
||||
|
||||
pyodideWorker = new PyodideWorker();
|
||||
// Reuse the shared Pyodide worker when code interpreter is active,
|
||||
// so files written here are immediately visible in PyodideFileNav.
|
||||
// Otherwise fall back to a throwaway worker.
|
||||
const sharedWorker = $pyodideWorkerStore;
|
||||
const isShared = !!sharedWorker;
|
||||
const worker = sharedWorker ?? new PyodideWorker();
|
||||
|
||||
pyodideWorker.postMessage({
|
||||
if (!isShared) {
|
||||
localPyodideWorker = worker;
|
||||
}
|
||||
|
||||
worker.postMessage({
|
||||
id: id,
|
||||
code: code,
|
||||
packages: packages
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
const timeoutId = setTimeout(() => {
|
||||
if (executing) {
|
||||
executing = false;
|
||||
stderr = 'Execution Time Limit Exceeded';
|
||||
pyodideWorker.terminate();
|
||||
if (!isShared) {
|
||||
worker.terminate();
|
||||
localPyodideWorker = null;
|
||||
}
|
||||
}
|
||||
}, 60000);
|
||||
|
||||
pyodideWorker.onmessage = (event) => {
|
||||
console.log('pyodideWorker.onmessage', event);
|
||||
const { id, ...data } = event.data;
|
||||
const handler = (event) => {
|
||||
// Ignore messages from other requests on the shared worker
|
||||
if (event.data?.id !== id) return;
|
||||
|
||||
console.log(id, data);
|
||||
console.log('pyodideWorker.onmessage', event);
|
||||
const { id: _id, ...data } = event.data;
|
||||
|
||||
console.log(_id, data);
|
||||
|
||||
if (data['stdout']) {
|
||||
stdout = data['stdout'];
|
||||
@@ -320,11 +335,20 @@
|
||||
data['stderr'] && (stderr = data['stderr']);
|
||||
data['result'] && (result = data['result']);
|
||||
|
||||
clearTimeout(timeoutId);
|
||||
worker.removeEventListener('message', handler);
|
||||
executing = false;
|
||||
|
||||
// Signal PyodideFileNav to auto-refresh after execution
|
||||
window.dispatchEvent(new Event('pyodide:files'));
|
||||
};
|
||||
|
||||
pyodideWorker.onerror = (event) => {
|
||||
worker.addEventListener('message', handler);
|
||||
|
||||
worker.onerror = (event) => {
|
||||
console.log('pyodideWorker.onerror', event);
|
||||
clearTimeout(timeoutId);
|
||||
worker.removeEventListener('message', handler);
|
||||
executing = false;
|
||||
};
|
||||
};
|
||||
@@ -412,8 +436,9 @@
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
if (pyodideWorker) {
|
||||
pyodideWorker.terminate();
|
||||
if (localPyodideWorker) {
|
||||
localPyodideWorker.terminate();
|
||||
localPyodideWorker = null;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { getContext, onMount, tick } from 'svelte';
|
||||
import { getContext, onMount, onDestroy, tick } from 'svelte';
|
||||
import { pyodideWorker } from '$lib/stores';
|
||||
import PyodideWorkerConstructor from '$lib/workers/pyodide.worker?worker';
|
||||
import type { FileEntry } from '$lib/apis/terminal';
|
||||
@@ -282,9 +282,21 @@
|
||||
|
||||
// ── Lifecycle ─────────────────────────────────────────────────────────
|
||||
|
||||
const onFilesChanged = async () => {
|
||||
try {
|
||||
await sendWorkerMessage({ type: 'fs:sync' });
|
||||
} catch {}
|
||||
loadDir(currentPath);
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
ensureWorker();
|
||||
loadDir(currentPath);
|
||||
window.addEventListener('pyodide:files', onFilesChanged);
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
window.removeEventListener('pyodide:files', onFilesChanged);
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -335,14 +347,18 @@
|
||||
{selectedFile}
|
||||
{loading}
|
||||
onNavigate={(path) => loadDir(path)}
|
||||
onRefresh={() => {
|
||||
if (selectedFile) {
|
||||
const name = selectedFile.split('/').pop() ?? '';
|
||||
openEntry({ name, type: 'file', size: 0 });
|
||||
} else {
|
||||
loadDir(currentPath);
|
||||
}
|
||||
}}
|
||||
onRefresh={async () => {
|
||||
// Sync from IndexedDB first to pick up files written by code execution
|
||||
try {
|
||||
await sendWorkerMessage({ type: 'fs:sync' });
|
||||
} catch {}
|
||||
if (selectedFile) {
|
||||
const name = selectedFile.split('/').pop() ?? '';
|
||||
openEntry({ name, type: 'file', size: 0 });
|
||||
} else {
|
||||
loadDir(currentPath);
|
||||
}
|
||||
}}
|
||||
onNewFolder={startNewFolder}
|
||||
onNewFile={startNewFile}
|
||||
onUploadFiles={uploadFiles}
|
||||
|
||||
@@ -305,6 +305,17 @@ self.onmessage = async (event) => {
|
||||
break;
|
||||
}
|
||||
|
||||
case 'fs:sync': {
|
||||
// Re-read from IndexedDB into memory to pick up externally written files
|
||||
(self.pyodide.FS as any).syncfs(true, (err: Error | null) => {
|
||||
if (err) {
|
||||
console.error('Error syncing from IndexedDB:', err);
|
||||
}
|
||||
self.postMessage({ id, type: 'fs:sync', success: !err });
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
console.warn('Unknown message type:', type);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user