@viji-dev/core 0.4.3 → 0.4.5

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.
@@ -6,7 +6,7 @@ class VijiCoreError extends Error {
6
6
  this.name = "VijiCoreError";
7
7
  }
8
8
  }
9
- const inlineScriptCode = '"use strict";\n(() => {\n // src/iframe/protocol.ts\n var PROTOCOL_VERSION = 1;\n function collectTransferables(msg) {\n switch (msg.type) {\n case "init": {\n const m = msg;\n const out = [];\n if (m.data?.canvas) out.push(m.data.canvas);\n const wasm = m.data?.cvWasmFiles;\n if (wasm) {\n out.push(\n wasm.simdLoaderJs,\n wasm.simdBinary,\n wasm.nosimdLoaderJs,\n wasm.nosimdBinary\n );\n }\n return out;\n }\n case "video-canvas-setup": {\n const m = msg;\n return m.data?.offscreenCanvas ? [m.data.offscreenCanvas] : [];\n }\n case "video-frame-update": {\n const m = msg;\n return m.data?.imageBitmap ? [m.data.imageBitmap] : [];\n }\n case "video-frame-direct": {\n const m = msg;\n return m.data?.imageBitmap ? [m.data.imageBitmap] : [];\n }\n case "parameter-update": {\n const m = msg;\n return m.data?.transferList ?? [];\n }\n case "parameter-batch-update": {\n const m = msg;\n return m.data?.transferList ?? [];\n }\n case "audio-analysis-update": {\n const m = msg;\n const out = [];\n if (m.data?.frequencyData?.buffer) out.push(m.data.frequencyData.buffer);\n if (m.data?.waveformData?.buffer) out.push(m.data.waveformData.buffer);\n return out;\n }\n case "capture-frame-result":\n case "auto-capture-result": {\n const data = msg.data;\n return data?.bitmap ? [data.bitmap] : [];\n }\n default:\n return [];\n }\n }\n\n // src/iframe/inline-script.ts\n var hostOrigin = null;\n var hostWindow = null;\n var worker = null;\n var canvas = null;\n var domHandlersAttached = false;\n var sensorHandlersAttached = false;\n function whenDomReady() {\n if (document.readyState === "loading") {\n return new Promise((resolve) => {\n document.addEventListener("DOMContentLoaded", () => resolve(), {\n once: true\n });\n });\n }\n return Promise.resolve();\n }\n async function announceReady() {\n await whenDomReady();\n const msg = {\n type: "iframe-ready",\n protocolVersion: PROTOCOL_VERSION\n };\n window.parent.postMessage(msg, "*");\n }\n function installHostListener() {\n window.addEventListener("message", (event) => {\n if (event.source !== window.parent) return;\n if (hostOrigin === null) {\n hostOrigin = event.origin;\n hostWindow = window.parent;\n } else if (event.origin !== hostOrigin) {\n return;\n }\n handleHostMessage(event.data).catch((err) => {\n reportError(err);\n });\n });\n }\n function postToHost(msg, transfer = []) {\n if (hostOrigin === null || hostWindow === null) {\n return;\n }\n const targetOrigin = hostOrigin === "null" ? "*" : hostOrigin;\n hostWindow.postMessage(msg, targetOrigin, transfer);\n }\n function reportError(err) {\n const e = err;\n const msg = e?.stack ? {\n type: "iframe-error",\n message: e.message ?? String(err),\n stack: e.stack\n } : {\n type: "iframe-error",\n message: e?.message ?? String(err)\n };\n if (hostOrigin && hostWindow) {\n const targetOrigin = hostOrigin === "null" ? "*" : hostOrigin;\n hostWindow.postMessage(msg, targetOrigin);\n } else {\n window.parent.postMessage(msg, "*");\n }\n }\n async function handleHostMessage(msg) {\n switch (msg.type) {\n case "viji-bootstrap":\n await handleBootstrap(msg);\n return;\n case "viji-host-message":\n relayHostToWorker(msg.payload);\n return;\n case "viji-resize":\n handleResize(msg.width, msg.height);\n return;\n case "viji-enable-sensors":\n setSensorsEnabled(msg.enabled);\n return;\n case "viji-enable-interaction":\n setInteractionEnabled(msg.enabled);\n return;\n case "viji-terminate":\n handleTerminate();\n return;\n }\n }\n async function handleBootstrap(msg) {\n if (worker) {\n return;\n }\n canvas = document.createElement("canvas");\n canvas.id = "viji-canvas";\n canvas.width = msg.init.canvasWidth;\n canvas.height = msg.init.canvasHeight;\n canvas.style.width = "100%";\n canvas.style.height = "100%";\n canvas.style.display = "block";\n canvas.tabIndex = 0;\n canvas.style.outline = "none";\n document.body.appendChild(canvas);\n const offscreen = canvas.transferControlToOffscreen();\n const workerSource = arrayBufferToString(msg.workerCode);\n const workerDataUrl = "data:text/javascript;base64," + base64Encode(workerSource);\n worker = new Worker(workerDataUrl, { type: "module" });\n worker.onerror = (e) => {\n reportError(new Error(`Worker error: ${e.message ?? String(e)}`));\n };\n worker.onmessage = (event) => {\n relayWorkerToHost(event.data);\n };\n const initId = `init_${Date.now()}`;\n const initMsg = {\n type: "init",\n id: initId,\n timestamp: Date.now(),\n data: {\n canvas: offscreen,\n isHeadless: msg.init.isHeadless,\n sc: msg.init.sc,\n rh: msg.init.rh,\n cvWasmFiles: msg.wasmFiles\n }\n };\n const initResponse = waitForWorkerMessage((m) => {\n return m && m.type === "init-response" && m.id === initId;\n });\n worker.postMessage(initMsg, [\n offscreen,\n msg.wasmFiles.simdLoaderJs,\n msg.wasmFiles.simdBinary,\n msg.wasmFiles.nosimdLoaderJs,\n msg.wasmFiles.nosimdBinary\n ]);\n await initResponse;\n if (msg.init.allowInteraction && !msg.init.isHeadless) {\n setInteractionEnabled(true);\n }\n if (msg.init.allowSensors && !msg.init.isHeadless) {\n setSensorsEnabled(true);\n }\n if (canvas) {\n canvas.addEventListener("contextmenu", (e) => e.preventDefault());\n }\n postToHost({ type: "viji-ready" });\n }\n function arrayBufferToString(buf) {\n return new TextDecoder("utf-8").decode(buf);\n }\n function base64Encode(s) {\n const bytes = new TextEncoder().encode(s);\n let binary = "";\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);\n return btoa(binary);\n }\n function waitForWorkerMessage(predicate) {\n return new Promise((resolve, reject) => {\n if (!worker) {\n reject(new Error("worker not spawned"));\n return;\n }\n const w = worker;\n const onceListener = (event) => {\n if (predicate(event.data)) {\n w.removeEventListener("message", onceListener);\n resolve(event.data);\n }\n };\n w.addEventListener("message", onceListener);\n });\n }\n function relayHostToWorker(payload) {\n if (!worker || !payload) return;\n try {\n const transfer = collectTransferables(payload);\n worker.postMessage(payload, transfer);\n } catch (err) {\n reportError(err);\n }\n }\n function relayWorkerToHost(payload) {\n if (!payload) return;\n try {\n const transfer = collectTransferables(payload);\n postToHost(\n { type: "worker-message", payload },\n transfer\n );\n } catch (err) {\n reportError(err);\n }\n }\n function handleResize(width, height) {\n if (!worker) return;\n worker.postMessage({\n type: "resolution-update",\n id: `resize_${Date.now()}`,\n timestamp: Date.now(),\n data: {\n effectiveWidth: width,\n effectiveHeight: height,\n displayScale: 1\n }\n });\n }\n var isMouseInCanvas = false;\n function setInteractionEnabled(enabled) {\n if (enabled === domHandlersAttached) return;\n if (!canvas) return;\n if (enabled) {\n canvas.addEventListener("mousedown", handleMouseEvent, { passive: false });\n canvas.addEventListener("mousemove", handleMouseEvent, { passive: false });\n canvas.addEventListener("mouseup", handleMouseEvent, { passive: false });\n canvas.addEventListener("mouseenter", handleMouseEnter, { passive: false });\n canvas.addEventListener("mouseleave", handleMouseLeave, { passive: false });\n canvas.addEventListener("wheel", handleWheelEvent, { passive: false });\n canvas.addEventListener("touchstart", handleTouchEvent, { passive: false });\n canvas.addEventListener("touchmove", handleTouchEvent, { passive: false });\n canvas.addEventListener("touchend", handleTouchEvent, { passive: false });\n canvas.addEventListener("touchcancel", handleTouchEvent, { passive: false });\n document.addEventListener("keydown", handleKeyboardEvent, { passive: false });\n document.addEventListener("keyup", handleKeyboardEvent, { passive: false });\n canvas.addEventListener("mousedown", focusCanvas);\n canvas.addEventListener("touchstart", focusCanvas);\n domHandlersAttached = true;\n } else {\n canvas.removeEventListener("mousedown", handleMouseEvent);\n canvas.removeEventListener("mousemove", handleMouseEvent);\n canvas.removeEventListener("mouseup", handleMouseEvent);\n canvas.removeEventListener("mouseenter", handleMouseEnter);\n canvas.removeEventListener("mouseleave", handleMouseLeave);\n canvas.removeEventListener("wheel", handleWheelEvent);\n canvas.removeEventListener("touchstart", handleTouchEvent);\n canvas.removeEventListener("touchmove", handleTouchEvent);\n canvas.removeEventListener("touchend", handleTouchEvent);\n canvas.removeEventListener("touchcancel", handleTouchEvent);\n document.removeEventListener("keydown", handleKeyboardEvent);\n document.removeEventListener("keyup", handleKeyboardEvent);\n canvas.removeEventListener("mousedown", focusCanvas);\n canvas.removeEventListener("touchstart", focusCanvas);\n domHandlersAttached = false;\n }\n }\n function focusCanvas() {\n if (canvas) canvas.focus();\n }\n function dualRoute(workerType, data) {\n if (worker) {\n worker.postMessage({\n type: workerType,\n id: `${workerType}_${Date.now()}`,\n timestamp: Date.now(),\n data\n });\n }\n postToHost({\n type: "interaction-event",\n kind: workerType,\n data\n });\n }\n function handleMouseEvent(event) {\n if (!canvas) return;\n event.preventDefault();\n const rect = canvas.getBoundingClientRect();\n const x = (event.clientX - rect.left) * (canvas.width / rect.width);\n const y = (event.clientY - rect.top) * (canvas.height / rect.height);\n dualRoute("mouse-update", {\n x,\n y,\n buttons: event.buttons,\n deltaX: event.movementX || 0,\n deltaY: event.movementY || 0,\n wheelDeltaX: 0,\n wheelDeltaY: 0,\n isInCanvas: isMouseInCanvas,\n timestamp: performance.now()\n });\n }\n function handleMouseEnter(event) {\n isMouseInCanvas = true;\n handleMouseEvent(event);\n }\n function handleMouseLeave(event) {\n isMouseInCanvas = false;\n handleMouseEvent(event);\n }\n function handleWheelEvent(event) {\n if (!canvas) return;\n event.preventDefault();\n const rect = canvas.getBoundingClientRect();\n const x = (event.clientX - rect.left) * (canvas.width / rect.width);\n const y = (event.clientY - rect.top) * (canvas.height / rect.height);\n dualRoute("mouse-update", {\n x,\n y,\n buttons: event.buttons,\n deltaX: 0,\n deltaY: 0,\n wheelDeltaX: event.deltaX,\n wheelDeltaY: event.deltaY,\n isInCanvas: isMouseInCanvas,\n timestamp: performance.now()\n });\n }\n var KEY_PASSTHROUGH = /* @__PURE__ */ new Set([\n "Tab",\n "F1",\n "F2",\n "F3",\n "F4",\n "F5",\n "F11",\n "F12"\n ]);\n function handleKeyboardEvent(event) {\n if (!KEY_PASSTHROUGH.has(event.key)) {\n event.preventDefault();\n }\n dualRoute("keyboard-update", {\n type: event.type,\n key: event.key,\n code: event.code,\n keyCode: event.keyCode,\n shiftKey: event.shiftKey,\n ctrlKey: event.ctrlKey,\n altKey: event.altKey,\n metaKey: event.metaKey,\n timestamp: performance.now()\n });\n }\n function handleTouchEvent(event) {\n if (!canvas) return;\n event.preventDefault();\n const rect = canvas.getBoundingClientRect();\n const scaleX = canvas.width / rect.width;\n const scaleY = canvas.height / rect.height;\n const canvasW = canvas.width;\n const canvasH = canvas.height;\n const mapTouch = (t) => {\n const cx = (t.clientX - rect.left) * scaleX;\n const cy = (t.clientY - rect.top) * scaleY;\n return {\n identifier: t.identifier,\n clientX: cx,\n clientY: cy,\n radiusX: t.radiusX ?? 0,\n radiusY: t.radiusY ?? 0,\n rotationAngle: t.rotationAngle ?? 0,\n force: t.force ?? 0,\n isInCanvas: cx >= 0 && cx <= canvasW && cy >= 0 && cy <= canvasH\n };\n };\n const changedMap = /* @__PURE__ */ new Map();\n for (let i = 0; i < event.changedTouches.length; i++) {\n const t = event.changedTouches[i];\n changedMap.set(t.identifier, mapTouch(t));\n }\n const touches = Array.from(event.touches).map((t) => {\n return changedMap.get(t.identifier) ?? mapTouch(t);\n });\n if (event.type === "touchend" || event.type === "touchcancel") {\n const activeIds = new Set(touches.map((t) => t.identifier));\n for (const [id, mapped] of changedMap) {\n if (!activeIds.has(id)) {\n touches.push({ ...mapped, ended: true });\n }\n }\n }\n dualRoute("touch-update", {\n type: event.type,\n touches,\n timestamp: performance.now()\n });\n }\n function setSensorsEnabled(enabled) {\n if (enabled === sensorHandlersAttached) return;\n if (enabled) {\n window.addEventListener("devicemotion", handleDeviceMotion);\n window.addEventListener("deviceorientation", handleDeviceOrientation);\n sensorHandlersAttached = true;\n } else {\n window.removeEventListener("devicemotion", handleDeviceMotion);\n window.removeEventListener("deviceorientation", handleDeviceOrientation);\n sensorHandlersAttached = false;\n }\n }\n function handleDeviceMotion(event) {\n if (!event.acceleration && !event.accelerationIncludingGravity && !event.rotationRate) {\n return;\n }\n postToHost({\n type: "sensor-event",\n kind: "motion",\n data: {\n acceleration: event.acceleration ? {\n x: event.acceleration.x,\n y: event.acceleration.y,\n z: event.acceleration.z\n } : null,\n accelerationIncludingGravity: event.accelerationIncludingGravity ? {\n x: event.accelerationIncludingGravity.x,\n y: event.accelerationIncludingGravity.y,\n z: event.accelerationIncludingGravity.z\n } : null,\n rotationRate: event.rotationRate ? {\n alpha: event.rotationRate.alpha,\n beta: event.rotationRate.beta,\n gamma: event.rotationRate.gamma\n } : null,\n interval: event.interval || 16\n }\n });\n }\n function handleDeviceOrientation(event) {\n postToHost({\n type: "sensor-event",\n kind: "orientation",\n data: {\n alpha: event.alpha,\n beta: event.beta,\n gamma: event.gamma,\n absolute: event.absolute || false\n }\n });\n }\n function handleTerminate() {\n setInteractionEnabled(false);\n setSensorsEnabled(false);\n if (worker) {\n worker.terminate();\n worker = null;\n }\n }\n installHostListener();\n announceReady().catch((err) => reportError(err));\n window.addEventListener("error", (e) => {\n reportError(e.error ?? new Error(e.message));\n });\n window.addEventListener("unhandledrejection", (e) => {\n reportError(e.reason ?? new Error("Unhandled promise rejection"));\n });\n})();\n';
9
+ const inlineScriptCode = '"use strict";\n(() => {\n // src/iframe/protocol.ts\n var PROTOCOL_VERSION = 1;\n function collectTransferables(msg) {\n switch (msg.type) {\n case "init": {\n const m = msg;\n const out = [];\n if (m.data?.canvas) out.push(m.data.canvas);\n const wasm = m.data?.cvWasmFiles;\n if (wasm) {\n out.push(\n wasm.simdLoaderJs,\n wasm.simdBinary,\n wasm.nosimdLoaderJs,\n wasm.nosimdBinary\n );\n }\n return out;\n }\n case "video-canvas-setup": {\n const m = msg;\n return m.data?.offscreenCanvas ? [m.data.offscreenCanvas] : [];\n }\n case "video-frame-update": {\n const m = msg;\n return m.data?.imageBitmap ? [m.data.imageBitmap] : [];\n }\n case "video-frame-direct": {\n const m = msg;\n return m.data?.imageBitmap ? [m.data.imageBitmap] : [];\n }\n case "parameter-update": {\n const m = msg;\n return m.data?.transferList ?? [];\n }\n case "parameter-batch-update": {\n const m = msg;\n return m.data?.transferList ?? [];\n }\n case "audio-analysis-update": {\n const m = msg;\n const out = [];\n if (m.data?.frequencyData?.buffer) out.push(m.data.frequencyData.buffer);\n if (m.data?.waveformData?.buffer) out.push(m.data.waveformData.buffer);\n return out;\n }\n case "capture-frame-result":\n case "auto-capture-result": {\n const data = msg.data;\n return data?.bitmap ? [data.bitmap] : [];\n }\n default:\n return [];\n }\n }\n\n // src/iframe/inline-script.ts\n var hostOrigin = null;\n var hostWindow = null;\n var worker = null;\n var canvas = null;\n var domHandlersAttached = false;\n var sensorHandlersAttached = false;\n function whenDomReady() {\n if (document.readyState === "loading") {\n return new Promise((resolve) => {\n document.addEventListener("DOMContentLoaded", () => resolve(), {\n once: true\n });\n });\n }\n return Promise.resolve();\n }\n async function announceReady() {\n await whenDomReady();\n const msg = {\n type: "iframe-ready",\n protocolVersion: PROTOCOL_VERSION\n };\n window.parent.postMessage(msg, "*");\n }\n function installHostListener() {\n window.addEventListener("message", (event) => {\n if (event.source !== window.parent) return;\n if (hostOrigin === null) {\n hostOrigin = event.origin;\n hostWindow = window.parent;\n } else if (event.origin !== hostOrigin) {\n return;\n }\n handleHostMessage(event.data).catch((err) => {\n reportError(err);\n });\n });\n }\n function postToHost(msg, transfer = []) {\n if (hostOrigin === null || hostWindow === null) {\n return;\n }\n const targetOrigin = hostOrigin === "null" ? "*" : hostOrigin;\n hostWindow.postMessage(msg, targetOrigin, transfer);\n }\n function reportError(err) {\n const e = err;\n const msg = e?.stack ? {\n type: "iframe-error",\n message: e.message ?? String(err),\n stack: e.stack\n } : {\n type: "iframe-error",\n message: e?.message ?? String(err)\n };\n if (hostOrigin && hostWindow) {\n const targetOrigin = hostOrigin === "null" ? "*" : hostOrigin;\n hostWindow.postMessage(msg, targetOrigin);\n } else {\n window.parent.postMessage(msg, "*");\n }\n }\n async function handleHostMessage(msg) {\n switch (msg.type) {\n case "viji-bootstrap":\n await handleBootstrap(msg);\n return;\n case "viji-host-message":\n relayHostToWorker(msg.payload);\n return;\n case "viji-resize":\n handleResize(msg.width, msg.height);\n return;\n case "viji-enable-sensors":\n setSensorsEnabled(msg.enabled);\n return;\n case "viji-enable-interaction":\n setInteractionEnabled(msg.enabled);\n return;\n case "viji-terminate":\n handleTerminate();\n return;\n }\n }\n async function handleBootstrap(msg) {\n if (worker) {\n return;\n }\n canvas = document.createElement("canvas");\n canvas.id = "viji-canvas";\n canvas.width = msg.init.canvasWidth;\n canvas.height = msg.init.canvasHeight;\n canvas.style.width = "100%";\n canvas.style.height = "100%";\n canvas.style.display = "block";\n canvas.tabIndex = 0;\n canvas.style.outline = "none";\n document.body.appendChild(canvas);\n const offscreen = canvas.transferControlToOffscreen();\n const workerSource = arrayBufferToString(msg.workerCode);\n const workerDataUrl = "data:text/javascript;base64," + base64Encode(workerSource);\n worker = new Worker(workerDataUrl, {\n type: "module",\n credentials: "omit"\n });\n worker.onerror = (e) => {\n reportError(new Error(`Worker error: ${e.message ?? String(e)}`));\n };\n worker.onmessage = (event) => {\n relayWorkerToHost(event.data);\n };\n const initId = `init_${Date.now()}`;\n const initMsg = {\n type: "init",\n id: initId,\n timestamp: Date.now(),\n data: {\n canvas: offscreen,\n isHeadless: msg.init.isHeadless,\n sc: msg.init.sc,\n rh: msg.init.rh,\n cvWasmFiles: msg.wasmFiles\n }\n };\n const initResponse = waitForWorkerMessage((m) => {\n return m && m.type === "init-response" && m.id === initId;\n });\n worker.postMessage(initMsg, [\n offscreen,\n msg.wasmFiles.simdLoaderJs,\n msg.wasmFiles.simdBinary,\n msg.wasmFiles.nosimdLoaderJs,\n msg.wasmFiles.nosimdBinary\n ]);\n await initResponse;\n if (msg.init.allowInteraction && !msg.init.isHeadless) {\n setInteractionEnabled(true);\n }\n if (msg.init.allowSensors && !msg.init.isHeadless) {\n setSensorsEnabled(true);\n }\n if (canvas) {\n canvas.addEventListener("contextmenu", (e) => e.preventDefault());\n }\n postToHost({ type: "viji-ready" });\n }\n function arrayBufferToString(buf) {\n return new TextDecoder("utf-8").decode(buf);\n }\n function base64Encode(s) {\n const bytes = new TextEncoder().encode(s);\n let binary = "";\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);\n return btoa(binary);\n }\n function waitForWorkerMessage(predicate) {\n return new Promise((resolve, reject) => {\n if (!worker) {\n reject(new Error("worker not spawned"));\n return;\n }\n const w = worker;\n const onceListener = (event) => {\n if (predicate(event.data)) {\n w.removeEventListener("message", onceListener);\n resolve(event.data);\n }\n };\n w.addEventListener("message", onceListener);\n });\n }\n function relayHostToWorker(payload) {\n if (!worker || !payload) return;\n try {\n const transfer = collectTransferables(payload);\n worker.postMessage(payload, transfer);\n } catch (err) {\n reportError(err);\n }\n }\n function relayWorkerToHost(payload) {\n if (!payload) return;\n try {\n const transfer = collectTransferables(payload);\n postToHost(\n { type: "worker-message", payload },\n transfer\n );\n } catch (err) {\n reportError(err);\n }\n }\n function handleResize(width, height) {\n if (!worker) return;\n worker.postMessage({\n type: "resolution-update",\n id: `resize_${Date.now()}`,\n timestamp: Date.now(),\n data: {\n effectiveWidth: width,\n effectiveHeight: height,\n displayScale: 1\n }\n });\n }\n var isMouseInCanvas = false;\n function setInteractionEnabled(enabled) {\n if (enabled === domHandlersAttached) return;\n if (!canvas) return;\n if (enabled) {\n canvas.addEventListener("mousedown", handleMouseEvent, { passive: false });\n canvas.addEventListener("mousemove", handleMouseEvent, { passive: false });\n canvas.addEventListener("mouseup", handleMouseEvent, { passive: false });\n canvas.addEventListener("mouseenter", handleMouseEnter, { passive: false });\n canvas.addEventListener("mouseleave", handleMouseLeave, { passive: false });\n canvas.addEventListener("wheel", handleWheelEvent, { passive: false });\n canvas.addEventListener("touchstart", handleTouchEvent, { passive: false });\n canvas.addEventListener("touchmove", handleTouchEvent, { passive: false });\n canvas.addEventListener("touchend", handleTouchEvent, { passive: false });\n canvas.addEventListener("touchcancel", handleTouchEvent, { passive: false });\n document.addEventListener("keydown", handleKeyboardEvent, { passive: false });\n document.addEventListener("keyup", handleKeyboardEvent, { passive: false });\n canvas.addEventListener("mousedown", focusCanvas);\n canvas.addEventListener("touchstart", focusCanvas);\n domHandlersAttached = true;\n } else {\n canvas.removeEventListener("mousedown", handleMouseEvent);\n canvas.removeEventListener("mousemove", handleMouseEvent);\n canvas.removeEventListener("mouseup", handleMouseEvent);\n canvas.removeEventListener("mouseenter", handleMouseEnter);\n canvas.removeEventListener("mouseleave", handleMouseLeave);\n canvas.removeEventListener("wheel", handleWheelEvent);\n canvas.removeEventListener("touchstart", handleTouchEvent);\n canvas.removeEventListener("touchmove", handleTouchEvent);\n canvas.removeEventListener("touchend", handleTouchEvent);\n canvas.removeEventListener("touchcancel", handleTouchEvent);\n document.removeEventListener("keydown", handleKeyboardEvent);\n document.removeEventListener("keyup", handleKeyboardEvent);\n canvas.removeEventListener("mousedown", focusCanvas);\n canvas.removeEventListener("touchstart", focusCanvas);\n domHandlersAttached = false;\n }\n }\n function focusCanvas() {\n if (canvas) canvas.focus();\n }\n function dualRoute(workerType, data) {\n if (worker) {\n worker.postMessage({\n type: workerType,\n id: `${workerType}_${Date.now()}`,\n timestamp: Date.now(),\n data\n });\n }\n postToHost({\n type: "interaction-event",\n kind: workerType,\n data\n });\n }\n function handleMouseEvent(event) {\n if (!canvas) return;\n event.preventDefault();\n const rect = canvas.getBoundingClientRect();\n const x = (event.clientX - rect.left) * (canvas.width / rect.width);\n const y = (event.clientY - rect.top) * (canvas.height / rect.height);\n dualRoute("mouse-update", {\n x,\n y,\n buttons: event.buttons,\n deltaX: event.movementX || 0,\n deltaY: event.movementY || 0,\n wheelDeltaX: 0,\n wheelDeltaY: 0,\n isInCanvas: isMouseInCanvas,\n timestamp: performance.now()\n });\n }\n function handleMouseEnter(event) {\n isMouseInCanvas = true;\n handleMouseEvent(event);\n }\n function handleMouseLeave(event) {\n isMouseInCanvas = false;\n handleMouseEvent(event);\n }\n function handleWheelEvent(event) {\n if (!canvas) return;\n event.preventDefault();\n const rect = canvas.getBoundingClientRect();\n const x = (event.clientX - rect.left) * (canvas.width / rect.width);\n const y = (event.clientY - rect.top) * (canvas.height / rect.height);\n dualRoute("mouse-update", {\n x,\n y,\n buttons: event.buttons,\n deltaX: 0,\n deltaY: 0,\n wheelDeltaX: event.deltaX,\n wheelDeltaY: event.deltaY,\n isInCanvas: isMouseInCanvas,\n timestamp: performance.now()\n });\n }\n var KEY_PASSTHROUGH = /* @__PURE__ */ new Set([\n "Tab",\n "F1",\n "F2",\n "F3",\n "F4",\n "F5",\n "F11",\n "F12"\n ]);\n function handleKeyboardEvent(event) {\n if (!KEY_PASSTHROUGH.has(event.key)) {\n event.preventDefault();\n }\n dualRoute("keyboard-update", {\n type: event.type,\n key: event.key,\n code: event.code,\n keyCode: event.keyCode,\n shiftKey: event.shiftKey,\n ctrlKey: event.ctrlKey,\n altKey: event.altKey,\n metaKey: event.metaKey,\n timestamp: performance.now()\n });\n }\n function handleTouchEvent(event) {\n if (!canvas) return;\n event.preventDefault();\n const rect = canvas.getBoundingClientRect();\n const scaleX = canvas.width / rect.width;\n const scaleY = canvas.height / rect.height;\n const canvasW = canvas.width;\n const canvasH = canvas.height;\n const mapTouch = (t) => {\n const cx = (t.clientX - rect.left) * scaleX;\n const cy = (t.clientY - rect.top) * scaleY;\n return {\n identifier: t.identifier,\n clientX: cx,\n clientY: cy,\n radiusX: t.radiusX ?? 0,\n radiusY: t.radiusY ?? 0,\n rotationAngle: t.rotationAngle ?? 0,\n force: t.force ?? 0,\n isInCanvas: cx >= 0 && cx <= canvasW && cy >= 0 && cy <= canvasH\n };\n };\n const changedMap = /* @__PURE__ */ new Map();\n for (let i = 0; i < event.changedTouches.length; i++) {\n const t = event.changedTouches[i];\n changedMap.set(t.identifier, mapTouch(t));\n }\n const touches = Array.from(event.touches).map((t) => {\n return changedMap.get(t.identifier) ?? mapTouch(t);\n });\n if (event.type === "touchend" || event.type === "touchcancel") {\n const activeIds = new Set(touches.map((t) => t.identifier));\n for (const [id, mapped] of changedMap) {\n if (!activeIds.has(id)) {\n touches.push({ ...mapped, ended: true });\n }\n }\n }\n dualRoute("touch-update", {\n type: event.type,\n touches,\n timestamp: performance.now()\n });\n }\n function setSensorsEnabled(enabled) {\n if (enabled === sensorHandlersAttached) return;\n if (enabled) {\n window.addEventListener("devicemotion", handleDeviceMotion);\n window.addEventListener("deviceorientation", handleDeviceOrientation);\n sensorHandlersAttached = true;\n } else {\n window.removeEventListener("devicemotion", handleDeviceMotion);\n window.removeEventListener("deviceorientation", handleDeviceOrientation);\n sensorHandlersAttached = false;\n }\n }\n function handleDeviceMotion(event) {\n if (!event.acceleration && !event.accelerationIncludingGravity && !event.rotationRate) {\n return;\n }\n postToHost({\n type: "sensor-event",\n kind: "motion",\n data: {\n acceleration: event.acceleration ? {\n x: event.acceleration.x,\n y: event.acceleration.y,\n z: event.acceleration.z\n } : null,\n accelerationIncludingGravity: event.accelerationIncludingGravity ? {\n x: event.accelerationIncludingGravity.x,\n y: event.accelerationIncludingGravity.y,\n z: event.accelerationIncludingGravity.z\n } : null,\n rotationRate: event.rotationRate ? {\n alpha: event.rotationRate.alpha,\n beta: event.rotationRate.beta,\n gamma: event.rotationRate.gamma\n } : null,\n interval: event.interval || 16\n }\n });\n }\n function handleDeviceOrientation(event) {\n postToHost({\n type: "sensor-event",\n kind: "orientation",\n data: {\n alpha: event.alpha,\n beta: event.beta,\n gamma: event.gamma,\n absolute: event.absolute || false\n }\n });\n }\n function handleTerminate() {\n setInteractionEnabled(false);\n setSensorsEnabled(false);\n if (worker) {\n worker.terminate();\n worker = null;\n }\n }\n installHostListener();\n announceReady().catch((err) => reportError(err));\n window.addEventListener("error", (e) => {\n reportError(e.error ?? new Error(e.message));\n });\n window.addEventListener("unhandledrejection", (e) => {\n reportError(e.reason ?? new Error("Unhandled promise rejection"));\n });\n})();\n';
10
10
  const IFRAME_ALLOW = "accelerometer; gyroscope; magnetometer; camera; microphone";
