chore: upload sw script from runner iframe
Some checks failed
Docs / build (push) Has been cancelled

hopefully this should fix firefox 🙏
This commit is contained in:
alina 🌸 2025-01-21 07:02:42 +03:00
parent c2107bf01d
commit 78dde9a3fe
Signed by: teidesu
SSH key fingerprint: SHA256:uNeCpw6aTSU4aIObXLvHfLkDa82HWH9EiOj9AXOIRpI
5 changed files with 39 additions and 19 deletions

View file

@ -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 }) {
</DropdownMenu>
</div>
</div>
<div class="bg-border h-px shrink-0" />
<div class="h-px shrink-0 bg-border" />
<Devtools
class={cn('size-full grow-0', props.isResizing && 'pointer-events-none')}
iframeRef={setDevtoolsIframe}

View file

@ -19,6 +19,9 @@ await build({
format: 'esm',
outfile: 'src/sw/iframe/script-bundled.js',
define: defines,
external: ['@mtcute/web'],
external: [
'@mtcute/web',
'./sw.ts',
],
minify: true,
})

View file

@ -12,7 +12,10 @@ let nextId = 0
const pending = new Map<number, Deferred<any>>()
export async function swInvokeMethod(request: SwMessage) {
const sw = await getServiceWorker()
return swInvokeMethodInner(request, await getServiceWorker())
}
export async function swInvokeMethodInner(request: SwMessage, sw: ServiceWorker) {
if (!registered) {
navigator.serviceWorker.addEventListener('message', (e) => {
const { id, result, error } = (e as MessageEvent).data

View file

@ -1,4 +1,7 @@
import { asNonNull } from '@fuman/utils'
import { Long, TelegramClient } from '@mtcute/web'
import { nanoid } from 'nanoid'
import { swInvokeMethodInner } from '../client.ts'
type ConnectionState = import('@mtcute/web').ConnectionState
type TelegramClientOptions = import('@mtcute/web').TelegramClientOptions
@ -31,6 +34,7 @@ chobitsu.setOnMessage((message: string) => {
let lastAccountId: string | undefined
let lastConnectionState: ConnectionState | undefined
let currentScriptId: string | undefined
let logUpdates = false
let verboseLogs = false
@ -70,7 +74,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 +106,12 @@ window.addEventListener('message', ({ data }) => {
window.parent.postMessage({ event: 'PING' }, HOST_ORIGIN)
}, 500)
} else if (data.event === 'RUN') {
currentScriptId = nanoid()
await swInvokeMethodInner({ event: 'UPLOAD_SCRIPT', name: currentScriptId, files: data.files }, asNonNull(navigator.serviceWorker.controller))
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 +121,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 +161,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

View file

@ -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': {