sygnal 7.0.0 → 7.2.0-preview.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +632 -0
- package/dist/agent-ui.cjs.js +592 -0
- package/dist/agent-ui.cjs.js.map +1 -0
- package/dist/agent-ui.esm.js +582 -0
- package/dist/agent-ui.esm.js.map +1 -0
- package/dist/api.cjs.js +63 -0
- package/dist/api.cjs.js.map +1 -0
- package/dist/api.esm.js +2 -0
- package/dist/api.esm.js.map +1 -0
- package/dist/astro/index.cjs.js +968 -4
- package/dist/astro/index.cjs.js.map +1 -1
- package/dist/astro/index.mjs +968 -4
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/server.cjs.js +73 -45
- package/dist/astro/server.cjs.js.map +1 -1
- package/dist/astro/server.mjs +73 -45
- package/dist/astro/server.mjs.map +1 -1
- package/dist/canvas.cjs.js +2919 -0
- package/dist/canvas.cjs.js.map +1 -0
- package/dist/canvas.esm.js +2866 -0
- package/dist/canvas.esm.js.map +1 -0
- package/dist/devtools.cjs.js +38 -6
- package/dist/devtools.cjs.js.map +1 -1
- package/dist/devtools.esm.js +38 -6
- package/dist/devtools.esm.js.map +1 -1
- package/dist/diagnostics.cjs.js +224 -20
- package/dist/diagnostics.cjs.js.map +1 -1
- package/dist/diagnostics.esm.js +224 -20
- package/dist/diagnostics.esm.js.map +1 -1
- package/dist/guide/accessibility.md +1 -1
- package/dist/guide/ai-compose.md +150 -0
- package/dist/guide/behaviors.md +2 -1
- package/dist/guide/collaborative-state.md +265 -0
- package/dist/guide/element-commands.md +36 -2
- package/dist/guide/forms-reference.md +5 -5
- package/dist/guide/forms.md +3 -2
- package/dist/guide/http.md +28 -1
- package/dist/guide/islands.md +240 -0
- package/dist/guide/recipes/code-editor.md +1 -1
- package/dist/guide/renderers/agent-ui.md +138 -0
- package/dist/guide/renderers/custom-targets.md +126 -0
- package/dist/guide/renderers/overview.md +120 -0
- package/dist/guide/renderers/react-native.md +128 -0
- package/dist/guide/renderers/terminal.md +306 -0
- package/dist/guide/renderers/three.md +332 -0
- package/dist/guide/renderers/write-once.md +137 -0
- package/dist/guide/resources.md +2 -0
- package/dist/guide/sandboxed-components.md +223 -0
- package/dist/guide/timers.md +32 -5
- package/dist/guide/typed-apis.md +442 -0
- package/dist/guide/ui/accordion.md +11 -0
- package/dist/guide/ui/combobox.md +112 -8
- package/dist/guide/ui/dialog.md +96 -20
- package/dist/guide/ui/menu.md +57 -5
- package/dist/guide/ui/overview.md +8 -4
- package/dist/guide/ui/popover.md +69 -9
- package/dist/guide/ui/select.md +54 -4
- package/dist/guide/ui/tabs.md +1 -1
- package/dist/guide/ui/tooltip.md +7 -5
- package/dist/guide/virtual-collections.md +3 -0
- package/dist/guide/widgets.md +90 -1
- package/dist/host.cjs.js +2181 -0
- package/dist/host.cjs.js.map +1 -0
- package/dist/host.esm.js +2146 -0
- package/dist/host.esm.js.map +1 -0
- package/dist/index.cjs.js +3948 -586
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +584 -44
- package/dist/index.esm.js +3918 -586
- package/dist/index.esm.js.map +1 -1
- package/dist/primitives.cjs.js +143 -0
- package/dist/primitives.cjs.js.map +1 -0
- package/dist/primitives.esm.js +133 -0
- package/dist/primitives.esm.js.map +1 -0
- package/dist/react-native.cjs.js +248 -0
- package/dist/react-native.cjs.js.map +1 -0
- package/dist/react-native.esm.js +244 -0
- package/dist/react-native.esm.js.map +1 -0
- package/dist/replay.cjs.js +39 -0
- package/dist/replay.cjs.js.map +1 -0
- package/dist/replay.esm.js +2 -0
- package/dist/replay.esm.js.map +1 -0
- package/dist/sandbox-build.cjs.js +140 -0
- package/dist/sandbox-build.cjs.js.map +1 -0
- package/dist/sandbox-build.esm.js +137 -0
- package/dist/sandbox-build.esm.js.map +1 -0
- package/dist/sandbox-kernel.esm.js +212 -0
- package/dist/sandbox-kernel.esm.js.map +1 -0
- package/dist/sandbox-worker.cjs.js +857 -0
- package/dist/sandbox-worker.cjs.js.map +1 -0
- package/dist/sandbox-worker.esm.js +854 -0
- package/dist/sandbox-worker.esm.js.map +1 -0
- package/dist/sandbox.cjs.js +1425 -0
- package/dist/sandbox.cjs.js.map +1 -0
- package/dist/sandbox.esm.js +1406 -0
- package/dist/sandbox.esm.js.map +1 -0
- package/dist/sygnal.min.js +1 -1
- package/dist/sygnal.min.js.map +1 -1
- package/dist/terminal.cjs.js +1314 -0
- package/dist/terminal.cjs.js.map +1 -0
- package/dist/terminal.esm.js +1304 -0
- package/dist/terminal.esm.js.map +1 -0
- package/dist/three.cjs.js +1111 -0
- package/dist/three.cjs.js.map +1 -0
- package/dist/three.esm.js +1079 -0
- package/dist/three.esm.js.map +1 -0
- package/dist/ui-combobox.cjs.js +256 -18
- package/dist/ui-combobox.cjs.js.map +1 -1
- package/dist/ui-combobox.esm.js +256 -18
- package/dist/ui-combobox.esm.js.map +1 -1
- package/dist/ui-menu.cjs.js +150 -16
- package/dist/ui-menu.cjs.js.map +1 -1
- package/dist/ui-menu.esm.js +151 -17
- package/dist/ui-menu.esm.js.map +1 -1
- package/dist/ui-select.cjs.js +95 -9
- package/dist/ui-select.cjs.js.map +1 -1
- package/dist/ui-select.esm.js +95 -9
- package/dist/ui-select.esm.js.map +1 -1
- package/dist/ui.cjs.js +679 -173
- package/dist/ui.cjs.js.map +1 -1
- package/dist/ui.esm.js +679 -175
- package/dist/ui.esm.js.map +1 -1
- package/dist/vike/config/package.json +1 -1
- package/dist/vite/plugin.cjs.js +968 -4
- package/dist/vite/plugin.cjs.js.map +1 -1
- package/dist/vite/plugin.mjs +968 -4
- package/dist/vite/plugin.mjs.map +1 -1
- package/dist/worker-page.cjs.js +669 -0
- package/dist/worker-page.cjs.js.map +1 -0
- package/dist/worker-page.esm.js +665 -0
- package/dist/worker-page.esm.js.map +1 -0
- package/dist/worker.cjs.js +377 -0
- package/dist/worker.cjs.js.map +1 -0
- package/dist/worker.esm.js +374 -0
- package/dist/worker.esm.js.map +1 -0
- package/dist/yjs-testing.cjs.js +98 -0
- package/dist/yjs-testing.cjs.js.map +1 -0
- package/dist/yjs-testing.esm.js +77 -0
- package/dist/yjs-testing.esm.js.map +1 -0
- package/dist/yjs.cjs.js +923 -0
- package/dist/yjs.cjs.js.map +1 -0
- package/dist/yjs.esm.js +900 -0
- package/dist/yjs.esm.js.map +1 -0
- package/dist/zag.cjs.js +11 -1
- package/dist/zag.cjs.js.map +1 -1
- package/dist/zag.esm.js +11 -1
- package/dist/zag.esm.js.map +1 -1
- package/llms/ai.md +65 -0
- package/llms/collaboration.md +5 -0
- package/llms/graphics.md +10 -0
- package/llms/renderers.md +7 -0
- package/llms/replay.md +5 -0
- package/llms/sandbox.md +5 -0
- package/llms/typed-apis.md +5 -0
- package/llms/ui.md +10 -0
- package/llms-full.txt +444 -0
- package/llms.txt +37 -35
- package/package.json +139 -3
- package/src/agent-ui/mcp.ts +152 -0
- package/src/agent-ui/snapshot.ts +212 -0
- package/src/agent-ui.d.ts +106 -0
- package/src/agent-ui.ts +249 -0
- package/src/ai.d.ts +95 -2
- package/src/api.d.ts +303 -0
- package/src/api.ts +9 -0
- package/src/canvas/Canvas.ts +585 -0
- package/src/canvas/backend.ts +627 -0
- package/src/canvas/geometry.ts +187 -0
- package/src/canvas/gesture.ts +23 -0
- package/src/canvas/image.ts +197 -0
- package/src/canvas/kit.ts +130 -0
- package/src/canvas/paint.ts +260 -0
- package/src/canvas/pointer.ts +25 -0
- package/src/canvas/snap.ts +68 -0
- package/src/canvas/svg.ts +99 -0
- package/src/canvas.d.ts +373 -0
- package/src/canvas.ts +46 -0
- package/src/core/actions.ts +14 -3
- package/src/core/cell.ts +12 -4
- package/src/core/debug.ts +8 -3
- package/src/core/hooks.ts +16 -2
- package/src/core/hosts/collection.ts +1 -1
- package/src/core/hosts/switchable.ts +26 -8
- package/src/core/instance.ts +98 -45
- package/src/core/markers/portal.ts +4 -0
- package/src/core/registry.ts +4 -0
- package/src/core/runtime.ts +34 -25
- package/src/core/statics.ts +5 -5
- package/src/cycle/dom/EventDelegator.ts +37 -33
- package/src/cycle/dom/MainDOMSource.ts +16 -14
- package/src/cycle/dom/enrichEventStream.ts +13 -9
- package/src/cycle/dom/fromEvent.ts +6 -10
- package/src/cycle/dom/index.ts +11 -7
- package/src/cycle/dom/isolate.ts +13 -6
- package/src/cycle/dom/makeDOMDriver.ts +6 -2
- package/src/cycle/dom/utils.ts +9 -2
- package/src/cycle/run/adapt.ts +4 -12
- package/src/devtools.d.ts +9 -0
- package/src/devtools.ts +2 -1
- package/src/extra/ai/compose/catalog.ts +2 -1
- package/src/extra/ai/compose/decisions.ts +1 -2
- package/src/extra/ai/compose/generated.ts +234 -0
- package/src/extra/ai/compose/index.ts +6 -2
- package/src/extra/ai/compose/layout.ts +3 -1
- package/src/extra/ai/compose/llm.ts +7 -3
- package/src/extra/ai/compose/types.ts +2 -2
- package/src/extra/ai/transports/shared.ts +3 -1
- package/src/extra/api/contract.ts +485 -0
- package/src/extra/api/index.ts +26 -0
- package/src/extra/behaviors.ts +3 -3
- package/src/extra/controlled.ts +44 -0
- package/src/extra/copyAsTest.ts +22 -0
- package/src/extra/devtools.ts +5 -3
- package/src/extra/devtoolsActions.ts +8 -0
- package/src/extra/devtoolsNext.ts +1 -1
- package/src/extra/diagnostics/checks/actionLog.ts +8 -3
- package/src/extra/diagnostics/checks/behaviors.ts +25 -0
- package/src/extra/diagnostics/checks/elementCommands.ts +17 -5
- package/src/extra/diagnostics/checks/index.ts +1 -1
- package/src/extra/diagnostics/checks/next.ts +78 -4
- package/src/extra/diagnostics/checks/props.ts +6 -1
- package/src/extra/diagnostics/checks/replies.ts +11 -7
- package/src/extra/diagnostics/checks/timers.ts +8 -2
- package/src/extra/diagnostics/checks/virtual.ts +11 -0
- package/src/extra/diagnostics/codes.ts +51 -1
- package/src/extra/elementCommands.ts +20 -4
- package/src/extra/fetchDriver.ts +4 -1
- package/src/extra/fetchEventSource.ts +6 -2
- package/src/extra/field.ts +29 -0
- package/src/extra/form.ts +42 -16
- package/src/extra/frame.ts +54 -0
- package/src/extra/keymap.ts +41 -0
- package/src/extra/pager.ts +2 -0
- package/src/extra/persist.ts +2 -1
- package/src/extra/pointer.ts +262 -0
- package/src/extra/processForm.ts +34 -1
- package/src/extra/replay/address.ts +49 -0
- package/src/extra/replay/entropy.ts +99 -0
- package/src/extra/replay/format.ts +263 -0
- package/src/extra/replay/index.ts +8 -0
- package/src/extra/replay/inert.ts +22 -0
- package/src/extra/replay/recorder.ts +247 -0
- package/src/extra/replay/replayer.ts +234 -0
- package/src/extra/replay/report.ts +126 -0
- package/src/extra/replay/schema.ts +52 -0
- package/src/extra/replay/version.ts +3 -0
- package/src/extra/router.ts +7 -3
- package/src/extra/selection.ts +2 -0
- package/src/extra/socketDriver.ts +51 -6
- package/src/extra/ssr.ts +128 -42
- package/src/extra/testing.ts +295 -39
- package/src/extra/timers.ts +96 -7
- package/src/extra/undo.ts +2 -0
- package/src/extra/virtual.ts +25 -2
- package/src/extra/widget.ts +106 -17
- package/src/host/actions.ts +383 -0
- package/src/host/delegation.ts +101 -0
- package/src/host/dom.ts +553 -0
- package/src/host/driver.ts +185 -0
- package/src/host/selector.ts +119 -0
- package/src/host/style.ts +51 -0
- package/src/host.d.ts +298 -0
- package/src/host.ts +46 -0
- package/src/index.d.ts +302 -38
- package/src/index.ts +15 -3
- package/src/pragma/blocks.ts +211 -0
- package/src/pragma/index.ts +44 -10
- package/src/primitives.d.ts +54 -0
- package/src/primitives.ts +136 -0
- package/src/react-native.d.ts +57 -0
- package/src/react-native.ts +285 -0
- package/src/react-peers.d.ts +21 -3
- package/src/replay.d.ts +185 -0
- package/src/replay.ts +6 -0
- package/src/sandbox/build.ts +119 -0
- package/src/sandbox/create.ts +187 -0
- package/src/sandbox/engine.ts +267 -0
- package/src/sandbox/generated.ts +195 -0
- package/src/sandbox/kernel.ts +180 -0
- package/src/sandbox/mirror.ts +269 -0
- package/src/sandbox/protocol.ts +128 -0
- package/src/sandbox/quickjs.ts +74 -0
- package/src/sandbox/ssr.ts +41 -0
- package/src/sandbox/widget.ts +60 -0
- package/src/sandbox/worker-entry.ts +59 -0
- package/src/sandbox/worker.ts +137 -0
- package/src/sandbox-build.d.ts +12 -0
- package/src/sandbox-build.ts +6 -0
- package/src/sandbox.d.ts +299 -0
- package/src/sandbox.ts +25 -0
- package/src/shared.ts +12 -0
- package/src/terminal/paint.ts +712 -0
- package/src/terminal.d.ts +167 -0
- package/src/terminal.ts +530 -0
- package/src/three/assets.ts +170 -0
- package/src/three/host.ts +36 -0
- package/src/three/scene.ts +217 -0
- package/src/three/target.ts +252 -0
- package/src/three.d.ts +221 -0
- package/src/three.ts +30 -0
- package/src/ui/accordion.ts +21 -7
- package/src/ui/dialog.ts +192 -90
- package/src/ui/disclosure.ts +2 -0
- package/src/ui/dom.ts +30 -0
- package/src/ui/layers.ts +132 -0
- package/src/ui/popover.ts +120 -21
- package/src/ui/shared.ts +98 -12
- package/src/ui/stack.ts +18 -0
- package/src/ui/tabs.ts +2 -0
- package/src/ui/toaster.ts +16 -15
- package/src/ui/tooltip.ts +24 -8
- package/src/ui/tooltips.ts +26 -14
- package/src/ui/zag/combobox.ts +180 -13
- package/src/ui/zag/menu.ts +97 -17
- package/src/ui/zag/select.ts +15 -4
- package/src/ui/zag/shared.ts +60 -8
- package/src/ui-combobox.d.ts +16 -1
- package/src/ui-menu.d.ts +22 -7
- package/src/ui-zag-types.d.ts +13 -5
- package/src/ui.d.ts +62 -7
- package/src/ui.ts +2 -2
- package/src/vite/api.ts +186 -0
- package/src/vite/compile.ts +280 -0
- package/src/vite/plugin.d.ts +34 -0
- package/src/vite/plugin.ts +78 -4
- package/src/vite/sandbox.ts +16 -0
- package/src/worker/page.ts +396 -0
- package/src/worker/protocol.ts +48 -0
- package/src/worker/target.ts +282 -0
- package/src/worker-page.d.ts +42 -0
- package/src/worker-page.ts +12 -0
- package/src/worker.d.ts +65 -0
- package/src/worker.ts +16 -0
- package/src/yjs/driver.ts +253 -0
- package/src/yjs/mapping.ts +389 -0
- package/src/yjs/shared.ts +138 -0
- package/src/yjs/testing.ts +91 -0
- package/src/yjs-testing.d.ts +34 -0
- package/src/yjs-testing.ts +7 -0
- package/src/yjs.d.ts +109 -0
- package/src/yjs.ts +18 -0
- package/src/zag.d.ts +2 -0
- package/src/zag.ts +8 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-build.cjs.js","sources":["../src/sandbox/quickjs.ts","../src/sandbox/build.ts"],"sourcesContent":["/*\n * The QuickJS WASM module: `quickjs-emscripten-core` + `@jitl/quickjs-wasmfile-release-sync`,\n * optional peer dependencies (D209), loaded on first use. Stock packages only (README §9 Q6):\n * a quickjs-ng variant can be passed as `variant`.\n */\nimport {SandboxError} from './protocol'\n\nlet compiled: Promise<WebAssembly.Module> | null = null\nlet shared: Promise<any> | null = null\n\nexport interface LoadQuickJSOptions {\n /** the whole linear memory of a fresh instance capped at this (heap, ArrayBuffers, C stack) */\n maxWasmBytes?: number\n /** a shared module (one per page) instead of a fresh instance: no ArrayBuffer cap, and one crash poisons it for everyone */\n shared?: boolean\n /** another variant (default '@jitl/quickjs-wasmfile-release-sync') */\n variant?: any\n /** the .wasm bytes or a compiled WebAssembly.Module (default: the variant's own file) */\n wasm?: ArrayBuffer | Uint8Array | WebAssembly.Module\n}\n\nconst isNode = () => typeof (globalThis as any).process == 'object' && !!(globalThis as any).process.versions?.node && typeof (globalThis as any).window == 'undefined'\n\n/**\n * A QuickJS module. By default a fresh instance whose own `WebAssembly.Memory` is capped at\n * `maxWasmBytes` (64 MB): QuickJS's `setMemoryLimit()` doesn't count ArrayBuffer storage, so\n * without the cap a guest can grow the instance to 2 GB (README finding 1). Instances share\n * one compiled `WebAssembly.Module` (compiled once per page).\n */\nexport async function loadQuickJS(opts: LoadQuickJSOptions = {}): Promise<any> {\n if (opts.shared && !opts.wasm && !opts.variant && shared) return shared\n const p = load(opts)\n if (opts.shared && !opts.wasm && !opts.variant) shared = p\n return p\n}\n\nasync function load({maxWasmBytes = 64 << 20, shared: sh, variant, wasm}: LoadQuickJSOptions): Promise<any> {\n let core: any, base: any\n try {\n core = await import('quickjs-emscripten-core')\n base = variant || (await import('@jitl/quickjs-wasmfile-release-sync')).default\n } catch (e: any) {\n throw new Error(\"sygnal/sandbox needs quickjs-emscripten-core and @jitl/quickjs-wasmfile-release-sync (optional peer dependencies): npm install quickjs-emscripten-core @jitl/quickjs-wasmfile-release-sync (\" + (e?.message || e) + ')')\n }\n const custom: any = {}\n if (wasm) custom.wasmModule = wasm instanceof WebAssembly.Module ? wasm : await WebAssembly.compile(wasm as any)\n else if (!variant && isNode()) custom.wasmModule = await (compiled ??= nodeWasm())\n // a browser without `wasm` lets the variant fetch its .wasm itself (the bundler emits the file)\n if (!sh) custom.wasmMemory = new WebAssembly.Memory({initial: 256, maximum: Math.max(256, Math.ceil(maxWasmBytes / 65536))})\n return core.newQuickJSWASMModuleFromVariant(Object.keys(custom).length ? core.newVariant(base, custom) : base)\n}\n\nasync function nodeWasm(): Promise<WebAssembly.Module> {\n const [{readFile}, {createRequire}] = await Promise.all([nodeImport('node:fs/promises'), nodeImport('node:module')])\n // next to sygnal (a peer), else from the app's root\n let file: string\n try { file = createRequire(import.meta.url).resolve('@jitl/quickjs-wasmfile-release-sync/wasm') } catch {\n file = createRequire((globalThis as any).process.cwd() + '/').resolve('@jitl/quickjs-wasmfile-release-sync/wasm')\n }\n return WebAssembly.compile(await readFile(file))\n}\n\n// Node built-ins by a name bundlers don't follow (a browser bundle never loads them)\nexport const nodeImport = (name: string): Promise<any> => import(/* @vite-ignore */ /* webpackIgnore: true */ name)\n\n/**\n * Modules a guest crashed: the host's stack overflowed or the WASM trapped in the middle of a\n * QuickJS call, so its C state was unwound without cleanup. createSandbox refuses them.\n */\nexport const poisoned = new WeakSet<object>()\nexport const checkModule = (QJS: any) => {\n if (!QJS || typeof QJS.newRuntime != 'function') throw new TypeError('sygnal/sandbox: quickjs must be a module from loadQuickJS()')\n if (poisoned.has(QJS)) throw new SandboxError('crash', 'this QuickJS module crashed earlier; load a fresh one')\n}\n","/*\n * The guest kernel, built from the app's installed packages (README §7 option (a), §9 Q1; D209:\n * Sygnal's npm package never ships xstream or snabbdom prebuilt into it). sygnal/vite resolves\n * `sygnal/sandbox/kernel?raw` to this function's output (the project's own Vite), and\n * `buildSandboxKernel()` (sygnal/sandbox/build) does it for other toolchains (Vite, esbuild or\n * Rollup, whichever the project has).\n *\n * The output is one script: the platform prelude (timers, console, microtasks on `__host`,\n * which the core's modules read when they load), then dist/sandbox-kernel.esm.js bundled as an\n * IIFE with the installed sygnal (dist/index.esm.js and dist/host.esm.js of the same package: one\n * core), xstream and snabbdom. `process.env.NODE_ENV` is 'production'; xstream's `globalthis`\n * dependency is Sygnal's shim (as sygnal/vite does, G-099).\n */\nimport {nodeImport} from './quickjs'\n\n// The platform a bare QuickJS context lacks. A plain script, so it runs before the bundle's modules.\nexport const PLATFORM = `var global = globalThis;\n(function () {\n var H = globalThis.__host, G = globalThis, timers = new Map(), intervals = new Map(), seq = 0;\n G.__sandboxTimers = timers;\n G.queueMicrotask = G.queueMicrotask || function (f) { Promise.resolve().then(f) };\n G.setTimeout = function (f, ms) { var id = ++seq; timers.set(id, f); H.timer(id, +ms || 0); return id };\n G.clearTimeout = function (id) { if (timers.delete(id)) H.clearTimer(id) };\n // the core's macrotask hop (runtime.ts macro()): its own channel, so a component's timers can't starve it\n G.setImmediate = function (f) { var id = ++seq; timers.set(id, f); H.timer(id, -1); return id };\n G.clearImmediate = G.clearTimeout;\n G.setInterval = function (f, ms) { var box = {}; var tick = function () { box.id = G.setTimeout(tick, ms); f() }; box.id = G.setTimeout(tick, ms); var id = ++seq; intervals.set(id, box); return id };\n G.clearInterval = function (id) { var b = intervals.get(id); if (b) { intervals.delete(id); G.clearTimeout(b.id) } };\n G.requestAnimationFrame = function (f) { return G.setTimeout(function () { f(Date.now()) }, 16) };\n G.cancelAnimationFrame = G.clearTimeout;\n var fmt = function (a) { return a.map(function (x) { if (typeof x == 'string') return x; if (x instanceof Error) return x.name + ': ' + x.message; try { return JSON.stringify(x) } catch (e) { return String(x) } }).join(' ') };\n G.console = {\n log: function () { H.log('log', fmt([].slice.call(arguments))) }, info: function () { H.log('log', fmt([].slice.call(arguments))) },\n warn: function () { H.log('warn', fmt([].slice.call(arguments))) }, error: function () { H.log('error', fmt([].slice.call(arguments))) },\n debug: function () {},\n };\n})();\n`\n\nexport interface BuildSandboxKernelOptions {\n /** where the app's packages are installed (default: process.cwd()) */\n root?: string\n /** 'auto' (default): the project's Vite, else esbuild, else Rollup */\n bundler?: 'auto' | 'vite' | 'esbuild' | 'rollup'\n /** default true */\n minify?: boolean\n}\n\n/** The guest kernel script for createSandbox / <Sandboxed> (`kernel`), built from the installed packages */\nexport async function buildSandboxKernel(opts: BuildSandboxKernelOptions = {}): Promise<string> {\n const [path, {createRequire}, {pathToFileURL}, fs] = await Promise.all([nodeImport('node:path'), nodeImport('node:module'), nodeImport('node:url'), nodeImport('node:fs')])\n const root: string = path.resolve(opts.root || (globalThis as any).process.cwd())\n const fromRoot = createRequire(path.join(root, 'package.json'))\n // the app's sygnal (else this one): its dist/ holds the kernel entry, the core and the kit\n let main: string\n try { main = fromRoot.resolve('sygnal') } catch { main = createRequire(import.meta.url).resolve('sygnal') }\n const dist = path.dirname(main)\n const entry = path.join(dist, 'sandbox-kernel.esm.js')\n const files = {\n sygnal: path.join(dist, 'index.esm.js'),\n 'sygnal/host': path.join(dist, 'host.esm.js'),\n globalthis: path.join(dist, 'shims/globalthis.cjs'),\n }\n for (const f of [entry, ...Object.values(files)]) if (!fs.existsSync(f)) throw new Error(`buildSandboxKernel: ${f} is missing (an incomplete sygnal install?)`)\n const minify = opts.minify !== false\n const define = {'process.env.NODE_ENV': '\"production\"'}\n const has = (name: string) => { try { fromRoot.resolve(name); return true } catch { return false } }\n const want = opts.bundler || 'auto'\n const bundler = want !== 'auto' ? want : has('vite') ? 'vite' : has('esbuild') ? 'esbuild' : has('rollup') ? 'rollup' : null\n if (!bundler) throw new Error('buildSandboxKernel: needs vite, esbuild or rollup installed in ' + root)\n const load = (name: string) => import(/* @vite-ignore */ pathToFileURL(resolveEsm(fromRoot, fs, path, name)).href)\n let code: string\n\n if (bundler === 'esbuild') {\n const esbuild = await load('esbuild')\n const r = await (esbuild.build || esbuild.default.build)({\n entryPoints: [entry], bundle: true, write: false, format: 'iife', platform: 'browser', target: 'es2020',\n minify, define, alias: files, logLevel: 'silent', legalComments: 'none',\n })\n code = r.outputFiles[0].text\n } else if (bundler === 'rollup') {\n const {rollup} = await load('rollup')\n const plugins: any[] = [{\n name: 'sygnal-kernel', resolveId: (id: string) => (files as any)[id] || null,\n transform: (c: string) => (c.includes('process.env.NODE_ENV') ? c.split('process.env.NODE_ENV').join(define['process.env.NODE_ENV']) : null),\n }]\n const req = async (n: string) => { const m = await load(n); return m.default || m }\n if (has('@rollup/plugin-node-resolve')) plugins.push((await load('@rollup/plugin-node-resolve')).nodeResolve({browser: true}))\n if (has('@rollup/plugin-commonjs')) plugins.push((await req('@rollup/plugin-commonjs'))())\n if (minify && has('@rollup/plugin-terser')) plugins.push((await req('@rollup/plugin-terser'))({ecma: 2020}))\n const b = await rollup({input: entry, plugins, onwarn: () => {}})\n code = (await b.generate({format: 'iife', name: '__sygnalKernel'})).output[0].code\n await b.close()\n } else {\n const vite = await load('vite')\n const out: any = await vite.build({\n configFile: false, root, logLevel: 'silent', mode: 'production', define,\n resolve: {alias: Object.entries(files).map(([find, replacement]) => ({find: new RegExp(`^${find.replace('/', '\\\\/')}$`), replacement}))},\n build: {write: false, minify, target: 'es2020', lib: {entry, formats: ['iife'], name: '__sygnalKernel', fileName: () => 'kernel.js'}, rollupOptions: {output: {inlineDynamicImports: true}}},\n })\n const o = (Array.isArray(out) ? out[0] : out).output\n code = o.find((c: any) => c.type === 'chunk').code\n }\n return PLATFORM + code\n}\n\n// a package's ESM entry, as resolved from the app (import() needs a file URL, not a bare name, to resolve from there)\nfunction resolveEsm(req: any, fs: any, path: any, name: string): string {\n try {\n const pj = req.resolve(`${name}/package.json`)\n const pkg = JSON.parse(fs.readFileSync(pj, 'utf8'))\n const dot = typeof pkg.exports == 'string' ? pkg.exports : pkg.exports?.['.']\n let e = typeof dot == 'string' ? dot : dot?.import ?? pkg.module ?? pkg.main ?? 'index.js'\n if (e && typeof e == 'object') e = e.default\n return path.join(path.dirname(pj), e)\n } catch {\n return req.resolve(name)\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The QuickJS WASM module: `quickjs-emscripten-core` + `@jitl/quickjs-wasmfile-release-sync`,
|
|
3
|
+
* optional peer dependencies (D209), loaded on first use. Stock packages only (README §9 Q6):
|
|
4
|
+
* a quickjs-ng variant can be passed as `variant`.
|
|
5
|
+
*/
|
|
6
|
+
// Node built-ins by a name bundlers don't follow (a browser bundle never loads them)
|
|
7
|
+
const nodeImport = (name) => import(/* @vite-ignore */ /* webpackIgnore: true */ name);
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
* The guest kernel, built from the app's installed packages (README §7 option (a), §9 Q1; D209:
|
|
11
|
+
* Sygnal's npm package never ships xstream or snabbdom prebuilt into it). sygnal/vite resolves
|
|
12
|
+
* `sygnal/sandbox/kernel?raw` to this function's output (the project's own Vite), and
|
|
13
|
+
* `buildSandboxKernel()` (sygnal/sandbox/build) does it for other toolchains (Vite, esbuild or
|
|
14
|
+
* Rollup, whichever the project has).
|
|
15
|
+
*
|
|
16
|
+
* The output is one script: the platform prelude (timers, console, microtasks on `__host`,
|
|
17
|
+
* which the core's modules read when they load), then dist/sandbox-kernel.esm.js bundled as an
|
|
18
|
+
* IIFE with the installed sygnal (dist/index.esm.js and dist/host.esm.js of the same package: one
|
|
19
|
+
* core), xstream and snabbdom. `process.env.NODE_ENV` is 'production'; xstream's `globalthis`
|
|
20
|
+
* dependency is Sygnal's shim (as sygnal/vite does, G-099).
|
|
21
|
+
*/
|
|
22
|
+
// The platform a bare QuickJS context lacks. A plain script, so it runs before the bundle's modules.
|
|
23
|
+
const PLATFORM = `var global = globalThis;
|
|
24
|
+
(function () {
|
|
25
|
+
var H = globalThis.__host, G = globalThis, timers = new Map(), intervals = new Map(), seq = 0;
|
|
26
|
+
G.__sandboxTimers = timers;
|
|
27
|
+
G.queueMicrotask = G.queueMicrotask || function (f) { Promise.resolve().then(f) };
|
|
28
|
+
G.setTimeout = function (f, ms) { var id = ++seq; timers.set(id, f); H.timer(id, +ms || 0); return id };
|
|
29
|
+
G.clearTimeout = function (id) { if (timers.delete(id)) H.clearTimer(id) };
|
|
30
|
+
// the core's macrotask hop (runtime.ts macro()): its own channel, so a component's timers can't starve it
|
|
31
|
+
G.setImmediate = function (f) { var id = ++seq; timers.set(id, f); H.timer(id, -1); return id };
|
|
32
|
+
G.clearImmediate = G.clearTimeout;
|
|
33
|
+
G.setInterval = function (f, ms) { var box = {}; var tick = function () { box.id = G.setTimeout(tick, ms); f() }; box.id = G.setTimeout(tick, ms); var id = ++seq; intervals.set(id, box); return id };
|
|
34
|
+
G.clearInterval = function (id) { var b = intervals.get(id); if (b) { intervals.delete(id); G.clearTimeout(b.id) } };
|
|
35
|
+
G.requestAnimationFrame = function (f) { return G.setTimeout(function () { f(Date.now()) }, 16) };
|
|
36
|
+
G.cancelAnimationFrame = G.clearTimeout;
|
|
37
|
+
var fmt = function (a) { return a.map(function (x) { if (typeof x == 'string') return x; if (x instanceof Error) return x.name + ': ' + x.message; try { return JSON.stringify(x) } catch (e) { return String(x) } }).join(' ') };
|
|
38
|
+
G.console = {
|
|
39
|
+
log: function () { H.log('log', fmt([].slice.call(arguments))) }, info: function () { H.log('log', fmt([].slice.call(arguments))) },
|
|
40
|
+
warn: function () { H.log('warn', fmt([].slice.call(arguments))) }, error: function () { H.log('error', fmt([].slice.call(arguments))) },
|
|
41
|
+
debug: function () {},
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
`;
|
|
45
|
+
/** The guest kernel script for createSandbox / <Sandboxed> (`kernel`), built from the installed packages */
|
|
46
|
+
async function buildSandboxKernel(opts = {}) {
|
|
47
|
+
const [path, { createRequire }, { pathToFileURL }, fs] = await Promise.all([nodeImport('node:path'), nodeImport('node:module'), nodeImport('node:url'), nodeImport('node:fs')]);
|
|
48
|
+
const root = path.resolve(opts.root || globalThis.process.cwd());
|
|
49
|
+
const fromRoot = createRequire(path.join(root, 'package.json'));
|
|
50
|
+
// the app's sygnal (else this one): its dist/ holds the kernel entry, the core and the kit
|
|
51
|
+
let main;
|
|
52
|
+
try {
|
|
53
|
+
main = fromRoot.resolve('sygnal');
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
main = createRequire(import.meta.url).resolve('sygnal');
|
|
57
|
+
}
|
|
58
|
+
const dist = path.dirname(main);
|
|
59
|
+
const entry = path.join(dist, 'sandbox-kernel.esm.js');
|
|
60
|
+
const files = {
|
|
61
|
+
sygnal: path.join(dist, 'index.esm.js'),
|
|
62
|
+
'sygnal/host': path.join(dist, 'host.esm.js'),
|
|
63
|
+
globalthis: path.join(dist, 'shims/globalthis.cjs'),
|
|
64
|
+
};
|
|
65
|
+
for (const f of [entry, ...Object.values(files)])
|
|
66
|
+
if (!fs.existsSync(f))
|
|
67
|
+
throw new Error(`buildSandboxKernel: ${f} is missing (an incomplete sygnal install?)`);
|
|
68
|
+
const minify = opts.minify !== false;
|
|
69
|
+
const define = { 'process.env.NODE_ENV': '"production"' };
|
|
70
|
+
const has = (name) => { try {
|
|
71
|
+
fromRoot.resolve(name);
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return false;
|
|
76
|
+
} };
|
|
77
|
+
const want = opts.bundler || 'auto';
|
|
78
|
+
const bundler = want !== 'auto' ? want : has('vite') ? 'vite' : has('esbuild') ? 'esbuild' : has('rollup') ? 'rollup' : null;
|
|
79
|
+
if (!bundler)
|
|
80
|
+
throw new Error('buildSandboxKernel: needs vite, esbuild or rollup installed in ' + root);
|
|
81
|
+
const load = (name) => import(/* @vite-ignore */ pathToFileURL(resolveEsm(fromRoot, fs, path, name)).href);
|
|
82
|
+
let code;
|
|
83
|
+
if (bundler === 'esbuild') {
|
|
84
|
+
const esbuild = await load('esbuild');
|
|
85
|
+
const r = await (esbuild.build || esbuild.default.build)({
|
|
86
|
+
entryPoints: [entry], bundle: true, write: false, format: 'iife', platform: 'browser', target: 'es2020',
|
|
87
|
+
minify, define, alias: files, logLevel: 'silent', legalComments: 'none',
|
|
88
|
+
});
|
|
89
|
+
code = r.outputFiles[0].text;
|
|
90
|
+
}
|
|
91
|
+
else if (bundler === 'rollup') {
|
|
92
|
+
const { rollup } = await load('rollup');
|
|
93
|
+
const plugins = [{
|
|
94
|
+
name: 'sygnal-kernel', resolveId: (id) => files[id] || null,
|
|
95
|
+
transform: (c) => (c.includes('process.env.NODE_ENV') ? c.split('process.env.NODE_ENV').join(define['process.env.NODE_ENV']) : null),
|
|
96
|
+
}];
|
|
97
|
+
const req = async (n) => { const m = await load(n); return m.default || m; };
|
|
98
|
+
if (has('@rollup/plugin-node-resolve'))
|
|
99
|
+
plugins.push((await load('@rollup/plugin-node-resolve')).nodeResolve({ browser: true }));
|
|
100
|
+
if (has('@rollup/plugin-commonjs'))
|
|
101
|
+
plugins.push((await req('@rollup/plugin-commonjs'))());
|
|
102
|
+
if (minify && has('@rollup/plugin-terser'))
|
|
103
|
+
plugins.push((await req('@rollup/plugin-terser'))({ ecma: 2020 }));
|
|
104
|
+
const b = await rollup({ input: entry, plugins, onwarn: () => { } });
|
|
105
|
+
code = (await b.generate({ format: 'iife', name: '__sygnalKernel' })).output[0].code;
|
|
106
|
+
await b.close();
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
const vite = await load('vite');
|
|
110
|
+
const out = await vite.build({
|
|
111
|
+
configFile: false, root, logLevel: 'silent', mode: 'production', define,
|
|
112
|
+
resolve: { alias: Object.entries(files).map(([find, replacement]) => ({ find: new RegExp(`^${find.replace('/', '\\/')}$`), replacement })) },
|
|
113
|
+
build: { write: false, minify, target: 'es2020', lib: { entry, formats: ['iife'], name: '__sygnalKernel', fileName: () => 'kernel.js' }, rollupOptions: { output: { inlineDynamicImports: true } } },
|
|
114
|
+
});
|
|
115
|
+
const o = (Array.isArray(out) ? out[0] : out).output;
|
|
116
|
+
code = o.find((c) => c.type === 'chunk').code;
|
|
117
|
+
}
|
|
118
|
+
return PLATFORM + code;
|
|
119
|
+
}
|
|
120
|
+
// a package's ESM entry, as resolved from the app (import() needs a file URL, not a bare name, to resolve from there)
|
|
121
|
+
function resolveEsm(req, fs, path, name) {
|
|
122
|
+
try {
|
|
123
|
+
const pj = req.resolve(`${name}/package.json`);
|
|
124
|
+
const pkg = JSON.parse(fs.readFileSync(pj, 'utf8'));
|
|
125
|
+
const dot = typeof pkg.exports == 'string' ? pkg.exports : pkg.exports?.['.'];
|
|
126
|
+
let e = typeof dot == 'string' ? dot : dot?.import ?? pkg.module ?? pkg.main ?? 'index.js';
|
|
127
|
+
if (e && typeof e == 'object')
|
|
128
|
+
e = e.default;
|
|
129
|
+
return path.join(path.dirname(pj), e);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return req.resolve(name);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export { buildSandboxKernel };
|
|
137
|
+
//# sourceMappingURL=sandbox-build.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-build.esm.js","sources":["../src/sandbox/quickjs.ts","../src/sandbox/build.ts"],"sourcesContent":["/*\n * The QuickJS WASM module: `quickjs-emscripten-core` + `@jitl/quickjs-wasmfile-release-sync`,\n * optional peer dependencies (D209), loaded on first use. Stock packages only (README §9 Q6):\n * a quickjs-ng variant can be passed as `variant`.\n */\nimport {SandboxError} from './protocol'\n\nlet compiled: Promise<WebAssembly.Module> | null = null\nlet shared: Promise<any> | null = null\n\nexport interface LoadQuickJSOptions {\n /** the whole linear memory of a fresh instance capped at this (heap, ArrayBuffers, C stack) */\n maxWasmBytes?: number\n /** a shared module (one per page) instead of a fresh instance: no ArrayBuffer cap, and one crash poisons it for everyone */\n shared?: boolean\n /** another variant (default '@jitl/quickjs-wasmfile-release-sync') */\n variant?: any\n /** the .wasm bytes or a compiled WebAssembly.Module (default: the variant's own file) */\n wasm?: ArrayBuffer | Uint8Array | WebAssembly.Module\n}\n\nconst isNode = () => typeof (globalThis as any).process == 'object' && !!(globalThis as any).process.versions?.node && typeof (globalThis as any).window == 'undefined'\n\n/**\n * A QuickJS module. By default a fresh instance whose own `WebAssembly.Memory` is capped at\n * `maxWasmBytes` (64 MB): QuickJS's `setMemoryLimit()` doesn't count ArrayBuffer storage, so\n * without the cap a guest can grow the instance to 2 GB (README finding 1). Instances share\n * one compiled `WebAssembly.Module` (compiled once per page).\n */\nexport async function loadQuickJS(opts: LoadQuickJSOptions = {}): Promise<any> {\n if (opts.shared && !opts.wasm && !opts.variant && shared) return shared\n const p = load(opts)\n if (opts.shared && !opts.wasm && !opts.variant) shared = p\n return p\n}\n\nasync function load({maxWasmBytes = 64 << 20, shared: sh, variant, wasm}: LoadQuickJSOptions): Promise<any> {\n let core: any, base: any\n try {\n core = await import('quickjs-emscripten-core')\n base = variant || (await import('@jitl/quickjs-wasmfile-release-sync')).default\n } catch (e: any) {\n throw new Error(\"sygnal/sandbox needs quickjs-emscripten-core and @jitl/quickjs-wasmfile-release-sync (optional peer dependencies): npm install quickjs-emscripten-core @jitl/quickjs-wasmfile-release-sync (\" + (e?.message || e) + ')')\n }\n const custom: any = {}\n if (wasm) custom.wasmModule = wasm instanceof WebAssembly.Module ? wasm : await WebAssembly.compile(wasm as any)\n else if (!variant && isNode()) custom.wasmModule = await (compiled ??= nodeWasm())\n // a browser without `wasm` lets the variant fetch its .wasm itself (the bundler emits the file)\n if (!sh) custom.wasmMemory = new WebAssembly.Memory({initial: 256, maximum: Math.max(256, Math.ceil(maxWasmBytes / 65536))})\n return core.newQuickJSWASMModuleFromVariant(Object.keys(custom).length ? core.newVariant(base, custom) : base)\n}\n\nasync function nodeWasm(): Promise<WebAssembly.Module> {\n const [{readFile}, {createRequire}] = await Promise.all([nodeImport('node:fs/promises'), nodeImport('node:module')])\n // next to sygnal (a peer), else from the app's root\n let file: string\n try { file = createRequire(import.meta.url).resolve('@jitl/quickjs-wasmfile-release-sync/wasm') } catch {\n file = createRequire((globalThis as any).process.cwd() + '/').resolve('@jitl/quickjs-wasmfile-release-sync/wasm')\n }\n return WebAssembly.compile(await readFile(file))\n}\n\n// Node built-ins by a name bundlers don't follow (a browser bundle never loads them)\nexport const nodeImport = (name: string): Promise<any> => import(/* @vite-ignore */ /* webpackIgnore: true */ name)\n\n/**\n * Modules a guest crashed: the host's stack overflowed or the WASM trapped in the middle of a\n * QuickJS call, so its C state was unwound without cleanup. createSandbox refuses them.\n */\nexport const poisoned = new WeakSet<object>()\nexport const checkModule = (QJS: any) => {\n if (!QJS || typeof QJS.newRuntime != 'function') throw new TypeError('sygnal/sandbox: quickjs must be a module from loadQuickJS()')\n if (poisoned.has(QJS)) throw new SandboxError('crash', 'this QuickJS module crashed earlier; load a fresh one')\n}\n","/*\n * The guest kernel, built from the app's installed packages (README §7 option (a), §9 Q1; D209:\n * Sygnal's npm package never ships xstream or snabbdom prebuilt into it). sygnal/vite resolves\n * `sygnal/sandbox/kernel?raw` to this function's output (the project's own Vite), and\n * `buildSandboxKernel()` (sygnal/sandbox/build) does it for other toolchains (Vite, esbuild or\n * Rollup, whichever the project has).\n *\n * The output is one script: the platform prelude (timers, console, microtasks on `__host`,\n * which the core's modules read when they load), then dist/sandbox-kernel.esm.js bundled as an\n * IIFE with the installed sygnal (dist/index.esm.js and dist/host.esm.js of the same package: one\n * core), xstream and snabbdom. `process.env.NODE_ENV` is 'production'; xstream's `globalthis`\n * dependency is Sygnal's shim (as sygnal/vite does, G-099).\n */\nimport {nodeImport} from './quickjs'\n\n// The platform a bare QuickJS context lacks. A plain script, so it runs before the bundle's modules.\nexport const PLATFORM = `var global = globalThis;\n(function () {\n var H = globalThis.__host, G = globalThis, timers = new Map(), intervals = new Map(), seq = 0;\n G.__sandboxTimers = timers;\n G.queueMicrotask = G.queueMicrotask || function (f) { Promise.resolve().then(f) };\n G.setTimeout = function (f, ms) { var id = ++seq; timers.set(id, f); H.timer(id, +ms || 0); return id };\n G.clearTimeout = function (id) { if (timers.delete(id)) H.clearTimer(id) };\n // the core's macrotask hop (runtime.ts macro()): its own channel, so a component's timers can't starve it\n G.setImmediate = function (f) { var id = ++seq; timers.set(id, f); H.timer(id, -1); return id };\n G.clearImmediate = G.clearTimeout;\n G.setInterval = function (f, ms) { var box = {}; var tick = function () { box.id = G.setTimeout(tick, ms); f() }; box.id = G.setTimeout(tick, ms); var id = ++seq; intervals.set(id, box); return id };\n G.clearInterval = function (id) { var b = intervals.get(id); if (b) { intervals.delete(id); G.clearTimeout(b.id) } };\n G.requestAnimationFrame = function (f) { return G.setTimeout(function () { f(Date.now()) }, 16) };\n G.cancelAnimationFrame = G.clearTimeout;\n var fmt = function (a) { return a.map(function (x) { if (typeof x == 'string') return x; if (x instanceof Error) return x.name + ': ' + x.message; try { return JSON.stringify(x) } catch (e) { return String(x) } }).join(' ') };\n G.console = {\n log: function () { H.log('log', fmt([].slice.call(arguments))) }, info: function () { H.log('log', fmt([].slice.call(arguments))) },\n warn: function () { H.log('warn', fmt([].slice.call(arguments))) }, error: function () { H.log('error', fmt([].slice.call(arguments))) },\n debug: function () {},\n };\n})();\n`\n\nexport interface BuildSandboxKernelOptions {\n /** where the app's packages are installed (default: process.cwd()) */\n root?: string\n /** 'auto' (default): the project's Vite, else esbuild, else Rollup */\n bundler?: 'auto' | 'vite' | 'esbuild' | 'rollup'\n /** default true */\n minify?: boolean\n}\n\n/** The guest kernel script for createSandbox / <Sandboxed> (`kernel`), built from the installed packages */\nexport async function buildSandboxKernel(opts: BuildSandboxKernelOptions = {}): Promise<string> {\n const [path, {createRequire}, {pathToFileURL}, fs] = await Promise.all([nodeImport('node:path'), nodeImport('node:module'), nodeImport('node:url'), nodeImport('node:fs')])\n const root: string = path.resolve(opts.root || (globalThis as any).process.cwd())\n const fromRoot = createRequire(path.join(root, 'package.json'))\n // the app's sygnal (else this one): its dist/ holds the kernel entry, the core and the kit\n let main: string\n try { main = fromRoot.resolve('sygnal') } catch { main = createRequire(import.meta.url).resolve('sygnal') }\n const dist = path.dirname(main)\n const entry = path.join(dist, 'sandbox-kernel.esm.js')\n const files = {\n sygnal: path.join(dist, 'index.esm.js'),\n 'sygnal/host': path.join(dist, 'host.esm.js'),\n globalthis: path.join(dist, 'shims/globalthis.cjs'),\n }\n for (const f of [entry, ...Object.values(files)]) if (!fs.existsSync(f)) throw new Error(`buildSandboxKernel: ${f} is missing (an incomplete sygnal install?)`)\n const minify = opts.minify !== false\n const define = {'process.env.NODE_ENV': '\"production\"'}\n const has = (name: string) => { try { fromRoot.resolve(name); return true } catch { return false } }\n const want = opts.bundler || 'auto'\n const bundler = want !== 'auto' ? want : has('vite') ? 'vite' : has('esbuild') ? 'esbuild' : has('rollup') ? 'rollup' : null\n if (!bundler) throw new Error('buildSandboxKernel: needs vite, esbuild or rollup installed in ' + root)\n const load = (name: string) => import(/* @vite-ignore */ pathToFileURL(resolveEsm(fromRoot, fs, path, name)).href)\n let code: string\n\n if (bundler === 'esbuild') {\n const esbuild = await load('esbuild')\n const r = await (esbuild.build || esbuild.default.build)({\n entryPoints: [entry], bundle: true, write: false, format: 'iife', platform: 'browser', target: 'es2020',\n minify, define, alias: files, logLevel: 'silent', legalComments: 'none',\n })\n code = r.outputFiles[0].text\n } else if (bundler === 'rollup') {\n const {rollup} = await load('rollup')\n const plugins: any[] = [{\n name: 'sygnal-kernel', resolveId: (id: string) => (files as any)[id] || null,\n transform: (c: string) => (c.includes('process.env.NODE_ENV') ? c.split('process.env.NODE_ENV').join(define['process.env.NODE_ENV']) : null),\n }]\n const req = async (n: string) => { const m = await load(n); return m.default || m }\n if (has('@rollup/plugin-node-resolve')) plugins.push((await load('@rollup/plugin-node-resolve')).nodeResolve({browser: true}))\n if (has('@rollup/plugin-commonjs')) plugins.push((await req('@rollup/plugin-commonjs'))())\n if (minify && has('@rollup/plugin-terser')) plugins.push((await req('@rollup/plugin-terser'))({ecma: 2020}))\n const b = await rollup({input: entry, plugins, onwarn: () => {}})\n code = (await b.generate({format: 'iife', name: '__sygnalKernel'})).output[0].code\n await b.close()\n } else {\n const vite = await load('vite')\n const out: any = await vite.build({\n configFile: false, root, logLevel: 'silent', mode: 'production', define,\n resolve: {alias: Object.entries(files).map(([find, replacement]) => ({find: new RegExp(`^${find.replace('/', '\\\\/')}$`), replacement}))},\n build: {write: false, minify, target: 'es2020', lib: {entry, formats: ['iife'], name: '__sygnalKernel', fileName: () => 'kernel.js'}, rollupOptions: {output: {inlineDynamicImports: true}}},\n })\n const o = (Array.isArray(out) ? out[0] : out).output\n code = o.find((c: any) => c.type === 'chunk').code\n }\n return PLATFORM + code\n}\n\n// a package's ESM entry, as resolved from the app (import() needs a file URL, not a bare name, to resolve from there)\nfunction resolveEsm(req: any, fs: any, path: any, name: string): string {\n try {\n const pj = req.resolve(`${name}/package.json`)\n const pkg = JSON.parse(fs.readFileSync(pj, 'utf8'))\n const dot = typeof pkg.exports == 'string' ? pkg.exports : pkg.exports?.['.']\n let e = typeof dot == 'string' ? dot : dot?.import ?? pkg.module ?? pkg.main ?? 'index.js'\n if (e && typeof e == 'object') e = e.default\n return path.join(path.dirname(pj), e)\n } catch {\n return req.resolve(name)\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { xs, run, makeFetchDriver, createElement, ABORT, classes, set, toggle, event, debounce, throttle, delay, dropRepeats, sampleCombine, Collection, Switchable } from 'sygnal';
|
|
2
|
+
import { HostDocument, HostEvent, makeHostDriver, nodeId } from 'sygnal/host';
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* The guest kernel: runs INSIDE the QuickJS context, next to the untrusted component.
|
|
6
|
+
*
|
|
7
|
+
* Built as dist/sandbox-kernel.esm.js with 'sygnal' and 'sygnal/host' external; sygnal/vite
|
|
8
|
+
* (`sygnal/sandbox/kernel?raw`) or buildSandboxKernel() bundles it with the app's installed
|
|
9
|
+
* sygnal, xstream and snabbdom into one script (D209: never shipped prebuilt), after the
|
|
10
|
+
* platform prelude (build.ts PLATFORM: timers, console, microtasks; the core's modules read
|
|
11
|
+
* setTimeout when they load). Nothing here is a security boundary: the component runs in the
|
|
12
|
+
* same context and can tamper with all of it. The boundary is the bridge (`__host`), which the
|
|
13
|
+
* page checks (engine.ts, mirror.ts). The kernel only makes the guest side convenient:
|
|
14
|
+
*
|
|
15
|
+
* - the component renders through the real core into a sygnal/host tree (HostDocument);
|
|
16
|
+
* - after each entry the tree goes out as JSON (ids from nodeId; a subtree whose revision didn't
|
|
17
|
+
* move goes out as its bare id), with the event types the app listens for;
|
|
18
|
+
* - events come in as {id, type, init}: the kernel finds the host element, syncs value/checked
|
|
19
|
+
* as a browser would have, dispatches a HostEvent and returns whether it was prevented;
|
|
20
|
+
* - drivers: DOM (host tree), STATE (the core's own), EVENTS (a bus; each event also goes to the
|
|
21
|
+
* page), PROPS (from the page), HTTP (makeFetchDriver over the page's checked fetch).
|
|
22
|
+
*/
|
|
23
|
+
const PROTOCOL = 1;
|
|
24
|
+
const G = globalThis;
|
|
25
|
+
const H = G.__host;
|
|
26
|
+
const timers = G.__sandboxTimers;
|
|
27
|
+
// --- the tree going out --------------------------------------------------------------------------
|
|
28
|
+
const doc = new HostDocument();
|
|
29
|
+
const byId = new Map(); // id → host node (events look elements up)
|
|
30
|
+
const sent = new Map(); // id → revision last sent
|
|
31
|
+
// {i, t, a, s, v, k, c} for an element, {i, x} for a text, a bare id for an unchanged subtree
|
|
32
|
+
function ser(n, out) {
|
|
33
|
+
const i = nodeId(n);
|
|
34
|
+
out.set(i, n);
|
|
35
|
+
if (sent.get(i) === n.revision) {
|
|
36
|
+
mark(n, out);
|
|
37
|
+
return i;
|
|
38
|
+
}
|
|
39
|
+
sent.set(i, n.revision);
|
|
40
|
+
if (n.nodeType === 3)
|
|
41
|
+
return { i, x: String(n.textContent) };
|
|
42
|
+
const a = {};
|
|
43
|
+
for (const [k, v] of n.attributes)
|
|
44
|
+
a[k] = v;
|
|
45
|
+
const s = {};
|
|
46
|
+
for (const k of Object.keys(n.style))
|
|
47
|
+
s[k] = String(n.style[k]);
|
|
48
|
+
const o = { i, t: n.localName, a, c: n.childNodes.map((c) => ser(c, out)) };
|
|
49
|
+
if (Object.keys(s).length)
|
|
50
|
+
o.s = s;
|
|
51
|
+
if (/^(input|textarea|select)$/.test(n.localName)) {
|
|
52
|
+
o.v = n.value;
|
|
53
|
+
o.k = n.checked;
|
|
54
|
+
}
|
|
55
|
+
if (n.localName === 'option' && n.selected)
|
|
56
|
+
o.k = true;
|
|
57
|
+
return o;
|
|
58
|
+
}
|
|
59
|
+
// an unchanged subtree's nodes stay addressable
|
|
60
|
+
function mark(n, out) { if (n.childNodes)
|
|
61
|
+
for (const c of n.childNodes) {
|
|
62
|
+
out.set(nodeId(c), c);
|
|
63
|
+
mark(c, out);
|
|
64
|
+
} }
|
|
65
|
+
let dirty = false, lastMsg = '', focused = null;
|
|
66
|
+
function flushTree() {
|
|
67
|
+
dirty = false;
|
|
68
|
+
const out = new Map();
|
|
69
|
+
const tree = doc.body.childNodes.map((c) => ser(c, out));
|
|
70
|
+
byId.clear();
|
|
71
|
+
for (const [k, v] of out)
|
|
72
|
+
byId.set(k, v);
|
|
73
|
+
for (const k of [...sent.keys()])
|
|
74
|
+
if (!out.has(k))
|
|
75
|
+
sent.delete(k);
|
|
76
|
+
// the event types to listen for at the sandbox root (delegated, as the DOM driver does)
|
|
77
|
+
const types = [...new Set([...doc.delegates].map((d) => d.type))];
|
|
78
|
+
const msg = { v: PROTOCOL, tree, types };
|
|
79
|
+
// focus the guest moved (autoFocus, an ELEMENT focus command); the page applies it only with
|
|
80
|
+
// the focus capability and while focus is inside the box
|
|
81
|
+
const active = doc.activeElement;
|
|
82
|
+
if (active && active !== focused && byId.has(nodeId(active)))
|
|
83
|
+
msg.f = nodeId(active);
|
|
84
|
+
focused = active;
|
|
85
|
+
const json = JSON.stringify(msg);
|
|
86
|
+
// nothing moved (a change that patched back to what was sent): no message
|
|
87
|
+
if (json !== lastMsg || tree.some((n) => typeof n != 'number'))
|
|
88
|
+
H.render(lastMsg = json);
|
|
89
|
+
}
|
|
90
|
+
// one render per guest entry: the page calls __sandbox.flush() once the entry's promise jobs ran
|
|
91
|
+
// (a checkbox click changes the tree twice, its checked state, then the patch: one message)
|
|
92
|
+
doc.onChange = () => { dirty = true; };
|
|
93
|
+
// --- events coming in ----------------------------------------------------------------------------
|
|
94
|
+
const EVENT_FIELDS = /^(key|code|shiftKey|ctrlKey|altKey|metaKey|button|clientX|clientY|deltaX|deltaY|detail)$/;
|
|
95
|
+
const props$ = xs.createWithMemory();
|
|
96
|
+
const fetches = new Map();
|
|
97
|
+
let app;
|
|
98
|
+
G.__sandbox = {
|
|
99
|
+
v: PROTOCOL,
|
|
100
|
+
// returns 1 when the guest prevented the default action
|
|
101
|
+
dispatch(id, type, initJson) {
|
|
102
|
+
const el = byId.get(id);
|
|
103
|
+
if (!el || el.nodeType !== 1)
|
|
104
|
+
return 0;
|
|
105
|
+
const init = JSON.parse(initJson || '{}');
|
|
106
|
+
if ('value' in init)
|
|
107
|
+
el.value = init.value;
|
|
108
|
+
if ('checked' in init)
|
|
109
|
+
el.checked = !!init.checked;
|
|
110
|
+
if (type === 'focus' || type === 'focusin')
|
|
111
|
+
doc.activeElement = focused = el;
|
|
112
|
+
const e = new HostEvent(type, { bubbles: !/^(focus|blur|mouseenter|mouseleave)$/.test(type) });
|
|
113
|
+
for (const k in init)
|
|
114
|
+
if (EVENT_FIELDS.test(k))
|
|
115
|
+
e[k] = init[k];
|
|
116
|
+
return el.dispatchEvent(e) ? 0 : 1;
|
|
117
|
+
},
|
|
118
|
+
flush() { if (dirty || doc.activeElement !== focused)
|
|
119
|
+
flushTree(); return 0; },
|
|
120
|
+
fire(id) { const f = timers.get(id); timers.delete(id); if (f)
|
|
121
|
+
f(); },
|
|
122
|
+
resolve(id, ok, payload) {
|
|
123
|
+
const p = fetches.get(id);
|
|
124
|
+
fetches.delete(id);
|
|
125
|
+
if (p)
|
|
126
|
+
ok ? p.ok(JSON.parse(payload)) : p.fail(new Error(payload));
|
|
127
|
+
},
|
|
128
|
+
props(json) { props$.shamefullySendNext(JSON.parse(json)); },
|
|
129
|
+
start(exportName) {
|
|
130
|
+
const mod = G.module.exports;
|
|
131
|
+
const App = exportName ? mod[exportName] : (mod.default || Object.values(mod).find((v) => typeof v == 'function'));
|
|
132
|
+
if (typeof App != 'function')
|
|
133
|
+
throw new Error('sandbox: the source exports no component');
|
|
134
|
+
// a root without state never renders (SYG204); generated code often has none
|
|
135
|
+
if (App.initialState === undefined)
|
|
136
|
+
App.initialState = {};
|
|
137
|
+
wiringCheck(App);
|
|
138
|
+
app = run(App, {
|
|
139
|
+
DOM: makeHostDriver(doc, { onError: (e) => console.error('patch', String(e?.message || e)) }),
|
|
140
|
+
EVENTS: eventsDriver,
|
|
141
|
+
PROPS: () => ({ stream: props$, get: (k) => props$.map((p) => (k ? p?.[k] : p)) }),
|
|
142
|
+
HTTP: makeFetchDriver({ fetch: pageFetch }),
|
|
143
|
+
}, { useDefaultDrivers: false });
|
|
144
|
+
return 1;
|
|
145
|
+
},
|
|
146
|
+
dispose() { app && app.dispose(); },
|
|
147
|
+
};
|
|
148
|
+
// sygnal-check's SYG101 at boot, on the actions the intent really returns: an action with no model
|
|
149
|
+
// entry does nothing and throws nothing (the core's own check is in the dev build only). Model-written
|
|
150
|
+
// code gets this wrong silently, so the kernel says so; a page may treat the line as a failure
|
|
151
|
+
// (compose.generated does). Behavior actions ('page.COMPOSE') belong to `uses`: not checked.
|
|
152
|
+
function wiringCheck(App) {
|
|
153
|
+
const intent = App.intent, model = App.model;
|
|
154
|
+
if (typeof intent != 'function' || (model != null && typeof model != 'object'))
|
|
155
|
+
return;
|
|
156
|
+
App.intent = function (...args) {
|
|
157
|
+
const out = intent.apply(this, args);
|
|
158
|
+
if (out && typeof out == 'object') {
|
|
159
|
+
for (const k of Object.keys(out)) {
|
|
160
|
+
if (k.includes('.') || (model && Object.prototype.hasOwnProperty.call(model, k)))
|
|
161
|
+
continue;
|
|
162
|
+
console.warn(`[Sygnal SYG101] intent action '${k}' has no model entry, so it never does anything; add '${k}' to model or remove it from intent`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return out;
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
// --- drivers -------------------------------------------------------------------------------------
|
|
169
|
+
// HTTP: the core's own makeFetchDriver over a Response-shaped capability; the page checks the URL
|
|
170
|
+
let fetchSeq = 0;
|
|
171
|
+
const pageFetch = (url, init = {}) => new Promise((ok, fail) => {
|
|
172
|
+
const id = ++fetchSeq;
|
|
173
|
+
fetches.set(id, { ok, fail });
|
|
174
|
+
H.fetch(id, String(url), JSON.stringify({ method: init.method || 'GET', headers: init.headers || {}, body: typeof init.body == 'string' ? init.body : undefined }));
|
|
175
|
+
}).then((r) => ({
|
|
176
|
+
ok: r.status >= 200 && r.status < 300, status: r.status, statusText: '',
|
|
177
|
+
headers: { get: (k) => r.headers[String(k).toLowerCase()] ?? null },
|
|
178
|
+
json: async () => JSON.parse(r.body), text: async () => r.body,
|
|
179
|
+
}));
|
|
180
|
+
// EVENTS: an in-guest bus (eventBusDriver needs EventTarget); each event also goes to the page,
|
|
181
|
+
// which only delivers the types declared in `emits`, validated by their schemas
|
|
182
|
+
function eventsDriver(out$) {
|
|
183
|
+
const bus = xs.create();
|
|
184
|
+
out$.addListener({
|
|
185
|
+
next: (ev) => {
|
|
186
|
+
bus.shamefullySendNext(ev);
|
|
187
|
+
try {
|
|
188
|
+
H.emit(JSON.stringify({ type: String(ev?.type), data: ev?.data }));
|
|
189
|
+
}
|
|
190
|
+
catch (e) {
|
|
191
|
+
console.error('EVENTS: data must be JSON', String(e));
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
error: () => { }, complete: () => { },
|
|
195
|
+
});
|
|
196
|
+
return { select: (type) => bus.filter((ev) => !type || ev.type === type || (Array.isArray(type) && type.includes(ev.type))).map((ev) => ev.data ?? null) };
|
|
197
|
+
}
|
|
198
|
+
// what a component may import: `require('sygnal')` (a compiled `import {ABORT} from 'sygnal'`)
|
|
199
|
+
function Fragment() { }
|
|
200
|
+
Fragment.__sygnalFragment = true;
|
|
201
|
+
const SYGNAL = Object.freeze({ xs, createElement, Fragment, ABORT, classes, set, toggle, event, debounce, throttle, delay, dropRepeats, sampleCombine, Collection, Switchable });
|
|
202
|
+
G.require = (name) => {
|
|
203
|
+
if (name === 'sygnal' || name === 'sygnal/jsx')
|
|
204
|
+
return SYGNAL;
|
|
205
|
+
throw new Error(`sandbox: '${name}' can't be imported here`);
|
|
206
|
+
};
|
|
207
|
+
// the JSX a host compiles guest code to: __h(tag, props, ...children), __frag
|
|
208
|
+
G.__h = createElement;
|
|
209
|
+
G.__frag = Fragment;
|
|
210
|
+
G.module = { exports: {} };
|
|
211
|
+
G.exports = G.module.exports;
|
|
212
|
+
//# sourceMappingURL=sandbox-kernel.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-kernel.esm.js","sources":["../src/sandbox/kernel.ts"],"sourcesContent":["/*\n * The guest kernel: runs INSIDE the QuickJS context, next to the untrusted component.\n *\n * Built as dist/sandbox-kernel.esm.js with 'sygnal' and 'sygnal/host' external; sygnal/vite\n * (`sygnal/sandbox/kernel?raw`) or buildSandboxKernel() bundles it with the app's installed\n * sygnal, xstream and snabbdom into one script (D209: never shipped prebuilt), after the\n * platform prelude (build.ts PLATFORM: timers, console, microtasks; the core's modules read\n * setTimeout when they load). Nothing here is a security boundary: the component runs in the\n * same context and can tamper with all of it. The boundary is the bridge (`__host`), which the\n * page checks (engine.ts, mirror.ts). The kernel only makes the guest side convenient:\n *\n * - the component renders through the real core into a sygnal/host tree (HostDocument);\n * - after each entry the tree goes out as JSON (ids from nodeId; a subtree whose revision didn't\n * move goes out as its bare id), with the event types the app listens for;\n * - events come in as {id, type, init}: the kernel finds the host element, syncs value/checked\n * as a browser would have, dispatches a HostEvent and returns whether it was prevented;\n * - drivers: DOM (host tree), STATE (the core's own), EVENTS (a bus; each event also goes to the\n * page), PROPS (from the page), HTTP (makeFetchDriver over the page's checked fetch).\n */\nimport {run, xs, createElement, makeFetchDriver, ABORT, classes, set, toggle, event, debounce, throttle, delay, dropRepeats, sampleCombine, Collection, Switchable} from '../index'\nimport {HostDocument, HostEvent, makeHostDriver, nodeId} from '../host'\n\nconst PROTOCOL = 1\nconst G: any = globalThis\nconst H: any = G.__host\nconst timers: Map<number, () => void> = G.__sandboxTimers\n\n// --- the tree going out --------------------------------------------------------------------------\nconst doc: any = new HostDocument()\nconst byId = new Map<number, any>() // id → host node (events look elements up)\nconst sent = new Map<number, number>() // id → revision last sent\n// {i, t, a, s, v, k, c} for an element, {i, x} for a text, a bare id for an unchanged subtree\nfunction ser(n: any, out: Map<number, any>): any {\n const i = nodeId(n)\n out.set(i, n)\n if (sent.get(i) === n.revision) { mark(n, out); return i }\n sent.set(i, n.revision)\n if (n.nodeType === 3) return {i, x: String(n.textContent)}\n const a: any = {}\n for (const [k, v] of n.attributes) a[k] = v\n const s: any = {}\n for (const k of Object.keys(n.style)) s[k] = String(n.style[k])\n const o: any = {i, t: n.localName, a, c: n.childNodes.map((c: any) => ser(c, out))}\n if (Object.keys(s).length) o.s = s\n if (/^(input|textarea|select)$/.test(n.localName)) { o.v = n.value; o.k = n.checked }\n if (n.localName === 'option' && n.selected) o.k = true\n return o\n}\n// an unchanged subtree's nodes stay addressable\nfunction mark(n: any, out: Map<number, any>) { if (n.childNodes) for (const c of n.childNodes) { out.set(nodeId(c), c); mark(c, out) } }\n\nlet dirty = false, lastMsg = '', focused: any = null\nfunction flushTree() {\n dirty = false\n const out = new Map<number, any>()\n const tree = doc.body.childNodes.map((c: any) => ser(c, out))\n byId.clear()\n for (const [k, v] of out) byId.set(k, v)\n for (const k of [...sent.keys()]) if (!out.has(k)) sent.delete(k)\n // the event types to listen for at the sandbox root (delegated, as the DOM driver does)\n const types = [...new Set([...doc.delegates].map((d: any) => d.type))]\n const msg: any = {v: PROTOCOL, tree, types}\n // focus the guest moved (autoFocus, an ELEMENT focus command); the page applies it only with\n // the focus capability and while focus is inside the box\n const active = doc.activeElement\n if (active && active !== focused && byId.has(nodeId(active))) msg.f = nodeId(active)\n focused = active\n const json = JSON.stringify(msg)\n // nothing moved (a change that patched back to what was sent): no message\n if (json !== lastMsg || tree.some((n: any) => typeof n != 'number')) H.render(lastMsg = json)\n}\n// one render per guest entry: the page calls __sandbox.flush() once the entry's promise jobs ran\n// (a checkbox click changes the tree twice, its checked state, then the patch: one message)\ndoc.onChange = () => { dirty = true }\n\n// --- events coming in ----------------------------------------------------------------------------\nconst EVENT_FIELDS = /^(key|code|shiftKey|ctrlKey|altKey|metaKey|button|clientX|clientY|deltaX|deltaY|detail)$/\nconst props$: any = xs.createWithMemory()\nconst fetches = new Map<number, {ok: (v: any) => void; fail: (e: any) => void}>()\nlet app: any\n\nG.__sandbox = {\n v: PROTOCOL,\n // returns 1 when the guest prevented the default action\n dispatch(id: number, type: string, initJson: string) {\n const el = byId.get(id)\n if (!el || el.nodeType !== 1) return 0\n const init = JSON.parse(initJson || '{}')\n if ('value' in init) el.value = init.value\n if ('checked' in init) el.checked = !!init.checked\n if (type === 'focus' || type === 'focusin') doc.activeElement = focused = el\n const e: any = new HostEvent(type, {bubbles: !/^(focus|blur|mouseenter|mouseleave)$/.test(type)})\n for (const k in init) if (EVENT_FIELDS.test(k)) e[k] = init[k]\n return el.dispatchEvent(e) ? 0 : 1\n },\n flush() { if (dirty || doc.activeElement !== focused) flushTree(); return 0 },\n fire(id: number) { const f = timers.get(id); timers.delete(id); if (f) f() },\n resolve(id: number, ok: number, payload: string) {\n const p = fetches.get(id)\n fetches.delete(id)\n if (p) ok ? p.ok(JSON.parse(payload)) : p.fail(new Error(payload))\n },\n props(json: string) { props$.shamefullySendNext(JSON.parse(json)) },\n start(exportName: string) {\n const mod = G.module.exports\n const App = exportName ? mod[exportName] : (mod.default || Object.values(mod).find((v) => typeof v == 'function'))\n if (typeof App != 'function') throw new Error('sandbox: the source exports no component')\n // a root without state never renders (SYG204); generated code often has none\n if (App.initialState === undefined) App.initialState = {}\n wiringCheck(App)\n app = run(App, {\n DOM: makeHostDriver(doc, {onError: (e: any) => console.error('patch', String(e?.message || e))}),\n EVENTS: eventsDriver,\n PROPS: () => ({stream: props$, get: (k?: string) => props$.map((p: any) => (k ? p?.[k] : p))}),\n HTTP: makeFetchDriver({fetch: pageFetch as any}),\n } as any, {useDefaultDrivers: false} as any)\n return 1\n },\n dispose() { app && app.dispose() },\n}\n\n// sygnal-check's SYG101 at boot, on the actions the intent really returns: an action with no model\n// entry does nothing and throws nothing (the core's own check is in the dev build only). Model-written\n// code gets this wrong silently, so the kernel says so; a page may treat the line as a failure\n// (compose.generated does). Behavior actions ('page.COMPOSE') belong to `uses`: not checked.\nfunction wiringCheck(App: any) {\n const intent = App.intent, model = App.model\n if (typeof intent != 'function' || (model != null && typeof model != 'object')) return\n App.intent = function (this: any, ...args: any[]) {\n const out = intent.apply(this, args)\n if (out && typeof out == 'object') {\n for (const k of Object.keys(out)) {\n if (k.includes('.') || (model && Object.prototype.hasOwnProperty.call(model, k))) continue\n console.warn(`[Sygnal SYG101] intent action '${k}' has no model entry, so it never does anything; add '${k}' to model or remove it from intent`)\n }\n }\n return out\n }\n}\n\n// --- drivers -------------------------------------------------------------------------------------\n// HTTP: the core's own makeFetchDriver over a Response-shaped capability; the page checks the URL\nlet fetchSeq = 0\nconst pageFetch = (url: string, init: any = {}) => new Promise((ok, fail) => {\n const id = ++fetchSeq\n fetches.set(id, {ok, fail})\n H.fetch(id, String(url), JSON.stringify({method: init.method || 'GET', headers: init.headers || {}, body: typeof init.body == 'string' ? init.body : undefined}))\n}).then((r: any) => ({\n ok: r.status >= 200 && r.status < 300, status: r.status, statusText: '',\n headers: {get: (k: string) => r.headers[String(k).toLowerCase()] ?? null},\n json: async () => JSON.parse(r.body), text: async () => r.body,\n}))\n\n// EVENTS: an in-guest bus (eventBusDriver needs EventTarget); each event also goes to the page,\n// which only delivers the types declared in `emits`, validated by their schemas\nfunction eventsDriver(out$: any) {\n const bus: any = xs.create()\n out$.addListener({\n next: (ev: any) => {\n bus.shamefullySendNext(ev)\n try { H.emit(JSON.stringify({type: String(ev?.type), data: ev?.data})) } catch (e) { console.error('EVENTS: data must be JSON', String(e)) }\n },\n error: () => {}, complete: () => {},\n })\n return {select: (type?: string | string[]) => bus.filter((ev: any) => !type || ev.type === type || (Array.isArray(type) && type.includes(ev.type))).map((ev: any) => ev.data ?? null)}\n}\n\n// what a component may import: `require('sygnal')` (a compiled `import {ABORT} from 'sygnal'`)\nfunction Fragment() {}\n;(Fragment as any).__sygnalFragment = true\nconst SYGNAL = Object.freeze({xs, createElement, Fragment, ABORT, classes, set, toggle, event, debounce, throttle, delay, dropRepeats, sampleCombine, Collection, Switchable})\nG.require = (name: string) => {\n if (name === 'sygnal' || name === 'sygnal/jsx') return SYGNAL\n throw new Error(`sandbox: '${name}' can't be imported here`)\n}\n// the JSX a host compiles guest code to: __h(tag, props, ...children), __frag\nG.__h = createElement\nG.__frag = Fragment\nG.module = {exports: {}}\nG.exports = G.module.exports\n"],"names":[],"mappings":"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"}
|