11
11
  const OPAQUE_ORIGIN = "null";
12
12
  function collectTransferables(msg) {
@@ -125,12 +125,29 @@ class IFrameManager {
125
125
  * Creates the secure iframe loaded from a blob URL with opaque origin.
126
126
  * Resolves once the iframe element is appended; the inline-script's
127
127
  * `iframe-ready` envelope is awaited via `waitForReady()`.
128
+ *
129
+ * Element setup order is intentional: every attribute that affects
130
+ * navigation (`sandbox`, `credentialless`, `allow`) and the `src`
131
+ * itself are assigned BEFORE the element is connected to the DOM.
132
+ * This guarantees the very first (and only) navigation the browser
133
+ * performs is to our blob URL with all attributes already in place,
134
+ * rather than briefly running an `about:blank` step with default
135
+ * attributes when `appendChild` fires before `src`.
128
136
  */
129
137
  async createSecureIFrame() {
130
138
  try {
131
139
  const iframe = document.createElement("iframe");
132
140
  iframe.sandbox.add("allow-scripts");
141
+ iframe.setAttribute("credentialless", "");
133
142
  iframe.allow = IFRAME_ALLOW;
143
+ this.iframeReadyPromise = new Promise((resolve, reject) => {
144
+ this.iframeReadyResolver = resolve;
145
+ this.iframeReadyRejecter = reject;
146
+ });
147
+ this.installHostMessageListener(iframe);
148
+ const iframeContent = this.generateIFrameHTML();
149
+ const blob = new Blob([iframeContent], { type: "text/html" });
150
+ iframe.src = URL.createObjectURL(blob);
134
151
  if (this.isHeadless) {
135
152
  const { width, height } = this.explicitResolution;
136
153
  iframe.style.cssText = `
@@ -152,14 +169,6 @@ class IFrameManager {
152
169
  iframe.style.cssText = `position:absolute;top:0;left:0;width:100%;height:100%;border:none;${visibility}`;
153
170
  this.hostContainer.appendChild(iframe);
154
171
  }
155
- this.iframeReadyPromise = new Promise((resolve, reject) => {
156
- this.iframeReadyResolver = resolve;
157
- this.iframeReadyRejecter = reject;
158
- });
159
- this.installHostMessageListener(iframe);
160
- const iframeContent = this.generateIFrameHTML();
161
- const blob = new Blob([iframeContent], { type: "text/html" });
162
- iframe.src = URL.createObjectURL(blob);
163
172
  const timeoutId = setTimeout(() => {
164
173
  if (this.iframeReadyRejecter) {
165
174
  const r = this.iframeReadyRejecter;
@@ -574,7 +583,7 @@ class IFrameManager {
574
583
  }
575
584
  }
576
585
  }
577
- const workerUrl = "" + new URL("assets/viji.worker-DiQyLnqS.js", import.meta.url).href;
586
+ const workerUrl = "" + new URL("assets/viji.worker-D1yRmN8m.js", import.meta.url).href;
578
587
  const simdLoaderJs = new URL("assets/wasm/vision_wasm_internal.js", import.meta.url).href;
579
588
  const simdBinary = new URL("assets/wasm/vision_wasm_internal.wasm", import.meta.url).href;
580
589
  const nosimdLoaderJs = new URL("assets/wasm/vision_wasm_nosimd_internal.js", import.meta.url).href;
@@ -1790,7 +1799,7 @@ class EssentiaOnsetDetection {
1790
1799
  this.initPromise = (async () => {
1791
1800
  try {
1792
1801
  const essentiaModule = await import("./essentia.js-core.es-DnrJE0uR.js");
1793
- const wasmModule = await import("./essentia-wasm.web-CpSS-HV6.js").then((n) => n.e);
1802
+ const wasmModule = await import("./essentia-wasm.web-BbdWO0Xs.js").then((n) => n.e);
1794
1803
  const EssentiaClass = essentiaModule.Essentia || essentiaModule.default?.Essentia || essentiaModule.default;
1795
1804
  let WASMModule = wasmModule.default || wasmModule.EssentiaWASM || wasmModule.default?.EssentiaWASM;
1796
1805
  if (!WASMModule) {
@@ -10594,4 +10603,4 @@ export {
10594
10603
  VijiCoreError as b,
10595
10604
  getDefaultExportFromCjs as g
10596
10605
  };
10597
- //# sourceMappingURL=index-BlVguPnk.js.map
10606
+ //# sourceMappingURL=index-DUg1Foui.js.map