diff --git a/packages/repl/src/components/runner/Runner.tsx b/packages/repl/src/components/runner/Runner.tsx
index 8614cf6..445f00a 100644
--- a/packages/repl/src/components/runner/Runner.tsx
+++ b/packages/repl/src/components/runner/Runner.tsx
@@ -1,15 +1,23 @@
import type { DropdownMenuTriggerProps } from '@kobalte/core/dropdown-menu'
+import type { mtcute } from 'mtcute-repl-worker/client'
import type { CustomTypeScriptWorker } from '../editor/utils/custom-worker.ts'
import { timers } from '@fuman/utils'
import { persistentAtom } from '@nanostores/persistent'
import { LucideCheck, LucidePlay, LucidePlug, LucideRefreshCw, LucideSkull, LucideUnplug } from 'lucide-solid'
import { languages, Uri } from 'monaco-editor/esm/vs/editor/editor.api.js'
-import { type mtcute, workerInvoke } from 'mtcute-repl-worker/client'
-import { nanoid } from 'nanoid'
import { createEffect, createSignal, on, onCleanup, onMount } from 'solid-js'
import { Dynamic } from 'solid-js/web'
import { Button } from '../../lib/components/ui/button.tsx'
-import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuGroupLabel, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from '../../lib/components/ui/dropdown-menu.tsx'
+import {
+ DropdownMenu,
+ DropdownMenuCheckboxItem,
+ DropdownMenuContent,
+ DropdownMenuGroup,
+ DropdownMenuGroupLabel,
+ DropdownMenuItem,
+ DropdownMenuSeparator,
+ DropdownMenuTrigger,
+} from '../../lib/components/ui/dropdown-menu.tsx'
import { cn } from '../../lib/utils.ts'
import { $activeAccountId } from '../../store/accounts.ts'
import { $tabs } from '../../store/tabs.ts'
@@ -41,7 +49,6 @@ export function Runner(props: { isResizing: boolean }) {
const enableUpdates = useStore($enableUpdates)
const enableVerbose = useStore($enableVerbose)
- let currentScriptId: string | undefined
let deadTimer: timers.Timer | undefined
let inactivityTimer: timers.Timer | undefined
let iframeContainerRef!: HTMLIFrameElement
@@ -102,8 +109,6 @@ export function Runner(props: { isResizing: boolean }) {
}
case 'SCRIPT_END': {
setRunning(false)
- workerInvoke('sw', 'forgetScript', { name: currentScriptId! })
- currentScriptId = undefined
rescheduleInactivityTimer()
break
}
@@ -180,12 +185,9 @@ export function Runner(props: { isResizing: boolean }) {
}
}
- currentScriptId = nanoid()
- await workerInvoke('sw', 'uploadScript', { name: currentScriptId, files })
-
runnerIframe()!.contentWindow!.postMessage({
event: 'RUN',
- scriptId: currentScriptId,
+ files,
exports,
}, '*')
setRunning(true)
@@ -328,7 +330,7 @@ export function Runner(props: { isResizing: boolean }) {
-
+
{
let lastAccountId: string | undefined
let lastConnectionState: ConnectionState | undefined
+let currentScriptId: string | undefined
let logUpdates = false
let verboseLogs = false
@@ -70,7 +73,7 @@ function initClient(accountId: string, verbose: boolean) {
})
}
-window.addEventListener('message', ({ data }) => {
+window.addEventListener('message', async ({ data }) => {
if (data.event === 'INIT') {
sendToDevtools({
method: 'Page.frameNavigated',
@@ -102,9 +105,12 @@ window.addEventListener('message', ({ data }) => {
window.parent.postMessage({ event: 'PING' }, HOST_ORIGIN)
}, 500)
} else if (data.event === 'RUN') {
+ currentScriptId = nanoid()
+ await swInvokeMethod({ event: 'UPLOAD_SCRIPT', name: currentScriptId, files: data.files })
+
const el = document.createElement('script')
el.type = 'module'
- let script = `import * as result from "/sw/runtime/script/${data.scriptId}/main.js";`
+ let script = `import * as result from "/sw/runtime/script/${currentScriptId}/main.js";`
for (const exportName of data.exports ?? []) {
script += `window.${exportName} = result.${exportName};`
}
@@ -114,9 +120,11 @@ window.addEventListener('message', ({ data }) => {
script += 'console.log("[mtcute-repl] Script ended");'
}
script += 'window.__handleScriptEnd();'
+
el.textContent = script
el.addEventListener('error', e => window.__handleScriptEnd(e.error))
window.__currentScript = el
+
document.body.appendChild(el)
} else if (data.event === 'FROM_DEVTOOLS') {
chobitsu.sendRawMessage(data.value)
@@ -152,6 +160,9 @@ window.addEventListener('message', ({ data }) => {
window.__handleScriptEnd = (error) => {
if (!window.__currentScript) return
+ if (currentScriptId) {
+ swInvokeMethod({ event: 'FORGET_SCRIPT', name: currentScriptId }).catch(console.error)
+ }
window.parent.postMessage({ event: 'SCRIPT_END', error }, HOST_ORIGIN)
window.__currentScript.remove()
window.__currentScript = undefined
diff --git a/packages/worker/src/sw/main.ts b/packages/worker/src/sw/main.ts
index 5d295da..8b967ae 100644
--- a/packages/worker/src/sw/main.ts
+++ b/packages/worker/src/sw/main.ts
@@ -59,19 +59,19 @@ export type SwMessage =
| { event: 'CLEAR_AVATAR_CACHE', accountId: string }
| { event: 'CLEAR_CACHE' }
-function handleMessage(msg: SwMessage) {
+async function handleMessage(msg: SwMessage) {
switch (msg.event) {
case 'UPLOAD_SCRIPT': {
- uploadScript(msg.name, msg.files)
+ await uploadScript(msg.name, msg.files)
break
}
case 'FORGET_SCRIPT': {
- forgetScript(msg.name)
+ await forgetScript(msg.name)
break
}
case 'CLEAR_CACHE': {
clearCache()
- forgetAllScripts()
+ await forgetAllScripts()
break
}
case 'CLEAR_AVATAR_CACHE': {
diff --git a/packages/worker/src/sw/register.ts b/packages/worker/src/sw/register.ts
index d1aac57..592860d 100644
--- a/packages/worker/src/sw/register.ts
+++ b/packages/worker/src/sw/register.ts
@@ -4,6 +4,7 @@ import workerUrl from '../../sw.ts?worker&url'
const swInitDeferred = new Deferred()
export async function waitForServiceWorkerInit() {
+ if (location.pathname.startsWith('/sw/')) return
await swInitDeferred.promise
}