diff --git a/.gitattributes b/.gitattributes index 193bcec..9f5971d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -9,4 +9,4 @@ *.xbin binary *.las binary *.lcc binary - +apps/control-station/vendor/rerun-web-viewer-0.34.1/re_viewer_bg.nodedc.wasm filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore index 0674369..307135a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ __pycache__/ .coverage htmlcov/ dist/ +apps/control-station/dist-shadow/ build/ *.egg-info/ diff --git a/README.md b/README.md index d05db64..b96cb7a 100644 --- a/README.md +++ b/README.md @@ -158,13 +158,16 @@ local reception; plugin-commanded v0.5.0 acquisition uses the separately gated canonical K1 START/STOP dialogue. Plugin v0.6.0 makes the local connection direction explicit. Bridge remains the -default; Direct Connect sends the same reviewed BLE frame with credentials for -an already-running controller hotspot; Quick Connect sends no BLE write and -instead associates this Mac with the K1 AP once. Each mode has a distinct -topology attestation and no automatic retry. The Bridge path is physically -accepted. Direct Connect and the Mission Core Quick Connect host adapter are -implemented and offline-verified but still require their own owner-operated -physical acceptance cycles; see [ADR 0013](docs/adr/0013-k1-local-connection-matrix.md). +default and accepted product path; Direct Connect sends the reviewed station +provisioning frame for an already-running controller hotspot. Quick Connect +sends one separately reviewed AP-enable frame and can associate a prepared Mac +through CoreWLAN. Its device activation and prepared-host association were +physically accepted, but credential bootstrap is not portable: a clean host +cannot acquire the firmware-defined AP material from the reviewed BLE protocol. +Quick Connect therefore remains laboratory functionality, with no automatic +firmware download, iPhone extraction or hard-coded fallback. Each mode has a +distinct topology attestation and no automatic retry; see +[ADR 0013](docs/adr/0013-k1-local-connection-matrix.md). The exact recovered `ModelingRequest` start/stop encoder, response correlator and device-status state machine are installed in the operator-gated interactive diff --git a/apps/control-station/scripts/patch-rerun-web-viewer.mjs b/apps/control-station/scripts/patch-rerun-web-viewer.mjs index 9b780c4..0c0cc77 100644 --- a/apps/control-station/scripts/patch-rerun-web-viewer.mjs +++ b/apps/control-station/scripts/patch-rerun-web-viewer.mjs @@ -1,10 +1,15 @@ -import { readFileSync, writeFileSync } from "node:fs"; +import { createHash } from "node:crypto"; +import { copyFileSync, readFileSync, writeFileSync } from "node:fs"; import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; const root = resolve(dirname(fileURLToPath(import.meta.url)), ".."); const packageRoot = resolve(root, "node_modules/@rerun-io/web-viewer"); const manifest = JSON.parse(readFileSync(resolve(packageRoot, "package.json"), "utf8")); +const vendorRoot = resolve(root, "vendor/rerun-web-viewer-0.34.1"); + +const sha256File = (path) => + createHash("sha256").update(readFileSync(path)).digest("hex"); if (manifest.version !== "0.34.1") { throw new Error( @@ -12,6 +17,51 @@ if (manifest.version !== "0.34.1") { ); } +const vendorRuntime = [ + { + label: "wasm runtime", + packagePath: resolve(packageRoot, "re_viewer_bg.wasm"), + vendorPath: resolve(vendorRoot, "re_viewer_bg.nodedc.wasm"), + publishedSha256: "3fe7aab8ea6bb0fd03c3ef694932943411ee174029e398c539c390beb0824d35", + previousNodedcSha256: "1c25e8cecd7641e6f8044d00a6a1cf9d08a615b6f8737026c7d93623b3e06ee7", + nodedcSha256: "38d19bac06b7c3b8e549489469cf7c4a24f319ec953849e4656b5827a6c105bb", + }, + { + label: "wasm JavaScript glue", + packagePath: resolve(packageRoot, "re_viewer.js"), + vendorPath: resolve(vendorRoot, "re_viewer.nodedc.js"), + publishedSha256: "7c4ba900820137a6ba23e0f7f57d56e3b007db0de3825d5c8bf0d7684b3cc6a6", + nodedcSha256: "0f7b76c9f24cbd8437021b5d37499894aeadc586183e422ebc82ef556d7b8339", + }, +]; + +for (const runtime of vendorRuntime) { + const vendorSha256 = sha256File(runtime.vendorPath); + if (vendorSha256 !== runtime.nodedcSha256) { + throw new Error( + `Refusing corrupt NODE.DC Rerun ${runtime.label}: ${vendorSha256} != ${runtime.nodedcSha256}`, + ); + } + + const installedSha256 = sha256File(runtime.packagePath); + if ( + ![ + runtime.publishedSha256, + runtime.previousNodedcSha256, + runtime.nodedcSha256, + ].includes(installedSha256) + ) { + throw new Error( + `Refusing to replace unexpected Rerun ${runtime.label}: ${installedSha256}`, + ); + } + + copyFileSync(runtime.vendorPath, runtime.packagePath); + if (sha256File(runtime.packagePath) !== runtime.nodedcSha256) { + throw new Error(`NODE.DC Rerun ${runtime.label} verification failed after copy`); + } +} + const patches = [ { label: "compiled watchdog", @@ -57,5 +107,5 @@ for (const path of [resolve(packageRoot, "index.js"), resolve(packageRoot, "inde } console.log( - "Patched @rerun-io/web-viewer 0.34.1 watchdog teardown and singleton global keyup listener.", + "Patched @rerun-io/web-viewer 0.34.1 native zoom-to-cursor, watchdog teardown, and singleton global keyup listener.", ); diff --git a/apps/control-station/scripts/transform-rerun-web-viewer-glue.mjs b/apps/control-station/scripts/transform-rerun-web-viewer-glue.mjs new file mode 100644 index 0000000..5031d33 --- /dev/null +++ b/apps/control-station/scripts/transform-rerun-web-viewer-glue.mjs @@ -0,0 +1,128 @@ +import { createHash } from "node:crypto"; +import { readFileSync, writeFileSync } from "node:fs"; +import { resolve } from "node:path"; + +const [inputArgument, outputArgument] = process.argv.slice(2); +if (!inputArgument || !outputArgument) { + throw new Error("Usage: node transform-rerun-web-viewer-glue.mjs INPUT OUTPUT"); +} + +const inputPath = resolve(inputArgument); +const outputPath = resolve(outputArgument); +const expectedGeneratedSha256 = + "cc196a93c5be972c801d46be4dc9934f7f042eb62941f0aa0678f1c8416c6874"; + +const sha256 = (value) => createHash("sha256").update(value).digest("hex"); +let code = readFileSync(inputPath, "utf8"); + +if (sha256(code) !== expectedGeneratedSha256) { + throw new Error(`Refusing to transform unexpected wasm-bindgen output: ${inputPath}`); +} + +// This is the same no-modules-base transformation used by Rerun 0.34.1's +// rerun_js/web-viewer/build-wasm.mjs. Each factory call gets isolated closure state. +const wrapperStart = "let wasm_bindgen = (function(exports) {"; +const wrapperEnd = `return Object.assign(__wbg_init, { initSync }, exports); +})({ __proto__: null });`; + +if (!code.includes(wrapperStart) || !code.includes(wrapperEnd)) { + throw new Error("Rerun wasm-bindgen wrapper markers no longer match"); +} +code = code.replace(wrapperStart, "").replace(wrapperEnd, ""); + +code = ` +export default function() { +const exports = { __proto__: null }; +${code} + +function deinit() { + __wbg_init.__wbindgen_wasm_module = null; + wasmModule = null; + wasm = null; + cachedDataViewMemory0 = null; + cachedFloat32ArrayMemory0 = null; + cachedInt16ArrayMemory0 = null; + cachedInt32ArrayMemory0 = null; + cachedInt8ArrayMemory0 = null; + cachedUint16ArrayMemory0 = null; + cachedUint32ArrayMemory0 = null; + cachedUint8ArrayMemory0 = null; +} + +return Object.assign(__wbg_init, { initSync, deinit }, exports); +} +`; + +const closureDtorsOriginal = `const CLOSURE_DTORS = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(state => wasm.__wbindgen_destroy_closure(state.a, state.b));`; +const closureDtorsPatch = `const CLOSURE_DTORS = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(state => { + if (wasm) wasm.__wbindgen_destroy_closure(state.a, state.b); + });`; + +if (!code.includes(closureDtorsOriginal)) { + throw new Error("Rerun CLOSURE_DTORS block no longer matches"); +} +code = code.replace(closureDtorsOriginal, closureDtorsPatch); + +const makeMutClosureOriginal = `function makeMutClosure(arg0, arg1, f) { + const state = { a: arg0, b: arg1, cnt: 1 }; + const real = (...args) => { + + // First up with a closure we increment the internal reference + // count. This ensures that the Rust closure environment won't + // be deallocated while we're invoking it. + state.cnt++; + const a = state.a; + state.a = 0; + try { + return f(a, state.b, ...args); + } finally { + state.a = a; + real._wbg_cb_unref(); + } + }; + real._wbg_cb_unref = () => { + if (--state.cnt === 0) { + wasm.__wbindgen_destroy_closure(state.a, state.b); + state.a = 0; + CLOSURE_DTORS.unregister(state); + } + }; + CLOSURE_DTORS.register(real, state, state); + return real; + }`; +const makeMutClosurePatch = `function makeMutClosure(arg0, arg1, f) { + const state = { a: arg0, b: arg1, cnt: 1 }; + const real = (...args) => { + state.cnt++; + const a = state.a; + state.a = 0; + try { + if (!wasm) return; + return f(a, state.b, ...args); + } finally { + state.a = a; + real._wbg_cb_unref(); + } + }; + real._wbg_cb_unref = () => { + if (--state.cnt === 0) { + if (wasm) wasm.__wbindgen_destroy_closure(state.a, state.b); + state.a = 0; + CLOSURE_DTORS.unregister(state); + } + }; + CLOSURE_DTORS.register(real, state, state); + return real; + }`; + +if (!code.includes(makeMutClosureOriginal)) { + throw new Error("Rerun makeMutClosure block no longer matches"); +} +code = code.replace(makeMutClosureOriginal, makeMutClosurePatch); + +writeFileSync(outputPath, code); +console.log(`Transformed Rerun wasm glue: ${sha256(code)} ${outputPath}`); diff --git a/apps/control-station/src/App.tsx b/apps/control-station/src/App.tsx index a7a9be3..6b5efa8 100644 --- a/apps/control-station/src/App.tsx +++ b/apps/control-station/src/App.tsx @@ -88,7 +88,22 @@ const paletteOptions: Array<{ value: PointPalette; label: string; description: s { value: "custom", label: "Свой цвет", description: "Один назначенный цвет" }, ]; -function toViewerSettings(settings: SceneSettings): ViewerSettings { +interface LivePerceptionLayers { + detections2d: boolean; + segmentation: boolean; + cuboids3d: boolean; +} + +const defaultLivePerceptionLayers: LivePerceptionLayers = { + detections2d: false, + segmentation: false, + cuboids3d: false, +}; + +function toViewerSettings( + settings: SceneSettings, + perception: LivePerceptionLayers = defaultLivePerceptionLayers, +): ViewerSettings { return { point_size: settings.pointSize, color_mode: settings.colorMode, @@ -98,6 +113,9 @@ function toViewerSettings(settings: SceneSettings): ViewerSettings { show_points: settings.showPoints, show_trajectory: settings.showTrajectory, show_grid: settings.showGrid, + show_detections_2d: perception.detections2d, + show_segmentation: perception.segmentation, + show_cuboids_3d: perception.cuboids3d, }; } @@ -149,6 +167,9 @@ export default function App() { const [layoutSaveNotice, setLayoutSaveNotice] = useState(null); const [sceneSettings, setSceneSettings] = useState(defaultSceneSettings); const [displayDraft, setDisplayDraft] = useState(defaultSceneSettings); + const [livePerceptionLayers, setLivePerceptionLayers] = useState( + defaultLivePerceptionLayers, + ); const sourceSwitchBlocked = isSpatialSourceSwitchBlocked(runtime.state); const sourceSwitchBlockedReason = sourceSwitchBlocked ? SPATIAL_SOURCE_SWITCH_BLOCKED_REASON @@ -161,6 +182,8 @@ export default function App() { const confirmedSceneSettingsRef = useRef(defaultSceneSettings); const viewerSettingsCommitTimerRef = useRef(null); const runtimeUpdateViewerSettingsRef = useRef(runtime.updateViewerSettings); + const livePerceptionLayersRef = useRef(defaultLivePerceptionLayers); + const livePerceptionRevisionRef = useRef(0); const replayActiveRef = useRef(false); const sceneSettingsCommitterActiveRef = useRef(true); const sceneSettingsCommitterRef = useRef | null>(null); @@ -197,7 +220,9 @@ export default function App() { sceneSettingsCommitterRef.current = createLatestAsyncCommitter({ commit: (settings) => replayActiveRef.current ? Promise.resolve(true) - : runtimeUpdateViewerSettingsRef.current(toViewerSettings(settings)), + : runtimeUpdateViewerSettingsRef.current( + toViewerSettings(settings, livePerceptionLayersRef.current), + ), onSettled: ({ value, applied, superseded }) => { if (!sceneSettingsCommitterActiveRef.current) return; if (applied) confirmedSceneSettingsRef.current = value; @@ -275,6 +300,13 @@ export default function App() { sceneSettingsCommitterRef.current?.isBusy() ) return; const merged = mergeViewerSettings(sceneSettingsRef.current, remote); + const remoteLayers = { + detections2d: remote.show_detections_2d ?? false, + segmentation: remote.show_segmentation ?? false, + cuboids3d: remote.show_cuboids_3d ?? false, + }; + livePerceptionLayersRef.current = remoteLayers; + setLivePerceptionLayers(remoteLayers); sceneSettingsRef.current = merged; confirmedSceneSettingsRef.current = merged; setSceneSettings(merged); @@ -334,7 +366,9 @@ export default function App() { return; } appliedProfileKeyRef.current = applicationKey; - void runtime.updateViewerSettings(toViewerSettings(profile.sceneSettings)).then((applied) => { + void runtime.updateViewerSettings( + toViewerSettings(profile.sceneSettings, livePerceptionLayersRef.current), + ).then((applied) => { if (!applied && appliedProfileKeyRef.current === applicationKey) { appliedProfileKeyRef.current = null; } @@ -441,6 +475,21 @@ export default function App() { activateSceneWindow("layers"); }; + const changeLivePerceptionLayers = useCallback((next: LivePerceptionLayers) => { + const previous = livePerceptionLayersRef.current; + const revision = ++livePerceptionRevisionRef.current; + livePerceptionLayersRef.current = next; + setLivePerceptionLayers(next); + if (replayActiveRef.current) return; + void runtimeUpdateViewerSettingsRef.current( + toViewerSettings(sceneSettingsRef.current, next), + ).then((applied) => { + if (applied || livePerceptionRevisionRef.current !== revision) return; + livePerceptionLayersRef.current = previous; + setLivePerceptionLayers(previous); + }); + }, []); + const beginRecordedReplaySwitch = useCallback(async () => { if (sourceSwitchBlockedRef.current) { throw new Error(SPATIAL_SOURCE_SWITCH_BLOCKED_REASON); @@ -706,6 +755,8 @@ export default function App() { onAccumulationChange={(accumulationSeconds) => stageDisplayPatch({ accumulationSeconds })} onAccumulationCommit={flushDisplaySettings} + livePerceptionLayers={livePerceptionLayers} + onLivePerceptionLayersChange={changeLivePerceptionLayers} observationLayout={observationLayout} spatialControls={selection?.SpatialControlsView ? { diff --git a/apps/control-station/src/components/FloatingObservationWindow.tsx b/apps/control-station/src/components/FloatingObservationWindow.tsx index aa19187..1db8273 100644 --- a/apps/control-station/src/components/FloatingObservationWindow.tsx +++ b/apps/control-station/src/components/FloatingObservationWindow.tsx @@ -72,6 +72,7 @@ export function FloatingObservationWindow({ rect, maximized, active, + hidden = false, onRectChange, onMaximizedChange, onActivate, @@ -89,6 +90,7 @@ export function FloatingObservationWindow({ rect?: ObservationWindowRect; maximized: boolean; active: boolean; + hidden?: boolean; onRectChange: (rect: ObservationWindowRect) => void; onMaximizedChange: (maximized: boolean) => void; onActivate: () => void; @@ -153,7 +155,7 @@ export function FloatingObservationWindow({ resizable={source.capabilities.resizable} active={active} zIndex={maximized ? 15 : active ? 9 : 7} - className="floating-observation-window" + className={`floating-observation-window${hidden ? " floating-observation-window--hidden" : ""}`} onPointerDownCapture={(event) => { if (!shouldCaptureWorkspacePointer(event.button, event.target as HTMLElement)) return; try { diff --git a/apps/control-station/src/components/ObservationSessionSelect.tsx b/apps/control-station/src/components/ObservationSessionSelect.tsx index 9381606..ffc264b 100644 --- a/apps/control-station/src/components/ObservationSessionSelect.tsx +++ b/apps/control-station/src/components/ObservationSessionSelect.tsx @@ -52,18 +52,17 @@ const preparationLabel: Record = { requesting: "Запрашиваем подготовку", queued: "В очереди", validating: "Проверяем запись", - exporting: "Готовим облако точек", + exporting: "Готовим операторскую сцену", finalizing: "Завершаем подготовку", failed: "Подготовка не выполнена", cancelled: "Подготовка отменена", }; -function progressCopy( - phase: ObservationPreparationPhase, - progress: number | null, -): string { - const label = preparationLabel[phase]; - return progress === null ? label : `${label} · ${Math.round(progress * 100)}%`; +function progressCopy(phase: ObservationPreparationPhase): string { + // Backend progress values are phase markers and heartbeat revisions, not a + // measured fraction of bytes or frames. Presenting 0.5 as "50%" made a + // healthy long export look stalled, especially after a browser reload. + return preparationLabel[phase]; } function formatStartedAt(value: string): string { @@ -126,7 +125,7 @@ export function ObservationSessionSelect({ onReplaySettled, }); const triggerCopy = sessions.replayProgress - ? progressCopy(sessions.replayProgress.phase, sessions.replayProgress.progress) + ? progressCopy(sessions.replayProgress.phase) : sessions.state === "loading" ? "Загружаем сессии…" : "Сохранённые сессии"; diff --git a/apps/control-station/src/components/RecordedFmp4Player.tsx b/apps/control-station/src/components/RecordedFmp4Player.tsx index 1e78b16..62be9e5 100644 --- a/apps/control-station/src/components/RecordedFmp4Player.tsx +++ b/apps/control-station/src/components/RecordedFmp4Player.tsx @@ -1,5 +1,3 @@ -import { sha256 } from "@noble/hashes/sha2.js"; -import { bytesToHex } from "@noble/hashes/utils.js"; import { useEffect, useMemo, useRef, useState } from "react"; import { @@ -11,7 +9,6 @@ import { type ObservationSessionFetch, } from "../core/observation/sessionArchive"; import { - MAX_RECORDED_MEDIA_SOURCE_BYTES, type RecordedAdmissionPhase, type RecordedCameraAdmissionState, } from "../core/observation/recordedSessionAdmission"; @@ -22,32 +19,11 @@ export interface RecordedObservationPlayback { playing: boolean; } -export interface RecordedMediaLoadProgress { - loadedBytes: number; - totalBytes: number; - loadedParts: number; - totalParts: number; -} - -interface VerifiedRecordedMediaEpoch { - descriptor: ObservationRecordedMediaEpoch; - readonly init: ArrayBuffer; - readonly segments: readonly ArrayBuffer[]; -} - -export interface VerifiedRecordedMediaArchive { +export interface RecordedMediaArchive { manifest: ObservationRecordedMediaManifest; - epochs: readonly VerifiedRecordedMediaEpoch[]; byteLength: number; } -interface RecordedMediaBinaryDescriptor { - url: string; - byteLength: number; - sha256: string; - accept: string; -} - export type RecordedMediaPresentationState = "loading" | "ready" | "waiting" | "error"; export const RECORDED_MEDIA_DURATION_TOLERANCE_SECONDS = 1; @@ -134,205 +110,33 @@ function sourceContract(source: ObservationSourceDescriptor): ObservationRecorde }; } -function expectedPayloadEtag(digest: string): string { - return `"sha256:${digest}"`; -} - -export async function fetchVerifiedRecordedMediaBytes( - descriptor: RecordedMediaBinaryDescriptor, - { - signal, - fetcher = globalThis.fetch, - }: { signal?: AbortSignal; fetcher?: ObservationSessionFetch } = {}, -): Promise { - let response: Response; - try { - response = await fetcher(descriptor.url, { - method: "GET", - headers: { - Accept: descriptor.accept, - "If-Match": expectedPayloadEtag(descriptor.sha256), - }, - signal, - }); - } catch (error) { - if (error instanceof DOMException && error.name === "AbortError") throw error; - throw new ObservationSessionContractError( - "Не удалось загрузить канонический фрагмент записанного видео.", - ); - } - if (!response.ok || response.status !== 200) { - throw new ObservationSessionContractError( - `Фрагмент записанного видео вернул HTTP ${response.status}.`, - ); - } - if (response.headers.get("ETag") !== expectedPayloadEtag(descriptor.sha256)) { - throw new ObservationSessionContractError( - "Фрагмент записанного видео не соответствует immutable manifest.", - ); - } - const contentLength = response.headers.get("Content-Length"); - if ( - contentLength === null || - !/^[1-9][0-9]*$/.test(contentLength) || - Number(contentLength) !== descriptor.byteLength - ) { - throw new ObservationSessionContractError( - "Длина фрагмента записанного видео не соответствует immutable manifest.", - ); - } - const payload = await response.arrayBuffer(); - if (payload.byteLength !== descriptor.byteLength) { - throw new ObservationSessionContractError( - "Фрагмент записанного видео был усечён во время передачи.", - ); - } - const digest = bytesToHex(sha256(new Uint8Array(payload))); - if (digest !== descriptor.sha256) { - throw new ObservationSessionContractError( - "SHA-256 фрагмента записанного видео не совпадает с immutable manifest.", - ); - } - return payload; -} - -function manifestIdentity(manifest: ObservationRecordedMediaManifest): string { - return JSON.stringify(manifest); -} - -export async function fetchVerifiedRecordedMediaArchive( +export async function fetchRecordedMediaArchive( source: ObservationRecordedMediaSource, { signal, fetcher = globalThis.fetch, - onProgress, }: { signal?: AbortSignal; fetcher?: ObservationSessionFetch; - onProgress?: (progress: RecordedMediaLoadProgress) => void; } = {}, -): Promise { +): Promise { const manifest = await fetchObservationRecordedMediaManifest(source, { signal, fetcher, expectedGenerationSha256: source.manifestGenerationSha256, }); - const totalBytes = manifest.epochs.reduce( - (archiveTotal, epoch) => archiveTotal + epoch.initByteLength + epoch.segments.reduce( - (epochTotal, segment) => epochTotal + segment.byteLength, - 0, - ), - 0, - ); - const totalParts = manifest.epochs.reduce( - (total, epoch) => total + 1 + epoch.segments.length, - 0, - ); + const totalBytes = manifest.epochs.reduce((total, epoch) => total + epoch.byteLength, 0); if ( + !Number.isSafeInteger(totalBytes) || totalBytes < 1 || - totalBytes > MAX_RECORDED_MEDIA_SOURCE_BYTES || totalBytes !== manifest.byteLength || totalBytes !== source.byteLength ) { throw new ObservationSessionContractError( - "Размер записанного медиаканала выходит за безопасный лимит браузера.", + "Размеры потоков записанного медиаканала не совпадают с manifest.", ); } - let loadedBytes = 0; - let loadedParts = 0; - const publishProgress = () => onProgress?.({ - loadedBytes, - totalBytes, - loadedParts, - totalParts, - }); - publishProgress(); - - const epochs: VerifiedRecordedMediaEpoch[] = []; - for (const epoch of manifest.epochs) { - const init = await fetchVerifiedRecordedMediaBytes({ - url: epoch.initUrl, - byteLength: epoch.initByteLength, - sha256: epoch.initSha256, - accept: "video/mp4", - }, { signal, fetcher }); - loadedBytes += init.byteLength; - loadedParts += 1; - publishProgress(); - - const segments: ArrayBuffer[] = []; - for (const segment of epoch.segments) { - const payload = await fetchVerifiedRecordedMediaBytes({ - url: segment.url, - byteLength: segment.byteLength, - sha256: segment.sha256, - accept: "video/iso.segment", - }, { signal, fetcher }); - segments.push(payload); - loadedBytes += payload.byteLength; - loadedParts += 1; - publishProgress(); - } - epochs.push({ descriptor: epoch, init, segments }); - } - - // Bind the complete byte set to the same manifest generation at both ends - // of the transfer. A replacement during a long camera download fails closed. - const confirmed = await fetchObservationRecordedMediaManifest(source, { - signal, - fetcher, - expectedGenerationSha256: manifest.generationSha256, - }); - if (manifestIdentity(confirmed) !== manifestIdentity(manifest)) { - throw new ObservationSessionContractError( - "Manifest записанного видео изменился во время полной загрузки.", - ); - } - if (loadedBytes !== source.byteLength) { - throw new ObservationSessionContractError( - "Полная загрузка камеры не совпала с launch byte_length.", - ); - } - return { manifest, epochs, byteLength: loadedBytes }; -} - -export function appendRecordedMediaBuffer( - sourceBuffer: SourceBuffer, - payload: ArrayBuffer, - signal: AbortSignal, -): Promise { - return new Promise((resolve, reject) => { - const onUpdateEnd = () => { - cleanup(); - resolve(); - }; - const onError = () => { - cleanup(); - reject(new Error("SourceBuffer rejected archived fMP4 data")); - }; - const onAbort = () => { - cleanup(); - reject(new DOMException("Aborted", "AbortError")); - }; - const cleanup = () => { - sourceBuffer.removeEventListener("updateend", onUpdateEnd); - sourceBuffer.removeEventListener("error", onError); - signal.removeEventListener("abort", onAbort); - }; - if (signal.aborted) { - onAbort(); - return; - } - sourceBuffer.addEventListener("updateend", onUpdateEnd, { once: true }); - sourceBuffer.addEventListener("error", onError, { once: true }); - signal.addEventListener("abort", onAbort, { once: true }); - try { - sourceBuffer.appendBuffer(payload); - } catch (error) { - cleanup(); - reject(error); - } - }); + return { manifest, byteLength: totalBytes }; } function videoHasSeekableArchive( @@ -358,17 +162,22 @@ function waitForSeekableArchive( if (videoHasSeekableArchive(video, declaredDurationSeconds)) return Promise.resolve(); return new Promise((resolve, reject) => { const events = ["loadedmetadata", "durationchange", "progress", "canplay"] as const; - const timeout = globalThis.setTimeout(() => { - cleanup(); - reject(new Error("Archived camera did not become seekable")); - }, 20_000); + let stallTimer: ReturnType | undefined; + const armStallTimer = () => { + if (stallTimer !== undefined) globalThis.clearTimeout(stallTimer); + stallTimer = globalThis.setTimeout(() => { + cleanup(); + reject(new Error("Archived camera stream stalled")); + }, 45_000); + }; const cleanup = () => { - globalThis.clearTimeout(timeout); + if (stallTimer !== undefined) globalThis.clearTimeout(stallTimer); for (const event of events) video.removeEventListener(event, onProgress); video.removeEventListener("error", onError); signal.removeEventListener("abort", onAbort); }; const onProgress = () => { + armStallTimer(); if (!videoHasSeekableArchive(video, declaredDurationSeconds)) return; cleanup(); resolve(); @@ -384,43 +193,30 @@ function waitForSeekableArchive( for (const event of events) video.addEventListener(event, onProgress); video.addEventListener("error", onError, { once: true }); signal.addEventListener("abort", onAbort, { once: true }); + armStallTimer(); }); } -async function mountVerifiedRecordedEpoch( +async function mountRecordedEpochStream( video: HTMLVideoElement, - epoch: VerifiedRecordedMediaEpoch, + descriptor: ObservationRecordedMediaEpoch, signal: AbortSignal, ): Promise<() => void> { - const descriptor = epoch.descriptor; if (!descriptor.mediaType.startsWith("video/mp4;") || !video.canPlayType(descriptor.mediaType)) { throw new Error("Archived camera codec is not supported"); } if (signal.aborted) throw new DOMException("Aborted", "AbortError"); - // A sealed fragmented-MP4 generation is already complete and immutable. - // Present it as one Blob so Chromium can index and seek the whole archive - // without retaining the same 166+ MiB epoch in a quota-limited MSE - // SourceBuffer. Every constituent byte was fetched and SHA-256 verified - // before this boundary, and Blob preserves their canonical order. - const payload = new Blob([epoch.init, ...epoch.segments], { - type: descriptor.mediaType, - }); - const expectedByteLength = epoch.init.byteLength + epoch.segments.reduce( - (total, segment) => total + segment.byteLength, - 0, - ); - if (payload.size !== expectedByteLength) { - throw new Error("Archived camera Blob is incomplete"); - } - const objectUrl = URL.createObjectURL(payload); + // The generation token binds the native media request to the exact manifest. + // The browser range-streams the virtual init+fragment file from the server; + // no complete camera archive is copied into JavaScript memory. const cleanup = () => { video.pause(); video.removeAttribute("src"); video.load(); - URL.revokeObjectURL(objectUrl); }; - video.src = objectUrl; + video.preload = "auto"; + video.src = descriptor.streamUrl; video.load(); try { await waitForSeekableArchive( @@ -483,22 +279,15 @@ export function RecordedFmp4Player({ recordedDelivery?.timelineEndSeconds, ], ); - const [archive, setArchive] = useState(null); + const [archive, setArchive] = useState(null); const [state, setState] = useState<"loading" | "ready" | "error">("loading"); const [readyGeneration, setReadyGeneration] = useState(null); - const [progress, setProgress] = useState(null); const [bufferRevision, setBufferRevision] = useState(0); const currentSeconds = playback?.currentSeconds ?? contract?.timelineStartSeconds ?? 0; const epoch = useMemo( () => selectRecordedMediaEpoch(archive?.manifest.epochs ?? [], currentSeconds), [archive?.manifest.epochs, currentSeconds], ); - const verifiedEpoch = useMemo( - () => epoch - ? archive?.epochs.find(({ descriptor }) => descriptor.ordinal === epoch.ordinal) ?? null - : null, - [archive?.epochs, epoch], - ); const waitingForEpoch = Boolean(archive && !epoch); const selectedGeneration = contract && epoch ? `${contract.manifestGenerationSha256}:${epoch.ordinal}:${epoch.timelineStartSeconds}:${epoch.timelineEndSeconds}` @@ -514,7 +303,6 @@ export function RecordedFmp4Player({ useEffect(() => { if (!contract) { setArchive(null); - setProgress(null); setReadyGeneration(null); setState("error"); reportAdmission({ @@ -527,7 +315,6 @@ export function RecordedFmp4Player({ if (!prepare) return; const abort = new AbortController(); setArchive(null); - setProgress(null); setReadyGeneration(null); setState("loading"); reportAdmission({ @@ -535,12 +322,7 @@ export function RecordedFmp4Player({ byteLength: contract.byteLength, message: null, }); - void fetchVerifiedRecordedMediaArchive(contract, { - signal: abort.signal, - onProgress: (next) => { - if (!abort.signal.aborted) setProgress(next); - }, - }) + void fetchRecordedMediaArchive(contract, { signal: abort.signal }) .then((loaded) => { if (abort.signal.aborted) return; setArchive(loaded); @@ -566,11 +348,11 @@ export function RecordedFmp4Player({ const abort = new AbortController(); let disposed = false; void (async () => { - for (const candidate of archive.epochs) { + for (const candidate of archive.manifest.epochs) { const probe = document.createElement("video"); probe.muted = true; probe.playsInline = true; - const cleanup = await mountVerifiedRecordedEpoch(probe, candidate, abort.signal); + const cleanup = await mountRecordedEpochStream(probe, candidate, abort.signal); cleanup(); if (disposed || abort.signal.aborted) return; } @@ -602,8 +384,8 @@ export function RecordedFmp4Player({ useEffect(() => { const video = videoRef.current; - if (!video || !verifiedEpoch) return; - const epochDescriptor = verifiedEpoch.descriptor; + if (!video || !epoch) return; + const epochDescriptor = epoch; const generation = contract ? `${contract.manifestGenerationSha256}:${epochDescriptor.ordinal}:${epochDescriptor.timelineStartSeconds}:${epochDescriptor.timelineEndSeconds}` : null; @@ -615,7 +397,7 @@ export function RecordedFmp4Player({ const loadEpoch = async () => { try { - cleanup = await mountVerifiedRecordedEpoch(video, verifiedEpoch, abort.signal); + cleanup = await mountRecordedEpochStream(video, epochDescriptor, abort.signal); if (disposed || abort.signal.aborted) { cleanup(); cleanup = null; @@ -648,7 +430,7 @@ export function RecordedFmp4Player({ abort.abort(); cleanup?.(); }; - }, [archive?.byteLength, contract, verifiedEpoch]); + }, [archive?.byteLength, contract, epoch]); useEffect(() => { const video = videoRef.current; @@ -679,10 +461,6 @@ export function RecordedFmp4Player({ } }, [archive?.byteLength, bufferRevision, currentSeconds, epoch, playback?.playing, visualState]); - const progressPercent = progress && progress.totalBytes > 0 - ? Math.min(100, Math.floor((progress.loadedBytes / progress.totalBytes) * 100)) - : 0; - return (
) : null}
diff --git a/apps/control-station/src/components/RerunViewport.tsx b/apps/control-station/src/components/RerunViewport.tsx index 7662983..8bfc1ca 100644 --- a/apps/control-station/src/components/RerunViewport.tsx +++ b/apps/control-station/src/components/RerunViewport.tsx @@ -4,7 +4,14 @@ import type { SceneSettings } from "../sceneSettings"; import type { RecordedAdmissionPhase } from "../core/observation/recordedSessionAdmission"; export type RerunViewportStatus = "idle" | "loading" | "ready" | "error"; -export type RecordedRerunView = "spatial" | "perception" | "metrics"; +export type RecordedRerunView = "spatial" | "perception" | "perception3d" | "metrics"; + +export interface RecordedPerceptionLayers { + enabled: boolean; + detections2d: boolean; + segmentation: boolean; + cuboids3d: boolean; +} export interface RerunSelection { entityPath: string; @@ -57,6 +64,8 @@ export interface RerunViewportProps { | "customColor" >; recordedView?: RecordedRerunView; + recordedViewResetGeneration?: 0 | 1; + recordedPerceptionLayers?: RecordedPerceptionLayers; onPerceptionAvailabilityChange?: (available: boolean) => void; } @@ -438,11 +447,20 @@ export async function fetchRecordedBlueprintRrd( origin, signal, activeView = "spatial", + viewResetGeneration = 0, + perceptionLayers = { + enabled: false, + detections2d: false, + segmentation: false, + cuboids3d: false, + }, fetcher = globalThis.fetch, }: { origin: string; signal?: AbortSignal; activeView?: RecordedRerunView; + viewResetGeneration?: 0 | 1; + perceptionLayers?: RecordedPerceptionLayers; fetcher?: typeof globalThis.fetch; }, ): Promise { @@ -461,7 +479,14 @@ export async function fetchRecordedBlueprintRrd( settings.pointSize > 32 || !["turbo", "viridis", "plasma", "grayscale", "custom"].includes(settings.palette) || !/^#[0-9A-Fa-f]{6}$/.test(settings.customColor) || - !["spatial", "perception", "metrics"].includes(activeView) || + !["spatial", "perception", "perception3d", "metrics"].includes(activeView) || + ![0, 1].includes(viewResetGeneration) || + [ + perceptionLayers.enabled, + perceptionLayers.detections2d, + perceptionLayers.segmentation, + perceptionLayers.cuboids3d, + ].some((value) => typeof value !== "boolean") || identity.applicationId !== "nodedc_mission_core_recorded" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(identity.recordingId) ) { @@ -485,6 +510,11 @@ export async function fetchRecordedBlueprintRrd( palette: settings.palette, custom_color: settings.customColor, active_view: activeView, + view_reset_generation: viewResetGeneration, + unified_perception: perceptionLayers.enabled, + show_detections_2d: perceptionLayers.detections2d, + show_segmentation: perceptionLayers.segmentation, + show_cuboids_3d: perceptionLayers.cuboids3d, }), signal, }); @@ -588,6 +618,13 @@ export function RerunViewport({ onPlaybackControllerChange, sceneSettings, recordedView = "spatial", + recordedViewResetGeneration = 0, + recordedPerceptionLayers = { + enabled: false, + detections2d: false, + segmentation: false, + cuboids3d: false, + }, onPerceptionAvailabilityChange, }: RerunViewportProps) { const hostRef = useRef(null); @@ -596,6 +633,7 @@ export function RerunViewport({ const [retryNonce, setRetryNonce] = useState(0); const blueprintChannelRef = useRef(null); const perceptionChannelRef = useRef(null); + const loadedPerceptionChannelRef = useRef(null); const recordedIdentityRef = useRef(null); const presentationGateRef = useRef(presentationGate); presentationGateRef.current = presentationGate; @@ -1123,11 +1161,11 @@ export function RerunViewport({ ]); useEffect(() => { - onPerceptionAvailabilityChange?.(false); - }, [onPerceptionAvailabilityChange, recordedPerceptionUrl]); + loadedPerceptionChannelRef.current = null; + }, [recordedPerceptionUrl]); useEffect(() => { - if (!recordedPerceptionUrl) return; + if (!recordedPerceptionUrl || !recordedPerceptionLayers.enabled) return; const active = perceptionChannelRef.current; const identity = recordedIdentityRef.current; if ( @@ -1136,6 +1174,10 @@ export function RerunViewport({ active.endpointUrl !== recordedPerceptionUrl || !active.channel.ready ) return; + if (loadedPerceptionChannelRef.current === active) { + onPerceptionAvailabilityChange?.(true); + return; + } const abort = new AbortController(); void fetchRecordedPerceptionRrd(recordedPerceptionUrl, identity, { origin: window.location.origin, @@ -1154,6 +1196,7 @@ export function RerunViewport({ return; } active.channel.send_rrd(payload); + loadedPerceptionChannelRef.current = active; onPerceptionAvailabilityChange?.(true); }).catch(() => { onPerceptionAvailabilityChange?.(false); @@ -1163,6 +1206,7 @@ export function RerunViewport({ }, [ onPerceptionAvailabilityChange, perceptionChannelRevision, + recordedPerceptionLayers.enabled, recordedPerceptionUrl, ]); @@ -1181,6 +1225,8 @@ export function RerunViewport({ origin: window.location.origin, signal: abort.signal, activeView: recordedView, + viewResetGeneration: recordedViewResetGeneration, + perceptionLayers: recordedPerceptionLayers, }).then((payload) => { if ( abort.signal.aborted || @@ -1200,6 +1246,11 @@ export function RerunViewport({ blueprintChannelRevision, recordedBlueprintUrl, recordedView, + recordedViewResetGeneration, + recordedPerceptionLayers.enabled, + recordedPerceptionLayers.detections2d, + recordedPerceptionLayers.segmentation, + recordedPerceptionLayers.cuboids3d, sceneSettings?.accumulationSeconds, sceneSettings?.customColor, sceneSettings?.palette, diff --git a/apps/control-station/src/core/observation/recordedObservationSources.ts b/apps/control-station/src/core/observation/recordedObservationSources.ts index a0fe15a..cb5e310 100644 --- a/apps/control-station/src/core/observation/recordedObservationSources.ts +++ b/apps/control-station/src/core/observation/recordedObservationSources.ts @@ -38,47 +38,57 @@ export function recordedObservationSources( spatialRegistration: "native", }, }; - const media = launch.mediaSources.map((source, index): ObservationSourceDescriptor => ({ - id: source.id, - sourceId: source.id, - semanticChannelId: "camera.video.recorded", - label: source.label, - description: "Сохранённый видеоканал на общей временной шкале сессии", - modality: "video", - role: "auxiliary", - availability: "available", - transport: "recording", - endpointLabel: "Сохранённая сессия", - previewUrl: null, - delivery: { - id: `${launch.sessionId}:${source.id}`, - kind: "recorded-fmp4-manifest", - url: source.manifestUrl, - mediaType: source.mediaType, - manifestGenerationSha256: source.manifestGenerationSha256, - byteLength: source.byteLength, - timelineStartSeconds: source.timelineStartSeconds, - timelineEndSeconds: source.timelineEndSeconds, - }, - activation: null, - provider: { - pluginId: "missioncore.session-archive", - pluginVersion: "1", - modelId: "recorded-media", - compatibilityProfileId: null, - }, - binding: {}, - capabilities: { - overlay: true, - fullscreen: true, - resizable: true, - defaultVisible: index < 2, - timelineMode: "recorded", - seekable: true, - sessionRecording: true, - clockId: "session_time", - spatialRegistration: "unresolved", - }, - })); + const media = launch.mediaSources.map((source, index): ObservationSourceDescriptor => { + const perception = source.id.startsWith("recorded.perception."); + return { + id: source.id, + sourceId: source.id, + semanticChannelId: perception + ? "camera.perception.panoptic.recorded" + : "camera.video.recorded", + label: source.label, + description: perception + ? "Покадровая instance + semantic сегментация на общей временной шкале" + : "Сохранённый видеоканал на общей временной шкале сессии", + modality: "video", + role: "auxiliary", + availability: "available", + transport: "recording", + endpointLabel: "Сохранённая сессия", + previewUrl: null, + delivery: { + id: `${launch.sessionId}:${source.id}`, + kind: "recorded-fmp4-manifest", + url: source.manifestUrl, + mediaType: source.mediaType, + manifestGenerationSha256: source.manifestGenerationSha256, + byteLength: source.byteLength, + timelineStartSeconds: source.timelineStartSeconds, + timelineEndSeconds: source.timelineEndSeconds, + }, + activation: null, + provider: { + pluginId: "missioncore.session-archive", + pluginVersion: "1", + modelId: perception ? "recorded-panoptic-perception" : "recorded-media", + compatibilityProfileId: null, + }, + binding: {}, + capabilities: { + overlay: true, + fullscreen: true, + resizable: true, + // AI presentation belongs to the unified Rerun composition. Keep the + // pre-rendered perception video as an explicit fallback instead of + // opening it as a second, independently controlled stream. + defaultVisible: !perception && index < 2, + timelineMode: "recorded", + seekable: true, + sessionRecording: true, + clockId: "session_time", + spatialRegistration: perception ? "calibrated" : "unresolved", + }, + }; + }); return [spatial, ...media]; } diff --git a/apps/control-station/src/core/observation/recordedSessionAdmission.ts b/apps/control-station/src/core/observation/recordedSessionAdmission.ts index c3c3e0b..214ba7f 100644 --- a/apps/control-station/src/core/observation/recordedSessionAdmission.ts +++ b/apps/control-station/src/core/observation/recordedSessionAdmission.ts @@ -1,12 +1,8 @@ -// A device-agnostic frontend safety policy. Sixteen channels covers multi-rig -// vehicles while the independent byte/concurrency limits keep admission -// bounded. One real accepted archive is ~163 MiB for a single camera, so the -// old 128 MiB laboratory ceiling rejected a valid sealed generation before the -// first manifest request. OPFS-backed sealed generations remain the scaling -// path beyond this in-memory policy. +// Camera count and preparation concurrency remain device-agnostic scheduling +// policy. Recorded duration and aggregate bytes are deliberately not admission +// criteria: sealed media is presented through a generation-bound HTTP stream, +// so a one-, three- or ten-hour recording never has to fit in browser memory. export const MAX_RECORDED_CAMERA_SOURCES = 16; -export const MAX_RECORDED_MEDIA_SOURCE_BYTES = 256 * 1024 * 1024; -export const MAX_RECORDED_SESSION_CAMERA_BYTES = 512 * 1024 * 1024; export const MAX_CONCURRENT_RECORDED_CAMERA_PREPARATIONS = 1; export type RecordedAdmissionPhase = "loading" | "ready" | "error"; @@ -32,18 +28,12 @@ export function recordedCameraDescriptorPreflight( ): RecordedAdmissionPhase { if (sources.length > MAX_RECORDED_CAMERA_SOURCES) return "error"; if (new Set(sources.map(({ id }) => id)).size !== sources.length) return "error"; - let totalBytes = 0; for (const source of sources) { if ( !source.id || !Number.isSafeInteger(source.byteLength) || - source.byteLength < 1 || - source.byteLength > MAX_RECORDED_MEDIA_SOURCE_BYTES + source.byteLength < 1 ) return "error"; - totalBytes += source.byteLength; - if (!Number.isSafeInteger(totalBytes) || totalBytes > MAX_RECORDED_SESSION_CAMERA_BYTES) { - return "error"; - } } return "ready"; } @@ -67,7 +57,6 @@ export function recordedSessionAdmissionPhase( if (sourceIds.length > MAX_RECORDED_CAMERA_SOURCES || spatialPhase === "error") { return "error"; } - let totalBytes = 0; for (const sourceId of sourceIds) { const camera = cameras[sourceId]; if (!camera || camera.phase === "error") return "error"; @@ -75,13 +64,10 @@ export function recordedSessionAdmissionPhase( if (camera.byteLength !== null) { if ( !Number.isSafeInteger(camera.byteLength) || - camera.byteLength < 1 || - camera.byteLength > MAX_RECORDED_MEDIA_SOURCE_BYTES + camera.byteLength < 1 ) return "error"; - totalBytes += camera.byteLength; } } - if (totalBytes > MAX_RECORDED_SESSION_CAMERA_BYTES) return "error"; if (spatialPhase !== "ready") return "loading"; return sourceIds.every((sourceId) => cameras[sourceId]?.phase === "ready") ? "ready" diff --git a/apps/control-station/src/core/observation/sessionArchive.ts b/apps/control-station/src/core/observation/sessionArchive.ts index 009f26e..5d88940 100644 --- a/apps/control-station/src/core/observation/sessionArchive.ts +++ b/apps/control-station/src/core/observation/sessionArchive.ts @@ -1,7 +1,5 @@ import { MAX_RECORDED_CAMERA_SOURCES, - MAX_RECORDED_MEDIA_SOURCE_BYTES, - MAX_RECORDED_SESSION_CAMERA_BYTES, } from "./recordedSessionAdmission"; export type ObservationSessionStatus = @@ -99,19 +97,8 @@ export interface ObservationRecordedMediaEpoch { timelineStartSeconds: number; timelineEndSeconds: number; mediaType: string; - initUrl: string; - initByteLength: number; - initSha256: string; - segmentCount: number; - segmentUrlPrefix: string; - segments: readonly ObservationRecordedMediaSegment[]; -} - -export interface ObservationRecordedMediaSegment { - sequence: number; - url: string; byteLength: number; - sha256: string; + streamUrl: string; } export interface ObservationRecordedMediaManifest { @@ -215,18 +202,8 @@ const RECORDED_MEDIA_EPOCH_KEYS = new Set([ "timeline_start_seconds", "timeline_end_seconds", "media_type", - "init_url", - "init_byte_length", - "init_sha256", - "segment_count", - "segment_url_prefix", - "segments", -]); -const RECORDED_MEDIA_SEGMENT_KEYS = new Set([ - "sequence", - "url", "byte_length", - "sha256", + "stream_url", ]); const SAFE_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/; const SAFE_MODALITY = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$/; @@ -234,10 +211,9 @@ const ISO_WITH_TIMEZONE = /^\d{4}-\d{2}-\d{2}T.+(?:Z|[+-]\d{2}:\d{2})$/; const SHA256 = /^[a-f0-9]{64}$/; const SAFE_RECORDING_URL = /^\/api\/v1\/observation-sessions\/[A-Za-z0-9._%:-]+\/recording\.rrd$/; const SAFE_PREPARATION_URL = /^\/api\/v1\/observation-sessions\/[A-Za-z0-9._%:-]+\/recording-preparation$/; -const SAFE_MEDIA_MANIFEST_URL = /^\/api\/v1\/observation-sessions\/[A-Za-z0-9._%:-]+\/media\/[A-Za-z0-9._%-]+\/manifest$/; +const SAFE_MEDIA_MANIFEST_URL = /^\/api\/v1\/observation-sessions\/[A-Za-z0-9._%:-]+\/(?:media\/[A-Za-z0-9._%-]+|perception-media\/result-[a-f0-9]{64})\/manifest$/; +const SAFE_MEDIA_STREAM_URL = /^\/api\/v1\/observation-sessions\/[A-Za-z0-9._%:-]+\/(?:media\/[A-Za-z0-9._%-]+\/epochs\/[1-9][0-9]*|perception-media\/result-[a-f0-9]{64})\/recording\.mp4\?generation=[a-f0-9]{64}$/; const SAFE_MP4_MEDIA_TYPE = /^video\/mp4(?:; codecs="[A-Za-z0-9.,_-]+")?$/; -const MAX_RECORDED_INIT_BYTES = 8 * 1024 * 1024; -const MAX_RECORDED_SEGMENT_BYTES = 64 * 1024 * 1024; export class ObservationSessionContractError extends Error { constructor(message: string) { @@ -570,15 +546,6 @@ export function decodeObservationSessionReplay( "Descriptor записи содержит повторяющиеся медиаканалы.", ); } - const mediaByteLength = mediaSources.reduce((total, source) => total + source.byteLength, 0); - if ( - !Number.isSafeInteger(mediaByteLength) || - mediaByteLength > MAX_RECORDED_SESSION_CAMERA_BYTES - ) { - throw new ObservationSessionContractError( - "Совокупный объём записанных медиаканалов превышает безопасный лимит браузера.", - ); - } return { kind: "rerun-recording", sessionId, @@ -709,7 +676,10 @@ function decodeRecordedMediaSource( } assertExactKeys(value, RECORDED_MEDIA_SOURCE_KEYS, `Медиаканал ${index}`); const id = requireString(value.id, `media_sources[${index}].id`, 128); - if (!SAFE_ID.test(id) || !id.startsWith("recorded.camera.")) { + if ( + !SAFE_ID.test(id) || + (!id.startsWith("recorded.camera.") && !id.startsWith("recorded.perception.")) + ) { throw new ObservationSessionContractError("Медиаканал содержит небезопасный opaque id."); } if (value.modality !== "video" || value.media_type !== "video/mp4") { @@ -728,10 +698,10 @@ function decodeRecordedMediaSource( "Медиаканал не содержит immutable generation SHA-256.", ); } - const sessionPrefix = `/api/v1/observation-sessions/${encodeURIComponent(sessionId)}/media/`; + const sessionBase = `/api/v1/observation-sessions/${encodeURIComponent(sessionId)}/`; if ( !SAFE_MEDIA_MANIFEST_URL.test(manifestUrl) || - !manifestUrl.startsWith(sessionPrefix) || + !manifestUrl.startsWith(sessionBase) || manifestUrl.includes("..") ) { throw new ObservationSessionContractError( @@ -765,7 +735,7 @@ function decodeRecordedMediaSource( byteLength: requireFiniteNumber( value.byte_length, `media_sources[${index}].byte_length`, - { minimum: 1, maximum: MAX_RECORDED_MEDIA_SOURCE_BYTES, integer: true }, + { minimum: 1, maximum: Number.MAX_SAFE_INTEGER, integer: true }, ), mediaType: "video/mp4", timelineStartSeconds, @@ -784,22 +754,21 @@ export function decodeObservationRecordedMediaManifest( } assertExactKeys(payload, RECORDED_MEDIA_MANIFEST_KEYS, "Manifest записанного видео"); if ( - payload.schema_version !== "missioncore.observation-recorded-media/v2" || + payload.schema_version !== "missioncore.observation-recorded-media/v3" || payload.source_id !== source.id || typeof payload.generation_sha256 !== "string" || !SHA256.test(payload.generation_sha256) || payload.generation_sha256 !== source.manifestGenerationSha256 || payload.synchronization !== "host-arrival-best-effort" || !Array.isArray(payload.epochs) || - payload.epochs.length < 1 || - payload.epochs.length > 1_000 + payload.epochs.length < 1 ) { throw new ObservationSessionContractError("Manifest записанного видео несовместим."); } const manifestBase = source.manifestUrl.slice(0, -"/manifest".length); const manifestByteLength = requireFiniteNumber(payload.byte_length, "manifest.byte_length", { minimum: 1, - maximum: MAX_RECORDED_MEDIA_SOURCE_BYTES, + maximum: Number.MAX_SAFE_INTEGER, integer: true, }); if (manifestByteLength !== source.byteLength) { @@ -833,7 +802,7 @@ export function decodeObservationRecordedMediaManifest( assertExactKeys(entry, RECORDED_MEDIA_EPOCH_KEYS, `Codec epoch ${index}`); const ordinal = requireFiniteNumber(entry.ordinal, `epochs[${index}].ordinal`, { minimum: 1, - maximum: 1_000, + maximum: Number.MAX_SAFE_INTEGER, integer: true, }); if (ordinal !== index + 1) { @@ -860,87 +829,28 @@ export function decodeObservationRecordedMediaManifest( if (!SAFE_MP4_MEDIA_TYPE.test(mediaType)) { throw new ObservationSessionContractError("Codec epoch содержит небезопасный media type."); } - const initUrl = requireString(entry.init_url, `epochs[${index}].init_url`, 512); - const segmentUrlPrefix = requireString( - entry.segment_url_prefix, - `epochs[${index}].segment_url_prefix`, - 512, + const byteLength = requireFiniteNumber( + entry.byte_length, + `epochs[${index}].byte_length`, + { minimum: 1, maximum: Number.MAX_SAFE_INTEGER, integer: true }, ); - const expectedEpochBase = `${manifestBase}/epochs/${ordinal}`; + const streamUrl = requireString(entry.stream_url, `epochs[${index}].stream_url`, 768); + const expectedEpochBase = source.id.startsWith("recorded.perception.") + ? manifestBase + : `${manifestBase}/epochs/${ordinal}`; + const expectedStreamUrl = + `${expectedEpochBase}/recording.mp4?generation=${payload.generation_sha256}`; if ( - initUrl !== `${expectedEpochBase}/init.mp4` || - segmentUrlPrefix !== `${expectedEpochBase}/segments/` || - initUrl.includes("..") || - segmentUrlPrefix.includes("..") + !SAFE_MEDIA_STREAM_URL.test(streamUrl) || + streamUrl !== expectedStreamUrl || + streamUrl.includes("..") ) { throw new ObservationSessionContractError("Codec epoch содержит небезопасный API URL."); } - const initByteLength = requireFiniteNumber( - entry.init_byte_length, - `epochs[${index}].init_byte_length`, - { minimum: 1, maximum: MAX_RECORDED_INIT_BYTES, integer: true }, - ); - if (typeof entry.init_sha256 !== "string" || !SHA256.test(entry.init_sha256)) { - throw new ObservationSessionContractError("Codec epoch не содержит SHA-256 init-сегмента."); - } - const segmentCount = requireFiniteNumber( - entry.segment_count, - `epochs[${index}].segment_count`, - { minimum: 1, maximum: 500_000, integer: true }, - ); - if (!Array.isArray(entry.segments) || entry.segments.length !== segmentCount) { + declaredBytes += byteLength; + if (!Number.isSafeInteger(declaredBytes)) { throw new ObservationSessionContractError( - "Codec epoch содержит неполный список канонических сегментов.", - ); - } - const segments = entry.segments.map((segment, segmentIndex): ObservationRecordedMediaSegment => { - if (!isRecord(segment)) { - throw new ObservationSessionContractError( - `Сегмент epochs[${index}].segments[${segmentIndex}] должен быть объектом.`, - ); - } - assertExactKeys( - segment, - RECORDED_MEDIA_SEGMENT_KEYS, - `Сегмент epochs[${index}].segments[${segmentIndex}]`, - ); - const sequence = requireFiniteNumber( - segment.sequence, - `epochs[${index}].segments[${segmentIndex}].sequence`, - { minimum: 1, maximum: 500_000, integer: true }, - ); - if (sequence !== segmentIndex + 1) { - throw new ObservationSessionContractError( - "Codec epoch содержит непоследовательный сегмент.", - ); - } - const url = requireString( - segment.url, - `epochs[${index}].segments[${segmentIndex}].url`, - 512, - ); - if (url !== `${segmentUrlPrefix}${sequence}.m4s` || url.includes("..")) { - throw new ObservationSessionContractError( - "Codec epoch содержит небезопасный URL сегмента.", - ); - } - const byteLength = requireFiniteNumber( - segment.byte_length, - `epochs[${index}].segments[${segmentIndex}].byte_length`, - { minimum: 1, maximum: MAX_RECORDED_SEGMENT_BYTES, integer: true }, - ); - if (typeof segment.sha256 !== "string" || !SHA256.test(segment.sha256)) { - throw new ObservationSessionContractError( - "Codec epoch содержит сегмент без SHA-256.", - ); - } - declaredBytes += byteLength; - return { sequence, url, byteLength, sha256: segment.sha256 }; - }); - declaredBytes += initByteLength; - if (declaredBytes > MAX_RECORDED_MEDIA_SOURCE_BYTES) { - throw new ObservationSessionContractError( - "Записанный медиаканал превышает безопасный лимит браузера.", + "Суммарный размер codec epoch выходит за точный числовой диапазон клиента.", ); } return { @@ -948,17 +858,13 @@ export function decodeObservationRecordedMediaManifest( timelineStartSeconds, timelineEndSeconds, mediaType, - initUrl, - initByteLength, - initSha256: entry.init_sha256, - segmentCount, - segmentUrlPrefix, - segments, + byteLength, + streamUrl, }; }); if (declaredBytes !== manifestByteLength) { throw new ObservationSessionContractError( - "Сумма init- и media-сегментов не совпадает с размером immutable manifest.", + "Сумма codec epoch не совпадает с размером immutable manifest.", ); } if ( diff --git a/apps/control-station/src/core/observation/useObservationSessions.ts b/apps/control-station/src/core/observation/useObservationSessions.ts index adbd0bc..5fa1400 100644 --- a/apps/control-station/src/core/observation/useObservationSessions.ts +++ b/apps/control-station/src/core/observation/useObservationSessions.ts @@ -285,11 +285,16 @@ export async function resolveObservationSessionReplay( sessionId: string, options: ObservationPreparationPollingOptions, ): Promise { - const response = await withRequestTimeout( - options.signal, - Math.max(100, options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS), - (signal) => replayObservationSession(sessionId, { signal, fetcher: options.fetcher }), - ); + // The initial replay request may restore and integrity-check large, already + // published artifacts before it can return either a launch descriptor or a + // background-preparation handle. Its duration therefore scales with the + // recording package and must not be confused with a stalled status poll. + // Keep it cancellable by the owning UI attempt, but do not impose the short + // per-poll timeout used once the server has returned a preparation handle. + const response = await replayObservationSession(sessionId, { + signal: options.signal, + fetcher: options.fetcher, + }); if (response.kind === "ready") return response.launch; if (!pendingPreparation(response.preparation)) { options.onUpdate?.(response.preparation); diff --git a/apps/control-station/src/core/runtime/contracts.ts b/apps/control-station/src/core/runtime/contracts.ts index 797ee38..e0f7ec3 100644 --- a/apps/control-station/src/core/runtime/contracts.ts +++ b/apps/control-station/src/core/runtime/contracts.ts @@ -22,6 +22,9 @@ export interface ViewerSettings { show_points: boolean; show_trajectory: boolean; show_grid: boolean; + show_detections_2d: boolean; + show_segmentation: boolean; + show_cuboids_3d: boolean; } export interface StreamMetrics { @@ -29,6 +32,10 @@ export interface StreamMetrics { frameRateHz?: number | null; pointCount?: number | null; droppedPreviewFrames?: number | null; + aiLatencyMs?: number | null; + aiFrameRateHz?: number | null; + aiDroppedFrames?: number | null; + aiStaleMs?: number | null; elapsedSeconds?: number | null; routeDistanceMeters?: number | null; speedMetersPerSecond?: number | null; diff --git a/apps/control-station/src/styles/observation.css b/apps/control-station/src/styles/observation.css index 58f9e88..5fd1f05 100644 --- a/apps/control-station/src/styles/observation.css +++ b/apps/control-station/src/styles/observation.css @@ -32,6 +32,25 @@ backdrop-filter: blur(18px); } +.scene-navigation-hint { + position: absolute; + z-index: 11; + right: 0.85rem; + bottom: 4.9rem; + display: flex; + align-items: center; + gap: 0.75rem; + border: 1px solid rgb(255 255 255 / 0.07); + border-radius: 999px; + background: rgb(9 10 13 / 0.7); + color: var(--nodedc-text-muted); + padding: 0.42rem 0.65rem; + font-size: 0.52rem; + font-weight: 680; + pointer-events: none; + backdrop-filter: blur(14px); +} + .scene-source-picker__trigger { position: relative; } @@ -350,6 +369,11 @@ i[data-availability="error"] { box-shadow: 0 1.5rem 4rem rgb(0 0 0 / 0.34); } +.floating-observation-window--hidden { + visibility: hidden; + pointer-events: none; +} + .observation-timeline { display: block; min-width: 0; diff --git a/apps/control-station/src/styles/spatial.css b/apps/control-station/src/styles/spatial.css index 1ce67a9..e0fb96c 100644 --- a/apps/control-station/src/styles/spatial.css +++ b/apps/control-station/src/styles/spatial.css @@ -25,6 +25,20 @@ gap: 0.45rem; } +.spatial-toolbar__view-switch { + display: inline-flex; + align-items: center; + gap: 0.25rem; + border: 1px solid rgb(255 255 255 / 0.07); + border-radius: 999px; + background: rgb(255 255 255 / 0.025); + padding: 0.2rem; +} + +.spatial-toolbar__view-switch .nodedc-button { + border-radius: 999px; +} + .spatial-viewport-shell { position: relative; min-width: 0; diff --git a/apps/control-station/src/workspaces/Workspaces.tsx b/apps/control-station/src/workspaces/Workspaces.tsx index ceb9be1..706cd9b 100644 --- a/apps/control-station/src/workspaces/Workspaces.tsx +++ b/apps/control-station/src/workspaces/Workspaces.tsx @@ -45,7 +45,6 @@ import { type RerunPlaybackState, type RerunSelection, type RerunViewportStatus, - type RecordedRerunView, } from "../components/RerunViewport"; import { capabilityStatusLabel, @@ -124,6 +123,16 @@ export interface WorkspaceRendererProps { accumulationSeconds: number; onAccumulationChange: (value: number) => void; onAccumulationCommit: () => void; + livePerceptionLayers: { + detections2d: boolean; + segmentation: boolean; + cuboids3d: boolean; + }; + onLivePerceptionLayersChange: (next: { + detections2d: boolean; + segmentation: boolean; + cuboids3d: boolean; + }) => void; observationLayout: ObservationLayoutController; navigation: WorkspaceNavigation; spatialControls: { @@ -286,6 +295,8 @@ function SpatialWorkspace({ accumulationSeconds, onAccumulationChange, onAccumulationCommit, + livePerceptionLayers, + onLivePerceptionLayersChange, observationLayout, navigation, spatialControls, @@ -295,8 +306,13 @@ function SpatialWorkspace({ const [selection, setSelection] = useState(null); const [playbackState, setPlaybackState] = useState(null); const [playbackController, setPlaybackController] = useState(null); - const [recordedRerunView, setRecordedRerunView] = useState("spatial"); - const [perceptionAvailable, setPerceptionAvailable] = useState(false); + const [recordedViewResetGeneration, setRecordedViewResetGeneration] = useState<0 | 1>(0); + const [perceptionAvailability, setPerceptionAvailability] = useState< + "unknown" | "available" | "unavailable" + >("unknown"); + const [showDetections2d, setShowDetections2d] = useState(false); + const [showSegmentation, setShowSegmentation] = useState(false); + const [showCuboids3d, setShowCuboids3d] = useState(false); const recordedSource = state?.sourceMode === "replay" || /\.rrd(?:$|[?#])/i.test(sourceUrl); const recordedSessionGate: RecordedAdmissionPhase = recordedSource ? recordedSessionAdmission?.phase ?? "loading" @@ -309,6 +325,8 @@ function SpatialWorkspace({ const latency = pipelineLatency(metrics); const frameRate = finiteMetric(metrics?.frameRateHz); const points = finiteMetric(metrics?.pointCount); + const aiLatency = finiteMetric(metrics?.aiLatencyMs); + const aiFrameRate = finiteMetric(metrics?.aiFrameRateHz); const observationSources = state?.observationSources ?? []; const pointCloudSource = observationSources.find((source) => source.modality === "point-cloud"); const pointCloudVisible = pointCloudSource @@ -317,13 +335,29 @@ function SpatialWorkspace({ const mediaSources = observationSources.filter( (source) => source.capabilities.overlay && source.modality !== "point-cloud", ); + const recordedPerceptionSupported = recordedSource && perceptionAvailability !== "unavailable"; + const recordedPerceptionEnabled = showDetections2d || showSegmentation || showCuboids3d; + const unifiedPerception = recordedPerceptionSupported && recordedPerceptionEnabled; + const livePerceptionAvailable = !recordedSource && streamActive; + const detections2dActive = recordedSource + ? showDetections2d + : livePerceptionLayers.detections2d; + const segmentationActive = recordedSource + ? showSegmentation + : livePerceptionLayers.segmentation; + const cuboids3dActive = recordedSource + ? showCuboids3d + : livePerceptionLayers.cuboids3d; const visibleMediaSources = mediaSources.filter((source) => - observationLayout.visibleSourceIds.has(source.id), + observationLayout.visibleSourceIds.has(source.id) && + !source.id.startsWith("recorded.perception."), ); + const presentedMediaSourceCount = unifiedPerception ? 0 : visibleMediaSources.length; const pointCloudFocused = Boolean( pointCloudSource && observationLayout.focusedSourceId === pointCloudSource.id, ); - const floatingSourceMaximized = Boolean(observationLayout.maximizedFloatingSourceId); + const floatingSourceMaximized = !unifiedPerception && + Boolean(observationLayout.maximizedFloatingSourceId); const timeline = state?.observationTimeline; const viewportRef = useRef(null); const intentionalSourceEnd = !recordedSource && [ @@ -373,13 +407,20 @@ function SpatialWorkspace({ [], ); const onPerceptionAvailabilityChange = useCallback((available: boolean) => { - setPerceptionAvailable(available); - if (!available) setRecordedRerunView("spatial"); + setPerceptionAvailability(available ? "available" : "unavailable"); + if (!available) { + setShowDetections2d(false); + setShowSegmentation(false); + setShowCuboids3d(false); + } }, []); useEffect(() => { - setPerceptionAvailable(false); - setRecordedRerunView("spatial"); + setPerceptionAvailability("unknown"); + setShowDetections2d(false); + setShowSegmentation(false); + setShowCuboids3d(false); + setRecordedViewResetGeneration(0); }, [sourceUrl]); useEffect(() => { @@ -389,8 +430,10 @@ function SpatialWorkspace({ setSelection(null); setPlaybackState(null); setPlaybackController(null); - setPerceptionAvailable(false); - setRecordedRerunView("spatial"); + setPerceptionAvailability("unknown"); + setShowDetections2d(false); + setShowSegmentation(false); + setShowCuboids3d(false); }, [pointCloudVisible, sourceUrl]); useEffect(() => { @@ -428,20 +471,74 @@ function SpatialWorkspace({ className="spatial-workspace" data-focused={pointCloudFocused || floatingSourceMaximized ? "true" : undefined} > -
+
СЦЕНА 3D · RERUN
- {recordedSource && perceptionAvailable ? ( + {recordedPerceptionSupported || livePerceptionAvailable ? ( +
+ + + + +
+ ) : null} + {recordedSource && presentedViewerStatus === "ready" ? ( ) : null}
{!pointCloudFocused && !floatingSourceMaximized && state?.sourceMode && state.sourceMode !== "idle" && !sourceUrl.trim() ? ( @@ -575,10 +690,17 @@ function SpatialWorkspace({
) : null} + {presentedViewerStatus === "ready" && !floatingSourceMaximized ? ( +
+ Колесо · зум к курсору + WASD · свободный проход +
+ ) : null} + {!pointCloudFocused && !floatingSourceMaximized && recordedPlaybackReady ? ( ) : null} - {!pointCloudFocused ? visibleMediaSources.map((source, index) => ( + {visibleMediaSources.map((source, index) => (
diff --git a/apps/control-station/test/observationSessions.test.mjs b/apps/control-station/test/observationSessions.test.mjs index d9498b4..aa88ea9 100644 --- a/apps/control-station/test/observationSessions.test.mjs +++ b/apps/control-station/test/observationSessions.test.mjs @@ -484,6 +484,31 @@ test("202 preparation polls through explicit phases and reveals launch only when assert.deepEqual(calls.map((entry) => entry[2]), [null, preparationEtag, preparationEtag]); }); +test("initial replay restore is not mistaken for a stalled preparation poll", async () => { + const sessionId = "session-20260716T205632Z"; + let requestSignal; + const launch = await resolveObservationSessionReplay(sessionId, { + signal: new AbortController().signal, + requestTimeoutMs: 100, + fetcher: async (_input, init) => { + requestSignal = init.signal; + await new Promise((resolve, reject) => { + const timer = setTimeout(resolve, 150); + init.signal.addEventListener("abort", () => { + clearTimeout(timer); + reject(new DOMException("cancelled", "AbortError")); + }, { once: true }); + }); + return new Response(JSON.stringify(replay({ session_id: sessionId })), { + status: 200, + headers: { "Content-Type": "application/json" }, + }); + }, + }); + assert.equal(requestSignal.aborted, false); + assert.equal(launch.sessionId, sessionId); +}); + test("status-ready response must match the preparation ETag before launch is accepted", async () => { const decoded = decodeObservationSessionPreparation( preparation({ state: "finalizing", progress: 0.95 }), @@ -704,6 +729,29 @@ test("switching saved sessions aborts only local polling and never cancels share assert.doesNotMatch(selectorSource, /cancelReplay|>\s*Отменить\s* { + const selectorSource = await readFile( + new URL("../src/components/ObservationSessionSelect.tsx", import.meta.url), + "utf8", + ); + + assert.match(selectorSource, /exporting:\s*["']Готовим операторскую сцену["']/); + assert.doesNotMatch(selectorSource, /Math\.round\(progress\s*\*\s*100\)/); +}); + +test("unified recorded AI view keeps the raw camera mounted but does not cover overlays", async () => { + const workspaceSource = await readFile( + new URL("../src/workspaces/Workspaces.tsx", import.meta.url), + "utf8", + ); + + assert.match(workspaceSource, /hidden=\{pointCloudFocused \|\| unifiedPerception\}/); + assert.match( + workspaceSource, + /presentedMediaSourceCount = unifiedPerception \? 0 : visibleMediaSources\.length/, + ); +}); + test("replay descriptor rejects path leaks, mismatched sessions and non-seekable data", () => { assert.throws( () => decodeObservationSessionReplay(replay({ source_url: "file:///private/session.rrd" })), @@ -776,7 +824,7 @@ test("replay decodes opaque recorded cameras and their same-origin fMP4 manifest ); const manifest = decodeObservationRecordedMediaManifest({ - schema_version: "missioncore.observation-recorded-media/v2", + schema_version: "missioncore.observation-recorded-media/v3", source_id: source.id, generation_sha256: "c".repeat(64), byte_length: 3_266, @@ -788,21 +836,15 @@ test("replay decodes opaque recorded cameras and their same-origin fMP4 manifest timeline_start_seconds: 0.25, timeline_end_seconds: 20, media_type: 'video/mp4; codecs="avc1.640028"', - init_url: source.manifest_url.replace("/manifest", "/epochs/1/init.mp4"), - init_byte_length: 128, - init_sha256: "a".repeat(64), - segment_count: 12, - segment_url_prefix: source.manifest_url.replace("/manifest", "/epochs/1/segments/"), - segments: Array.from({ length: 12 }, (_, index) => ({ - sequence: index + 1, - url: source.manifest_url.replace("/manifest", `/epochs/1/segments/${index + 1}.m4s`), - byte_length: 256 + index, - sha256: "b".repeat(64), - })), + byte_length: 3_266, + stream_url: source.manifest_url.replace( + "/manifest", + `/epochs/1/recording.mp4?generation=${"c".repeat(64)}`, + ), }], }, decoded.mediaSources[0]); - assert.equal(manifest.epochs[0].segmentCount, 12); - assert.equal(manifest.epochs[0].segments.length, 12); + assert.equal(manifest.epochs[0].byteLength, 3_266); + assert.match(manifest.epochs[0].streamUrl, /recording\.mp4\?generation=/); assert.equal(manifest.epochs[0].timelineStartSeconds, 0.25); assert.throws( () => decodeObservationRecordedMediaManifest({ @@ -821,7 +863,7 @@ test("replay decodes opaque recorded cameras and their same-origin fMP4 manifest ); assert.throws( () => decodeObservationRecordedMediaManifest({ - schema_version: "missioncore.observation-recorded-media/v2", + schema_version: "missioncore.observation-recorded-media/v3", source_id: source.id, generation_sha256: "c".repeat(64), byte_length: 3_267, @@ -834,6 +876,53 @@ test("replay decodes opaque recorded cameras and their same-origin fMP4 manifest ); }); +test("replay decodes a synchronized full-epoch perception video", () => { + const sessionId = "20260720T065719Z_viewer_live"; + const resultId = `result-${"d".repeat(64)}`; + const generation = "e".repeat(64); + const source = { + id: "recorded.perception.right", + label: "Сегментация · камера right", + modality: "video", + manifest_url: `/api/v1/observation-sessions/${sessionId}/perception-media/${resultId}/manifest`, + manifest_generation_sha256: generation, + byte_length: 12_345_678, + media_type: "video/mp4", + timeline_start_seconds: 35.421857292, + timeline_end_seconds: 484.144857292, + seekable: true, + synchronization: "host-arrival-best-effort", + }; + const decoded = decodeObservationSessionReplay(replay({ + session_id: sessionId, + timeline_end_seconds: 500, + media_sources: [source], + })); + assert.equal(decoded.mediaSources[0].id, "recorded.perception.right"); + assert.equal(decoded.mediaSources[0].manifestUrl, source.manifest_url); + + const manifest = decodeObservationRecordedMediaManifest({ + schema_version: "missioncore.observation-recorded-media/v3", + source_id: source.id, + generation_sha256: generation, + byte_length: source.byte_length, + timeline_start_seconds: source.timeline_start_seconds, + timeline_end_seconds: source.timeline_end_seconds, + synchronization: "host-arrival-best-effort", + epochs: [{ + ordinal: 1, + timeline_start_seconds: source.timeline_start_seconds, + timeline_end_seconds: source.timeline_end_seconds, + media_type: 'video/mp4; codecs="avc1.640028"', + byte_length: source.byte_length, + stream_url: `/api/v1/observation-sessions/${sessionId}/perception-media/${resultId}/recording.mp4?generation=${generation}`, + }], + }, decoded.mediaSources[0]); + assert.equal(manifest.epochs.length, 1); + assert.equal(manifest.epochs[0].timelineStartSeconds, source.timeline_start_seconds); + assert.equal(manifest.epochs[0].timelineEndSeconds, source.timeline_end_seconds); +}); + test("recorded camera contracts reject foreign origins, path escapes and unknown fields", () => { const sessionId = "session-20260716T205632Z"; const base = { @@ -888,7 +977,7 @@ test("recorded camera contracts reject foreign origins, path escapes and unknown })); assert.throws( () => decodeObservationRecordedMediaManifest({ - schema_version: "missioncore.observation-recorded-media/v2", + schema_version: "missioncore.observation-recorded-media/v3", source_id: base.id, generation_sha256: "c".repeat(64), byte_length: 384, @@ -900,17 +989,8 @@ test("recorded camera contracts reject foreign origins, path escapes and unknown timeline_start_seconds: 0, timeline_end_seconds: 20, media_type: 'video/mp4; codecs="avc1.640028"', - init_url: "file:///private/init.mp4", - init_byte_length: 128, - init_sha256: "a".repeat(64), - segment_count: 1, - segment_url_prefix: "file:///private/segments/", - segments: [{ - sequence: 1, - url: "file:///private/segments/1.m4s", - byte_length: 256, - sha256: "b".repeat(64), - }], + byte_length: 384, + stream_url: "file:///private/recording.mp4", }], }, decoded.mediaSources[0]), /небезопасный API URL/, diff --git a/apps/control-station/test/observationSources.test.mjs b/apps/control-station/test/observationSources.test.mjs index 603cb5c..7a4bc0d 100644 --- a/apps/control-station/test/observationSources.test.mjs +++ b/apps/control-station/test/observationSources.test.mjs @@ -269,7 +269,14 @@ test("recorded blueprint fetch is bounded, strict and sends only display setting { applicationId: "nodedc_mission_core_recorded", recordingId: "recording-001" }, { origin: "http://127.0.0.1:5174", - activeView: "perception", + activeView: "perception3d", + viewResetGeneration: 1, + perceptionLayers: { + enabled: true, + detections2d: true, + segmentation: false, + cuboids3d: true, + }, fetcher: async (input, init) => { calls.push({ input: String(input), init, body: JSON.parse(String(init.body)) }); return new Response(payload, { @@ -292,7 +299,12 @@ test("recorded blueprint fetch is bounded, strict and sends only display setting point_size: 4.5, palette: "custom", custom_color: "#35d7c1", - active_view: "perception", + active_view: "perception3d", + view_reset_generation: 1, + unified_perception: true, + show_detections_2d: true, + show_segmentation: false, + show_cuboids_3d: true, }); await assert.rejects( @@ -665,7 +677,7 @@ test("camera delivery rejects literal and encoded endpoint or credential leaks", "/api/preview?upstream=rtsp://camera.local/live", "/api/preview?upstream=rtsp%3A%2F%2Fcamera.local%2Flive", "/api/preview?upstream=rtsp%253A%252F%252Fcamera.local%252Flive", - "/api/preview?endpoint=192.168.68.52:8554", + "/api/preview?endpoint=192.0.2.52:8554", "/api/preview?endpoint=192%2E168%2E68%2E52", "/api/preview?password=not-for-the-browser", "/api/preview?%70%61%73%73%77%6f%72%64=not-for-the-browser", diff --git a/apps/control-station/test/recordedCameraBuffering.test.mjs b/apps/control-station/test/recordedCameraBuffering.test.mjs index f7e5bfe..4c8b4a9 100644 --- a/apps/control-station/test/recordedCameraBuffering.test.mjs +++ b/apps/control-station/test/recordedCameraBuffering.test.mjs @@ -1,15 +1,13 @@ import assert from "node:assert/strict"; -import { createHash } from "node:crypto"; import { readFile } from "node:fs/promises"; import { after, before, test } from "node:test"; import { createServer } from "vite"; let server; -let fetchVerifiedRecordedMediaArchive; +let fetchRecordedMediaArchive; let recordedMediaPresentationState; let recordedMediaSeekableCoverage; -let appendRecordedMediaBuffer; before(async () => { server = await createServer({ @@ -18,10 +16,9 @@ before(async () => { server: { middlewareMode: true }, }); ({ - fetchVerifiedRecordedMediaArchive, + fetchRecordedMediaArchive, recordedMediaPresentationState, recordedMediaSeekableCoverage, - appendRecordedMediaBuffer, } = await server.ssrLoadModule("/src/components/RecordedFmp4Player.tsx")); }); @@ -29,41 +26,28 @@ after(async () => { await server?.close(); }); -function digest(payload) { - return createHash("sha256").update(payload).digest("hex"); -} - -function fixture() { +function fixture({ byteLength = 36_000_000_000 } = {}) { const manifestUrl = "/api/v1/observation-sessions/session-1/media/camera-1/manifest"; - const init = Buffer.from("canonical-init"); - const first = Buffer.from("canonical-first-fragment"); - const second = Buffer.from("canonical-second-fragment"); const generation = "a".repeat(64); - const segmentPrefix = manifestUrl.replace("/manifest", "/epochs/1/segments/"); + const streamUrl = manifestUrl.replace( + "/manifest", + `/epochs/1/recording.mp4?generation=${generation}`, + ); const manifest = { - schema_version: "missioncore.observation-recorded-media/v2", + schema_version: "missioncore.observation-recorded-media/v3", source_id: "recorded.camera.camera-1", generation_sha256: generation, - byte_length: init.byteLength + first.byteLength + second.byteLength, + byte_length: byteLength, timeline_start_seconds: 0, - timeline_end_seconds: 20, + timeline_end_seconds: 36_000, synchronization: "host-arrival-best-effort", epochs: [{ ordinal: 1, timeline_start_seconds: 0, - timeline_end_seconds: 20, + timeline_end_seconds: 36_000, media_type: 'video/mp4; codecs="avc1.640028"', - init_url: manifestUrl.replace("/manifest", "/epochs/1/init.mp4"), - init_byte_length: init.byteLength, - init_sha256: digest(init), - segment_count: 2, - segment_url_prefix: segmentPrefix, - segments: [first, second].map((payload, index) => ({ - sequence: index + 1, - url: `${segmentPrefix}${index + 1}.m4s`, - byte_length: payload.byteLength, - sha256: digest(payload), - })), + byte_length: byteLength, + stream_url: streamUrl, }], }; const source = { @@ -72,14 +56,14 @@ function fixture() { modality: "video", manifestUrl, manifestGenerationSha256: generation, - byteLength: manifest.byte_length, + byteLength, mediaType: "video/mp4", timelineStartSeconds: 0, - timelineEndSeconds: 20, + timelineEndSeconds: 36_000, seekable: true, synchronization: "host-arrival-best-effort", }; - return { source, manifest, generation, init, first, second }; + return { source, manifest, generation, streamUrl }; } function jsonResponse(payload, generation) { @@ -92,145 +76,54 @@ function jsonResponse(payload, generation) { }); } -function mediaResponse(payload, sha = digest(payload), length = payload.byteLength) { - return new Response(payload, { - status: 200, - headers: { - "Content-Length": String(length), - ETag: `"sha256:${sha}"`, +test("multi-hour camera admission fetches only its compact generation-bound manifest", async () => { + const { source, manifest, generation, streamUrl } = fixture(); + const requested = []; + const archive = await fetchRecordedMediaArchive(source, { + fetcher: async (input, request = {}) => { + requested.push(String(input)); + assert.equal(new Headers(request.headers).get("If-Match"), `"sha256:${generation}"`); + return jsonResponse(manifest, generation); }, }); -} -function deferred() { - let resolve; - let reject; - const promise = new Promise((resolvePromise, rejectPromise) => { - resolve = resolvePromise; - reject = rejectPromise; - }); - return { promise, resolve, reject }; -} - -async function flushAsync() { - await new Promise((resolve) => setTimeout(resolve, 0)); - await new Promise((resolve) => setTimeout(resolve, 0)); -} - -test("recorded camera archive stays pending until every canonical byte is verified", async () => { - const { source, manifest, generation, init, first, second } = fixture(); - const finalSegment = deferred(); - const requested = []; - let manifestRequests = 0; - const fetcher = async (input, request = {}) => { - const url = String(input); - requested.push(url); - const headers = new Headers(request.headers); - if (url === source.manifestUrl) { - manifestRequests += 1; - assert.equal(headers.get("If-Match"), `"sha256:${generation}"`); - return jsonResponse(manifest, generation); - } - const epoch = manifest.epochs[0]; - if (url === epoch.init_url) { - assert.equal(headers.get("If-Match"), `"sha256:${epoch.init_sha256}"`); - return mediaResponse(init); - } - if (url === epoch.segments[0].url) return mediaResponse(first); - if (url === epoch.segments[1].url) return finalSegment.promise; - throw new Error(`Unexpected URL ${url}`); - }; - - let settled = false; - const archivePromise = fetchVerifiedRecordedMediaArchive(source, { fetcher }) - .then((archive) => { - settled = true; - return archive; - }); - await flushAsync(); - - assert.equal(settled, false, "init and a partial segment prefix must not publish the camera"); - assert.deepEqual(requested.slice(0, 4), [ - source.manifestUrl, - manifest.epochs[0].init_url, - manifest.epochs[0].segments[0].url, - manifest.epochs[0].segments[1].url, - ]); - - finalSegment.resolve(mediaResponse(second)); - const archive = await archivePromise; - assert.equal(manifestRequests, 2, "the immutable generation is revalidated after transfer"); - assert.equal(archive.byteLength, init.byteLength + first.byteLength + second.byteLength); - assert.equal(archive.epochs[0].segments.length, 2); + assert.deepEqual(requested, [source.manifestUrl]); + assert.equal(archive.byteLength, 36_000_000_000); + assert.equal(archive.manifest.epochs[0].streamUrl, streamUrl); }); -test("first camera manifest request is launch-generation bound and rejects replacement", async () => { +test("first camera manifest request rejects a replaced generation", async () => { const { source, manifest, generation } = fixture(); const replacementGeneration = "d".repeat(64); - let requests = 0; - const fetcher = async (input, request = {}) => { - requests += 1; - assert.equal(String(input), source.manifestUrl); - assert.equal( - new Headers(request.headers).get("If-Match"), - `"sha256:${generation}"`, - ); - return jsonResponse( - { ...manifest, generation_sha256: replacementGeneration }, - replacementGeneration, - ); - }; - await assert.rejects( - fetchVerifiedRecordedMediaArchive(source, { fetcher }), + fetchRecordedMediaArchive(source, { + fetcher: async (_input, request = {}) => { + assert.equal(new Headers(request.headers).get("If-Match"), `"sha256:${generation}"`); + return jsonResponse( + { ...manifest, generation_sha256: replacementGeneration }, + replacementGeneration, + ); + }, + }), /несовместим|заменён/, ); - assert.equal(requests, 1); }); -test("recorded camera archive fails closed on truncation despite plausible headers", async () => { - const { source, manifest, generation, init, first, second } = fixture(); - const fetcher = async (input) => { - const url = String(input); - if (url === source.manifestUrl) return jsonResponse(manifest, generation); - const epoch = manifest.epochs[0]; - if (url === epoch.init_url) return mediaResponse(init); - if (url === epoch.segments[0].url) return mediaResponse(first); - if (url === epoch.segments[1].url) { - return mediaResponse(second.subarray(0, second.byteLength - 1), digest(second), second.byteLength); - } - throw new Error(`Unexpected URL ${url}`); +test("camera manifest fails closed when epoch bytes do not match launch bytes", async () => { + const { source, manifest, generation } = fixture(); + const mismatched = { + ...manifest, + epochs: [{ ...manifest.epochs[0], byte_length: manifest.byte_length - 1 }], }; - await assert.rejects( - fetchVerifiedRecordedMediaArchive(source, { fetcher }), - /усечён/, + fetchRecordedMediaArchive(source, { + fetcher: async () => jsonResponse(mismatched, generation), + }), + /не совпадает/, ); }); -test("recorded camera archive fails closed when bytes are replaced under an old ETag", async () => { - const { source, manifest, generation, init, first, second } = fixture(); - const replacement = Buffer.from(second.map((value) => value ^ 0xff)); - assert.equal(replacement.byteLength, second.byteLength); - const fetcher = async (input) => { - const url = String(input); - if (url === source.manifestUrl) return jsonResponse(manifest, generation); - const epoch = manifest.epochs[0]; - if (url === epoch.init_url) return mediaResponse(init); - if (url === epoch.segments[0].url) return mediaResponse(first); - if (url === epoch.segments[1].url) { - return mediaResponse(replacement, digest(second), second.byteLength); - } - throw new Error(`Unexpected URL ${url}`); - }; - - await assert.rejects( - fetchVerifiedRecordedMediaArchive(source, { fetcher }), - /SHA-256/, - ); -}); - -test("camera presentation gate opens only for the completely appended selected epoch", () => { +test("camera presentation gate opens only for the seekable selected epoch", () => { assert.equal(recordedMediaPresentationState("loading", null, "g1", false), "loading"); assert.equal(recordedMediaPresentationState("ready", null, "g1", false), "loading"); assert.equal(recordedMediaPresentationState("ready", "g2", "g1", false), "loading"); @@ -251,40 +144,13 @@ test("decoded duration and seekable range cover the complete declared epoch", () assert.equal(recordedMediaSeekableCoverage(20, 20, 20, 1, 1.01), false); }); -test("aborting SourceBuffer append removes every temporary listener", async () => { - const listeners = new Map(); - const sourceBuffer = { - addEventListener(type, listener) { - const bucket = listeners.get(type) ?? new Set(); - bucket.add(listener); - listeners.set(type, bucket); - }, - removeEventListener(type, listener) { - listeners.get(type)?.delete(listener); - }, - appendBuffer() {}, - }; - const abort = new AbortController(); - const pending = appendRecordedMediaBuffer( - sourceBuffer, - new ArrayBuffer(8), - abort.signal, - ); - assert.equal(listeners.get("updateend")?.size, 1); - assert.equal(listeners.get("error")?.size, 1); - abort.abort(); - await assert.rejects(pending, (error) => error?.name === "AbortError"); - assert.equal(listeners.get("updateend")?.size, 0); - assert.equal(listeners.get("error")?.size, 0); -}); - -test("verified camera archives remain immutable for safe player remount", async () => { +test("recorded player range-streams and never builds a whole-video RAM Blob", async () => { const source = await readFile( new URL("../src/components/RecordedFmp4Player.tsx", import.meta.url), "utf8", ); - assert.doesNotMatch(source, /\.init\s*=\s*new ArrayBuffer/); - assert.doesNotMatch(source, /\.segments\.length\s*=\s*0/); + assert.match(source, /video\.src\s*=\s*descriptor\.streamUrl/); + assert.doesNotMatch(source, /new Blob\(|response\.arrayBuffer\(|SourceBuffer/); }); test("loading and error overlays fully conceal recorded camera pixels", async () => { @@ -301,3 +167,20 @@ test("loading and error overlays fully conceal recorded camera pixels", async () /\.recorded-media-player__notice\s*\{[^}]*inset:\s*0;[^}]*background:\s*#070809/s, ); }); + +test("point-cloud fullscreen keeps the admitted recorded camera worker mounted", async () => { + const source = await readFile( + new URL("../src/workspaces/Workspaces.tsx", import.meta.url), + "utf8", + ); + assert.match(source, /\{visibleMediaSources\.map\(\(source, index\) => \(/); + assert.match(source, /hidden=\{pointCloudFocused \|\| unifiedPerception\}/); + assert.doesNotMatch( + source, + /\{!pointCloudFocused \? visibleMediaSources\.map/, + ); + assert.doesNotMatch( + source, + /\(pointCloudFocused \|\| !observationLayout\.visibleSourceIds\.has\(source\.id\)\)/, + ); +}); diff --git a/apps/control-station/test/recordedSessionAdmission.test.mjs b/apps/control-station/test/recordedSessionAdmission.test.mjs index 1ee5aa6..d2de4f6 100644 --- a/apps/control-station/test/recordedSessionAdmission.test.mjs +++ b/apps/control-station/test/recordedSessionAdmission.test.mjs @@ -78,34 +78,27 @@ test("any RRD or camera failure closes the complete recorded session", () => { ); }); -test("camera admission enforces independent 16/256/512 MiB limits before fetching", () => { +test("camera admission keeps source scheduling bounded but has no duration or byte ceiling", () => { const { MAX_RECORDED_CAMERA_SOURCES, - MAX_RECORDED_MEDIA_SOURCE_BYTES, - MAX_RECORDED_SESSION_CAMERA_BYTES, recordedCameraDescriptorPreflight, } = admission; assert.equal(MAX_RECORDED_CAMERA_SOURCES, 16); - assert.equal(MAX_RECORDED_MEDIA_SOURCE_BYTES, 256 * 1024 * 1024); - assert.equal(MAX_RECORDED_SESSION_CAMERA_BYTES, 512 * 1024 * 1024); assert.equal(recordedCameraDescriptorPreflight( Array.from({ length: 2 }, (_, index) => ({ id: `camera.${index}`, - byteLength: MAX_RECORDED_MEDIA_SOURCE_BYTES, + byteLength: 36_000_000_000, })), ), "ready"); assert.equal(recordedCameraDescriptorPreflight( Array.from({ length: 17 }, (_, index) => ({ id: `camera.${index}`, byteLength: 1 })), ), "error"); assert.equal(recordedCameraDescriptorPreflight([ - { id: "camera.large", byteLength: MAX_RECORDED_MEDIA_SOURCE_BYTES + 1 }, + { id: "camera.ten-hours", byteLength: 36_000_000_000 }, + ]), "ready"); + assert.equal(recordedCameraDescriptorPreflight([ + { id: "camera.invalid", byteLength: Number.MAX_SAFE_INTEGER + 1 }, ]), "error"); - assert.equal(recordedCameraDescriptorPreflight( - Array.from({ length: 5 }, (_, index) => ({ - id: `camera.${index}`, - byteLength: 110 * 1024 * 1024, - })), - ), "error"); assert.equal(recordedCameraDescriptorPreflight([ { id: "camera.duplicate", byteLength: 1 }, { id: "camera.duplicate", byteLength: 1 }, diff --git a/apps/control-station/test/rerunWebViewerVendor.test.mjs b/apps/control-station/test/rerunWebViewerVendor.test.mjs new file mode 100644 index 0000000..50014df --- /dev/null +++ b/apps/control-station/test/rerunWebViewerVendor.test.mjs @@ -0,0 +1,67 @@ +import assert from "node:assert/strict"; +import { createHash } from "node:crypto"; +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; +import test from "node:test"; + +import makeRerunRuntime from "../vendor/rerun-web-viewer-0.34.1/re_viewer.nodedc.js"; + +const root = resolve(import.meta.dirname, ".."); +const packageRoot = resolve(root, "node_modules/@rerun-io/web-viewer"); +const vendorRoot = resolve(root, "vendor/rerun-web-viewer-0.34.1"); + +const sha256 = (path) => + createHash("sha256").update(readFileSync(path)).digest("hex"); + +test("NODE.DC Rerun runtime is the audited 0.34.1 zoom-to-cursor build", () => { + const manifest = JSON.parse(readFileSync(resolve(packageRoot, "package.json"), "utf8")); + assert.equal(manifest.version, "0.34.1"); + + const expectedWasm = "38d19bac06b7c3b8e549489469cf7c4a24f319ec953849e4656b5827a6c105bb"; + const expectedGlue = "0f7b76c9f24cbd8437021b5d37499894aeadc586183e422ebc82ef556d7b8339"; + + assert.equal(sha256(resolve(vendorRoot, "re_viewer_bg.nodedc.wasm")), expectedWasm); + assert.equal(sha256(resolve(vendorRoot, "re_viewer.nodedc.js")), expectedGlue); + assert.equal(sha256(resolve(packageRoot, "re_viewer_bg.wasm")), expectedWasm); + assert.equal(sha256(resolve(packageRoot, "re_viewer.js")), expectedGlue); +}); + +test("custom JavaScript glue references only exports present in its paired WASM", () => { + const wasmPath = resolve(vendorRoot, "re_viewer_bg.nodedc.wasm"); + const gluePath = resolve(vendorRoot, "re_viewer.nodedc.js"); + const module = new WebAssembly.Module(readFileSync(wasmPath)); + const exports = new Set(WebAssembly.Module.exports(module).map(({ name }) => name)); + const imports = WebAssembly.Module.imports(module); + const glue = readFileSync(gluePath, "utf8"); + const referencedExports = new Set( + [...glue.matchAll(/\bwasm\.([A-Za-z_$][\w$]*)/g)].map((match) => match[1]), + ); + const missingExports = [...referencedExports].filter((name) => !exports.has(name)); + + assert.equal(imports.length, 927); + assert.equal(exports.size, 79); + assert.deepEqual(missingExports, []); + assert.match(glue, /export default function\(\)/); + assert.match(glue, /if \(!wasm\) return;/); +}); + +test("custom Rerun WASM initializes and grows its externref table", () => { + const runtime = makeRerunRuntime(); + runtime.initSync({ + module: readFileSync(resolve(vendorRoot, "re_viewer_bg.nodedc.wasm")), + }); + + assert.equal(typeof runtime.WebHandle, "function"); + runtime.deinit(); +}); + +test("source patch carries cursor pivot, minimum-radius handoff, and geometry tests", () => { + const patch = readFileSync(resolve(vendorRoot, "NODEDC_ZOOM_TO_CURSOR.patch"), "utf8"); + + assert.match(patch, /fn pointer_ray_direction/); + assert.match(patch, /fn zoom_orbit_towards_pointer/); + assert.match(patch, /near_limit_hands_excess_zoom_to_cursor_directed_dolly/); + assert.match(patch, /crossing_near_limit_preserves_unconsumed_scene_scaled_zoom/); + assert.match(patch, /remaining_zoom_factor\.ln\(\) \* self\.speed/); + assert.match(patch, /off_center_pointer_stays_on_the_same_view_ray/); +}); diff --git a/apps/control-station/vendor/rerun-web-viewer-0.34.1/BUILD_INFO.md b/apps/control-station/vendor/rerun-web-viewer-0.34.1/BUILD_INFO.md new file mode 100644 index 0000000..1dc915e --- /dev/null +++ b/apps/control-station/vendor/rerun-web-viewer-0.34.1/BUILD_INFO.md @@ -0,0 +1,68 @@ +# NODE.DC Rerun web viewer 0.34.1 + +This directory contains the audited Mission Core camera-controller override for +`@rerun-io/web-viewer` 0.34.1. It changes only the native orbital zoom behavior: + +- the pointer ray selects an anchor on the current focus plane; +- eye position and look target scale around that anchor, so the point under the + cursor remains under the cursor; +- after Rerun's `0.02 m` near-plane safety radius is reached, excess zoom becomes + a cursor-directed dolly scaled by the scene's navigation speed instead of + silently ignoring the wheel or moving by imperceptible millimeters; +- first-person movement, orbit rotation, panning, WASD and Rerun's zoom-out cap + are unchanged. + +## Source identity + +- Upstream: `rerun-io/rerun` +- Tag: `0.34.1` +- Commit: `4efb18f17f6f0e41985cda99a2bdcd012febc8d5` +- Patched file: `crates/viewer/re_view_spatial/src/eye.rs` +- Patch: `NODEDC_ZOOM_TO_CURSOR.patch` +- Rust: `1.92.0` +- Binaryen / `wasm-opt`: `117` (the version pinned by Rerun's `pixi.lock`) +- Build image: `rust:1.92-bookworm` +- Build image digest: + `sha256:e90e846de4124376164ddfbaab4b0774c7bdeef5e738866295e5a90a34a307a2` +- Build date: `2026-07-22` (`Europe/Moscow`) + +## Reproduction + +Apply the patch to the exact upstream commit, then run Rerun's own builder: + +```sh +git apply NODEDC_ZOOM_TO_CURSOR.patch +cargo test -p re_view_spatial --lib eye::tests:: -- --nocapture +cargo run -p re_dev_tools -- build-web-viewer \ + --release -g \ + --target no-modules-base \ + --no-default-features \ + --features map_view \ + -o rerun_js/web-viewer +``` + +The container also needs Binaryen `117` for Rerun's final `wasm-opt -O2` step. +Binaryen `108` from Debian 12 must not be used: it produced a module whose +`externref` table could not grow during initialization. The +generated `re_viewer.js` is transformed with +`scripts/transform-rerun-web-viewer-glue.mjs`, which mirrors Rerun 0.34.1's +`rerun_js/web-viewer/build-wasm.mjs` no-modules wrapper and teardown guards. + +## Verified artifacts + +| Artifact | SHA-256 | +| --- | --- | +| `re_viewer_bg.nodedc.wasm` | `38d19bac06b7c3b8e549489469cf7c4a24f319ec953849e4656b5827a6c105bb` | +| raw generated `re_viewer.js` | `cc196a93c5be972c801d46be4dc9934f7f042eb62941f0aa0678f1c8416c6874` | +| `re_viewer.nodedc.js` | `0f7b76c9f24cbd8437021b5d37499894aeadc586183e422ebc82ef556d7b8339` | + +The focused Rust suite completed with `5 passed, 0 failed`, including the +orbit-to-dolly boundary case. A Node `initSync` +smoke test completed successfully, including the `externref` table-growth step. +The Mission Core Node suite also checks both artifact hashes and verifies that +every `wasm.*` reference in the JavaScript glue exists in the paired WASM +exports. + +`scripts/patch-rerun-web-viewer.mjs` installs the pair after npm extracts the +official package. It accepts only the known published or NODE.DC hashes and +fails closed on any other package contents. diff --git a/apps/control-station/vendor/rerun-web-viewer-0.34.1/NODEDC_ZOOM_TO_CURSOR.patch b/apps/control-station/vendor/rerun-web-viewer-0.34.1/NODEDC_ZOOM_TO_CURSOR.patch new file mode 100644 index 0000000..5c6b0a7 --- /dev/null +++ b/apps/control-station/vendor/rerun-web-viewer-0.34.1/NODEDC_ZOOM_TO_CURSOR.patch @@ -0,0 +1,230 @@ +diff --git a/crates/viewer/re_view_spatial/src/eye.rs b/crates/viewer/re_view_spatial/src/eye.rs +index e59b311..3f33259 100644 +--- a/crates/viewer/re_view_spatial/src/eye.rs ++++ b/crates/viewer/re_view_spatial/src/eye.rs +@@ -512,8 +512,85 @@ impl EyeController { + } + } + ++ /// Returns the world-space ray under the pointer. ++ /// ++ /// Keeping this calculation local to the eye controller lets orbital zoom use the pointer ++ /// synchronously. GPU picking arrives a frame later and would make the zoom pivot visibly lag. ++ fn pointer_ray_direction(&self, rect: Rect, pointer: egui::Pos2) -> Option { ++ if !rect.contains(pointer) || rect.width() <= 0.0 || rect.height() <= 0.0 { ++ return None; ++ } ++ ++ let fov_y = self.fov_y.unwrap_or(Eye::DEFAULT_FOV_Y); ++ let aspect_ratio = rect.width() / rect.height(); ++ let focal_scale = (fov_y * 0.5).tan(); ++ let x = (2.0 * (pointer.x - rect.left()) / rect.width() - 1.0) ++ * focal_scale ++ * aspect_ratio; ++ let y = (1.0 - 2.0 * (pointer.y - rect.top()) / rect.height()) * focal_scale; ++ ++ (self.rotation() * vec3(x, y, -1.0)).try_normalize() ++ } ++ ++ /// Zoom an orbital eye around the point under the pointer on the current focus plane. ++ /// ++ /// The position and look target are scaled around the same anchor. This preserves the ++ /// projected pointer position while retaining the existing orbit direction and controls. ++ /// Once the near-plane safety radius is reached, excess zoom becomes a cursor-directed dolly ++ /// measured in the scene's navigation speed instead of near-plane millimeters. ++ fn zoom_orbit_towards_pointer( ++ &mut self, ++ zoom_factor: f32, ++ max_radius: f32, ++ rect: Rect, ++ pointer: Option, ++ ) { ++ let radius = self.radius(); ++ if !radius.is_finite() || radius <= f32::MIN_POSITIVE { ++ return; ++ } ++ ++ let requested_radius = radius / zoom_factor; ++ let new_radius = requested_radius.clamp(Self::MIN_ORBIT_DISTANCE, max_radius); ++ let scale = new_radius / radius; ++ ++ let ray_direction = pointer.and_then(|pointer| self.pointer_ray_direction(rect, pointer)); ++ if let Some(ray_direction) = ray_direction { ++ let forward = self.fwd(); ++ let denominator = ray_direction.dot(forward); ++ if denominator > 1.0e-4 { ++ let anchor = self.pos + ray_direction * (radius / denominator); ++ self.pos = anchor + (self.pos - anchor) * scale; ++ self.look_target = anchor + (self.look_target - anchor) * scale; ++ ++ if requested_radius < Self::MIN_ORBIT_DISTANCE { ++ // Shrinking the remaining 2 cm orbit radius consumes only part of this input. ++ // Hand the logarithmic remainder to the same scene-scaled speed used by WASD ++ // and first-person scroll. Basing this on the near-plane remainder itself made ++ // each wheel event move by millimeters and felt indistinguishable from a hard ++ // zoom limit on building- and map-scale recordings. ++ let orbit_zoom_factor = (radius / Self::MIN_ORBIT_DISTANCE).max(1.0); ++ let remaining_zoom_factor = zoom_factor / orbit_zoom_factor; ++ if remaining_zoom_factor > 1.0 && remaining_zoom_factor.is_finite() { ++ let dolly = remaining_zoom_factor.ln() * self.speed as f32; ++ self.pos += ray_direction * dolly; ++ self.look_target += ray_direction * dolly; ++ } ++ } ++ self.did_interact = true; ++ return; ++ } ++ } ++ ++ // Pointer data can be absent for synthetic zoom events. Preserve Rerun's centered zoom ++ // behavior in that case instead of dropping the input. ++ self.pos = self.look_target - self.fwd() * new_radius; ++ self.did_interact = true; ++ } ++ + /// Handle zoom/scroll input. +- fn handle_zoom(&mut self, egui_ctx: &egui::Context, scene_bounding_box: &macaw::BoundingBox) { ++ fn handle_zoom(&mut self, response: &egui::Response, scene_bounding_box: &macaw::BoundingBox) { ++ let egui_ctx = &response.ctx; + let zoom_factor = egui_ctx.input(|input| { + // egui's default horizontal_scroll_modifier is shift, which is also our speed-up modifier. + // This means that a user who wants to speed up scroll-to-zoom will generate a horizontal scroll delta. +@@ -528,22 +605,12 @@ impl EyeController { + + match self.kind { + Eye3DKind::Orbital => { +- let radius = self.pos.distance(self.look_target); +- + // Cap zoom-out against the scene bounding box. If we're already past the cap + // (e.g. right after loading) use the current radius instead — no snap-back. ++ let radius = self.radius(); + let max_radius = max_orbital_radius(scene_bounding_box).max(radius); +- let new_radius = (radius / zoom_factor).clamp(Self::MIN_ORBIT_DISTANCE, max_radius); +- +- // The user may be scrolling to move the camera closer, but are not realizing +- // the radius is now tiny. +- // TODO(emilk): inform the users somehow that scrolling won't help, and that they should use WSAD instead. +- // It might be tempting to start moving the camera here on scroll, but that would is bad for other reasons. +- +- if f32::MIN_POSITIVE < new_radius { +- self.pos = self.look_target - self.fwd() * new_radius; +- self.did_interact = true; +- } ++ let pointer = response.ctx.pointer_latest_pos(); ++ self.zoom_orbit_towards_pointer(zoom_factor, max_radius, response.rect, pointer); + } + Eye3DKind::FirstPerson => { + // Move along the forward axis when zooming in first person mode. +@@ -687,7 +754,7 @@ impl EyeController { + self.handle_drag(response, drag_threshold); + + if response.hovered() { +- self.handle_zoom(&response.ctx, scene_bounding_box); ++ self.handle_zoom(response, scene_bounding_box); + } + + if response.has_focus() { +@@ -1249,3 +1316,103 @@ impl EyeState { + Ok(eye) + } + } ++ ++#[cfg(test)] ++mod tests { ++ use super::*; ++ ++ fn orbital_controller(pos: Vec3, look_target: Vec3) -> EyeController { ++ EyeController { ++ pos, ++ look_target, ++ kind: Eye3DKind::Orbital, ++ speed: 1.0, ++ eye_up: Vec3::Z, ++ fov_y: Some(Eye::DEFAULT_FOV_Y), ++ did_interact: false, ++ } ++ } ++ ++ fn test_rect() -> Rect { ++ Rect::from_min_size(egui::Pos2::ZERO, egui::vec2(800.0, 600.0)) ++ } ++ ++ fn assert_vec3_close(actual: Vec3, expected: Vec3) { ++ assert!( ++ actual.abs_diff_eq(expected, 1.0e-5), ++ "actual={actual:?}, expected={expected:?}" ++ ); ++ } ++ ++ #[test] ++ fn centered_pointer_keeps_the_orbit_target() { ++ let rect = test_rect(); ++ let mut controller = orbital_controller(vec3(0.0, -10.0, 0.0), Vec3::ZERO); ++ ++ controller.zoom_orbit_towards_pointer(2.0, 100.0, rect, Some(rect.center())); ++ ++ assert_vec3_close(controller.pos, vec3(0.0, -5.0, 0.0)); ++ assert_vec3_close(controller.look_target, Vec3::ZERO); ++ assert!(controller.did_interact); ++ } ++ ++ #[test] ++ fn off_center_pointer_stays_on_the_same_view_ray() { ++ let rect = test_rect(); ++ let pointer = egui::pos2(650.0, 240.0); ++ let mut controller = orbital_controller(vec3(0.0, -10.0, 0.0), Vec3::ZERO); ++ let original_ray = controller ++ .pointer_ray_direction(rect, pointer) ++ .expect("test pointer must produce a ray"); ++ let forward = controller.fwd(); ++ let anchor = controller.pos ++ + original_ray * (controller.radius() / original_ray.dot(forward)); ++ ++ controller.zoom_orbit_towards_pointer(2.0, 100.0, rect, Some(pointer)); ++ ++ assert!((controller.radius() - 5.0).abs() < 1.0e-5); ++ let ray_after = (anchor - controller.pos).normalize(); ++ assert!(ray_after.dot(original_ray) > 0.99999); ++ } ++ ++ #[test] ++ fn near_limit_hands_excess_zoom_to_cursor_directed_dolly() { ++ let rect = test_rect(); ++ let radius = EyeController::MIN_ORBIT_DISTANCE; ++ let mut controller = orbital_controller(vec3(0.0, -radius, 0.0), Vec3::ZERO); ++ let old_pos = controller.pos; ++ let old_target = controller.look_target; ++ ++ controller.zoom_orbit_towards_pointer(2.0, 100.0, rect, Some(rect.center())); ++ ++ assert!((controller.radius() - radius).abs() < 1.0e-6); ++ assert_vec3_close(controller.pos, old_pos + Vec3::Y * 2.0_f32.ln()); ++ assert_vec3_close( ++ controller.look_target, ++ old_target + Vec3::Y * 2.0_f32.ln(), ++ ); ++ assert_vec3_close(controller.look_target - controller.pos, Vec3::Y * radius); ++ } ++ ++ #[test] ++ fn crossing_near_limit_preserves_unconsumed_scene_scaled_zoom() { ++ let rect = test_rect(); ++ let mut controller = orbital_controller(vec3(0.0, -0.03, 0.0), Vec3::ZERO); ++ ++ controller.zoom_orbit_towards_pointer(3.0, 100.0, rect, Some(rect.center())); ++ ++ assert!((controller.radius() - EyeController::MIN_ORBIT_DISTANCE).abs() < 1.0e-6); ++ assert_vec3_close(controller.pos, vec3(0.0, 2.0_f32.ln() - 0.02, 0.0)); ++ assert_vec3_close(controller.look_target, vec3(0.0, 2.0_f32.ln(), 0.0)); ++ } ++ ++ #[test] ++ fn zoom_out_respects_scene_radius_cap() { ++ let rect = test_rect(); ++ let mut controller = orbital_controller(vec3(0.0, -10.0, 0.0), Vec3::ZERO); ++ ++ controller.zoom_orbit_towards_pointer(0.1, 25.0, rect, Some(rect.center())); ++ ++ assert!((controller.radius() - 25.0).abs() < 1.0e-5); ++ } ++} diff --git a/apps/control-station/vendor/rerun-web-viewer-0.34.1/re_viewer.nodedc.js b/apps/control-station/vendor/rerun-web-viewer-0.34.1/re_viewer.nodedc.js new file mode 100644 index 0000000..f084a23 --- /dev/null +++ b/apps/control-station/vendor/rerun-web-viewer-0.34.1/re_viewer.nodedc.js @@ -0,0 +1,4544 @@ + +export default function() { +const exports = { __proto__: null }; + + let script_src; + if (typeof document !== 'undefined' && document.currentScript !== null) { + script_src = new URL(document.currentScript.src, location.href).toString(); + } + + class IntoUnderlyingByteSource { + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + IntoUnderlyingByteSourceFinalization.unregister(this); + return ptr; + } + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_intounderlyingbytesource_free(ptr, 0); + } + /** + * @returns {number} + */ + get autoAllocateChunkSize() { + const ret = wasm.intounderlyingbytesource_autoAllocateChunkSize(this.__wbg_ptr); + return ret >>> 0; + } + cancel() { + const ptr = this.__destroy_into_raw(); + wasm.intounderlyingbytesource_cancel(ptr); + } + /** + * @param {ReadableByteStreamController} controller + * @returns {Promise} + */ + pull(controller) { + const ret = wasm.intounderlyingbytesource_pull(this.__wbg_ptr, controller); + return ret; + } + /** + * @param {ReadableByteStreamController} controller + */ + start(controller) { + wasm.intounderlyingbytesource_start(this.__wbg_ptr, controller); + } + /** + * @returns {ReadableStreamType} + */ + get type() { + const ret = wasm.intounderlyingbytesource_type(this.__wbg_ptr); + return __wbindgen_enum_ReadableStreamType[ret]; + } + } + if (Symbol.dispose) IntoUnderlyingByteSource.prototype[Symbol.dispose] = IntoUnderlyingByteSource.prototype.free; + exports.IntoUnderlyingByteSource = IntoUnderlyingByteSource; + + class IntoUnderlyingSink { + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + IntoUnderlyingSinkFinalization.unregister(this); + return ptr; + } + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_intounderlyingsink_free(ptr, 0); + } + /** + * @param {any} reason + * @returns {Promise} + */ + abort(reason) { + const ptr = this.__destroy_into_raw(); + const ret = wasm.intounderlyingsink_abort(ptr, reason); + return ret; + } + /** + * @returns {Promise} + */ + close() { + const ptr = this.__destroy_into_raw(); + const ret = wasm.intounderlyingsink_close(ptr); + return ret; + } + /** + * @param {any} chunk + * @returns {Promise} + */ + write(chunk) { + const ret = wasm.intounderlyingsink_write(this.__wbg_ptr, chunk); + return ret; + } + } + if (Symbol.dispose) IntoUnderlyingSink.prototype[Symbol.dispose] = IntoUnderlyingSink.prototype.free; + exports.IntoUnderlyingSink = IntoUnderlyingSink; + + class IntoUnderlyingSource { + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + IntoUnderlyingSourceFinalization.unregister(this); + return ptr; + } + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_intounderlyingsource_free(ptr, 0); + } + cancel() { + const ptr = this.__destroy_into_raw(); + wasm.intounderlyingsource_cancel(ptr); + } + /** + * @param {ReadableStreamDefaultController} controller + * @returns {Promise} + */ + pull(controller) { + const ret = wasm.intounderlyingsource_pull(this.__wbg_ptr, controller); + return ret; + } + } + if (Symbol.dispose) IntoUnderlyingSource.prototype[Symbol.dispose] = IntoUnderlyingSource.prototype.free; + exports.IntoUnderlyingSource = IntoUnderlyingSource; + + class WebHandle { + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + WebHandleFinalization.unregister(this); + return ptr; + } + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_webhandle_free(ptr, 0); + } + /** + * Add a new receiver streaming data from the given url. + * + * If `follow` is `true`, and the url is an HTTP source or file path, + * the viewer will open the stream + * in `Following` mode rather than `Playing` mode. + * + * Websocket streams are always opened in `Following` mode. + * + * It is an error to open a channel twice with the same id. + * @param {string} url + * @param {boolean | null} [follow] + */ + add_receiver(url, follow) { + const ptr0 = passStringToWasm0(url, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + wasm.webhandle_add_receiver(this.__wbg_ptr, ptr0, len0, isLikeNone(follow) ? 0xFFFFFF : follow ? 1 : 0); + } + /** + * Close an existing channel for streaming data. + * + * No-op if the channel is already closed. + * @param {string} id + */ + close_channel(id) { + const ptr0 = passStringToWasm0(id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + wasm.webhandle_close_channel(this.__wbg_ptr, ptr0, len0); + } + destroy() { + wasm.webhandle_destroy(this.__wbg_ptr); + } + /** + * @returns {string | undefined} + */ + get_active_recording_id() { + const ret = wasm.webhandle_get_active_recording_id(this.__wbg_ptr); + let v1; + if (ret[0] !== 0) { + v1 = getStringFromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + } + return v1; + } + /** + * @param {string} recording_id + * @returns {string | undefined} + */ + get_active_timeline(recording_id) { + const ptr0 = passStringToWasm0(recording_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.webhandle_get_active_timeline(this.__wbg_ptr, ptr0, len0); + let v2; + if (ret[0] !== 0) { + v2 = getStringFromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + } + return v2; + } + /** + * @param {string} recording_id + * @returns {boolean | undefined} + */ + get_playing(recording_id) { + const ptr0 = passStringToWasm0(recording_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.webhandle_get_playing(this.__wbg_ptr, ptr0, len0); + return ret === 0xFFFFFF ? undefined : ret !== 0; + } + /** + * @param {string} recording_id + * @param {string} timeline_name + * @returns {number | undefined} + */ + get_time_for_timeline(recording_id, timeline_name) { + const ptr0 = passStringToWasm0(recording_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(timeline_name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.webhandle_get_time_for_timeline(this.__wbg_ptr, ptr0, len0, ptr1, len1); + return ret[0] === 0 ? undefined : ret[1]; + } + /** + * @param {string} recording_id + * @param {string} timeline_name + * @returns {any} + */ + get_timeline_time_range(recording_id, timeline_name) { + const ptr0 = passStringToWasm0(recording_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(timeline_name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.webhandle_get_timeline_time_range(this.__wbg_ptr, ptr0, len0, ptr1, len1); + return ret; + } + /** + * @returns {boolean} + */ + has_panicked() { + const ret = wasm.webhandle_has_panicked(this.__wbg_ptr); + return ret !== 0; + } + /** + * @param {any} app_options + */ + constructor(app_options) { + const ret = wasm.webhandle_new(app_options); + if (ret[2]) { + throw takeFromExternrefTable0(ret[1]); + } + this.__wbg_ptr = ret[0] >>> 0; + WebHandleFinalization.register(this, this.__wbg_ptr, this); + return this; + } + /** + * Open a new channel for streaming data. + * + * It is an error to open a channel twice with the same id. + * @param {string} id + * @param {string} channel_name + */ + open_channel(id, channel_name) { + const ptr0 = passStringToWasm0(id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(channel_name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + wasm.webhandle_open_channel(this.__wbg_ptr, ptr0, len0, ptr1, len1); + } + /** + * @param {string} panel + * @param {string | null} [state] + */ + override_panel_state(panel, state) { + const ptr0 = passStringToWasm0(panel, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + var ptr1 = isLikeNone(state) ? 0 : passStringToWasm0(state, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + const ret = wasm.webhandle_override_panel_state(this.__wbg_ptr, ptr0, len0, ptr1, len1); + if (ret[1]) { + throw takeFromExternrefTable0(ret[0]); + } + } + /** + * @returns {string | undefined} + */ + panic_callstack() { + const ret = wasm.webhandle_panic_callstack(this.__wbg_ptr); + let v1; + if (ret[0] !== 0) { + v1 = getStringFromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + } + return v1; + } + /** + * @returns {string | undefined} + */ + panic_message() { + const ret = wasm.webhandle_panic_message(this.__wbg_ptr); + let v1; + if (ret[0] !== 0) { + v1 = getStringFromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + } + return v1; + } + /** + * @param {string} url + */ + remove_receiver(url) { + const ptr0 = passStringToWasm0(url, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + wasm.webhandle_remove_receiver(this.__wbg_ptr, ptr0, len0); + } + /** + * Add an rrd to the viewer directly from a byte array. + * @param {string} id + * @param {Uint8Array} data + */ + send_rrd_to_channel(id, data) { + const ptr0 = passStringToWasm0(id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(data, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + wasm.webhandle_send_rrd_to_channel(this.__wbg_ptr, ptr0, len0, ptr1, len1); + } + /** + * @param {string} id + * @param {Uint8Array} data + */ + send_table_to_channel(id, data) { + const ptr0 = passStringToWasm0(id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(data, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + wasm.webhandle_send_table_to_channel(this.__wbg_ptr, ptr0, len0, ptr1, len1); + } + /** + * @param {string} recording_id + */ + set_active_recording_id(recording_id) { + const ptr0 = passStringToWasm0(recording_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + wasm.webhandle_set_active_recording_id(this.__wbg_ptr, ptr0, len0); + } + /** + * Set the active timeline. + * + * This does nothing if the timeline can't be found. + * @param {string} recording_id + * @param {string} timeline_name + */ + set_active_timeline(recording_id, timeline_name) { + const ptr0 = passStringToWasm0(recording_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(timeline_name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + wasm.webhandle_set_active_timeline(this.__wbg_ptr, ptr0, len0, ptr1, len1); + } + /** + * @param {string} access_token + * @param {string} email + */ + set_credentials(access_token, email) { + const ptr0 = passStringToWasm0(access_token, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(email, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + wasm.webhandle_set_credentials(this.__wbg_ptr, ptr0, len0, ptr1, len1); + } + /** + * @param {string} recording_id + * @param {boolean} value + */ + set_playing(recording_id, value) { + const ptr0 = passStringToWasm0(recording_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + wasm.webhandle_set_playing(this.__wbg_ptr, ptr0, len0, value); + } + /** + * @param {string} recording_id + * @param {string} timeline_name + * @param {number} time + */ + set_time_for_timeline(recording_id, timeline_name, time) { + const ptr0 = passStringToWasm0(recording_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(timeline_name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + wasm.webhandle_set_time_for_timeline(this.__wbg_ptr, ptr0, len0, ptr1, len1, time); + } + /** + * @param {any} canvas + * @returns {Promise} + */ + start(canvas) { + const ret = wasm.webhandle_start(this.__wbg_ptr, canvas); + return ret; + } + /** + * @param {boolean | null} [value] + */ + toggle_panel_overrides(value) { + wasm.webhandle_toggle_panel_overrides(this.__wbg_ptr, isLikeNone(value) ? 0xFFFFFF : value ? 1 : 0); + } + } + if (Symbol.dispose) WebHandle.prototype[Symbol.dispose] = WebHandle.prototype.free; + exports.WebHandle = WebHandle; + + function __wbg_get_imports() { + const import0 = { + __proto__: null, + __wbg_Error_2e59b1b37a9a34c3: function(arg0, arg1) { + const ret = Error(getStringFromWasm0(arg0, arg1)); + return ret; + }, + __wbg_Number_e6ffdb596c888833: function(arg0) { + const ret = Number(arg0); + return ret; + }, + __wbg_Window_65ef42d29dc8174d: function(arg0) { + const ret = arg0.Window; + return ret; + }, + __wbg_WorkerGlobalScope_d272430d4a323303: function(arg0) { + const ret = arg0.WorkerGlobalScope; + return ret; + }, + __wbg___wbindgen_boolean_get_a86c216575a75c30: function(arg0) { + const v = arg0; + const ret = typeof(v) === 'boolean' ? v : undefined; + return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0; + }, + __wbg___wbindgen_debug_string_dd5d2d07ce9e6c57: function(arg0, arg1) { + const ret = debugString(arg1); + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg___wbindgen_in_4bd7a57e54337366: function(arg0, arg1) { + const ret = arg0 in arg1; + return ret; + }, + __wbg___wbindgen_is_falsy_c6ddfae1bb56d5ef: function(arg0) { + const ret = !arg0; + return ret; + }, + __wbg___wbindgen_is_function_49868bde5eb1e745: function(arg0) { + const ret = typeof(arg0) === 'function'; + return ret; + }, + __wbg___wbindgen_is_null_344c8750a8525473: function(arg0) { + const ret = arg0 === null; + return ret; + }, + __wbg___wbindgen_is_object_40c5a80572e8f9d3: function(arg0) { + const val = arg0; + const ret = typeof(val) === 'object' && val !== null; + return ret; + }, + __wbg___wbindgen_is_string_b29b5c5a8065ba1a: function(arg0) { + const ret = typeof(arg0) === 'string'; + return ret; + }, + __wbg___wbindgen_is_undefined_c0cca72b82b86f4d: function(arg0) { + const ret = arg0 === undefined; + return ret; + }, + __wbg___wbindgen_jsval_loose_eq_3a72ae764d46d944: function(arg0, arg1) { + const ret = arg0 == arg1; + return ret; + }, + __wbg___wbindgen_number_get_7579aab02a8a620c: function(arg0, arg1) { + const obj = arg1; + const ret = typeof(obj) === 'number' ? obj : undefined; + getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true); + }, + __wbg___wbindgen_string_get_914df97fcfa788f2: function(arg0, arg1) { + const obj = arg1; + const ret = typeof(obj) === 'string' ? obj : undefined; + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg___wbindgen_throw_81fc77679af83bc6: function(arg0, arg1) { + throw new Error(getStringFromWasm0(arg0, arg1)); + }, + __wbg__wbg_cb_unref_3c3b4f651835fbcb: function(arg0) { + arg0._wbg_cb_unref(); + }, + __wbg_abort_5ee4083ce26e0b01: function(arg0) { + arg0.abort(); + }, + __wbg_abort_7a67cb8f9383baa1: function(arg0, arg1) { + arg0.abort(arg1); + }, + __wbg_activeElement_41dff9147c0c1503: function(arg0) { + const ret = arg0.activeElement; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_activeElement_80ade59832af5117: function(arg0) { + const ret = arg0.activeElement; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_activeTexture_55755e76627be758: function(arg0, arg1) { + arg0.activeTexture(arg1 >>> 0); + }, + __wbg_activeTexture_bec0539b102730b3: function(arg0, arg1) { + arg0.activeTexture(arg1 >>> 0); + }, + __wbg_addEventListener_4696109b6f15c412: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + arg0.addEventListener(getStringFromWasm0(arg1, arg2), arg3, arg4); + }, arguments); }, + __wbg_addEventListener_83ef16da0995f634: function() { return handleError(function (arg0, arg1, arg2, arg3) { + arg0.addEventListener(getStringFromWasm0(arg1, arg2), arg3); + }, arguments); }, + __wbg_altKey_7a24c21194788eb1: function(arg0) { + const ret = arg0.altKey; + return ret; + }, + __wbg_altKey_dac3f7f22baf3c82: function(arg0) { + const ret = arg0.altKey; + return ret; + }, + __wbg_appendChild_8eab65de52dd0834: function() { return handleError(function (arg0, arg1) { + const ret = arg0.appendChild(arg1); + return ret; + }, arguments); }, + __wbg_append_760ac5e375d658fb: function(arg0, arg1, arg2, arg3, arg4) { + arg0.append(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, + __wbg_append_c015600138ae60bb: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + arg0.append(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments); }, + __wbg_arrayBuffer_7bba74066875530e: function(arg0) { + const ret = arg0.arrayBuffer(); + return ret; + }, + __wbg_arrayBuffer_dae084a298aa5fe0: function() { return handleError(function (arg0) { + const ret = arg0.arrayBuffer(); + return ret; + }, arguments); }, + __wbg_assign_45099f2ad297b03e: function() { return handleError(function (arg0, arg1, arg2) { + arg0.assign(getStringFromWasm0(arg1, arg2)); + }, arguments); }, + __wbg_at_16485bb9c4fe6761: function(arg0, arg1) { + const ret = arg0.at(arg1); + return ret; + }, + __wbg_attachShader_73ba3bb26991b2f3: function(arg0, arg1, arg2) { + arg0.attachShader(arg1, arg2); + }, + __wbg_attachShader_91626cdf6ee920b8: function(arg0, arg1, arg2) { + arg0.attachShader(arg1, arg2); + }, + __wbg_back_fc3cdc6f5de34e53: function() { return handleError(function (arg0) { + arg0.back(); + }, arguments); }, + __wbg_beginQuery_d7f3cb867735ca13: function(arg0, arg1, arg2) { + arg0.beginQuery(arg1 >>> 0, arg2); + }, + __wbg_beginRenderPass_865cbdfaecf89f93: function() { return handleError(function (arg0, arg1) { + const ret = arg0.beginRenderPass(arg1); + return ret; + }, arguments); }, + __wbg_bindAttribLocation_b392e15ce0851d95: function(arg0, arg1, arg2, arg3, arg4) { + arg0.bindAttribLocation(arg1, arg2 >>> 0, getStringFromWasm0(arg3, arg4)); + }, + __wbg_bindAttribLocation_d6ad755e506645eb: function(arg0, arg1, arg2, arg3, arg4) { + arg0.bindAttribLocation(arg1, arg2 >>> 0, getStringFromWasm0(arg3, arg4)); + }, + __wbg_bindBufferRange_bc7df7052feacd16: function(arg0, arg1, arg2, arg3, arg4, arg5) { + arg0.bindBufferRange(arg1 >>> 0, arg2 >>> 0, arg3, arg4, arg5); + }, + __wbg_bindBuffer_da48260900fd87cb: function(arg0, arg1, arg2) { + arg0.bindBuffer(arg1 >>> 0, arg2); + }, + __wbg_bindBuffer_ec76634c95f563c2: function(arg0, arg1, arg2) { + arg0.bindBuffer(arg1 >>> 0, arg2); + }, + __wbg_bindFramebuffer_c0a4ba2bb49f7c82: function(arg0, arg1, arg2) { + arg0.bindFramebuffer(arg1 >>> 0, arg2); + }, + __wbg_bindFramebuffer_d78e3a3bc89bd6b6: function(arg0, arg1, arg2) { + arg0.bindFramebuffer(arg1 >>> 0, arg2); + }, + __wbg_bindRenderbuffer_7b127e74cfceb241: function(arg0, arg1, arg2) { + arg0.bindRenderbuffer(arg1 >>> 0, arg2); + }, + __wbg_bindRenderbuffer_dbdb3dd0e2f70c84: function(arg0, arg1, arg2) { + arg0.bindRenderbuffer(arg1 >>> 0, arg2); + }, + __wbg_bindSampler_b8d48229c19b98af: function(arg0, arg1, arg2) { + arg0.bindSampler(arg1 >>> 0, arg2); + }, + __wbg_bindTexture_3f1c468809dfc331: function(arg0, arg1, arg2) { + arg0.bindTexture(arg1 >>> 0, arg2); + }, + __wbg_bindTexture_82948e04f9a38b3e: function(arg0, arg1, arg2) { + arg0.bindTexture(arg1 >>> 0, arg2); + }, + __wbg_bindVertexArrayOES_e9c08ca73f91231f: function(arg0, arg1) { + arg0.bindVertexArrayOES(arg1); + }, + __wbg_bindVertexArray_ef65b171588388e0: function(arg0, arg1) { + arg0.bindVertexArray(arg1); + }, + __wbg_blendColor_747326a5245db209: function(arg0, arg1, arg2, arg3, arg4) { + arg0.blendColor(arg1, arg2, arg3, arg4); + }, + __wbg_blendColor_a11f0977927bf536: function(arg0, arg1, arg2, arg3, arg4) { + arg0.blendColor(arg1, arg2, arg3, arg4); + }, + __wbg_blendEquationSeparate_91ba074ad013b85b: function(arg0, arg1, arg2) { + arg0.blendEquationSeparate(arg1 >>> 0, arg2 >>> 0); + }, + __wbg_blendEquationSeparate_faa06617b84f5c1f: function(arg0, arg1, arg2) { + arg0.blendEquationSeparate(arg1 >>> 0, arg2 >>> 0); + }, + __wbg_blendEquation_8627f3d7b1a7144e: function(arg0, arg1) { + arg0.blendEquation(arg1 >>> 0); + }, + __wbg_blendEquation_ecf1b35395da3338: function(arg0, arg1) { + arg0.blendEquation(arg1 >>> 0); + }, + __wbg_blendFuncSeparate_9de3db6383af1e0c: function(arg0, arg1, arg2, arg3, arg4) { + arg0.blendFuncSeparate(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, arg4 >>> 0); + }, + __wbg_blendFuncSeparate_fb17a9951727aac3: function(arg0, arg1, arg2, arg3, arg4) { + arg0.blendFuncSeparate(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, arg4 >>> 0); + }, + __wbg_blendFunc_6bd52d055ab15452: function(arg0, arg1, arg2) { + arg0.blendFunc(arg1 >>> 0, arg2 >>> 0); + }, + __wbg_blendFunc_9ec46725800dafb1: function(arg0, arg1, arg2) { + arg0.blendFunc(arg1 >>> 0, arg2 >>> 0); + }, + __wbg_blitFramebuffer_8a5340cdf51be775: function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) { + arg0.blitFramebuffer(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 >>> 0, arg10 >>> 0); + }, + __wbg_blockSize_e20f2753687379d2: function(arg0) { + const ret = arg0.blockSize; + return ret; + }, + __wbg_blur_2a28d7189bd9dbc7: function() { return handleError(function (arg0) { + arg0.blur(); + }, arguments); }, + __wbg_body_401b41698e8b50fe: function(arg0) { + const ret = arg0.body; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_body_9a25d64338506fbe: function(arg0) { + const ret = arg0.body; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_bottom_6dbc1e08a40f8ad4: function(arg0) { + const ret = arg0.bottom; + return ret; + }, + __wbg_bufferData_143a9bcd4d03d07c: function(arg0, arg1, arg2, arg3) { + arg0.bufferData(arg1 >>> 0, arg2, arg3 >>> 0); + }, + __wbg_bufferData_1db58b556ccdf08f: function(arg0, arg1, arg2, arg3) { + arg0.bufferData(arg1 >>> 0, arg2, arg3 >>> 0); + }, + __wbg_bufferData_74194b1c2d90193e: function(arg0, arg1, arg2, arg3) { + arg0.bufferData(arg1 >>> 0, arg2, arg3 >>> 0); + }, + __wbg_bufferData_e8a8c8a38ae9cbb2: function(arg0, arg1, arg2, arg3) { + arg0.bufferData(arg1 >>> 0, arg2, arg3 >>> 0); + }, + __wbg_bufferSubData_29c9a68f5152e39e: function(arg0, arg1, arg2, arg3) { + arg0.bufferSubData(arg1 >>> 0, arg2, arg3); + }, + __wbg_bufferSubData_870fa411e629e0be: function(arg0, arg1, arg2, arg3) { + arg0.bufferSubData(arg1 >>> 0, arg2, arg3); + }, + __wbg_buffer_a77cc90da4bdb503: function(arg0) { + const ret = arg0.buffer; + return ret; + }, + __wbg_button_225d9d40d1b0539a: function(arg0) { + const ret = arg0.button; + return ret; + }, + __wbg_byobRequest_41018d4f78e8364a: function(arg0) { + const ret = arg0.byobRequest; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_byteLength_f5c761c4472de41b: function(arg0) { + const ret = arg0.byteLength; + return ret; + }, + __wbg_byteOffset_7cd0c9f7e573845c: function(arg0) { + const ret = arg0.byteOffset; + return ret; + }, + __wbg_call_7f2987183bb62793: function() { return handleError(function (arg0, arg1) { + const ret = arg0.call(arg1); + return ret; + }, arguments); }, + __wbg_call_d578befcc3145dee: function() { return handleError(function (arg0, arg1, arg2) { + const ret = arg0.call(arg1, arg2); + return ret; + }, arguments); }, + __wbg_cancelAnimationFrame_19ab829762998ae9: function() { return handleError(function (arg0, arg1) { + arg0.cancelAnimationFrame(arg1); + }, arguments); }, + __wbg_cancel_8314206ca10b9605: function(arg0) { + const ret = arg0.cancel(); + return ret; + }, + __wbg_catch_32d296b856e661d9: function(arg0, arg1) { + const ret = arg0.catch(arg1); + return ret; + }, + __wbg_changedTouches_78d90c47b062c222: function(arg0) { + const ret = arg0.changedTouches; + return ret; + }, + __wbg_clearBufferfv_cd54aebb35643d0c: function(arg0, arg1, arg2, arg3, arg4) { + arg0.clearBufferfv(arg1 >>> 0, arg2, getArrayF32FromWasm0(arg3, arg4)); + }, + __wbg_clearBufferiv_ced17d2ca37ed768: function(arg0, arg1, arg2, arg3, arg4) { + arg0.clearBufferiv(arg1 >>> 0, arg2, getArrayI32FromWasm0(arg3, arg4)); + }, + __wbg_clearBufferuiv_d9e8389c736e29f5: function(arg0, arg1, arg2, arg3, arg4) { + arg0.clearBufferuiv(arg1 >>> 0, arg2, getArrayU32FromWasm0(arg3, arg4)); + }, + __wbg_clearDepth_124325f82e0ca22f: function(arg0, arg1) { + arg0.clearDepth(arg1); + }, + __wbg_clearDepth_c61614548cd3b4e0: function(arg0, arg1) { + arg0.clearDepth(arg1); + }, + __wbg_clearInterval_c7f2b17b895f0bc4: function(arg0, arg1) { + arg0.clearInterval(arg1); + }, + __wbg_clearStencil_2a902925d96d41de: function(arg0, arg1) { + arg0.clearStencil(arg1); + }, + __wbg_clearStencil_4d7e0568af04ac91: function(arg0, arg1) { + arg0.clearStencil(arg1); + }, + __wbg_clearTimeout_8d22a43d8d3c1bfa: function(arg0) { + const ret = clearTimeout(arg0); + return ret; + }, + __wbg_clearTimeout_ef38e23d3d8f7baf: function(arg0) { + const ret = clearTimeout(arg0); + return ret; + }, + __wbg_clearTimeout_f5a5134cd1e7d3fa: function(arg0, arg1) { + arg0.clearTimeout(arg1); + }, + __wbg_clear_4d247257533aabcb: function(arg0, arg1) { + arg0.clear(arg1 >>> 0); + }, + __wbg_clear_98a9ca84e00ae8e2: function(arg0, arg1) { + arg0.clear(arg1 >>> 0); + }, + __wbg_click_71fd1ebdfba801e9: function(arg0) { + arg0.click(); + }, + __wbg_clientWaitSync_d12a62026038cb46: function(arg0, arg1, arg2, arg3) { + const ret = arg0.clientWaitSync(arg1, arg2 >>> 0, arg3 >>> 0); + return ret; + }, + __wbg_clientX_d00d5c12d0187aaa: function(arg0) { + const ret = arg0.clientX; + return ret; + }, + __wbg_clientX_dbc3f9f00736bbd4: function(arg0) { + const ret = arg0.clientX; + return ret; + }, + __wbg_clientY_010f69b0d7c9cf50: function(arg0) { + const ret = arg0.clientY; + return ret; + }, + __wbg_clientY_864b67221ee11ca2: function(arg0) { + const ret = arg0.clientY; + return ret; + }, + __wbg_clipboardData_e9e89b525c2a07ab: function(arg0) { + const ret = arg0.clipboardData; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_clipboard_949fe156c7f0644e: function(arg0) { + const ret = arg0.clipboard; + return ret; + }, + __wbg_close_4b4bd60beb241196: function(arg0) { + arg0.close(); + }, + __wbg_close_9998ebb2f4515c42: function() { return handleError(function (arg0) { + arg0.close(); + }, arguments); }, + __wbg_close_a7c33e895baeb773: function() { return handleError(function (arg0) { + arg0.close(); + }, arguments); }, + __wbg_close_c33e1fa5b0d33158: function() { return handleError(function (arg0) { + arg0.close(); + }, arguments); }, + __wbg_close_d7dfb18ebacbdd81: function() { return handleError(function (arg0) { + arg0.close(); + }, arguments); }, + __wbg_closed_b7ba2aea8995f8fe: function() { return handleError(function (arg0) { + const ret = arg0.closed; + return ret; + }, arguments); }, + __wbg_code_8b9f98f9216b2f10: function(arg0) { + const ret = arg0.code; + return ret; + }, + __wbg_colorMask_134144611b082d70: function(arg0, arg1, arg2, arg3, arg4) { + arg0.colorMask(arg1 !== 0, arg2 !== 0, arg3 !== 0, arg4 !== 0); + }, + __wbg_colorMask_67f0083d53f15052: function(arg0, arg1, arg2, arg3, arg4) { + arg0.colorMask(arg1 !== 0, arg2 !== 0, arg3 !== 0, arg4 !== 0); + }, + __wbg_compileShader_30b1185156c62e3a: function(arg0, arg1) { + arg0.compileShader(arg1); + }, + __wbg_compileShader_d097925490ad9cba: function(arg0, arg1) { + arg0.compileShader(arg1); + }, + __wbg_compressedTexSubImage2D_63fd448bab71e19f: function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) { + arg0.compressedTexSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8); + }, + __wbg_compressedTexSubImage2D_6ca8f1d912fb0a21: function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + arg0.compressedTexSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8, arg9); + }, + __wbg_compressedTexSubImage2D_d6940ad4fd037f63: function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) { + arg0.compressedTexSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8); + }, + __wbg_compressedTexSubImage3D_a9dd717a25de88ae: function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) { + arg0.compressedTexSubImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 >>> 0, arg10); + }, + __wbg_compressedTexSubImage3D_cea1617c94dc89b1: function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) { + arg0.compressedTexSubImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 >>> 0, arg10, arg11); + }, + __wbg_configure_9750ce06cc4cea98: function() { return handleError(function (arg0, arg1) { + arg0.configure(arg1); + }, arguments); }, + __wbg_configure_c0a3d80e97c0e7b1: function() { return handleError(function (arg0, arg1) { + arg0.configure(arg1); + }, arguments); }, + __wbg_contentBoxSize_eeeb1078851bcdc4: function(arg0) { + const ret = arg0.contentBoxSize; + return ret; + }, + __wbg_contentRect_ffc7f5bc1857d6fe: function(arg0) { + const ret = arg0.contentRect; + return ret; + }, + __wbg_copyBufferSubData_ffd7512172742ce5: function(arg0, arg1, arg2, arg3, arg4, arg5) { + arg0.copyBufferSubData(arg1 >>> 0, arg2 >>> 0, arg3, arg4, arg5); + }, + __wbg_copyBufferToBuffer_3b119149df2dc5eb: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + arg0.copyBufferToBuffer(arg1, arg2, arg3, arg4); + }, arguments); }, + __wbg_copyBufferToBuffer_9e5aea97d7828aa3: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5) { + arg0.copyBufferToBuffer(arg1, arg2, arg3, arg4, arg5); + }, arguments); }, + __wbg_copyBufferToTexture_46f05a7a84552c50: function() { return handleError(function (arg0, arg1, arg2, arg3) { + arg0.copyBufferToTexture(arg1, arg2, arg3); + }, arguments); }, + __wbg_copyExternalImageToTexture_305b23364c470d9e: function() { return handleError(function (arg0, arg1, arg2, arg3) { + arg0.copyExternalImageToTexture(arg1, arg2, arg3); + }, arguments); }, + __wbg_copyTexSubImage2D_4a2d7e2efd99dfa8: function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) { + arg0.copyTexSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + }, + __wbg_copyTexSubImage2D_509ece20b65a16c7: function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) { + arg0.copyTexSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + }, + __wbg_copyTexSubImage3D_ef5526f572f36d56: function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + arg0.copyTexSubImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + }, + __wbg_copyTextureToBuffer_a9b82ac765521aab: function() { return handleError(function (arg0, arg1, arg2, arg3) { + arg0.copyTextureToBuffer(arg1, arg2, arg3); + }, arguments); }, + __wbg_createBindGroupLayout_59891d473ac8665d: function() { return handleError(function (arg0, arg1) { + const ret = arg0.createBindGroupLayout(arg1); + return ret; + }, arguments); }, + __wbg_createBindGroup_4cb86ff853df5c69: function(arg0, arg1) { + const ret = arg0.createBindGroup(arg1); + return ret; + }, + __wbg_createBuffer_3fa0256cba655273: function() { return handleError(function (arg0, arg1) { + const ret = arg0.createBuffer(arg1); + return ret; + }, arguments); }, + __wbg_createBuffer_8dc942ca97cf9d2a: function(arg0) { + const ret = arg0.createBuffer(); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_createBuffer_bdda716ebf68ba59: function(arg0) { + const ret = arg0.createBuffer(); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_createCommandEncoder_98e3b731629054b4: function(arg0, arg1) { + const ret = arg0.createCommandEncoder(arg1); + return ret; + }, + __wbg_createElement_8640e331213b402e: function() { return handleError(function (arg0, arg1, arg2) { + const ret = arg0.createElement(getStringFromWasm0(arg1, arg2)); + return ret; + }, arguments); }, + __wbg_createFramebuffer_3f2bfbc211cd82f2: function(arg0) { + const ret = arg0.createFramebuffer(); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_createFramebuffer_b2cc13b01b560d6f: function(arg0) { + const ret = arg0.createFramebuffer(); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_createImageBitmap_cb080b12f9a4532b: function() { return handleError(function (arg0, arg1) { + const ret = arg0.createImageBitmap(arg1); + return ret; + }, arguments); }, + __wbg_createObjectURL_470fa06cc4a9e8f0: function() { return handleError(function (arg0, arg1) { + const ret = URL.createObjectURL(arg1); + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, arguments); }, + __wbg_createPipelineLayout_270b4fd0b4230373: function(arg0, arg1) { + const ret = arg0.createPipelineLayout(arg1); + return ret; + }, + __wbg_createProgram_03cf82c6259699da: function(arg0) { + const ret = arg0.createProgram(); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_createProgram_ba013605ddf3824a: function(arg0) { + const ret = arg0.createProgram(); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_createQuery_6c795620aa1cd6db: function(arg0) { + const ret = arg0.createQuery(); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_createRenderPipeline_4c120add6a62a442: function() { return handleError(function (arg0, arg1) { + const ret = arg0.createRenderPipeline(arg1); + return ret; + }, arguments); }, + __wbg_createRenderbuffer_0029ab986ce8c0da: function(arg0) { + const ret = arg0.createRenderbuffer(); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_createRenderbuffer_5b5217ebb1024b24: function(arg0) { + const ret = arg0.createRenderbuffer(); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_createSampler_2f89f67a6a2aa51f: function(arg0) { + const ret = arg0.createSampler(); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_createSampler_95bff4f5405a3dd1: function(arg0, arg1) { + const ret = arg0.createSampler(arg1); + return ret; + }, + __wbg_createShaderModule_f0aa469466c7bdaa: function(arg0, arg1) { + const ret = arg0.createShaderModule(arg1); + return ret; + }, + __wbg_createShader_b2c5333fcc05114e: function(arg0, arg1) { + const ret = arg0.createShader(arg1 >>> 0); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_createShader_f556b21db86193fd: function(arg0, arg1) { + const ret = arg0.createShader(arg1 >>> 0); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_createTexture_28341edbcc7d129e: function() { return handleError(function (arg0, arg1) { + const ret = arg0.createTexture(arg1); + return ret; + }, arguments); }, + __wbg_createTexture_ab0a6dde87005cb1: function(arg0) { + const ret = arg0.createTexture(); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_createTexture_b2dbf72113bdda56: function(arg0) { + const ret = arg0.createTexture(); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_createVertexArrayOES_a89b0d9f1070e733: function(arg0) { + const ret = arg0.createVertexArrayOES(); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_createVertexArray_be0c22725872a475: function(arg0) { + const ret = arg0.createVertexArray(); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_createView_d04a0f9bdd723238: function() { return handleError(function (arg0, arg1) { + const ret = arg0.createView(arg1); + return ret; + }, arguments); }, + __wbg_ctrlKey_af896fa77d43a375: function(arg0) { + const ret = arg0.ctrlKey; + return ret; + }, + __wbg_ctrlKey_dc8c7fcd63c26948: function(arg0) { + const ret = arg0.ctrlKey; + return ret; + }, + __wbg_cullFace_a9283a49d745da71: function(arg0, arg1) { + arg0.cullFace(arg1 >>> 0); + }, + __wbg_cullFace_ee2bd5882746855f: function(arg0, arg1) { + arg0.cullFace(arg1 >>> 0); + }, + __wbg_dataTransfer_994cf664bb1da77f: function(arg0) { + const ret = arg0.dataTransfer; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_data_31cbb395bfd6c6ce: function(arg0, arg1) { + const ret = arg1.data; + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_data_60b50110c5bd9349: function(arg0) { + const ret = arg0.data; + return ret; + }, + __wbg_data_6265d63a72efdd9a: function(arg0, arg1) { + const ret = arg1.data; + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_debug_50e24f25b064ded1: function(arg0) { + console.debug(arg0); + }, + __wbg_debug_58754cc8dbfec7ec: function(arg0, arg1, arg2, arg3) { + console.debug(arg0, arg1, arg2, arg3); + }, + __wbg_decode_728a4fb6d8b559ae: function() { return handleError(function (arg0, arg1) { + arg0.decode(arg1); + }, arguments); }, + __wbg_deleteBuffer_38cfc45ad05c89ef: function(arg0, arg1) { + arg0.deleteBuffer(arg1); + }, + __wbg_deleteBuffer_ef356b1392cab959: function(arg0, arg1) { + arg0.deleteBuffer(arg1); + }, + __wbg_deleteFramebuffer_3385f016ae9cb4ca: function(arg0, arg1) { + arg0.deleteFramebuffer(arg1); + }, + __wbg_deleteFramebuffer_6395b8aef0749d3c: function(arg0, arg1) { + arg0.deleteFramebuffer(arg1); + }, + __wbg_deleteProgram_6eccd9aa110cbb2c: function(arg0, arg1) { + arg0.deleteProgram(arg1); + }, + __wbg_deleteProgram_e1eaf172c61bd109: function(arg0, arg1) { + arg0.deleteProgram(arg1); + }, + __wbg_deleteQuery_9fa8004f05bf6e44: function(arg0, arg1) { + arg0.deleteQuery(arg1); + }, + __wbg_deleteRenderbuffer_83a815667e112d6a: function(arg0, arg1) { + arg0.deleteRenderbuffer(arg1); + }, + __wbg_deleteRenderbuffer_e5753c22e2612fd3: function(arg0, arg1) { + arg0.deleteRenderbuffer(arg1); + }, + __wbg_deleteSampler_204829b1a680fa98: function(arg0, arg1) { + arg0.deleteSampler(arg1); + }, + __wbg_deleteShader_0784961238f3ba6f: function(arg0, arg1) { + arg0.deleteShader(arg1); + }, + __wbg_deleteShader_13b98e109c7ec22b: function(arg0, arg1) { + arg0.deleteShader(arg1); + }, + __wbg_deleteSync_68c37014fd090e43: function(arg0, arg1) { + arg0.deleteSync(arg1); + }, + __wbg_deleteTexture_57bf3a76dc0a7bf9: function(arg0, arg1) { + arg0.deleteTexture(arg1); + }, + __wbg_deleteTexture_72eed589178ae2f9: function(arg0, arg1) { + arg0.deleteTexture(arg1); + }, + __wbg_deleteVertexArrayOES_49cf118408f32324: function(arg0, arg1) { + arg0.deleteVertexArrayOES(arg1); + }, + __wbg_deleteVertexArray_51740ccf7085a65a: function(arg0, arg1) { + arg0.deleteVertexArray(arg1); + }, + __wbg_delete_096f196851a1f47b: function() { return handleError(function (arg0, arg1, arg2) { + delete arg0[getStringFromWasm0(arg1, arg2)]; + }, arguments); }, + __wbg_deltaMode_389ab9e0c7c47a3c: function(arg0) { + const ret = arg0.deltaMode; + return ret; + }, + __wbg_deltaX_6fd68d53fb18c3ea: function(arg0) { + const ret = arg0.deltaX; + return ret; + }, + __wbg_deltaY_d67fb1a74cff23bc: function(arg0) { + const ret = arg0.deltaY; + return ret; + }, + __wbg_depthFunc_4025ae02b54073f8: function(arg0, arg1) { + arg0.depthFunc(arg1 >>> 0); + }, + __wbg_depthFunc_b26bec47c7bcebee: function(arg0, arg1) { + arg0.depthFunc(arg1 >>> 0); + }, + __wbg_depthMask_2e4372fcba47dc49: function(arg0, arg1) { + arg0.depthMask(arg1 !== 0); + }, + __wbg_depthMask_d943acfff13d2ce2: function(arg0, arg1) { + arg0.depthMask(arg1 !== 0); + }, + __wbg_depthRange_0bcfa7da45794a56: function(arg0, arg1, arg2) { + arg0.depthRange(arg1, arg2); + }, + __wbg_depthRange_1430e03ed51da89f: function(arg0, arg1, arg2) { + arg0.depthRange(arg1, arg2); + }, + __wbg_description_f6ebcdce701b056b: function(arg0, arg1) { + const ret = arg1.description; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_destroy_a1ad55d8110037a7: function(arg0) { + arg0.destroy(); + }, + __wbg_destroy_ce807b0d8ddbb656: function(arg0) { + arg0.destroy(); + }, + __wbg_devicePixelContentBoxSize_74f4718d7ccbbda0: function(arg0) { + const ret = arg0.devicePixelContentBoxSize; + return ret; + }, + __wbg_devicePixelRatio_a0dc790882837272: function(arg0) { + const ret = arg0.devicePixelRatio; + return ret; + }, + __wbg_disableVertexAttribArray_502ba5544050cc4a: function(arg0, arg1) { + arg0.disableVertexAttribArray(arg1 >>> 0); + }, + __wbg_disableVertexAttribArray_a1f4414d0521b130: function(arg0, arg1) { + arg0.disableVertexAttribArray(arg1 >>> 0); + }, + __wbg_disable_5c6898ffc41889ea: function(arg0, arg1) { + arg0.disable(arg1 >>> 0); + }, + __wbg_disable_896f703cc44cf1e8: function(arg0, arg1) { + arg0.disable(arg1 >>> 0); + }, + __wbg_disconnect_99bdd53252c1a923: function(arg0) { + arg0.disconnect(); + }, + __wbg_displayHeight_6a09027747b2839c: function(arg0) { + const ret = arg0.displayHeight; + return ret; + }, + __wbg_displayWidth_969bcee30c9ba96e: function(arg0) { + const ret = arg0.displayWidth; + return ret; + }, + __wbg_document_a28a21ae315de4ea: function(arg0) { + const ret = arg0.document; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_done_547d467e97529006: function(arg0) { + const ret = arg0.done; + return ret; + }, + __wbg_drawArraysInstancedANGLE_73044a94e5127803: function(arg0, arg1, arg2, arg3, arg4) { + arg0.drawArraysInstancedANGLE(arg1 >>> 0, arg2, arg3, arg4); + }, + __wbg_drawArraysInstanced_f8a4998461298b8d: function(arg0, arg1, arg2, arg3, arg4) { + arg0.drawArraysInstanced(arg1 >>> 0, arg2, arg3, arg4); + }, + __wbg_drawArrays_079aad920afe1404: function(arg0, arg1, arg2, arg3) { + arg0.drawArrays(arg1 >>> 0, arg2, arg3); + }, + __wbg_drawArrays_b159d63fb955e0cb: function(arg0, arg1, arg2, arg3) { + arg0.drawArrays(arg1 >>> 0, arg2, arg3); + }, + __wbg_drawBuffersWEBGL_b187a1d10b662517: function(arg0, arg1) { + arg0.drawBuffersWEBGL(arg1); + }, + __wbg_drawBuffers_7f711677354b104a: function(arg0, arg1) { + arg0.drawBuffers(arg1); + }, + __wbg_drawElementsInstancedANGLE_93fa83c14a69f07c: function(arg0, arg1, arg2, arg3, arg4, arg5) { + arg0.drawElementsInstancedANGLE(arg1 >>> 0, arg2, arg3 >>> 0, arg4, arg5); + }, + __wbg_drawElementsInstanced_e67f42392ded7e15: function(arg0, arg1, arg2, arg3, arg4, arg5) { + arg0.drawElementsInstanced(arg1 >>> 0, arg2, arg3 >>> 0, arg4, arg5); + }, + __wbg_drawIndexed_cc7c04c1088cafad: function(arg0, arg1, arg2, arg3, arg4, arg5) { + arg0.drawIndexed(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, arg4, arg5 >>> 0); + }, + __wbg_draw_92eb37d6b3b2aab4: function(arg0, arg1, arg2, arg3, arg4) { + arg0.draw(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, arg4 >>> 0); + }, + __wbg_elementFromPoint_6c20f1acad715888: function(arg0, arg1, arg2) { + const ret = arg0.elementFromPoint(arg1, arg2); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_elementFromPoint_d497b2a177e5ac7c: function(arg0, arg1, arg2) { + const ret = arg0.elementFromPoint(arg1, arg2); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_enableVertexAttribArray_acf4abf519ab0114: function(arg0, arg1) { + arg0.enableVertexAttribArray(arg1 >>> 0); + }, + __wbg_enableVertexAttribArray_b4abeab358174fdb: function(arg0, arg1) { + arg0.enableVertexAttribArray(arg1 >>> 0); + }, + __wbg_enable_9328f475236428ef: function(arg0, arg1) { + arg0.enable(arg1 >>> 0); + }, + __wbg_enable_f1131cfcbbb57556: function(arg0, arg1) { + arg0.enable(arg1 >>> 0); + }, + __wbg_endQuery_9b3877af76f58a68: function(arg0, arg1) { + arg0.endQuery(arg1 >>> 0); + }, + __wbg_end_d49513b309f4ca43: function(arg0) { + arg0.end(); + }, + __wbg_enqueue_bb06efec8458a81a: function() { return handleError(function (arg0, arg1) { + arg0.enqueue(arg1); + }, arguments); }, + __wbg_entries_616b1a459b85be0b: function(arg0) { + const ret = Object.entries(arg0); + return ret; + }, + __wbg_error_38bec0a78dd8ded8: function(arg0) { + console.error(arg0); + }, + __wbg_error_b500091380f31ffc: function(arg0, arg1) { + let deferred0_0; + let deferred0_1; + try { + deferred0_0 = arg0; + deferred0_1 = arg1; + console.error(getStringFromWasm0(arg0, arg1)); + } finally { + wasm.__wbindgen_free(deferred0_0, deferred0_1, 1); + } + }, + __wbg_error_f6720b4bc5b9976f: function(arg0) { + const ret = arg0.error; + return ret; + }, + __wbg_error_f8d1622cb1d8c53c: function(arg0, arg1, arg2, arg3) { + console.error(arg0, arg1, arg2, arg3); + }, + __wbg_features_6906f30d3b243f58: function(arg0) { + const ret = arg0.features; + return ret; + }, + __wbg_fenceSync_76fd7e7573b1c3d3: function(arg0, arg1, arg2) { + const ret = arg0.fenceSync(arg1 >>> 0, arg2 >>> 0); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_fetch_1a731e18c5e21884: function(arg0, arg1) { + const ret = arg0.fetch(arg1); + return ret; + }, + __wbg_fetch_737feb0f4e4769cd: function(arg0, arg1) { + const ret = fetch(arg0, arg1); + return ret; + }, + __wbg_fetch_a920260d19124083: function(arg0, arg1, arg2) { + const ret = arg0.fetch(arg1, arg2); + return ret; + }, + __wbg_fetch_b371b952a61cca04: function(arg0) { + const ret = fetch(arg0); + return ret; + }, + __wbg_fetch_fa4854adc83457ba: function(arg0) { + const ret = fetch(arg0); + return ret; + }, + __wbg_files_49421c0860b80e49: function(arg0) { + const ret = arg0.files; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_files_becc181f99e4c14c: function(arg0) { + const ret = arg0.files; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_finish_6c7bba424ffe1bbc: function(arg0, arg1) { + const ret = arg0.finish(arg1); + return ret; + }, + __wbg_finish_c40b67ff2af88e0c: function(arg0) { + const ret = arg0.finish(); + return ret; + }, + __wbg_flush_2dbf18333ea13590: function(arg0) { + const ret = arg0.flush(); + return ret; + }, + __wbg_flush_3960af47143225d1: function(arg0) { + arg0.flush(); + }, + __wbg_flush_7044918ba0f7d59b: function(arg0) { + arg0.flush(); + }, + __wbg_focus_93aead258d471c93: function() { return handleError(function (arg0) { + arg0.focus(); + }, arguments); }, + __wbg_force_12fb0f147a1b59af: function(arg0) { + const ret = arg0.force; + return ret; + }, + __wbg_forward_67b33c508af383d0: function() { return handleError(function (arg0) { + arg0.forward(); + }, arguments); }, + __wbg_framebufferRenderbuffer_09fadd099736edc1: function(arg0, arg1, arg2, arg3, arg4) { + arg0.framebufferRenderbuffer(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, arg4); + }, + __wbg_framebufferRenderbuffer_2604d9558c7cddc1: function(arg0, arg1, arg2, arg3, arg4) { + arg0.framebufferRenderbuffer(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, arg4); + }, + __wbg_framebufferTexture2D_88c527c558c09cf5: function(arg0, arg1, arg2, arg3, arg4, arg5) { + arg0.framebufferTexture2D(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, arg4, arg5); + }, + __wbg_framebufferTexture2D_eddd6f0f599ffc34: function(arg0, arg1, arg2, arg3, arg4, arg5) { + arg0.framebufferTexture2D(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, arg4, arg5); + }, + __wbg_framebufferTextureLayer_e5625e06e97b63de: function(arg0, arg1, arg2, arg3, arg4, arg5) { + arg0.framebufferTextureLayer(arg1 >>> 0, arg2 >>> 0, arg3, arg4, arg5); + }, + __wbg_framebufferTextureMultiviewOVR_dbaa070c3a6c7ea3: function(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { + arg0.framebufferTextureMultiviewOVR(arg1 >>> 0, arg2 >>> 0, arg3, arg4, arg5, arg6); + }, + __wbg_frontFace_82dd2745b23de0b6: function(arg0, arg1) { + arg0.frontFace(arg1 >>> 0); + }, + __wbg_frontFace_8751ba7bc82d3bcb: function(arg0, arg1) { + arg0.frontFace(arg1 >>> 0); + }, + __wbg_getBindGroupLayout_3e25f08ba260b2a6: function(arg0, arg1) { + const ret = arg0.getBindGroupLayout(arg1 >>> 0); + return ret; + }, + __wbg_getBoundingClientRect_dd4198d549ad0fd6: function(arg0) { + const ret = arg0.getBoundingClientRect(); + return ret; + }, + __wbg_getBufferSubData_c064a23bd730f094: function(arg0, arg1, arg2, arg3) { + arg0.getBufferSubData(arg1 >>> 0, arg2, arg3); + }, + __wbg_getComputedStyle_032eef1be41bbff9: function() { return handleError(function (arg0, arg1) { + const ret = arg0.getComputedStyle(arg1); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, arguments); }, + __wbg_getContext_8ab47e12b2ed57e5: function() { return handleError(function (arg0, arg1, arg2) { + const ret = arg0.getContext(getStringFromWasm0(arg1, arg2)); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, arguments); }, + __wbg_getContext_8f1ff363618c55da: function() { return handleError(function (arg0, arg1, arg2) { + const ret = arg0.getContext(getStringFromWasm0(arg1, arg2)); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, arguments); }, + __wbg_getContext_9da116ef0547477e: function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = arg0.getContext(getStringFromWasm0(arg1, arg2), arg3); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, arguments); }, + __wbg_getContext_d61338bafcc57ccd: function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = arg0.getContext(getStringFromWasm0(arg1, arg2), arg3); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, arguments); }, + __wbg_getCurrentTexture_274b67f871b2dea5: function() { return handleError(function (arg0) { + const ret = arg0.getCurrentTexture(); + return ret; + }, arguments); }, + __wbg_getData_546274e368ce61dd: function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = arg1.getData(getStringFromWasm0(arg2, arg3)); + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, arguments); }, + __wbg_getElementById_1a2b69d69d3a074f: function(arg0, arg1, arg2) { + const ret = arg0.getElementById(getStringFromWasm0(arg1, arg2)); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_getExtension_ce16f3780572b35e: function() { return handleError(function (arg0, arg1, arg2) { + const ret = arg0.getExtension(getStringFromWasm0(arg1, arg2)); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, arguments); }, + __wbg_getIndexedParameter_a462264cdcf47430: function() { return handleError(function (arg0, arg1, arg2) { + const ret = arg0.getIndexedParameter(arg1 >>> 0, arg2 >>> 0); + return ret; + }, arguments); }, + __wbg_getItem_203869d4a1ba1433: function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = arg1.getItem(getStringFromWasm0(arg2, arg3)); + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, arguments); }, + __wbg_getMappedRange_59829576da3edd39: function() { return handleError(function (arg0, arg1, arg2) { + const ret = arg0.getMappedRange(arg1, arg2); + return ret; + }, arguments); }, + __wbg_getParameter_037149e897c929ad: function() { return handleError(function (arg0, arg1) { + const ret = arg0.getParameter(arg1 >>> 0); + return ret; + }, arguments); }, + __wbg_getParameter_09ce4298daa62d31: function() { return handleError(function (arg0, arg1) { + const ret = arg0.getParameter(arg1 >>> 0); + return ret; + }, arguments); }, + __wbg_getPreferredCanvasFormat_6f629398d892f0c9: function(arg0) { + const ret = arg0.getPreferredCanvasFormat(); + return (__wbindgen_enum_GpuTextureFormat.indexOf(ret) + 1 || 96) - 1; + }, + __wbg_getProgramInfoLog_b2d112da8cb8c5c5: function(arg0, arg1, arg2) { + const ret = arg1.getProgramInfoLog(arg2); + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_getProgramInfoLog_b4bc560fd6ea687d: function(arg0, arg1, arg2) { + const ret = arg1.getProgramInfoLog(arg2); + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_getProgramParameter_2b7693f9edfde93d: function(arg0, arg1, arg2) { + const ret = arg0.getProgramParameter(arg1, arg2 >>> 0); + return ret; + }, + __wbg_getProgramParameter_6dc3590345750abb: function(arg0, arg1, arg2) { + const ret = arg0.getProgramParameter(arg1, arg2 >>> 0); + return ret; + }, + __wbg_getPropertyValue_12e464ea4b1c3fe4: function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = arg1.getPropertyValue(getStringFromWasm0(arg2, arg3)); + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, arguments); }, + __wbg_getQueryParameter_e4d2a987adf1449e: function(arg0, arg1, arg2) { + const ret = arg0.getQueryParameter(arg1, arg2 >>> 0); + return ret; + }, + __wbg_getRandomValues_3f44b700395062e5: function() { return handleError(function (arg0, arg1) { + globalThis.crypto.getRandomValues(getArrayU8FromWasm0(arg0, arg1)); + }, arguments); }, + __wbg_getRandomValues_a697888e9ba1eee3: function() { return handleError(function (arg0, arg1) { + globalThis.crypto.getRandomValues(getArrayU8FromWasm0(arg0, arg1)); + }, arguments); }, + __wbg_getReader_b4b1868fbca77dbe: function() { return handleError(function (arg0) { + const ret = arg0.getReader(); + return ret; + }, arguments); }, + __wbg_getRootNode_cbe0078ee615c20a: function(arg0) { + const ret = arg0.getRootNode(); + return ret; + }, + __wbg_getShaderInfoLog_57aaac3110ec22f3: function(arg0, arg1, arg2) { + const ret = arg1.getShaderInfoLog(arg2); + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_getShaderInfoLog_737b1be2c43195d8: function(arg0, arg1, arg2) { + const ret = arg1.getShaderInfoLog(arg2); + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_getShaderParameter_2b6f35d96d51cc82: function(arg0, arg1, arg2) { + const ret = arg0.getShaderParameter(arg1, arg2 >>> 0); + return ret; + }, + __wbg_getShaderParameter_cc12071135e57d45: function(arg0, arg1, arg2) { + const ret = arg0.getShaderParameter(arg1, arg2 >>> 0); + return ret; + }, + __wbg_getSupportedExtensions_92b6dc82a889082d: function(arg0) { + const ret = arg0.getSupportedExtensions(); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_getSupportedProfiles_593187c5922410c6: function(arg0) { + const ret = arg0.getSupportedProfiles(); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_getSyncParameter_6c7d58a19ab45344: function(arg0, arg1, arg2) { + const ret = arg0.getSyncParameter(arg1, arg2 >>> 0); + return ret; + }, + __wbg_getTime_f6ac312467f7cf09: function(arg0) { + const ret = arg0.getTime(); + return ret; + }, + __wbg_getUniformBlockIndex_afbce80bbbee480c: function(arg0, arg1, arg2, arg3) { + const ret = arg0.getUniformBlockIndex(arg1, getStringFromWasm0(arg2, arg3)); + return ret; + }, + __wbg_getUniformLocation_2e7496f74219fc19: function(arg0, arg1, arg2, arg3) { + const ret = arg0.getUniformLocation(arg1, getStringFromWasm0(arg2, arg3)); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_getUniformLocation_8d93a5f3de4232bf: function(arg0, arg1, arg2, arg3) { + const ret = arg0.getUniformLocation(arg1, getStringFromWasm0(arg2, arg3)); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_get_22172cd3e3bb6c58: function(arg0, arg1) { + const ret = arg0[arg1 >>> 0]; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_get_4848e350b40afc16: function(arg0, arg1) { + const ret = arg0[arg1 >>> 0]; + return ret; + }, + __wbg_get_753152eb19d860b1: function(arg0, arg1) { + const ret = arg0[arg1 >>> 0]; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_get_761e9cf5d605bcbd: function(arg0, arg1) { + const ret = arg0[arg1 >>> 0]; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_get_cb1662031c6b2d85: function(arg0, arg1) { + const ret = arg0[arg1 >>> 0]; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_get_done_46f064515323cd59: function(arg0) { + const ret = arg0.done; + return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0; + }, + __wbg_get_ed0642c4b9d31ddf: function() { return handleError(function (arg0, arg1) { + const ret = Reflect.get(arg0, arg1); + return ret; + }, arguments); }, + __wbg_get_f96702c6245e4ef9: function() { return handleError(function (arg0, arg1) { + const ret = Reflect.get(arg0, arg1); + return ret; + }, arguments); }, + __wbg_get_unchecked_7d7babe32e9e6a54: function(arg0, arg1) { + const ret = arg0[arg1 >>> 0]; + return ret; + }, + __wbg_get_value_28b7deb73d356d88: function(arg0) { + const ret = arg0.value; + return ret; + }, + __wbg_get_with_ref_key_6412cf3094599694: function(arg0, arg1) { + const ret = arg0[arg1]; + return ret; + }, + __wbg_gpu_cbd27ad0589bc0b3: function(arg0) { + const ret = arg0.gpu; + return ret; + }, + __wbg_hasOwn_8000c3db5749d89f: function(arg0, arg1) { + const ret = Object.hasOwn(arg0, arg1); + return ret; + }, + __wbg_has_3ec5c22db2e5237a: function() { return handleError(function (arg0, arg1) { + const ret = Reflect.has(arg0, arg1); + return ret; + }, arguments); }, + __wbg_has_dbcaf77712624019: function(arg0, arg1, arg2) { + const ret = arg0.has(getStringFromWasm0(arg1, arg2)); + return ret; + }, + __wbg_hash_da89606b87400cf8: function() { return handleError(function (arg0, arg1) { + const ret = arg1.hash; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, arguments); }, + __wbg_headers_e08dcb5aa09b9a63: function(arg0) { + const ret = arg0.headers; + return ret; + }, + __wbg_headers_f82eee91a0c91695: function(arg0) { + const ret = arg0.headers; + return ret; + }, + __wbg_height_09395aee19ee0c83: function(arg0) { + const ret = arg0.height; + return ret; + }, + __wbg_height_2f8ba47ff2d364fa: function(arg0) { + const ret = arg0.height; + return ret; + }, + __wbg_height_734034c3ff2654af: function(arg0) { + const ret = arg0.height; + return ret; + }, + __wbg_height_7b4d4d42e2cf1777: function(arg0) { + const ret = arg0.height; + return ret; + }, + __wbg_height_851bcd638e890abc: function(arg0) { + const ret = arg0.height; + return ret; + }, + __wbg_height_c9bfbe517e2c65f2: function(arg0) { + const ret = arg0.height; + return ret; + }, + __wbg_hidden_9d47d82daa2677c0: function(arg0) { + const ret = arg0.hidden; + return ret; + }, + __wbg_history_e0fde1755ec7a020: function() { return handleError(function (arg0) { + const ret = arg0.history; + return ret; + }, arguments); }, + __wbg_host_142a4b1e170efc7f: function() { return handleError(function (arg0, arg1) { + const ret = arg1.host; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, arguments); }, + __wbg_hostname_a42f31a9081ac639: function() { return handleError(function (arg0, arg1) { + const ret = arg1.hostname; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, arguments); }, + __wbg_href_bc5537e1b5176567: function(arg0, arg1) { + const ret = arg1.href; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_href_e111373f8d7ae763: function() { return handleError(function (arg0, arg1) { + const ret = arg1.href; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, arguments); }, + __wbg_identifier_db6b606c00c0fc57: function(arg0) { + const ret = arg0.identifier; + return ret; + }, + __wbg_includes_e1c3d5075ba084c5: function(arg0, arg1, arg2) { + const ret = arg0.includes(arg1, arg2); + return ret; + }, + __wbg_info_4e3339024d0fb613: function(arg0) { + console.info(arg0); + }, + __wbg_info_8e80eb6c0f1d9449: function(arg0, arg1, arg2, arg3) { + console.info(arg0, arg1, arg2, arg3); + }, + __wbg_info_91a8fcd51fd17fff: function(arg0) { + const ret = arg0.info; + return ret; + }, + __wbg_inlineSize_4d595b2867bf7d83: function(arg0) { + const ret = arg0.inlineSize; + return ret; + }, + __wbg_instanceof_ArrayBuffer_ff7c1337a5e3b33a: function(arg0) { + let result; + try { + result = arg0 instanceof ArrayBuffer; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_Document_fa497c324471af6b: function(arg0) { + let result; + try { + result = arg0 instanceof Document; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_DomException_37f96d3fb69189bd: function(arg0) { + let result; + try { + result = arg0 instanceof DOMException; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_Element_c4784e8a9522e087: function(arg0) { + let result; + try { + result = arg0 instanceof Element; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_Error_e3390d6805733dad: function(arg0) { + let result; + try { + result = arg0 instanceof Error; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_GpuAdapter_1297a3a5ce0db3ff: function(arg0) { + let result; + try { + result = arg0 instanceof GPUAdapter; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_GpuCanvasContext_13613277d7bf3768: function(arg0) { + let result; + try { + result = arg0 instanceof GPUCanvasContext; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_GpuOutOfMemoryError_100c4600c3e13387: function(arg0) { + let result; + try { + result = arg0 instanceof GPUOutOfMemoryError; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_GpuValidationError_94580aa7a41f3bdb: function(arg0) { + let result; + try { + result = arg0 instanceof GPUValidationError; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_HtmlAnchorElement_d244ac11562c8f69: function(arg0) { + let result; + try { + result = arg0 instanceof HTMLAnchorElement; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_HtmlButtonElement_94e31ca453766121: function(arg0) { + let result; + try { + result = arg0 instanceof HTMLButtonElement; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_HtmlCanvasElement_3cec11b30b0d54e4: function(arg0) { + let result; + try { + result = arg0 instanceof HTMLCanvasElement; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_HtmlElement_43b8bbfdb4aaefd5: function(arg0) { + let result; + try { + result = arg0 instanceof HTMLElement; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_HtmlInputElement_ed700e6a857d360a: function(arg0) { + let result; + try { + result = arg0 instanceof HTMLInputElement; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_ImageBitmap_d23d5f2ff367649d: function(arg0) { + let result; + try { + result = arg0 instanceof ImageBitmap; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_MessageEvent_3c68912ba847d8e1: function(arg0) { + let result; + try { + result = arg0 instanceof MessageEvent; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_ReadableStream_d46dd192e1ce3f88: function(arg0) { + let result; + try { + result = arg0 instanceof ReadableStream; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_ResizeObserverEntry_2934c3da74688b5b: function(arg0) { + let result; + try { + result = arg0 instanceof ResizeObserverEntry; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_ResizeObserverSize_5b368efa5128c601: function(arg0) { + let result; + try { + result = arg0 instanceof ResizeObserverSize; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_Response_06795eab66cc4036: function(arg0) { + let result; + try { + result = arg0 instanceof Response; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_ShadowRoot_9508b4512523f14c: function(arg0) { + let result; + try { + result = arg0 instanceof ShadowRoot; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_TypeError_dd6397f181d803d0: function(arg0) { + let result; + try { + result = arg0 instanceof TypeError; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_Uint8Array_4b8da683deb25d72: function(arg0) { + let result; + try { + result = arg0 instanceof Uint8Array; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_WebGl2RenderingContext_6502f76e53996a5e: function(arg0) { + let result; + try { + result = arg0 instanceof WebGL2RenderingContext; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_Window_c0fee4c064502536: function(arg0) { + let result; + try { + result = arg0 instanceof Window; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_invalidateFramebuffer_33d1760cdf66128f: function() { return handleError(function (arg0, arg1, arg2) { + arg0.invalidateFramebuffer(arg1 >>> 0, arg2); + }, arguments); }, + __wbg_isActive_453c915c78ca9cf6: function(arg0) { + const ret = arg0.isActive; + return ret; + }, + __wbg_isArray_db61795ad004c139: function(arg0) { + const ret = Array.isArray(arg0); + return ret; + }, + __wbg_isComposing_926558e85c1322f5: function(arg0) { + const ret = arg0.isComposing; + return ret; + }, + __wbg_isComposing_fc3ec12836b74836: function(arg0) { + const ret = arg0.isComposing; + return ret; + }, + __wbg_isSafeInteger_ea83862ba994770c: function(arg0) { + const ret = Number.isSafeInteger(arg0); + return ret; + }, + __wbg_isSecureContext_2ad7065a08159f29: function(arg0) { + const ret = arg0.isSecureContext; + return ret; + }, + __wbg_is_3ce118e1fc3aa47e: function(arg0, arg1) { + const ret = Object.is(arg0, arg1); + return ret; + }, + __wbg_item_f76abbdc0cf17647: function(arg0, arg1) { + const ret = arg0.item(arg1 >>> 0); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_items_38e88bb85ee8204a: function(arg0) { + const ret = arg0.items; + return ret; + }, + __wbg_iterator_de403ef31815a3e6: function() { + const ret = Symbol.iterator; + return ret; + }, + __wbg_keyCode_7772df4809d7d3d8: function(arg0) { + const ret = arg0.keyCode; + return ret; + }, + __wbg_key_1f885799907fdc30: function(arg0, arg1) { + const ret = arg1.key; + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_key_7cfa20193d517a74: function(arg0, arg1) { + const ret = arg1.key; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_label_9a8583e3a20fafc7: function(arg0, arg1) { + const ret = arg1.label; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_lastModified_f3daedc0b92f6ee2: function(arg0) { + const ret = arg0.lastModified; + return ret; + }, + __wbg_left_542bbb36968c6d4e: function(arg0) { + const ret = arg0.left; + return ret; + }, + __wbg_length_06fc61606800dfdc: function(arg0) { + const ret = arg0.length; + return ret; + }, + __wbg_length_0c32cb8543c8e4c8: function(arg0) { + const ret = arg0.length; + return ret; + }, + __wbg_length_2463cf44caac7a20: function(arg0) { + const ret = arg0.length; + return ret; + }, + __wbg_length_6e821edde497a532: function(arg0) { + const ret = arg0.length; + return ret; + }, + __wbg_length_c68a80a6327e9194: function(arg0) { + const ret = arg0.length; + return ret; + }, + __wbg_limits_25f7265ea0cad6c5: function(arg0) { + const ret = arg0.limits; + return ret; + }, + __wbg_limits_b3a1d99e863846d4: function(arg0) { + const ret = arg0.limits; + return ret; + }, + __wbg_linkProgram_4a3a45fa4d8d09f0: function(arg0, arg1) { + arg0.linkProgram(arg1); + }, + __wbg_linkProgram_d86c69f8f86f3031: function(arg0, arg1) { + arg0.linkProgram(arg1); + }, + __wbg_localStorage_b1a71e6b7afdce21: function() { return handleError(function (arg0) { + const ret = arg0.localStorage; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, arguments); }, + __wbg_location_91b3fdbca3c76d9e: function(arg0) { + const ret = arg0.location; + return ret; + }, + __wbg_mapAsync_e3cfbd141919d03c: function(arg0, arg1, arg2, arg3) { + const ret = arg0.mapAsync(arg1 >>> 0, arg2, arg3); + return ret; + }, + __wbg_matchMedia_1d8b96312cffb576: function() { return handleError(function (arg0, arg1, arg2) { + const ret = arg0.matchMedia(getStringFromWasm0(arg1, arg2)); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, arguments); }, + __wbg_matches_86946499f934a7fd: function(arg0) { + const ret = arg0.matches; + return ret; + }, + __wbg_maxBindGroups_7e4965b5daa53b23: function(arg0) { + const ret = arg0.maxBindGroups; + return ret; + }, + __wbg_maxBindingsPerBindGroup_5d11588150650215: function(arg0) { + const ret = arg0.maxBindingsPerBindGroup; + return ret; + }, + __wbg_maxBufferSize_b59f147488bf047a: function(arg0) { + const ret = arg0.maxBufferSize; + return ret; + }, + __wbg_maxColorAttachmentBytesPerSample_726ea37aedfb839a: function(arg0) { + const ret = arg0.maxColorAttachmentBytesPerSample; + return ret; + }, + __wbg_maxColorAttachments_62ecca7ef94d78e4: function(arg0) { + const ret = arg0.maxColorAttachments; + return ret; + }, + __wbg_maxComputeInvocationsPerWorkgroup_a14458d75e0b90ac: function(arg0) { + const ret = arg0.maxComputeInvocationsPerWorkgroup; + return ret; + }, + __wbg_maxComputeWorkgroupSizeX_6b8c17d5e4738e77: function(arg0) { + const ret = arg0.maxComputeWorkgroupSizeX; + return ret; + }, + __wbg_maxComputeWorkgroupSizeY_13b5de41c6e0bc2a: function(arg0) { + const ret = arg0.maxComputeWorkgroupSizeY; + return ret; + }, + __wbg_maxComputeWorkgroupSizeZ_b12d7f3e670aa0a2: function(arg0) { + const ret = arg0.maxComputeWorkgroupSizeZ; + return ret; + }, + __wbg_maxComputeWorkgroupStorageSize_886498bc3b0baa23: function(arg0) { + const ret = arg0.maxComputeWorkgroupStorageSize; + return ret; + }, + __wbg_maxComputeWorkgroupsPerDimension_144b6bbf6ac24451: function(arg0) { + const ret = arg0.maxComputeWorkgroupsPerDimension; + return ret; + }, + __wbg_maxDynamicStorageBuffersPerPipelineLayout_d81239ef90f4f920: function(arg0) { + const ret = arg0.maxDynamicStorageBuffersPerPipelineLayout; + return ret; + }, + __wbg_maxDynamicUniformBuffersPerPipelineLayout_0cca7d1cb9e5adf7: function(arg0) { + const ret = arg0.maxDynamicUniformBuffersPerPipelineLayout; + return ret; + }, + __wbg_maxInterStageShaderVariables_4504147f810dd43d: function(arg0) { + const ret = arg0.maxInterStageShaderVariables; + return ret; + }, + __wbg_maxSampledTexturesPerShaderStage_54e5ed0537676c83: function(arg0) { + const ret = arg0.maxSampledTexturesPerShaderStage; + return ret; + }, + __wbg_maxSamplersPerShaderStage_71315fab0d7f34b1: function(arg0) { + const ret = arg0.maxSamplersPerShaderStage; + return ret; + }, + __wbg_maxStorageBufferBindingSize_779fd522aaaa6f90: function(arg0) { + const ret = arg0.maxStorageBufferBindingSize; + return ret; + }, + __wbg_maxStorageBuffersPerShaderStage_c99b4f72aaf19e34: function(arg0) { + const ret = arg0.maxStorageBuffersPerShaderStage; + return ret; + }, + __wbg_maxStorageTexturesPerShaderStage_5403c17d11da5280: function(arg0) { + const ret = arg0.maxStorageTexturesPerShaderStage; + return ret; + }, + __wbg_maxTextureArrayLayers_eca9fa36b3d46099: function(arg0) { + const ret = arg0.maxTextureArrayLayers; + return ret; + }, + __wbg_maxTextureDimension1D_a7d9d7ecd19aae9b: function(arg0) { + const ret = arg0.maxTextureDimension1D; + return ret; + }, + __wbg_maxTextureDimension2D_c6a3937eb3ab18df: function(arg0) { + const ret = arg0.maxTextureDimension2D; + return ret; + }, + __wbg_maxTextureDimension3D_d941aa547d9e0801: function(arg0) { + const ret = arg0.maxTextureDimension3D; + return ret; + }, + __wbg_maxUniformBufferBindingSize_1e8c92a2094b7ce7: function(arg0) { + const ret = arg0.maxUniformBufferBindingSize; + return ret; + }, + __wbg_maxUniformBuffersPerShaderStage_83cde6650612f178: function(arg0) { + const ret = arg0.maxUniformBuffersPerShaderStage; + return ret; + }, + __wbg_maxVertexAttributes_dd313a3540d56e88: function(arg0) { + const ret = arg0.maxVertexAttributes; + return ret; + }, + __wbg_maxVertexBufferArrayStride_6fd082d9954d1f4a: function(arg0) { + const ret = arg0.maxVertexBufferArrayStride; + return ret; + }, + __wbg_maxVertexBuffers_bbd14712ac158c6f: function(arg0) { + const ret = arg0.maxVertexBuffers; + return ret; + }, + __wbg_message_1c3aafa647009286: function(arg0, arg1) { + const ret = arg1.message; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_metaKey_29a14f6b2fe9783e: function(arg0) { + const ret = arg0.metaKey; + return ret; + }, + __wbg_metaKey_cabf24bec9d42077: function(arg0) { + const ret = arg0.metaKey; + return ret; + }, + __wbg_minStorageBufferOffsetAlignment_726c386298254510: function(arg0) { + const ret = arg0.minStorageBufferOffsetAlignment; + return ret; + }, + __wbg_minUniformBufferOffsetAlignment_6df1f95f5974788e: function(arg0) { + const ret = arg0.minUniformBufferOffsetAlignment; + return ret; + }, + __wbg_name_c20e84db554b626b: function(arg0, arg1) { + const ret = arg1.name; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_navigator_9b09ea705d03d227: function(arg0) { + const ret = arg0.navigator; + return ret; + }, + __wbg_navigator_af52153252bdf29d: function(arg0) { + const ret = arg0.navigator; + return ret; + }, + __wbg_newValue_96509bb33d209ac9: function(arg0, arg1) { + const ret = arg1.newValue; + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_new_0_bfa2ef4bc447daa2: function() { + const ret = new Date(); + return ret; + }, + __wbg_new_0cf97f899a952e9e: function(arg0, arg1) { + const ret = new Intl.DateTimeFormat(arg0, arg1); + return ret; + }, + __wbg_new_0fec9fb02d03a383: function() { return handleError(function (arg0, arg1) { + const ret = new URL(getStringFromWasm0(arg0, arg1)); + return ret; + }, arguments); }, + __wbg_new_23ac95738b27f596: function() { return handleError(function (arg0) { + const ret = new EncodedVideoChunk(arg0); + return ret; + }, arguments); }, + __wbg_new_3a112826a89cb962: function() { return handleError(function () { + const ret = new Headers(); + return ret; + }, arguments); }, + __wbg_new_40792555590ec35c: function(arg0, arg1) { + try { + var state0 = {a: arg0, b: arg1}; + var cb0 = (arg0, arg1) => { + const a = state0.a; + state0.a = 0; + try { + return wasm_bindgen__convert__closures_____invoke__h2db2cddd57d3c13f(a, state0.b, arg0, arg1); + } finally { + state0.a = a; + } + }; + const ret = new Promise(cb0); + return ret; + } finally { + state0.a = 0; + } + }, + __wbg_new_47dfee3855dec446: function(arg0, arg1) { + const ret = new TypeError(getStringFromWasm0(arg0, arg1)); + return ret; + }, + __wbg_new_4f9fafbb3909af72: function() { + const ret = new Object(); + return ret; + }, + __wbg_new_5279b10692d16d29: function() { + const ret = new Error(); + return ret; + }, + __wbg_new_5d1c7a46f16959db: function() { + const ret = new Error(); + return ret; + }, + __wbg_new_6f89ec4f8aab68cc: function() { return handleError(function (arg0) { + const ret = new ResizeObserver(arg0); + return ret; + }, arguments); }, + __wbg_new_71d7eef92e920458: function() { return handleError(function (arg0) { + const ret = new VideoDecoder(arg0); + return ret; + }, arguments); }, + __wbg_new_7681c4155808e30a: function() { return handleError(function () { + const ret = new URLSearchParams(); + return ret; + }, arguments); }, + __wbg_new_9abbf7148481485e: function() { return handleError(function () { + const ret = new AbortController(); + return ret; + }, arguments); }, + __wbg_new_a560378ea1240b14: function(arg0) { + const ret = new Uint8Array(arg0); + return ret; + }, + __wbg_new_a5a447223ac6ad64: function() { return handleError(function () { + const ret = new FileReader(); + return ret; + }, arguments); }, + __wbg_new_e3b04b4d53d1b593: function(arg0, arg1) { + const ret = new Error(getStringFromWasm0(arg0, arg1)); + return ret; + }, + __wbg_new_f3c9df4f38f3f798: function() { + const ret = new Array(); + return ret; + }, + __wbg_new_from_slice_2580ff33d0d10520: function(arg0, arg1) { + const ret = new Uint8Array(getArrayU8FromWasm0(arg0, arg1)); + return ret; + }, + __wbg_new_typed_14d7cc391ce53d2c: function(arg0, arg1) { + try { + var state0 = {a: arg0, b: arg1}; + var cb0 = (arg0, arg1) => { + const a = state0.a; + state0.a = 0; + try { + return wasm_bindgen__convert__closures_____invoke__h2db2cddd57d3c13f(a, state0.b, arg0, arg1); + } finally { + state0.a = a; + } + }; + const ret = new Promise(cb0); + return ret; + } finally { + state0.a = 0; + } + }, + __wbg_new_with_byte_offset_and_length_6bfc75833d6170c8: function(arg0, arg1, arg2) { + const ret = new Uint8Array(arg0, arg1 >>> 0, arg2 >>> 0); + return ret; + }, + __wbg_new_with_image_bitmap_and_video_frame_init_2c62b03bed8b0694: function() { return handleError(function (arg0, arg1) { + const ret = new VideoFrame(arg0, arg1); + return ret; + }, arguments); }, + __wbg_new_with_length_9cedd08484b73942: function(arg0) { + const ret = new Uint8Array(arg0 >>> 0); + return ret; + }, + __wbg_new_with_record_from_str_to_blob_promise_50c718d98edeba27: function() { return handleError(function (arg0) { + const ret = new ClipboardItem(arg0); + return ret; + }, arguments); }, + __wbg_new_with_str_and_init_f663b6d334baa878: function() { return handleError(function (arg0, arg1, arg2) { + const ret = new Request(getStringFromWasm0(arg0, arg1), arg2); + return ret; + }, arguments); }, + __wbg_new_with_u8_array_sequence_and_options_0ea871c78d13a6d8: function() { return handleError(function (arg0, arg1) { + const ret = new Blob(arg0, arg1); + return ret; + }, arguments); }, + __wbg_next_01132ed6134b8ef5: function(arg0) { + const ret = arg0.next; + return ret; + }, + __wbg_next_b3713ec761a9dbfd: function() { return handleError(function (arg0) { + const ret = arg0.next(); + return ret; + }, arguments); }, + __wbg_now_2c44418ca0623664: function(arg0) { + const ret = arg0.now(); + return ret; + }, + __wbg_now_88621c9c9a4f3ffc: function() { + const ret = Date.now(); + return ret; + }, + __wbg_now_e7c6795a7f81e10f: function(arg0) { + const ret = arg0.now(); + return ret; + }, + __wbg_observe_aa0d17c78115be71: function(arg0, arg1, arg2) { + arg0.observe(arg1, arg2); + }, + __wbg_of_cc32e7afcce5ea8e: function(arg0) { + const ret = Array.of(arg0); + return ret; + }, + __wbg_offsetTop_03ccc0dfd690579b: function(arg0) { + const ret = arg0.offsetTop; + return ret; + }, + __wbg_ok_36f7b13b74596c24: function(arg0) { + const ret = arg0.ok; + return ret; + }, + __wbg_onSubmittedWorkDone_5f36409816d68e04: function(arg0) { + const ret = arg0.onSubmittedWorkDone(); + return ret; + }, + __wbg_open_60396cb239d529f9: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6) { + const ret = arg0.open(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4), getStringFromWasm0(arg5, arg6)); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, arguments); }, + __wbg_open_a3e83bb9ce5c4f9d: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + const ret = arg0.open(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, arguments); }, + __wbg_origin_068a8b12f26e8142: function() { return handleError(function (arg0, arg1) { + const ret = arg1.origin; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, arguments); }, + __wbg_performance_3fcf6e32a7e1ed0a: function(arg0) { + const ret = arg0.performance; + return ret; + }, + __wbg_performance_5ed3f6a3bbe36d0d: function(arg0) { + const ret = arg0.performance; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_pixelStorei_3dd51cd2a28442f6: function(arg0, arg1, arg2) { + arg0.pixelStorei(arg1 >>> 0, arg2); + }, + __wbg_pixelStorei_a5f8fc3966b8599d: function(arg0, arg1, arg2) { + arg0.pixelStorei(arg1 >>> 0, arg2); + }, + __wbg_polygonOffset_01073fa7aec4d962: function(arg0, arg1, arg2) { + arg0.polygonOffset(arg1, arg2); + }, + __wbg_polygonOffset_3e546c4ce04eeffd: function(arg0, arg1, arg2) { + arg0.polygonOffset(arg1, arg2); + }, + __wbg_port_97246809d787c307: function() { return handleError(function (arg0, arg1) { + const ret = arg1.port; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, arguments); }, + __wbg_preventDefault_9c72c03ba5e7d9c7: function(arg0) { + arg0.preventDefault(); + }, + __wbg_protocol_45fde0ce406160d8: function() { return handleError(function (arg0, arg1) { + const ret = arg1.protocol; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, arguments); }, + __wbg_prototypesetcall_3e05eb9545565046: function(arg0, arg1, arg2) { + Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), arg2); + }, + __wbg_pushState_a592a77c89a2f9c0: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5) { + arg0.pushState(arg1, getStringFromWasm0(arg2, arg3), arg4 === 0 ? undefined : getStringFromWasm0(arg4, arg5)); + }, arguments); }, + __wbg_push_6bdbc990be5ac37b: function(arg0, arg1) { + const ret = arg0.push(arg1); + return ret; + }, + __wbg_queryCounterEXT_e55dc61601cff79a: function(arg0, arg1, arg2) { + arg0.queryCounterEXT(arg1, arg2 >>> 0); + }, + __wbg_querySelectorAll_301982e9e4864dfa: function() { return handleError(function (arg0, arg1, arg2) { + const ret = arg0.querySelectorAll(getStringFromWasm0(arg1, arg2)); + return ret; + }, arguments); }, + __wbg_querySelector_744b8dc8f2dd6e5d: function() { return handleError(function (arg0, arg1, arg2) { + const ret = arg0.querySelector(getStringFromWasm0(arg1, arg2)); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, arguments); }, + __wbg_queueMicrotask_abaf92f0bd4e80a4: function(arg0) { + const ret = arg0.queueMicrotask; + return ret; + }, + __wbg_queueMicrotask_df5a6dac26d818f3: function(arg0) { + queueMicrotask(arg0); + }, + __wbg_queue_7bbf92178b06da19: function(arg0) { + const ret = arg0.queue; + return ret; + }, + __wbg_readAsArrayBuffer_981694de4b45e06b: function() { return handleError(function (arg0, arg1) { + arg0.readAsArrayBuffer(arg1); + }, arguments); }, + __wbg_readBuffer_a41d499ded234bd2: function(arg0, arg1) { + arg0.readBuffer(arg1 >>> 0); + }, + __wbg_readPixels_6effecfcb3dc1144: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { + arg0.readPixels(arg1, arg2, arg3, arg4, arg5 >>> 0, arg6 >>> 0, arg7); + }, arguments); }, + __wbg_readPixels_9b75a1927b6caa46: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { + arg0.readPixels(arg1, arg2, arg3, arg4, arg5 >>> 0, arg6 >>> 0, arg7); + }, arguments); }, + __wbg_readPixels_e434d71b868f30c5: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { + arg0.readPixels(arg1, arg2, arg3, arg4, arg5 >>> 0, arg6 >>> 0, arg7); + }, arguments); }, + __wbg_read_316bf844c93a6ccc: function(arg0) { + const ret = arg0.read(); + return ret; + }, + __wbg_releaseLock_b12f7593852f4c01: function(arg0) { + arg0.releaseLock(); + }, + __wbg_removeChild_874b23fe5a1ca1bb: function() { return handleError(function (arg0, arg1) { + const ret = arg0.removeChild(arg1); + return ret; + }, arguments); }, + __wbg_removeEventListener_e5033ab3bcad443c: function() { return handleError(function (arg0, arg1, arg2, arg3) { + arg0.removeEventListener(getStringFromWasm0(arg1, arg2), arg3); + }, arguments); }, + __wbg_removeItem_edd5e09fd7345519: function() { return handleError(function (arg0, arg1, arg2) { + arg0.removeItem(getStringFromWasm0(arg1, arg2)); + }, arguments); }, + __wbg_remove_b0ab1a7ea21cda2e: function(arg0) { + arg0.remove(); + }, + __wbg_renderbufferStorageMultisample_c07bc844d86d2200: function(arg0, arg1, arg2, arg3, arg4, arg5) { + arg0.renderbufferStorageMultisample(arg1 >>> 0, arg2, arg3 >>> 0, arg4, arg5); + }, + __wbg_renderbufferStorage_c208bd803fa3de68: function(arg0, arg1, arg2, arg3, arg4) { + arg0.renderbufferStorage(arg1 >>> 0, arg2 >>> 0, arg3, arg4); + }, + __wbg_renderbufferStorage_d95f75be57ae52b3: function(arg0, arg1, arg2, arg3, arg4) { + arg0.renderbufferStorage(arg1 >>> 0, arg2 >>> 0, arg3, arg4); + }, + __wbg_replaceState_b24491ac1a491629: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5) { + arg0.replaceState(arg1, getStringFromWasm0(arg2, arg3), arg4 === 0 ? undefined : getStringFromWasm0(arg4, arg5)); + }, arguments); }, + __wbg_requestAdapter_0049683abd339828: function(arg0, arg1) { + const ret = arg0.requestAdapter(arg1); + return ret; + }, + __wbg_requestAdapter_67400a4450a20436: function(arg0) { + const ret = arg0.requestAdapter(); + return ret; + }, + __wbg_requestAnimationFrame_e1628778767f2bf2: function() { return handleError(function (arg0, arg1) { + const ret = arg0.requestAnimationFrame(arg1); + return ret; + }, arguments); }, + __wbg_requestDevice_921f0a221b4492fa: function(arg0, arg1) { + const ret = arg0.requestDevice(arg1); + return ret; + }, + __wbg_reset_524d0a393037e3c5: function() { return handleError(function (arg0) { + arg0.reset(); + }, arguments); }, + __wbg_resolve_0a79de24e9d2267b: function(arg0) { + const ret = Promise.resolve(arg0); + return ret; + }, + __wbg_resolvedOptions_727aa0594a9b7d7a: function(arg0) { + const ret = arg0.resolvedOptions(); + return ret; + }, + __wbg_respond_87b5b47cbc9ee0b7: function() { return handleError(function (arg0, arg1) { + arg0.respond(arg1 >>> 0); + }, arguments); }, + __wbg_result_69b9c700f4d4f22f: function() { return handleError(function (arg0) { + const ret = arg0.result; + return ret; + }, arguments); }, + __wbg_right_7bb2640e243f1b81: function(arg0) { + const ret = arg0.right; + return ret; + }, + __wbg_samplerParameterf_453bd43b9e1b72f6: function(arg0, arg1, arg2, arg3) { + arg0.samplerParameterf(arg1, arg2 >>> 0, arg3); + }, + __wbg_samplerParameteri_e5395f9bf8379074: function(arg0, arg1, arg2, arg3) { + arg0.samplerParameteri(arg1, arg2 >>> 0, arg3); + }, + __wbg_scissor_2ab796946944a395: function(arg0, arg1, arg2, arg3, arg4) { + arg0.scissor(arg1, arg2, arg3, arg4); + }, + __wbg_scissor_6a7028a46e34c58f: function(arg0, arg1, arg2, arg3, arg4) { + arg0.scissor(arg1, arg2, arg3, arg4); + }, + __wbg_searchParams_601e53e1332b7ee8: function(arg0) { + const ret = arg0.searchParams; + return ret; + }, + __wbg_search_4e5c22f751154ad5: function() { return handleError(function (arg0, arg1) { + const ret = arg1.search; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, arguments); }, + __wbg_selectionEnd_6dfcdf4e62a8bbcd: function() { return handleError(function (arg0) { + const ret = arg0.selectionEnd; + return isLikeNone(ret) ? 0x100000001 : (ret) >>> 0; + }, arguments); }, + __wbg_selectionStart_5b16e02595e73f0d: function() { return handleError(function (arg0) { + const ret = arg0.selectionStart; + return isLikeNone(ret) ? 0x100000001 : (ret) >>> 0; + }, arguments); }, + __wbg_setAttribute_5799fb5befe29601: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + arg0.setAttribute(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments); }, + __wbg_setBindGroup_851043cf286f55f2: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6) { + arg0.setBindGroup(arg1 >>> 0, arg2, getArrayU32FromWasm0(arg3, arg4), arg5, arg6 >>> 0); + }, arguments); }, + __wbg_setBindGroup_b546d112a2d27da3: function(arg0, arg1, arg2) { + arg0.setBindGroup(arg1 >>> 0, arg2); + }, + __wbg_setIndexBuffer_994771910f4a92bf: function(arg0, arg1, arg2, arg3) { + arg0.setIndexBuffer(arg1, __wbindgen_enum_GpuIndexFormat[arg2], arg3); + }, + __wbg_setIndexBuffer_f0aa83f423c3ea49: function(arg0, arg1, arg2, arg3, arg4) { + arg0.setIndexBuffer(arg1, __wbindgen_enum_GpuIndexFormat[arg2], arg3, arg4); + }, + __wbg_setItem_67573afec8996fe4: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + arg0.setItem(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments); }, + __wbg_setPipeline_b0ecc74bdf8be629: function(arg0, arg1) { + arg0.setPipeline(arg1); + }, + __wbg_setProperty_872b034b6bcc67cd: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + arg0.setProperty(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments); }, + __wbg_setScissorRect_a1545e0e0ae58d7e: function(arg0, arg1, arg2, arg3, arg4) { + arg0.setScissorRect(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, arg4 >>> 0); + }, + __wbg_setTimeout_53fc0e252a92dca8: function(arg0, arg1) { + const ret = setTimeout(arg0, arg1); + return ret; + }, + __wbg_setTimeout_553bc247bec3e16e: function() { return handleError(function (arg0, arg1, arg2) { + const ret = arg0.setTimeout(arg1, arg2); + return ret; + }, arguments); }, + __wbg_setTimeout_91734b3436ad0e03: function(arg0, arg1) { + const ret = setTimeout(arg0, arg1); + return ret; + }, + __wbg_setVertexBuffer_1d85cc2da6e137a7: function(arg0, arg1, arg2, arg3, arg4) { + arg0.setVertexBuffer(arg1 >>> 0, arg2, arg3, arg4); + }, + __wbg_setVertexBuffer_7f434cea2ca9b640: function(arg0, arg1, arg2, arg3) { + arg0.setVertexBuffer(arg1 >>> 0, arg2, arg3); + }, + __wbg_setViewport_1963e6530328b01d: function(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { + arg0.setViewport(arg1, arg2, arg3, arg4, arg5, arg6); + }, + __wbg_set_16a9c1a07b3d38ec: function(arg0, arg1, arg2) { + arg0.set(getArrayU8FromWasm0(arg1, arg2)); + }, + __wbg_set_48cee61639a176a9: function(arg0, arg1, arg2, arg3, arg4) { + arg0.set(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, + __wbg_set_62f340d5d135b4db: function(arg0, arg1, arg2) { + arg0.set(arg1, arg2 >>> 0); + }, + __wbg_set_6be42768c690e380: function(arg0, arg1, arg2) { + arg0[arg1] = arg2; + }, + __wbg_set_8ee2d34facb8466e: function() { return handleError(function (arg0, arg1, arg2) { + const ret = Reflect.set(arg0, arg1, arg2); + return ret; + }, arguments); }, + __wbg_set_a_66601ffa2f4cbde8: function(arg0, arg1) { + arg0.a = arg1; + }, + __wbg_set_aa391f3af1ff0e9c: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + arg0.set(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments); }, + __wbg_set_accept_59891065e5b3f283: function(arg0, arg1, arg2) { + arg0.accept = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_access_08d6bdbda9aaa266: function(arg0, arg1) { + arg0.access = __wbindgen_enum_GpuStorageTextureAccess[arg1]; + }, + __wbg_set_address_mode_u_f80c73fc36e83289: function(arg0, arg1) { + arg0.addressModeU = __wbindgen_enum_GpuAddressMode[arg1]; + }, + __wbg_set_address_mode_v_3dee7a0095c326a6: function(arg0, arg1) { + arg0.addressModeV = __wbindgen_enum_GpuAddressMode[arg1]; + }, + __wbg_set_address_mode_w_e2be52f6efa2d9c7: function(arg0, arg1) { + arg0.addressModeW = __wbindgen_enum_GpuAddressMode[arg1]; + }, + __wbg_set_alpha_bb6680aaf01cdc62: function(arg0, arg1) { + arg0.alpha = arg1; + }, + __wbg_set_alpha_mode_84140629c3b15c51: function(arg0, arg1) { + arg0.alphaMode = __wbindgen_enum_GpuCanvasAlphaMode[arg1]; + }, + __wbg_set_alpha_to_coverage_enabled_cac9212446be9cab: function(arg0, arg1) { + arg0.alphaToCoverageEnabled = arg1 !== 0; + }, + __wbg_set_array_layer_count_01e36293bee85e02: function(arg0, arg1) { + arg0.arrayLayerCount = arg1 >>> 0; + }, + __wbg_set_array_stride_34f4a147a16bff79: function(arg0, arg1) { + arg0.arrayStride = arg1; + }, + __wbg_set_aspect_0675b2844dd12eb1: function(arg0, arg1) { + arg0.aspect = __wbindgen_enum_GpuTextureAspect[arg1]; + }, + __wbg_set_aspect_7829cca737701915: function(arg0, arg1) { + arg0.aspect = __wbindgen_enum_GpuTextureAspect[arg1]; + }, + __wbg_set_aspect_e09cb246c2df6f46: function(arg0, arg1) { + arg0.aspect = __wbindgen_enum_GpuTextureAspect[arg1]; + }, + __wbg_set_attributes_7ee8e82215809bfa: function(arg0, arg1) { + arg0.attributes = arg1; + }, + __wbg_set_autofocus_76fe163909c5a3cf: function() { return handleError(function (arg0, arg1) { + arg0.autofocus = arg1 !== 0; + }, arguments); }, + __wbg_set_b_103abfb3e69345a3: function(arg0, arg1) { + arg0.b = arg1; + }, + __wbg_set_base_array_layer_ff3450be9aa7d232: function(arg0, arg1) { + arg0.baseArrayLayer = arg1 >>> 0; + }, + __wbg_set_base_mip_level_43e77e5d237ede24: function(arg0, arg1) { + arg0.baseMipLevel = arg1 >>> 0; + }, + __wbg_set_beginning_of_pass_write_index_abea1e4e6c6095e1: function(arg0, arg1) { + arg0.beginningOfPassWriteIndex = arg1 >>> 0; + }, + __wbg_set_bind_group_layouts_078241cf2822c39e: function(arg0, arg1) { + arg0.bindGroupLayouts = arg1; + }, + __wbg_set_binding_d683cd9c1d4bcfed: function(arg0, arg1) { + arg0.binding = arg1 >>> 0; + }, + __wbg_set_binding_e9ba14423117de0a: function(arg0, arg1) { + arg0.binding = arg1 >>> 0; + }, + __wbg_set_blend_9eab91d6edf500f9: function(arg0, arg1) { + arg0.blend = arg1; + }, + __wbg_set_body_a304d09cb50cefbe: function(arg0, arg1) { + arg0.body = arg1; + }, + __wbg_set_box_b3facca2aa9c2ac2: function(arg0, arg1) { + arg0.box = __wbindgen_enum_ResizeObserverBoxOptions[arg1]; + }, + __wbg_set_buffer_598ab98a251b8f91: function(arg0, arg1) { + arg0.buffer = arg1; + }, + __wbg_set_buffer_73d9f6fea9c41867: function(arg0, arg1) { + arg0.buffer = arg1; + }, + __wbg_set_buffer_88dfc353992be57b: function(arg0, arg1) { + arg0.buffer = arg1; + }, + __wbg_set_buffers_93f3f75d7338864f: function(arg0, arg1) { + arg0.buffers = arg1; + }, + __wbg_set_bytes_per_row_0bdd54b7fc03c765: function(arg0, arg1) { + arg0.bytesPerRow = arg1 >>> 0; + }, + __wbg_set_bytes_per_row_4d62ead4cbf1cd75: function(arg0, arg1) { + arg0.bytesPerRow = arg1 >>> 0; + }, + __wbg_set_cache_cc687e2b96e9608c: function(arg0, arg1) { + arg0.cache = __wbindgen_enum_RequestCache[arg1]; + }, + __wbg_set_className_7ff38385280f6997: function(arg0, arg1, arg2) { + arg0.className = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_clear_value_c1a82bbe9a80b6ab: function(arg0, arg1) { + arg0.clearValue = arg1; + }, + __wbg_set_code_6a0d763da082dcfb: function(arg0, arg1, arg2) { + arg0.code = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_codec_300afcafcaa8aab8: function(arg0, arg1, arg2) { + arg0.codec = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_coded_height_e6a1bfe7492df11f: function(arg0, arg1) { + arg0.codedHeight = arg1 >>> 0; + }, + __wbg_set_coded_width_67bd47a375e150b1: function(arg0, arg1) { + arg0.codedWidth = arg1 >>> 0; + }, + __wbg_set_color_495aa415ae5a39c9: function(arg0, arg1) { + arg0.color = arg1; + }, + __wbg_set_color_attachments_6705c6b1e98a3040: function(arg0, arg1) { + arg0.colorAttachments = arg1; + }, + __wbg_set_compare_8aedfdbdc96ff4d7: function(arg0, arg1) { + arg0.compare = __wbindgen_enum_GpuCompareFunction[arg1]; + }, + __wbg_set_compare_a9a06469832600ec: function(arg0, arg1) { + arg0.compare = __wbindgen_enum_GpuCompareFunction[arg1]; + }, + __wbg_set_count_34ecf81b3ad7e448: function(arg0, arg1) { + arg0.count = arg1 >>> 0; + }, + __wbg_set_credentials_7693e63055f5e838: function(arg0, arg1) { + arg0.credentials = __wbindgen_enum_RequestCredentials[arg1]; + }, + __wbg_set_cull_mode_8e533f32672a379b: function(arg0, arg1) { + arg0.cullMode = __wbindgen_enum_GpuCullMode[arg1]; + }, + __wbg_set_data_9f92fc0aedb081b6: function(arg0, arg1) { + arg0.data = arg1; + }, + __wbg_set_depth_bias_07f95aa380a3e46e: function(arg0, arg1) { + arg0.depthBias = arg1; + }, + __wbg_set_depth_bias_clamp_968b03f74984c77b: function(arg0, arg1) { + arg0.depthBiasClamp = arg1; + }, + __wbg_set_depth_bias_slope_scale_478b204b4910400f: function(arg0, arg1) { + arg0.depthBiasSlopeScale = arg1; + }, + __wbg_set_depth_clear_value_25268aa6b7cae2e0: function(arg0, arg1) { + arg0.depthClearValue = arg1; + }, + __wbg_set_depth_compare_c017fcac5327dfbb: function(arg0, arg1) { + arg0.depthCompare = __wbindgen_enum_GpuCompareFunction[arg1]; + }, + __wbg_set_depth_fail_op_8484012cd5e4987c: function(arg0, arg1) { + arg0.depthFailOp = __wbindgen_enum_GpuStencilOperation[arg1]; + }, + __wbg_set_depth_load_op_ed90e4eaf314a16c: function(arg0, arg1) { + arg0.depthLoadOp = __wbindgen_enum_GpuLoadOp[arg1]; + }, + __wbg_set_depth_or_array_layers_f8981011496f12e7: function(arg0, arg1) { + arg0.depthOrArrayLayers = arg1 >>> 0; + }, + __wbg_set_depth_read_only_90cca09674f446be: function(arg0, arg1) { + arg0.depthReadOnly = arg1 !== 0; + }, + __wbg_set_depth_stencil_attachment_be8301fa499cd3db: function(arg0, arg1) { + arg0.depthStencilAttachment = arg1; + }, + __wbg_set_depth_stencil_d536398c1b29bb38: function(arg0, arg1) { + arg0.depthStencil = arg1; + }, + __wbg_set_depth_store_op_8e9b1d0e47077643: function(arg0, arg1) { + arg0.depthStoreOp = __wbindgen_enum_GpuStoreOp[arg1]; + }, + __wbg_set_depth_write_enabled_adc2094871d66639: function(arg0, arg1) { + arg0.depthWriteEnabled = arg1 !== 0; + }, + __wbg_set_description_393bafea84dc5561: function(arg0, arg1) { + arg0.description = arg1; + }, + __wbg_set_device_47147a331245777f: function(arg0, arg1) { + arg0.device = arg1; + }, + __wbg_set_dimension_b4da3979dc699ef8: function(arg0, arg1) { + arg0.dimension = __wbindgen_enum_GpuTextureViewDimension[arg1]; + }, + __wbg_set_dimension_d4f0c50e75083b7f: function(arg0, arg1) { + arg0.dimension = __wbindgen_enum_GpuTextureDimension[arg1]; + }, + __wbg_set_download_6fb6f1e8e782dd11: function(arg0, arg1, arg2) { + arg0.download = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_dst_factor_e44fc612d5e5bff4: function(arg0, arg1) { + arg0.dstFactor = __wbindgen_enum_GpuBlendFactor[arg1]; + }, + __wbg_set_duration_f64_acecfffcfce95ce5: function(arg0, arg1) { + arg0.duration = arg1; + }, + __wbg_set_end_of_pass_write_index_1cd39b9bafe090cc: function(arg0, arg1) { + arg0.endOfPassWriteIndex = arg1 >>> 0; + }, + __wbg_set_entries_070b048e4bea0c29: function(arg0, arg1) { + arg0.entries = arg1; + }, + __wbg_set_entries_f9b7f3d4e9faccf4: function(arg0, arg1) { + arg0.entries = arg1; + }, + __wbg_set_entry_point_0116a9f5d58cf0aa: function(arg0, arg1, arg2) { + arg0.entryPoint = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_entry_point_f04e91eced449196: function(arg0, arg1, arg2) { + arg0.entryPoint = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_error_f8cd539d5ba58a63: function(arg0, arg1) { + arg0.error = arg1; + }, + __wbg_set_external_texture_cf122b1392d58f37: function(arg0, arg1) { + arg0.externalTexture = arg1; + }, + __wbg_set_fail_op_e7eb17ed0228b457: function(arg0, arg1) { + arg0.failOp = __wbindgen_enum_GpuStencilOperation[arg1]; + }, + __wbg_set_flip_y_c75446cb371a71ee: function(arg0, arg1) { + arg0.flipY = arg1 !== 0; + }, + __wbg_set_format_119bda0a3d0b3f47: function(arg0, arg1) { + arg0.format = __wbindgen_enum_GpuTextureFormat[arg1]; + }, + __wbg_set_format_27c63de9b0ec1cb3: function(arg0, arg1) { + arg0.format = __wbindgen_enum_GpuTextureFormat[arg1]; + }, + __wbg_set_format_75eb905a003c2f61: function(arg0, arg1) { + arg0.format = __wbindgen_enum_GpuTextureFormat[arg1]; + }, + __wbg_set_format_8b8359f261ea64b9: function(arg0, arg1) { + arg0.format = __wbindgen_enum_GpuVertexFormat[arg1]; + }, + __wbg_set_format_a5d373801c562623: function(arg0, arg1) { + arg0.format = __wbindgen_enum_GpuTextureFormat[arg1]; + }, + __wbg_set_format_b08d87d5f33bcd89: function(arg0, arg1) { + arg0.format = __wbindgen_enum_GpuTextureFormat[arg1]; + }, + __wbg_set_format_c1a342a37ced3e12: function(arg0, arg1) { + arg0.format = __wbindgen_enum_GpuTextureFormat[arg1]; + }, + __wbg_set_fragment_41044c9110c69c90: function(arg0, arg1) { + arg0.fragment = arg1; + }, + __wbg_set_front_face_9c9f0518a3109d98: function(arg0, arg1) { + arg0.frontFace = __wbindgen_enum_GpuFrontFace[arg1]; + }, + __wbg_set_g_a39877021b450e75: function(arg0, arg1) { + arg0.g = arg1; + }, + __wbg_set_hardware_acceleration_08a7ff6130a1434c: function(arg0, arg1) { + arg0.hardwareAcceleration = __wbindgen_enum_HardwareAcceleration[arg1]; + }, + __wbg_set_has_dynamic_offset_69725fed837748fe: function(arg0, arg1) { + arg0.hasDynamicOffset = arg1 !== 0; + }, + __wbg_set_headers_6ab1105e542834e2: function(arg0, arg1) { + arg0.headers = arg1; + }, + __wbg_set_height_26ab95ff99e2b620: function(arg0, arg1) { + arg0.height = arg1 >>> 0; + }, + __wbg_set_height_7d0bbaf691aeef8f: function(arg0, arg1) { + arg0.height = arg1 >>> 0; + }, + __wbg_set_height_975770494a218d52: function(arg0, arg1) { + arg0.height = arg1 >>> 0; + }, + __wbg_set_href_72e78ccb3b2c5988: function(arg0, arg1, arg2) { + arg0.href = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_id_b1cffd0a170935f4: function(arg0, arg1, arg2) { + arg0.id = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_innerHTML_7e29b346becaeb8b: function(arg0, arg1, arg2) { + arg0.innerHTML = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_innerText_20f0b35c707c016a: function(arg0, arg1, arg2) { + arg0.innerText = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_integrity_0dcf8feff0f7e4d3: function(arg0, arg1, arg2) { + arg0.integrity = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_label_26577513096f145b: function(arg0, arg1, arg2) { + arg0.label = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_label_2816ddca7866dcfa: function(arg0, arg1, arg2) { + arg0.label = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_label_2a41a6f671383447: function(arg0, arg1, arg2) { + arg0.label = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_label_325c5e4b70c1568f: function(arg0, arg1, arg2) { + arg0.label = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_label_37d0faa0c9b7dee4: function(arg0, arg1, arg2) { + arg0.label = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_label_3e306b2e8f9db666: function(arg0, arg1, arg2) { + arg0.label = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_label_5514e44725004e89: function(arg0, arg1, arg2) { + arg0.label = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_label_570d3dee0e80279e: function(arg0, arg1, arg2) { + arg0.label = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_label_58fbc9fcc6363f16: function(arg0, arg1, arg2) { + arg0.label = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_label_5c952448f9d59f36: function(arg0, arg1, arg2) { + arg0.label = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_label_782e33de78d86641: function(arg0, arg1, arg2) { + arg0.label = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_label_837a3b8ff99c2db3: function(arg0, arg1, arg2) { + arg0.label = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_label_8df6673e1e141fcc: function(arg0, arg1, arg2) { + arg0.label = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_layout_a6ee8e74696bc0c8: function(arg0, arg1) { + arg0.layout = arg1; + }, + __wbg_set_layout_d701bf37a1e489c6: function(arg0, arg1) { + arg0.layout = arg1; + }, + __wbg_set_load_op_e8ff3e1c81f7398d: function(arg0, arg1) { + arg0.loadOp = __wbindgen_enum_GpuLoadOp[arg1]; + }, + __wbg_set_lod_max_clamp_a9f93b2e2ae9023d: function(arg0, arg1) { + arg0.lodMaxClamp = arg1; + }, + __wbg_set_lod_min_clamp_342b47161f1fa002: function(arg0, arg1) { + arg0.lodMinClamp = arg1; + }, + __wbg_set_mag_filter_28e863ff1a386f86: function(arg0, arg1) { + arg0.magFilter = __wbindgen_enum_GpuFilterMode[arg1]; + }, + __wbg_set_mapped_at_creation_7f0aad21612f3e22: function(arg0, arg1) { + arg0.mappedAtCreation = arg1 !== 0; + }, + __wbg_set_mask_a18cbdfc03a4cbd9: function(arg0, arg1) { + arg0.mask = arg1 >>> 0; + }, + __wbg_set_max_anisotropy_19e574a7e9cb009a: function(arg0, arg1) { + arg0.maxAnisotropy = arg1; + }, + __wbg_set_method_1971272fe557e972: function(arg0, arg1, arg2) { + arg0.method = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_min_binding_size_d70e460d165d9144: function(arg0, arg1) { + arg0.minBindingSize = arg1; + }, + __wbg_set_min_filter_5275c8a3815f9f0c: function(arg0, arg1) { + arg0.minFilter = __wbindgen_enum_GpuFilterMode[arg1]; + }, + __wbg_set_mip_level_09f903ba22486513: function(arg0, arg1) { + arg0.mipLevel = arg1 >>> 0; + }, + __wbg_set_mip_level_8d4dfc5d506cb37f: function(arg0, arg1) { + arg0.mipLevel = arg1 >>> 0; + }, + __wbg_set_mip_level_count_04af0d33c4905fac: function(arg0, arg1) { + arg0.mipLevelCount = arg1 >>> 0; + }, + __wbg_set_mip_level_count_dcb2ad32716506a5: function(arg0, arg1) { + arg0.mipLevelCount = arg1 >>> 0; + }, + __wbg_set_mipmap_filter_ae5e0e814693019b: function(arg0, arg1) { + arg0.mipmapFilter = __wbindgen_enum_GpuMipmapFilterMode[arg1]; + }, + __wbg_set_mode_d1b643087602281a: function(arg0, arg1) { + arg0.mode = __wbindgen_enum_RequestMode[arg1]; + }, + __wbg_set_module_0933874708065f3b: function(arg0, arg1) { + arg0.module = arg1; + }, + __wbg_set_module_a7a131494850e5f7: function(arg0, arg1) { + arg0.module = arg1; + }, + __wbg_set_multiple_390ca167c25b3a68: function(arg0, arg1) { + arg0.multiple = arg1 !== 0; + }, + __wbg_set_multisample_e857cbfca335c7f1: function(arg0, arg1) { + arg0.multisample = arg1; + }, + __wbg_set_multisampled_4ce4c32144215354: function(arg0, arg1) { + arg0.multisampled = arg1 !== 0; + }, + __wbg_set_offset_0e56098d94f81ccd: function(arg0, arg1) { + arg0.offset = arg1; + }, + __wbg_set_offset_baf6780761c43b24: function(arg0, arg1) { + arg0.offset = arg1; + }, + __wbg_set_offset_e316586bb85f0bd6: function(arg0, arg1) { + arg0.offset = arg1; + }, + __wbg_set_offset_eabaf12fe1c98ce7: function(arg0, arg1) { + arg0.offset = arg1; + }, + __wbg_set_once_21b4f52a7651545b: function(arg0, arg1) { + arg0.once = arg1 !== 0; + }, + __wbg_set_onclick_60f72f3e80d65322: function(arg0, arg1) { + arg0.onclick = arg1; + }, + __wbg_set_onload_130e9637450f8179: function(arg0, arg1) { + arg0.onload = arg1; + }, + __wbg_set_onuncapturederror_6632a118e96fdf4e: function(arg0, arg1) { + arg0.onuncapturederror = arg1; + }, + __wbg_set_operation_a91e5763a8313c6b: function(arg0, arg1) { + arg0.operation = __wbindgen_enum_GpuBlendOperation[arg1]; + }, + __wbg_set_optimize_for_latency_fdf609396e4819e3: function(arg0, arg1) { + arg0.optimizeForLatency = arg1 !== 0; + }, + __wbg_set_origin_24a61b4427e330e9: function(arg0, arg1) { + arg0.origin = arg1; + }, + __wbg_set_origin_9726209f22511ffa: function(arg0, arg1) { + arg0.origin = arg1; + }, + __wbg_set_origin_f7cd05478d9232f0: function(arg0, arg1) { + arg0.origin = arg1; + }, + __wbg_set_output_30bc75bf2a5d1416: function(arg0, arg1) { + arg0.output = arg1; + }, + __wbg_set_pass_op_eef0c5885ae707c3: function(arg0, arg1) { + arg0.passOp = __wbindgen_enum_GpuStencilOperation[arg1]; + }, + __wbg_set_power_preference_7d669fb9b41f7bf2: function(arg0, arg1) { + arg0.powerPreference = __wbindgen_enum_GpuPowerPreference[arg1]; + }, + __wbg_set_premultiplied_alpha_e49848a873888b3d: function(arg0, arg1) { + arg0.premultipliedAlpha = arg1 !== 0; + }, + __wbg_set_primitive_3462e090c7a78969: function(arg0, arg1) { + arg0.primitive = arg1; + }, + __wbg_set_query_set_62d86bdf10d64d37: function(arg0, arg1) { + arg0.querySet = arg1; + }, + __wbg_set_r_40fe44b2d9a401f4: function(arg0, arg1) { + arg0.r = arg1; + }, + __wbg_set_redirect_1d6df2c80bf90934: function(arg0, arg1) { + arg0.redirect = __wbindgen_enum_RequestRedirect[arg1]; + }, + __wbg_set_referrer_c0d0ce1b4c972d99: function(arg0, arg1, arg2) { + arg0.referrer = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_referrer_policy_48f3f15e75682149: function(arg0, arg1) { + arg0.referrerPolicy = __wbindgen_enum_ReferrerPolicy[arg1]; + }, + __wbg_set_required_features_3d00070d09235d7d: function(arg0, arg1) { + arg0.requiredFeatures = arg1; + }, + __wbg_set_required_limits_e0de55a49a48e3dc: function(arg0, arg1) { + arg0.requiredLimits = arg1; + }, + __wbg_set_resolve_target_6e7eda03a6886624: function(arg0, arg1) { + arg0.resolveTarget = arg1; + }, + __wbg_set_resource_fe1f979fce4afee2: function(arg0, arg1) { + arg0.resource = arg1; + }, + __wbg_set_rows_per_image_1f4a56a3c5d57e93: function(arg0, arg1) { + arg0.rowsPerImage = arg1 >>> 0; + }, + __wbg_set_rows_per_image_c616c70e60a35618: function(arg0, arg1) { + arg0.rowsPerImage = arg1 >>> 0; + }, + __wbg_set_sample_count_2b8ac49e1626ac13: function(arg0, arg1) { + arg0.sampleCount = arg1 >>> 0; + }, + __wbg_set_sample_type_3cecbd4699e2e5fb: function(arg0, arg1) { + arg0.sampleType = __wbindgen_enum_GpuTextureSampleType[arg1]; + }, + __wbg_set_sampler_12544c21977075c1: function(arg0, arg1) { + arg0.sampler = arg1; + }, + __wbg_set_shader_location_03356bf6a6da4332: function(arg0, arg1) { + arg0.shaderLocation = arg1 >>> 0; + }, + __wbg_set_signal_8564a226c5c6853c: function(arg0, arg1) { + arg0.signal = arg1; + }, + __wbg_set_size_0c20f73abce8f1ce: function(arg0, arg1) { + arg0.size = arg1; + }, + __wbg_set_size_cf04b4174c30722b: function(arg0, arg1) { + arg0.size = arg1; + }, + __wbg_set_size_f1207de283144c72: function(arg0, arg1) { + arg0.size = arg1; + }, + __wbg_set_source_7eb2b03d1177a7c8: function(arg0, arg1) { + arg0.source = arg1; + }, + __wbg_set_src_factor_c3668d4122497276: function(arg0, arg1) { + arg0.srcFactor = __wbindgen_enum_GpuBlendFactor[arg1]; + }, + __wbg_set_stencil_back_8d01a6c0477059b0: function(arg0, arg1) { + arg0.stencilBack = arg1; + }, + __wbg_set_stencil_clear_value_1f380af0bd0d9255: function(arg0, arg1) { + arg0.stencilClearValue = arg1 >>> 0; + }, + __wbg_set_stencil_front_f881c15b2d170653: function(arg0, arg1) { + arg0.stencilFront = arg1; + }, + __wbg_set_stencil_load_op_5cde31e71a964b58: function(arg0, arg1) { + arg0.stencilLoadOp = __wbindgen_enum_GpuLoadOp[arg1]; + }, + __wbg_set_stencil_read_mask_d79993adcfc418ab: function(arg0, arg1) { + arg0.stencilReadMask = arg1 >>> 0; + }, + __wbg_set_stencil_read_only_ac984029b821315e: function(arg0, arg1) { + arg0.stencilReadOnly = arg1 !== 0; + }, + __wbg_set_stencil_store_op_262e1df7b92404d3: function(arg0, arg1) { + arg0.stencilStoreOp = __wbindgen_enum_GpuStoreOp[arg1]; + }, + __wbg_set_stencil_write_mask_94ec6249877e083e: function(arg0, arg1) { + arg0.stencilWriteMask = arg1 >>> 0; + }, + __wbg_set_step_mode_241a8d5515fa964b: function(arg0, arg1) { + arg0.stepMode = __wbindgen_enum_GpuVertexStepMode[arg1]; + }, + __wbg_set_storage_texture_36be4834c501acab: function(arg0, arg1) { + arg0.storageTexture = arg1; + }, + __wbg_set_store_op_a95e8da4555c6010: function(arg0, arg1) { + arg0.storeOp = __wbindgen_enum_GpuStoreOp[arg1]; + }, + __wbg_set_strip_index_format_62c417aa65a4d277: function(arg0, arg1) { + arg0.stripIndexFormat = __wbindgen_enum_GpuIndexFormat[arg1]; + }, + __wbg_set_tabIndex_21aab214ff7b4d6e: function(arg0, arg1) { + arg0.tabIndex = arg1; + }, + __wbg_set_targets_6664b7e6ec5da9d3: function(arg0, arg1) { + arg0.targets = arg1; + }, + __wbg_set_texture_292332b872bf75e8: function(arg0, arg1) { + arg0.texture = arg1; + }, + __wbg_set_texture_64823aa8aca790b5: function(arg0, arg1) { + arg0.texture = arg1; + }, + __wbg_set_texture_738e6f6215515de3: function(arg0, arg1) { + arg0.texture = arg1; + }, + __wbg_set_timestamp_a6066fff24ba23db: function(arg0, arg1) { + arg0.timestamp = arg1; + }, + __wbg_set_timestamp_b63bdeb54c9f64dc: function(arg0, arg1) { + arg0.timestamp = arg1; + }, + __wbg_set_timestamp_writes_3854a564715b0ac7: function(arg0, arg1) { + arg0.timestampWrites = arg1; + }, + __wbg_set_topology_914716698f5868bb: function(arg0, arg1) { + arg0.topology = __wbindgen_enum_GpuPrimitiveTopology[arg1]; + }, + __wbg_set_type_17a1387b620bc902: function(arg0, arg1) { + arg0.type = __wbindgen_enum_GpuBufferBindingType[arg1]; + }, + __wbg_set_type_1c9054396ddd2edb: function(arg0, arg1, arg2) { + arg0.type = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_type_39703335940e3fc7: function(arg0, arg1) { + arg0.type = __wbindgen_enum_EncodedVideoChunkType[arg1]; + }, + __wbg_set_type_d4edb621ec2051e0: function(arg0, arg1) { + arg0.type = __wbindgen_enum_GpuSamplerBindingType[arg1]; + }, + __wbg_set_type_ef754f25329c9096: function(arg0, arg1, arg2) { + arg0.type = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_unclipped_depth_e23e3091db2ac351: function(arg0, arg1) { + arg0.unclippedDepth = arg1 !== 0; + }, + __wbg_set_usage_41b7d18f3f220e6c: function(arg0, arg1) { + arg0.usage = arg1 >>> 0; + }, + __wbg_set_usage_6ae4d85589906117: function(arg0, arg1) { + arg0.usage = arg1 >>> 0; + }, + __wbg_set_usage_e167dd772123f679: function(arg0, arg1) { + arg0.usage = arg1 >>> 0; + }, + __wbg_set_usage_f084cd416060ceee: function(arg0, arg1) { + arg0.usage = arg1 >>> 0; + }, + __wbg_set_value_1e50ba479347b273: function(arg0, arg1, arg2) { + arg0.value = getStringFromWasm0(arg1, arg2); + }, + __wbg_set_vertex_29812f650590fa45: function(arg0, arg1) { + arg0.vertex = arg1; + }, + __wbg_set_view_32a8132aec6de194: function(arg0, arg1) { + arg0.view = arg1; + }, + __wbg_set_view_506e5beadab34e99: function(arg0, arg1) { + arg0.view = arg1; + }, + __wbg_set_view_dimension_4a840560a13b4860: function(arg0, arg1) { + arg0.viewDimension = __wbindgen_enum_GpuTextureViewDimension[arg1]; + }, + __wbg_set_view_dimension_9ae69db849267b1a: function(arg0, arg1) { + arg0.viewDimension = __wbindgen_enum_GpuTextureViewDimension[arg1]; + }, + __wbg_set_view_formats_4d0b943f593dd219: function(arg0, arg1) { + arg0.viewFormats = arg1; + }, + __wbg_set_view_formats_cba8520bf0d83d62: function(arg0, arg1) { + arg0.viewFormats = arg1; + }, + __wbg_set_visibility_bbbf3d2b70571950: function(arg0, arg1) { + arg0.visibility = arg1 >>> 0; + }, + __wbg_set_width_0f26635b289b3c67: function(arg0, arg1) { + arg0.width = arg1 >>> 0; + }, + __wbg_set_width_1ae13bf0b65e6395: function(arg0, arg1) { + arg0.width = arg1 >>> 0; + }, + __wbg_set_width_81fa781e87b17891: function(arg0, arg1) { + arg0.width = arg1 >>> 0; + }, + __wbg_set_write_mask_949f521dcf3da2b5: function(arg0, arg1) { + arg0.writeMask = arg1 >>> 0; + }, + __wbg_set_x_15a4c893b3366fab: function(arg0, arg1) { + arg0.x = arg1 >>> 0; + }, + __wbg_set_x_7aa02c5d013f6852: function(arg0, arg1) { + arg0.x = arg1 >>> 0; + }, + __wbg_set_y_80ad367d70451024: function(arg0, arg1) { + arg0.y = arg1 >>> 0; + }, + __wbg_set_y_c631920a1c51a694: function(arg0, arg1) { + arg0.y = arg1 >>> 0; + }, + __wbg_set_z_7c526101c55ea2ae: function(arg0, arg1) { + arg0.z = arg1 >>> 0; + }, + __wbg_shaderSource_c235f38ba5b536d3: function(arg0, arg1, arg2, arg3) { + arg0.shaderSource(arg1, getStringFromWasm0(arg2, arg3)); + }, + __wbg_shaderSource_cae157a332281ae7: function(arg0, arg1, arg2, arg3) { + arg0.shaderSource(arg1, getStringFromWasm0(arg2, arg3)); + }, + __wbg_shiftKey_44bc0e4535e829c0: function(arg0) { + const ret = arg0.shiftKey; + return ret; + }, + __wbg_shiftKey_4f414ec7c42beae6: function(arg0) { + const ret = arg0.shiftKey; + return ret; + }, + __wbg_signal_9172c3282bfba2f5: function(arg0) { + const ret = arg0.signal; + return ret; + }, + __wbg_size_0549be120b7831da: function(arg0) { + const ret = arg0.size; + return ret; + }, + __wbg_size_7306c9406e13bf29: function(arg0) { + const ret = arg0.size; + return ret; + }, + __wbg_slice_21f4c5261d1fdd69: function(arg0, arg1) { + const ret = arg1.slice(); + const ptr1 = passArrayJsValueToWasm0(ret, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_stack_20d3a047502dc7bd: function(arg0, arg1) { + const ret = arg1.stack; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_stack_6476d1d46b80665a: function(arg0, arg1) { + const ret = arg1.stack; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_state_1051199353f1f2a2: function(arg0) { + const ret = arg0.state; + return (__wbindgen_enum_CodecState.indexOf(ret) + 1 || 4) - 1; + }, + __wbg_state_6d96f748e0572453: function() { return handleError(function (arg0) { + const ret = arg0.state; + return ret; + }, arguments); }, + __wbg_state_90f081dc1aa61b42: function(arg0) { + const ret = arg0.state; + return ret; + }, + __wbg_static_accessor_GLOBAL_THIS_a1248013d790bf5f: function() { + const ret = typeof globalThis === 'undefined' ? null : globalThis; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_static_accessor_GLOBAL_f2e0f995a21329ff: function() { + const ret = typeof global === 'undefined' ? null : global; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_static_accessor_SELF_24f78b6d23f286ea: function() { + const ret = typeof self === 'undefined' ? null : self; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_static_accessor_WINDOW_59fd959c540fe405: function() { + const ret = typeof window === 'undefined' ? null : window; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_statusText_128c4dad452b4075: function(arg0, arg1) { + const ret = arg1.statusText; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_status_44ecb0ac1da253f4: function(arg0) { + const ret = arg0.status; + return ret; + }, + __wbg_stencilFuncSeparate_4c0db85174d13a30: function(arg0, arg1, arg2, arg3, arg4) { + arg0.stencilFuncSeparate(arg1 >>> 0, arg2 >>> 0, arg3, arg4 >>> 0); + }, + __wbg_stencilFuncSeparate_bc6ee80dc1553732: function(arg0, arg1, arg2, arg3, arg4) { + arg0.stencilFuncSeparate(arg1 >>> 0, arg2 >>> 0, arg3, arg4 >>> 0); + }, + __wbg_stencilMaskSeparate_f50ef76311ff1c52: function(arg0, arg1, arg2) { + arg0.stencilMaskSeparate(arg1 >>> 0, arg2 >>> 0); + }, + __wbg_stencilMaskSeparate_fff5b95ab033d285: function(arg0, arg1, arg2) { + arg0.stencilMaskSeparate(arg1 >>> 0, arg2 >>> 0); + }, + __wbg_stencilMask_6d5efd2cf61c3bd8: function(arg0, arg1) { + arg0.stencilMask(arg1 >>> 0); + }, + __wbg_stencilMask_c3deb341c2545445: function(arg0, arg1) { + arg0.stencilMask(arg1 >>> 0); + }, + __wbg_stencilOpSeparate_04e9fc42ff22cc42: function(arg0, arg1, arg2, arg3, arg4) { + arg0.stencilOpSeparate(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, arg4 >>> 0); + }, + __wbg_stencilOpSeparate_08965f0c8c8055ce: function(arg0, arg1, arg2, arg3, arg4) { + arg0.stencilOpSeparate(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, arg4 >>> 0); + }, + __wbg_stopPropagation_000e2055cf404c4c: function(arg0) { + arg0.stopPropagation(); + }, + __wbg_stringify_a2c39d991e1bf91d: function() { return handleError(function (arg0) { + const ret = JSON.stringify(arg0); + return ret; + }, arguments); }, + __wbg_structuredClone_96dbcb8e0037e2f7: function() { return handleError(function (arg0) { + const ret = window.structuredClone(arg0); + return ret; + }, arguments); }, + __wbg_style_fbb0b56f71e97cf5: function(arg0) { + const ret = arg0.style; + return ret; + }, + __wbg_submit_b3bbead76cbf7627: function(arg0, arg1) { + arg0.submit(arg1); + }, + __wbg_texImage2D_29ce63ed3c9e7fd2: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + arg0.texImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, arg9); + }, arguments); }, + __wbg_texImage2D_35dad0302576d81d: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + arg0.texImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, arg9); + }, arguments); }, + __wbg_texImage2D_b708a52e67380671: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + arg0.texImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, arg9); + }, arguments); }, + __wbg_texImage3D_8cd441630ff7f672: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) { + arg0.texImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8 >>> 0, arg9 >>> 0, arg10); + }, arguments); }, + __wbg_texImage3D_f350e29c3bf4131a: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) { + arg0.texImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8 >>> 0, arg9 >>> 0, arg10); + }, arguments); }, + __wbg_texParameteri_2ae301ef0bcf17eb: function(arg0, arg1, arg2, arg3) { + arg0.texParameteri(arg1 >>> 0, arg2 >>> 0, arg3); + }, + __wbg_texParameteri_51f89620521fe4f5: function(arg0, arg1, arg2, arg3) { + arg0.texParameteri(arg1 >>> 0, arg2 >>> 0, arg3); + }, + __wbg_texStorage2D_9047841c0bc5a675: function(arg0, arg1, arg2, arg3, arg4, arg5) { + arg0.texStorage2D(arg1 >>> 0, arg2, arg3 >>> 0, arg4, arg5); + }, + __wbg_texStorage3D_3b9a3f42a3546d1c: function(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { + arg0.texStorage3D(arg1 >>> 0, arg2, arg3 >>> 0, arg4, arg5, arg6); + }, + __wbg_texSubImage2D_403156f007363972: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + arg0.texSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, arg9); + }, arguments); }, + __wbg_texSubImage2D_8ab7ce69fb3d7da8: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + arg0.texSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, arg9); + }, arguments); }, + __wbg_texSubImage2D_9489e066941c87f5: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + arg0.texSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, arg9); + }, arguments); }, + __wbg_texSubImage2D_97da2da339012c33: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + arg0.texSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, arg9); + }, arguments); }, + __wbg_texSubImage2D_a64a00fcd1aaf828: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + arg0.texSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, arg9); + }, arguments); }, + __wbg_texSubImage2D_d9826678d15a2def: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + arg0.texSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, arg9); + }, arguments); }, + __wbg_texSubImage2D_db8f79f2fc6bb8b3: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + arg0.texSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, arg9); + }, arguments); }, + __wbg_texSubImage2D_ec7844929d7e9fa7: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + arg0.texSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, arg9); + }, arguments); }, + __wbg_texSubImage2D_efd0d5d4f44425c3: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + arg0.texSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, arg9); + }, arguments); }, + __wbg_texSubImage3D_07b9b3cac3cc7a94: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) { + arg0.texSubImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 >>> 0, arg10 >>> 0, arg11); + }, arguments); }, + __wbg_texSubImage3D_5f9cbaf480a21838: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) { + arg0.texSubImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 >>> 0, arg10 >>> 0, arg11); + }, arguments); }, + __wbg_texSubImage3D_9dcb0cdd21e357a2: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) { + arg0.texSubImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 >>> 0, arg10 >>> 0, arg11); + }, arguments); }, + __wbg_texSubImage3D_b108481878a623b1: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) { + arg0.texSubImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 >>> 0, arg10 >>> 0, arg11); + }, arguments); }, + __wbg_texSubImage3D_b20e201d961c0724: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) { + arg0.texSubImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 >>> 0, arg10 >>> 0, arg11); + }, arguments); }, + __wbg_texSubImage3D_da3f8aa99d9a3b07: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) { + arg0.texSubImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 >>> 0, arg10 >>> 0, arg11); + }, arguments); }, + __wbg_texSubImage3D_dcd5f94889699451: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) { + arg0.texSubImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 >>> 0, arg10 >>> 0, arg11); + }, arguments); }, + __wbg_texSubImage3D_edaa3ed22d2c2d80: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) { + arg0.texSubImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 >>> 0, arg10 >>> 0, arg11); + }, arguments); }, + __wbg_then_00eed3ac0b8e82cb: function(arg0, arg1, arg2) { + const ret = arg0.then(arg1, arg2); + return ret; + }, + __wbg_then_479d77cb064907ee: function(arg0, arg1, arg2) { + const ret = arg0.then(arg1, arg2); + return ret; + }, + __wbg_then_a0c8db0381c8994c: function(arg0, arg1) { + const ret = arg0.then(arg1); + return ret; + }, + __wbg_timestamp_32a2f0974541dae3: function(arg0) { + const ret = arg0.timestamp; + return ret; + }, + __wbg_toString_6bb93e4c281b55a5: function(arg0) { + const ret = arg0.toString(); + return ret; + }, + __wbg_toString_891d991e862e1d44: function(arg0) { + const ret = arg0.toString(); + return ret; + }, + __wbg_top_a1a3c9fce4b7bf79: function(arg0) { + const ret = arg0.top; + return ret; + }, + __wbg_touches_077e4a58ee8e1500: function(arg0) { + const ret = arg0.touches; + return ret; + }, + __wbg_type_519bcbe4568b18ef: function(arg0, arg1) { + const ret = arg1.type; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_type_8f15c453c9572b22: function(arg0, arg1) { + const ret = arg1.type; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_uniform1f_3bfa2bd6c7fc00d4: function(arg0, arg1, arg2) { + arg0.uniform1f(arg1, arg2); + }, + __wbg_uniform1f_fc8bddcb58797aec: function(arg0, arg1, arg2) { + arg0.uniform1f(arg1, arg2); + }, + __wbg_uniform1i_a2d71c729752832f: function(arg0, arg1, arg2) { + arg0.uniform1i(arg1, arg2); + }, + __wbg_uniform1i_acce06d190ce18d5: function(arg0, arg1, arg2) { + arg0.uniform1i(arg1, arg2); + }, + __wbg_uniform1ui_d7a2cf8ee1de7325: function(arg0, arg1, arg2) { + arg0.uniform1ui(arg1, arg2 >>> 0); + }, + __wbg_uniform2fv_1dc67fed5264c610: function(arg0, arg1, arg2, arg3) { + arg0.uniform2fv(arg1, getArrayF32FromWasm0(arg2, arg3)); + }, + __wbg_uniform2fv_32ae18850ee36360: function(arg0, arg1, arg2, arg3) { + arg0.uniform2fv(arg1, getArrayF32FromWasm0(arg2, arg3)); + }, + __wbg_uniform2iv_80957dd3c0011c0b: function(arg0, arg1, arg2, arg3) { + arg0.uniform2iv(arg1, getArrayI32FromWasm0(arg2, arg3)); + }, + __wbg_uniform2iv_81603aa19386125f: function(arg0, arg1, arg2, arg3) { + arg0.uniform2iv(arg1, getArrayI32FromWasm0(arg2, arg3)); + }, + __wbg_uniform2uiv_1e6408df9680634c: function(arg0, arg1, arg2, arg3) { + arg0.uniform2uiv(arg1, getArrayU32FromWasm0(arg2, arg3)); + }, + __wbg_uniform3fv_667c3b6d0f6f5bb9: function(arg0, arg1, arg2, arg3) { + arg0.uniform3fv(arg1, getArrayF32FromWasm0(arg2, arg3)); + }, + __wbg_uniform3fv_a4a3b6f42df10d24: function(arg0, arg1, arg2, arg3) { + arg0.uniform3fv(arg1, getArrayF32FromWasm0(arg2, arg3)); + }, + __wbg_uniform3iv_5476a7841a1be50a: function(arg0, arg1, arg2, arg3) { + arg0.uniform3iv(arg1, getArrayI32FromWasm0(arg2, arg3)); + }, + __wbg_uniform3iv_739b2cd97bded380: function(arg0, arg1, arg2, arg3) { + arg0.uniform3iv(arg1, getArrayI32FromWasm0(arg2, arg3)); + }, + __wbg_uniform3uiv_6b0e93be0f86cc3c: function(arg0, arg1, arg2, arg3) { + arg0.uniform3uiv(arg1, getArrayU32FromWasm0(arg2, arg3)); + }, + __wbg_uniform4f_21572347c73b60b8: function(arg0, arg1, arg2, arg3, arg4, arg5) { + arg0.uniform4f(arg1, arg2, arg3, arg4, arg5); + }, + __wbg_uniform4f_50286376821185ad: function(arg0, arg1, arg2, arg3, arg4, arg5) { + arg0.uniform4f(arg1, arg2, arg3, arg4, arg5); + }, + __wbg_uniform4fv_f28a8dec371262c5: function(arg0, arg1, arg2, arg3) { + arg0.uniform4fv(arg1, getArrayF32FromWasm0(arg2, arg3)); + }, + __wbg_uniform4fv_ffa80ce12adb181d: function(arg0, arg1, arg2, arg3) { + arg0.uniform4fv(arg1, getArrayF32FromWasm0(arg2, arg3)); + }, + __wbg_uniform4iv_45f0c9ae8bad51b8: function(arg0, arg1, arg2, arg3) { + arg0.uniform4iv(arg1, getArrayI32FromWasm0(arg2, arg3)); + }, + __wbg_uniform4iv_f854c848a093b864: function(arg0, arg1, arg2, arg3) { + arg0.uniform4iv(arg1, getArrayI32FromWasm0(arg2, arg3)); + }, + __wbg_uniform4uiv_846e7f401ec81902: function(arg0, arg1, arg2, arg3) { + arg0.uniform4uiv(arg1, getArrayU32FromWasm0(arg2, arg3)); + }, + __wbg_uniformBlockBinding_0ed4d9a8f2505d33: function(arg0, arg1, arg2, arg3) { + arg0.uniformBlockBinding(arg1, arg2 >>> 0, arg3 >>> 0); + }, + __wbg_uniformMatrix2fv_172f98e9a2a32678: function(arg0, arg1, arg2, arg3, arg4) { + arg0.uniformMatrix2fv(arg1, arg2 !== 0, getArrayF32FromWasm0(arg3, arg4)); + }, + __wbg_uniformMatrix2fv_86768d70b036fe99: function(arg0, arg1, arg2, arg3, arg4) { + arg0.uniformMatrix2fv(arg1, arg2 !== 0, getArrayF32FromWasm0(arg3, arg4)); + }, + __wbg_uniformMatrix2x3fv_41c23e66a9d45d9b: function(arg0, arg1, arg2, arg3, arg4) { + arg0.uniformMatrix2x3fv(arg1, arg2 !== 0, getArrayF32FromWasm0(arg3, arg4)); + }, + __wbg_uniformMatrix2x4fv_183cd035e168f730: function(arg0, arg1, arg2, arg3, arg4) { + arg0.uniformMatrix2x4fv(arg1, arg2 !== 0, getArrayF32FromWasm0(arg3, arg4)); + }, + __wbg_uniformMatrix3fv_4a4f2baed9433227: function(arg0, arg1, arg2, arg3, arg4) { + arg0.uniformMatrix3fv(arg1, arg2 !== 0, getArrayF32FromWasm0(arg3, arg4)); + }, + __wbg_uniformMatrix3fv_dc7481350ed17ade: function(arg0, arg1, arg2, arg3, arg4) { + arg0.uniformMatrix3fv(arg1, arg2 !== 0, getArrayF32FromWasm0(arg3, arg4)); + }, + __wbg_uniformMatrix3x2fv_f8d83f5511a427ad: function(arg0, arg1, arg2, arg3, arg4) { + arg0.uniformMatrix3x2fv(arg1, arg2 !== 0, getArrayF32FromWasm0(arg3, arg4)); + }, + __wbg_uniformMatrix3x4fv_4142ecf80ac378f8: function(arg0, arg1, arg2, arg3, arg4) { + arg0.uniformMatrix3x4fv(arg1, arg2 !== 0, getArrayF32FromWasm0(arg3, arg4)); + }, + __wbg_uniformMatrix4fv_5395d1840e1704d7: function(arg0, arg1, arg2, arg3, arg4) { + arg0.uniformMatrix4fv(arg1, arg2 !== 0, getArrayF32FromWasm0(arg3, arg4)); + }, + __wbg_uniformMatrix4fv_b5e679a62b62a98d: function(arg0, arg1, arg2, arg3, arg4) { + arg0.uniformMatrix4fv(arg1, arg2 !== 0, getArrayF32FromWasm0(arg3, arg4)); + }, + __wbg_uniformMatrix4x2fv_aef25c3108f8e952: function(arg0, arg1, arg2, arg3, arg4) { + arg0.uniformMatrix4x2fv(arg1, arg2 !== 0, getArrayF32FromWasm0(arg3, arg4)); + }, + __wbg_uniformMatrix4x3fv_eec7712cae03a7f1: function(arg0, arg1, arg2, arg3, arg4) { + arg0.uniformMatrix4x3fv(arg1, arg2 !== 0, getArrayF32FromWasm0(arg3, arg4)); + }, + __wbg_unmap_817a2e3248a553fb: function(arg0) { + arg0.unmap(); + }, + __wbg_url_95d8a83d33709572: function(arg0, arg1) { + const ret = arg1.url; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_usage_265ef3d88b112387: function(arg0) { + const ret = arg0.usage; + return ret; + }, + __wbg_useProgram_a2f83fab51c79f54: function(arg0, arg1) { + arg0.useProgram(arg1); + }, + __wbg_useProgram_f79c775d2e8824a9: function(arg0, arg1) { + arg0.useProgram(arg1); + }, + __wbg_userActivation_16761a917b187328: function(arg0) { + const ret = arg0.userActivation; + return ret; + }, + __wbg_userAgent_d58193cc32293b16: function() { return handleError(function (arg0, arg1) { + const ret = arg1.userAgent; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, arguments); }, + __wbg_valueOf_4a6bac551a5efb8f: function(arg0) { + const ret = arg0.valueOf(); + return ret; + }, + __wbg_value_7f6052747ccf940f: function(arg0) { + const ret = arg0.value; + return ret; + }, + __wbg_value_c88240b8ee29611a: function(arg0, arg1) { + const ret = arg1.value; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbg_vertexAttribDivisorANGLE_1229b2a341928b1a: function(arg0, arg1, arg2) { + arg0.vertexAttribDivisorANGLE(arg1 >>> 0, arg2 >>> 0); + }, + __wbg_vertexAttribDivisor_01d7e6446210d446: function(arg0, arg1, arg2) { + arg0.vertexAttribDivisor(arg1 >>> 0, arg2 >>> 0); + }, + __wbg_vertexAttribIPointer_9ea5ec1a58b61fcf: function(arg0, arg1, arg2, arg3, arg4, arg5) { + arg0.vertexAttribIPointer(arg1 >>> 0, arg2, arg3 >>> 0, arg4, arg5); + }, + __wbg_vertexAttribPointer_63d8611810159fd4: function(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { + arg0.vertexAttribPointer(arg1 >>> 0, arg2, arg3 >>> 0, arg4 !== 0, arg5, arg6); + }, + __wbg_vertexAttribPointer_7db76295987fda72: function(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { + arg0.vertexAttribPointer(arg1 >>> 0, arg2, arg3 >>> 0, arg4 !== 0, arg5, arg6); + }, + __wbg_videoHeight_45a0ae1e784283ef: function(arg0) { + const ret = arg0.videoHeight; + return ret; + }, + __wbg_videoWidth_7940100dd8fd6df7: function(arg0) { + const ret = arg0.videoWidth; + return ret; + }, + __wbg_view_066479053a371038: function(arg0) { + const ret = arg0.view; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, + __wbg_viewport_1ac0b434f13a485b: function(arg0, arg1, arg2, arg3, arg4) { + arg0.viewport(arg1, arg2, arg3, arg4); + }, + __wbg_viewport_de5bbf3f5c97bfcf: function(arg0, arg1, arg2, arg3, arg4) { + arg0.viewport(arg1, arg2, arg3, arg4); + }, + __wbg_warn_2b0a27f629a4bb1e: function(arg0) { + console.warn(arg0); + }, + __wbg_warn_b5013c1036317367: function(arg0, arg1, arg2, arg3) { + console.warn(arg0, arg1, arg2, arg3); + }, + __wbg_width_4e12e0c19210bcc8: function(arg0) { + const ret = arg0.width; + return ret; + }, + __wbg_width_63032419f7a6952d: function(arg0) { + const ret = arg0.width; + return ret; + }, + __wbg_width_80cea93fc7f63070: function(arg0) { + const ret = arg0.width; + return ret; + }, + __wbg_width_92a77379d26c23da: function(arg0) { + const ret = arg0.width; + return ret; + }, + __wbg_width_9a5800683afb6ee8: function(arg0) { + const ret = arg0.width; + return ret; + }, + __wbg_width_e05356ef08639ff5: function(arg0) { + const ret = arg0.width; + return ret; + }, + __wbg_writeBuffer_24a10bfd5a8a57f7: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6) { + arg0.writeBuffer(arg1, arg2, getArrayU8FromWasm0(arg3, arg4), arg5, arg6); + }, arguments); }, + __wbg_writeText_622762687282c553: function(arg0, arg1, arg2) { + const ret = arg0.writeText(getStringFromWasm0(arg1, arg2)); + return ret; + }, + __wbg_writeTexture_acb28796746826c8: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5) { + arg0.writeTexture(arg1, getArrayU8FromWasm0(arg2, arg3), arg4, arg5); + }, arguments); }, + __wbg_write_00f6c35f2c69124a: function(arg0, arg1) { + const ret = arg0.write(arg1); + return ret; + }, + __wbindgen_cast_0000000000000001: function(arg0, arg1) { + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 23367, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h2d859dabe88806af); + return ret; + }, + __wbindgen_cast_0000000000000002: function(arg0, arg1) { + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 32608, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h2702d39e890c5700); + return ret; + }, + __wbindgen_cast_0000000000000003: function(arg0, arg1) { + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 33500, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__ha849d57a58c58ea3); + return ret; + }, + __wbindgen_cast_0000000000000004: function(arg0, arg1) { + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Array")], shim_idx: 23146, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h654f2e5a191bb1ee); + return ret; + }, + __wbindgen_cast_0000000000000005: function(arg0, arg1) { + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Error")], shim_idx: 27709, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h00dfff65e300f06d); + return ret; + }, + __wbindgen_cast_0000000000000006: function(arg0, arg1) { + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Event")], shim_idx: 23146, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h654f2e5a191bb1ee_5); + return ret; + }, + __wbindgen_cast_0000000000000007: function(arg0, arg1) { + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("GPUUncapturedErrorEvent")], shim_idx: 23367, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h2d859dabe88806af_6); + return ret; + }, + __wbindgen_cast_0000000000000008: function(arg0, arg1) { + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("PopStateEvent")], shim_idx: 8, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h3094ac52b8fe1530); + return ret; + }, + __wbindgen_cast_0000000000000009: function(arg0, arg1) { + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("StorageEvent")], shim_idx: 3756, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__hfbb6016647249ce9); + return ret; + }, + __wbindgen_cast_000000000000000a: function(arg0, arg1) { + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("VideoFrame")], shim_idx: 27709, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h00dfff65e300f06d_9); + return ret; + }, + __wbindgen_cast_000000000000000b: function(arg0, arg1) { + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("undefined")], shim_idx: 27710, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h35188a37ca76f649); + return ret; + }, + __wbindgen_cast_000000000000000c: function(arg0, arg1) { + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 1741, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__hc5762aa68c6ff5aa); + return ret; + }, + __wbindgen_cast_000000000000000d: function(arg0, arg1) { + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 23147, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h1ef8e462b630bb58); + return ret; + }, + __wbindgen_cast_000000000000000e: function(arg0, arg1) { + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 28291, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h240f5c8cbbc5c77c); + return ret; + }, + __wbindgen_cast_000000000000000f: function(arg0, arg1) { + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 6439, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__haeacc5df5e2c8588); + return ret; + }, + __wbindgen_cast_0000000000000010: function(arg0) { + // Cast intrinsic for `F64 -> Externref`. + const ret = arg0; + return ret; + }, + __wbindgen_cast_0000000000000011: function(arg0, arg1) { + // Cast intrinsic for `Ref(Slice(F32)) -> NamedExternref("Float32Array")`. + const ret = getArrayF32FromWasm0(arg0, arg1); + return ret; + }, + __wbindgen_cast_0000000000000012: function(arg0, arg1) { + // Cast intrinsic for `Ref(Slice(I16)) -> NamedExternref("Int16Array")`. + const ret = getArrayI16FromWasm0(arg0, arg1); + return ret; + }, + __wbindgen_cast_0000000000000013: function(arg0, arg1) { + // Cast intrinsic for `Ref(Slice(I32)) -> NamedExternref("Int32Array")`. + const ret = getArrayI32FromWasm0(arg0, arg1); + return ret; + }, + __wbindgen_cast_0000000000000014: function(arg0, arg1) { + // Cast intrinsic for `Ref(Slice(I8)) -> NamedExternref("Int8Array")`. + const ret = getArrayI8FromWasm0(arg0, arg1); + return ret; + }, + __wbindgen_cast_0000000000000015: function(arg0, arg1) { + // Cast intrinsic for `Ref(Slice(U16)) -> NamedExternref("Uint16Array")`. + const ret = getArrayU16FromWasm0(arg0, arg1); + return ret; + }, + __wbindgen_cast_0000000000000016: function(arg0, arg1) { + // Cast intrinsic for `Ref(Slice(U32)) -> NamedExternref("Uint32Array")`. + const ret = getArrayU32FromWasm0(arg0, arg1); + return ret; + }, + __wbindgen_cast_0000000000000017: function(arg0, arg1) { + // Cast intrinsic for `Ref(Slice(U8)) -> NamedExternref("Uint8Array")`. + const ret = getArrayU8FromWasm0(arg0, arg1); + return ret; + }, + __wbindgen_cast_0000000000000018: function(arg0, arg1) { + // Cast intrinsic for `Ref(String) -> Externref`. + const ret = getStringFromWasm0(arg0, arg1); + return ret; + }, + __wbindgen_init_externref_table: function() { + const table = wasm.__wbindgen_externrefs; + const offset = table.grow(4); + table.set(0, undefined); + table.set(offset + 0, undefined); + table.set(offset + 1, null); + table.set(offset + 2, true); + table.set(offset + 3, false); + }, + }; + return { + __proto__: null, + "./re_viewer_bg.js": import0, + }; + } + + function wasm_bindgen__convert__closures_____invoke__hc5762aa68c6ff5aa(arg0, arg1) { + wasm.wasm_bindgen__convert__closures_____invoke__hc5762aa68c6ff5aa(arg0, arg1); + } + + function wasm_bindgen__convert__closures_____invoke__h240f5c8cbbc5c77c(arg0, arg1) { + wasm.wasm_bindgen__convert__closures_____invoke__h240f5c8cbbc5c77c(arg0, arg1); + } + + function wasm_bindgen__convert__closures_____invoke__haeacc5df5e2c8588(arg0, arg1) { + wasm.wasm_bindgen__convert__closures_____invoke__haeacc5df5e2c8588(arg0, arg1); + } + + function wasm_bindgen__convert__closures_____invoke__h1ef8e462b630bb58(arg0, arg1) { + const ret = wasm.wasm_bindgen__convert__closures_____invoke__h1ef8e462b630bb58(arg0, arg1); + if (ret[1]) { + throw takeFromExternrefTable0(ret[0]); + } + } + + function wasm_bindgen__convert__closures_____invoke__h2d859dabe88806af(arg0, arg1, arg2) { + wasm.wasm_bindgen__convert__closures_____invoke__h2d859dabe88806af(arg0, arg1, arg2); + } + + function wasm_bindgen__convert__closures_____invoke__h2702d39e890c5700(arg0, arg1, arg2) { + wasm.wasm_bindgen__convert__closures_____invoke__h2702d39e890c5700(arg0, arg1, arg2); + } + + function wasm_bindgen__convert__closures_____invoke__h654f2e5a191bb1ee(arg0, arg1, arg2) { + wasm.wasm_bindgen__convert__closures_____invoke__h654f2e5a191bb1ee(arg0, arg1, arg2); + } + + function wasm_bindgen__convert__closures_____invoke__h00dfff65e300f06d(arg0, arg1, arg2) { + wasm.wasm_bindgen__convert__closures_____invoke__h00dfff65e300f06d(arg0, arg1, arg2); + } + + function wasm_bindgen__convert__closures_____invoke__h654f2e5a191bb1ee_5(arg0, arg1, arg2) { + wasm.wasm_bindgen__convert__closures_____invoke__h654f2e5a191bb1ee_5(arg0, arg1, arg2); + } + + function wasm_bindgen__convert__closures_____invoke__h2d859dabe88806af_6(arg0, arg1, arg2) { + wasm.wasm_bindgen__convert__closures_____invoke__h2d859dabe88806af_6(arg0, arg1, arg2); + } + + function wasm_bindgen__convert__closures_____invoke__hfbb6016647249ce9(arg0, arg1, arg2) { + wasm.wasm_bindgen__convert__closures_____invoke__hfbb6016647249ce9(arg0, arg1, arg2); + } + + function wasm_bindgen__convert__closures_____invoke__h00dfff65e300f06d_9(arg0, arg1, arg2) { + wasm.wasm_bindgen__convert__closures_____invoke__h00dfff65e300f06d_9(arg0, arg1, arg2); + } + + function wasm_bindgen__convert__closures_____invoke__ha849d57a58c58ea3(arg0, arg1, arg2) { + const ret = wasm.wasm_bindgen__convert__closures_____invoke__ha849d57a58c58ea3(arg0, arg1, arg2); + if (ret[1]) { + throw takeFromExternrefTable0(ret[0]); + } + } + + function wasm_bindgen__convert__closures_____invoke__h3094ac52b8fe1530(arg0, arg1, arg2) { + const ret = wasm.wasm_bindgen__convert__closures_____invoke__h3094ac52b8fe1530(arg0, arg1, arg2); + if (ret[1]) { + throw takeFromExternrefTable0(ret[0]); + } + } + + function wasm_bindgen__convert__closures_____invoke__h35188a37ca76f649(arg0, arg1, arg2) { + const ret = wasm.wasm_bindgen__convert__closures_____invoke__h35188a37ca76f649(arg0, arg1, arg2); + if (ret[1]) { + throw takeFromExternrefTable0(ret[0]); + } + } + + function wasm_bindgen__convert__closures_____invoke__h2db2cddd57d3c13f(arg0, arg1, arg2, arg3) { + wasm.wasm_bindgen__convert__closures_____invoke__h2db2cddd57d3c13f(arg0, arg1, arg2, arg3); + } + + + const __wbindgen_enum_CodecState = ["unconfigured", "configured", "closed"]; + + + const __wbindgen_enum_EncodedVideoChunkType = ["key", "delta"]; + + + const __wbindgen_enum_GpuAddressMode = ["clamp-to-edge", "repeat", "mirror-repeat"]; + + + const __wbindgen_enum_GpuBlendFactor = ["zero", "one", "src", "one-minus-src", "src-alpha", "one-minus-src-alpha", "dst", "one-minus-dst", "dst-alpha", "one-minus-dst-alpha", "src-alpha-saturated", "constant", "one-minus-constant", "src1", "one-minus-src1", "src1-alpha", "one-minus-src1-alpha"]; + + + const __wbindgen_enum_GpuBlendOperation = ["add", "subtract", "reverse-subtract", "min", "max"]; + + + const __wbindgen_enum_GpuBufferBindingType = ["uniform", "storage", "read-only-storage"]; + + + const __wbindgen_enum_GpuCanvasAlphaMode = ["opaque", "premultiplied"]; + + + const __wbindgen_enum_GpuCompareFunction = ["never", "less", "equal", "less-equal", "greater", "not-equal", "greater-equal", "always"]; + + + const __wbindgen_enum_GpuCullMode = ["none", "front", "back"]; + + + const __wbindgen_enum_GpuFilterMode = ["nearest", "linear"]; + + + const __wbindgen_enum_GpuFrontFace = ["ccw", "cw"]; + + + const __wbindgen_enum_GpuIndexFormat = ["uint16", "uint32"]; + + + const __wbindgen_enum_GpuLoadOp = ["load", "clear"]; + + + const __wbindgen_enum_GpuMipmapFilterMode = ["nearest", "linear"]; + + + const __wbindgen_enum_GpuPowerPreference = ["low-power", "high-performance"]; + + + const __wbindgen_enum_GpuPrimitiveTopology = ["point-list", "line-list", "line-strip", "triangle-list", "triangle-strip"]; + + + const __wbindgen_enum_GpuSamplerBindingType = ["filtering", "non-filtering", "comparison"]; + + + const __wbindgen_enum_GpuStencilOperation = ["keep", "zero", "replace", "invert", "increment-clamp", "decrement-clamp", "increment-wrap", "decrement-wrap"]; + + + const __wbindgen_enum_GpuStorageTextureAccess = ["write-only", "read-only", "read-write"]; + + + const __wbindgen_enum_GpuStoreOp = ["store", "discard"]; + + + const __wbindgen_enum_GpuTextureAspect = ["all", "stencil-only", "depth-only"]; + + + const __wbindgen_enum_GpuTextureDimension = ["1d", "2d", "3d"]; + + + const __wbindgen_enum_GpuTextureFormat = ["r8unorm", "r8snorm", "r8uint", "r8sint", "r16uint", "r16sint", "r16float", "rg8unorm", "rg8snorm", "rg8uint", "rg8sint", "r32uint", "r32sint", "r32float", "rg16uint", "rg16sint", "rg16float", "rgba8unorm", "rgba8unorm-srgb", "rgba8snorm", "rgba8uint", "rgba8sint", "bgra8unorm", "bgra8unorm-srgb", "rgb9e5ufloat", "rgb10a2uint", "rgb10a2unorm", "rg11b10ufloat", "rg32uint", "rg32sint", "rg32float", "rgba16uint", "rgba16sint", "rgba16float", "rgba32uint", "rgba32sint", "rgba32float", "stencil8", "depth16unorm", "depth24plus", "depth24plus-stencil8", "depth32float", "depth32float-stencil8", "bc1-rgba-unorm", "bc1-rgba-unorm-srgb", "bc2-rgba-unorm", "bc2-rgba-unorm-srgb", "bc3-rgba-unorm", "bc3-rgba-unorm-srgb", "bc4-r-unorm", "bc4-r-snorm", "bc5-rg-unorm", "bc5-rg-snorm", "bc6h-rgb-ufloat", "bc6h-rgb-float", "bc7-rgba-unorm", "bc7-rgba-unorm-srgb", "etc2-rgb8unorm", "etc2-rgb8unorm-srgb", "etc2-rgb8a1unorm", "etc2-rgb8a1unorm-srgb", "etc2-rgba8unorm", "etc2-rgba8unorm-srgb", "eac-r11unorm", "eac-r11snorm", "eac-rg11unorm", "eac-rg11snorm", "astc-4x4-unorm", "astc-4x4-unorm-srgb", "astc-5x4-unorm", "astc-5x4-unorm-srgb", "astc-5x5-unorm", "astc-5x5-unorm-srgb", "astc-6x5-unorm", "astc-6x5-unorm-srgb", "astc-6x6-unorm", "astc-6x6-unorm-srgb", "astc-8x5-unorm", "astc-8x5-unorm-srgb", "astc-8x6-unorm", "astc-8x6-unorm-srgb", "astc-8x8-unorm", "astc-8x8-unorm-srgb", "astc-10x5-unorm", "astc-10x5-unorm-srgb", "astc-10x6-unorm", "astc-10x6-unorm-srgb", "astc-10x8-unorm", "astc-10x8-unorm-srgb", "astc-10x10-unorm", "astc-10x10-unorm-srgb", "astc-12x10-unorm", "astc-12x10-unorm-srgb", "astc-12x12-unorm", "astc-12x12-unorm-srgb"]; + + + const __wbindgen_enum_GpuTextureSampleType = ["float", "unfilterable-float", "depth", "sint", "uint"]; + + + const __wbindgen_enum_GpuTextureViewDimension = ["1d", "2d", "2d-array", "cube", "cube-array", "3d"]; + + + const __wbindgen_enum_GpuVertexFormat = ["uint8", "uint8x2", "uint8x4", "sint8", "sint8x2", "sint8x4", "unorm8", "unorm8x2", "unorm8x4", "snorm8", "snorm8x2", "snorm8x4", "uint16", "uint16x2", "uint16x4", "sint16", "sint16x2", "sint16x4", "unorm16", "unorm16x2", "unorm16x4", "snorm16", "snorm16x2", "snorm16x4", "float16", "float16x2", "float16x4", "float32", "float32x2", "float32x3", "float32x4", "uint32", "uint32x2", "uint32x3", "uint32x4", "sint32", "sint32x2", "sint32x3", "sint32x4", "unorm10-10-10-2", "unorm8x4-bgra"]; + + + const __wbindgen_enum_GpuVertexStepMode = ["vertex", "instance"]; + + + const __wbindgen_enum_HardwareAcceleration = ["no-preference", "prefer-hardware", "prefer-software"]; + + + const __wbindgen_enum_ReadableStreamType = ["bytes"]; + + + const __wbindgen_enum_ReferrerPolicy = ["", "no-referrer", "no-referrer-when-downgrade", "origin", "origin-when-cross-origin", "unsafe-url", "same-origin", "strict-origin", "strict-origin-when-cross-origin"]; + + + const __wbindgen_enum_RequestCache = ["default", "no-store", "reload", "no-cache", "force-cache", "only-if-cached"]; + + + const __wbindgen_enum_RequestCredentials = ["omit", "same-origin", "include"]; + + + const __wbindgen_enum_RequestMode = ["same-origin", "no-cors", "cors", "navigate"]; + + + const __wbindgen_enum_RequestRedirect = ["follow", "error", "manual"]; + + + const __wbindgen_enum_ResizeObserverBoxOptions = ["border-box", "content-box", "device-pixel-content-box"]; + const IntoUnderlyingByteSourceFinalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_intounderlyingbytesource_free(ptr >>> 0, 1)); + const IntoUnderlyingSinkFinalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_intounderlyingsink_free(ptr >>> 0, 1)); + const IntoUnderlyingSourceFinalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_intounderlyingsource_free(ptr >>> 0, 1)); + const WebHandleFinalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_webhandle_free(ptr >>> 0, 1)); + + function addToExternrefTable0(obj) { + const idx = wasm.__externref_table_alloc(); + wasm.__wbindgen_externrefs.set(idx, obj); + return idx; + } + + const CLOSURE_DTORS = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(state => { + if (wasm) wasm.__wbindgen_destroy_closure(state.a, state.b); + }); + + function debugString(val) { + // primitive types + const type = typeof val; + if (type == 'number' || type == 'boolean' || val == null) { + return `${val}`; + } + if (type == 'string') { + return `"${val}"`; + } + if (type == 'symbol') { + const description = val.description; + if (description == null) { + return 'Symbol'; + } else { + return `Symbol(${description})`; + } + } + if (type == 'function') { + const name = val.name; + if (typeof name == 'string' && name.length > 0) { + return `Function(${name})`; + } else { + return 'Function'; + } + } + // objects + if (Array.isArray(val)) { + const length = val.length; + let debug = '['; + if (length > 0) { + debug += debugString(val[0]); + } + for(let i = 1; i < length; i++) { + debug += ', ' + debugString(val[i]); + } + debug += ']'; + return debug; + } + // Test for built-in + const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val)); + let className; + if (builtInMatches && builtInMatches.length > 1) { + className = builtInMatches[1]; + } else { + // Failed to match the standard '[object ClassName]' + return toString.call(val); + } + if (className == 'Object') { + // we're a user defined class or Object + // JSON.stringify avoids problems with cycles, and is generally much + // easier than looping through ownProperties of `val`. + try { + return 'Object(' + JSON.stringify(val) + ')'; + } catch (_) { + return 'Object'; + } + } + // errors + if (val instanceof Error) { + return `${val.name}: ${val.message}\n${val.stack}`; + } + // TODO we could test for more things here, like `Set`s and `Map`s. + return className; + } + + function getArrayF32FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getFloat32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len); + } + + function getArrayI16FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getInt16ArrayMemory0().subarray(ptr / 2, ptr / 2 + len); + } + + function getArrayI32FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getInt32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len); + } + + function getArrayI8FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getInt8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len); + } + + function getArrayU16FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getUint16ArrayMemory0().subarray(ptr / 2, ptr / 2 + len); + } + + function getArrayU32FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getUint32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len); + } + + function getArrayU8FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len); + } + + let cachedDataViewMemory0 = null; + function getDataViewMemory0() { + if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) { + cachedDataViewMemory0 = new DataView(wasm.memory.buffer); + } + return cachedDataViewMemory0; + } + + let cachedFloat32ArrayMemory0 = null; + function getFloat32ArrayMemory0() { + if (cachedFloat32ArrayMemory0 === null || cachedFloat32ArrayMemory0.byteLength === 0) { + cachedFloat32ArrayMemory0 = new Float32Array(wasm.memory.buffer); + } + return cachedFloat32ArrayMemory0; + } + + let cachedInt16ArrayMemory0 = null; + function getInt16ArrayMemory0() { + if (cachedInt16ArrayMemory0 === null || cachedInt16ArrayMemory0.byteLength === 0) { + cachedInt16ArrayMemory0 = new Int16Array(wasm.memory.buffer); + } + return cachedInt16ArrayMemory0; + } + + let cachedInt32ArrayMemory0 = null; + function getInt32ArrayMemory0() { + if (cachedInt32ArrayMemory0 === null || cachedInt32ArrayMemory0.byteLength === 0) { + cachedInt32ArrayMemory0 = new Int32Array(wasm.memory.buffer); + } + return cachedInt32ArrayMemory0; + } + + let cachedInt8ArrayMemory0 = null; + function getInt8ArrayMemory0() { + if (cachedInt8ArrayMemory0 === null || cachedInt8ArrayMemory0.byteLength === 0) { + cachedInt8ArrayMemory0 = new Int8Array(wasm.memory.buffer); + } + return cachedInt8ArrayMemory0; + } + + function getStringFromWasm0(ptr, len) { + ptr = ptr >>> 0; + return decodeText(ptr, len); + } + + let cachedUint16ArrayMemory0 = null; + function getUint16ArrayMemory0() { + if (cachedUint16ArrayMemory0 === null || cachedUint16ArrayMemory0.byteLength === 0) { + cachedUint16ArrayMemory0 = new Uint16Array(wasm.memory.buffer); + } + return cachedUint16ArrayMemory0; + } + + let cachedUint32ArrayMemory0 = null; + function getUint32ArrayMemory0() { + if (cachedUint32ArrayMemory0 === null || cachedUint32ArrayMemory0.byteLength === 0) { + cachedUint32ArrayMemory0 = new Uint32Array(wasm.memory.buffer); + } + return cachedUint32ArrayMemory0; + } + + let cachedUint8ArrayMemory0 = null; + function getUint8ArrayMemory0() { + if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) { + cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8ArrayMemory0; + } + + function handleError(f, args) { + try { + return f.apply(this, args); + } catch (e) { + const idx = addToExternrefTable0(e); + wasm.__wbindgen_exn_store(idx); + } + } + + function isLikeNone(x) { + return x === undefined || x === null; + } + + function makeMutClosure(arg0, arg1, f) { + const state = { a: arg0, b: arg1, cnt: 1 }; + const real = (...args) => { + state.cnt++; + const a = state.a; + state.a = 0; + try { + if (!wasm) return; + return f(a, state.b, ...args); + } finally { + state.a = a; + real._wbg_cb_unref(); + } + }; + real._wbg_cb_unref = () => { + if (--state.cnt === 0) { + if (wasm) wasm.__wbindgen_destroy_closure(state.a, state.b); + state.a = 0; + CLOSURE_DTORS.unregister(state); + } + }; + CLOSURE_DTORS.register(real, state, state); + return real; + } + + function passArray8ToWasm0(arg, malloc) { + const ptr = malloc(arg.length * 1, 1) >>> 0; + getUint8ArrayMemory0().set(arg, ptr / 1); + WASM_VECTOR_LEN = arg.length; + return ptr; + } + + function passArrayJsValueToWasm0(array, malloc) { + const ptr = malloc(array.length * 4, 4) >>> 0; + for (let i = 0; i < array.length; i++) { + const add = addToExternrefTable0(array[i]); + getDataViewMemory0().setUint32(ptr + 4 * i, add, true); + } + WASM_VECTOR_LEN = array.length; + return ptr; + } + + function passStringToWasm0(arg, malloc, realloc) { + if (realloc === undefined) { + const buf = cachedTextEncoder.encode(arg); + const ptr = malloc(buf.length, 1) >>> 0; + getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf); + WASM_VECTOR_LEN = buf.length; + return ptr; + } + + let len = arg.length; + let ptr = malloc(len, 1) >>> 0; + + const mem = getUint8ArrayMemory0(); + + let offset = 0; + + for (; offset < len; offset++) { + const code = arg.charCodeAt(offset); + if (code > 0x7F) break; + mem[ptr + offset] = code; + } + if (offset !== len) { + if (offset !== 0) { + arg = arg.slice(offset); + } + ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0; + const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len); + const ret = cachedTextEncoder.encodeInto(arg, view); + + offset += ret.written; + ptr = realloc(ptr, len, offset, 1) >>> 0; + } + + WASM_VECTOR_LEN = offset; + return ptr; + } + + function takeFromExternrefTable0(idx) { + const value = wasm.__wbindgen_externrefs.get(idx); + wasm.__externref_table_dealloc(idx); + return value; + } + + let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }); + cachedTextDecoder.decode(); + function decodeText(ptr, len) { + return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len)); + } + + const cachedTextEncoder = new TextEncoder(); + + if (!('encodeInto' in cachedTextEncoder)) { + cachedTextEncoder.encodeInto = function (arg, view) { + const buf = cachedTextEncoder.encode(arg); + view.set(buf); + return { + read: arg.length, + written: buf.length + }; + }; + } + + let WASM_VECTOR_LEN = 0; + + let wasmModule, wasm; + function __wbg_finalize_init(instance, module) { + wasm = instance.exports; + wasmModule = module; + cachedDataViewMemory0 = null; + cachedFloat32ArrayMemory0 = null; + cachedInt16ArrayMemory0 = null; + cachedInt32ArrayMemory0 = null; + cachedInt8ArrayMemory0 = null; + cachedUint16ArrayMemory0 = null; + cachedUint32ArrayMemory0 = null; + cachedUint8ArrayMemory0 = null; + wasm.__wbindgen_start(); + return wasm; + } + + async function __wbg_load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + } catch (e) { + const validResponse = module.ok && expectedResponseType(module.type); + + if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + + } else { throw e; } + } + } + + const bytes = await module.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + } else { + const instance = await WebAssembly.instantiate(module, imports); + + if (instance instanceof WebAssembly.Instance) { + return { instance, module }; + } else { + return instance; + } + } + + function expectedResponseType(type) { + switch (type) { + case 'basic': case 'cors': case 'default': return true; + } + return false; + } + } + + function initSync(module) { + if (wasm !== undefined) return wasm; + + + if (module !== undefined) { + if (Object.getPrototypeOf(module) === Object.prototype) { + ({module} = module) + } else { + console.warn('using deprecated parameters for `initSync()`; pass a single object instead') + } + } + + const imports = __wbg_get_imports(); + if (!(module instanceof WebAssembly.Module)) { + module = new WebAssembly.Module(module); + } + const instance = new WebAssembly.Instance(module, imports); + return __wbg_finalize_init(instance, module); + } + + async function __wbg_init(module_or_path) { + if (wasm !== undefined) return wasm; + + + if (module_or_path !== undefined) { + if (Object.getPrototypeOf(module_or_path) === Object.prototype) { + ({module_or_path} = module_or_path) + } else { + console.warn('using deprecated parameters for the initialization function; pass a single object instead') + } + } + + + const imports = __wbg_get_imports(); + + if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) { + module_or_path = fetch(module_or_path); + } + + const { instance, module } = await __wbg_load(await module_or_path, imports); + + return __wbg_finalize_init(instance, module); + } + + + + +function deinit() { + __wbg_init.__wbindgen_wasm_module = null; + wasmModule = null; + wasm = null; + cachedDataViewMemory0 = null; + cachedFloat32ArrayMemory0 = null; + cachedInt16ArrayMemory0 = null; + cachedInt32ArrayMemory0 = null; + cachedInt8ArrayMemory0 = null; + cachedUint16ArrayMemory0 = null; + cachedUint32ArrayMemory0 = null; + cachedUint8ArrayMemory0 = null; +} + +return Object.assign(__wbg_init, { initSync, deinit }, exports); +} diff --git a/apps/control-station/vendor/rerun-web-viewer-0.34.1/re_viewer_bg.nodedc.wasm b/apps/control-station/vendor/rerun-web-viewer-0.34.1/re_viewer_bg.nodedc.wasm new file mode 100644 index 0000000..82593e2 --- /dev/null +++ b/apps/control-station/vendor/rerun-web-viewer-0.34.1/re_viewer_bg.nodedc.wasm @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:38d19bac06b7c3b8e549489469cf7c4a24f319ec953849e4656b5827a6c105bb +size 48595790 diff --git a/apps/control-station/vite.config.ts b/apps/control-station/vite.config.ts index 642bb45..6bc1df8 100644 --- a/apps/control-station/vite.config.ts +++ b/apps/control-station/vite.config.ts @@ -53,6 +53,13 @@ export default defineConfig(({ mode }) => { host: "127.0.0.1", port: 4173, strictPort: true, + proxy: { + "/api": { + target: apiTarget, + changeOrigin: false, + ws: true, + }, + }, }, }; }); diff --git a/docs/01_IMPLEMENTATION_PLAN.md b/docs/01_IMPLEMENTATION_PLAN.md index 2f70b36..5639bde 100644 --- a/docs/01_IMPLEMENTATION_PLAN.md +++ b/docs/01_IMPLEMENTATION_PLAN.md @@ -3,7 +3,7 @@ This plan supersedes the app-dependent experiment order in the reference Bible. Each gate produces evidence and an explicit GO, PAUSE or BLOCKED result. -## Current checkpoint — 2026-07-19 +## Current checkpoint — 2026-07-20 | Stage | Result | | --- | --- | @@ -11,7 +11,7 @@ Each gate produces evidence and an explicit GO, PAUSE or BLOCKED result. | Gate 1 physical operation | GO — autonomous double-click start/stop verified | | Stage 1 BLE discovery | GO — repeatable advertisement and GATT profile | | Stage 2 BLE provisioning | GO — reviewed 99-byte profile, LAN association confirmed | -| Stage 2 local connection matrix | GO (implementation) — Bridge remains physically accepted; Direct Connect reuses the reviewed one-shot BLE frame; Quick Connect uses one CoreWLAN host association and no GATT write. Direct Connect and Mission Core Quick Connect still require separate physical acceptance | +| Stage 2 local connection matrix | GO for Bridge/direct-LAN; LAB-ONLY for Quick Connect — firmware review proved the K1 3.0.2 AP credential is firmware-constant and the SSID follows the `XGR-` identity/MAC rule. One prepared Mac completed AP-enable, AP-ready, CoreWLAN association and the normal control lifecycle. The successful host had been seeded from the reviewed firmware archive; a copied build on a clean host cannot acquire that material automatically. Automatic firmware download, iPhone extraction and hard-coding were rejected. Bridge remains the product path; Direct Connect remains physically pending | | Stage 3 application session | GO — MQTT 3.1.1 on confirmed K1 TCP 1883 | | Stage 4 artifacts/flows | GO — bounded capture, hashes and negative control | | Stage 5 point cloud | GO — raw-LZ4 protobuf, 1,140 live frames decoded | diff --git a/docs/04_K1_WIFI_PROVISIONING_PROFILE.md b/docs/04_K1_WIFI_PROVISIONING_PROFILE.md index ecf72a3..1eff7bb 100644 --- a/docs/04_K1_WIFI_PROVISIONING_PROFILE.md +++ b/docs/04_K1_WIFI_PROVISIONING_PROFILE.md @@ -16,6 +16,35 @@ profile is not a generic XGRIDS protocol claim and must not be used for fuzzing. - The application sends operator-supplied router credentials; it does not derive them from the K1 and it does not require the password of the K1's own AP. +The 99-byte `7f01` profile is used when K1 joins an external network (Bridge or +controller hotspot). It is not the Quick Connect bootstrap. A live Mission Core +negative run on 2026-07-19 proved that host association alone cannot work while +the reviewed K1 remains in station mode: `7f02` still reported the existing LAN. + +Re-review of the owner-supplied LixelGO QuickLink branch then recovered the +missing first step. After a real BLE connection, LixelGO sends one fixed +100-byte frame to the same `7f01` characteristic: bytes `0..98` are zero and +byte `99` is `0x01`. Its callback is the AP-launch result; only then does the +application passes that device record's `WiFiAP_SSID` and `WiFiAP_Password` to +the operating-system connector. Later analysis of the official K1 `3.0.2` +firmware recovered the upstream source: `lixel_nman` invokes the bundled +NetworkManager AP script, which assigns a firmware-constant WPA2 credential. +The persisted app fields are per-device records, but the reviewed firmware +material is not per-device. The reviewed app requests write-without-response. +Mission Core follows the live characteristic properties on macOS, where this K1 +advertises write-with-response, and never retries either transport or command +automatically. + +The browser/API carries no AP password. An optional laboratory importer authenticates the +exact official `3.0.2` archive, resolves the reviewed material without printing +it and installs one firmware-scoped credential source in the OS secure store. +Mission Core then binds a device-scoped host profile ID to the selected +BLE-advertised SSID. Before any device write, the macOS helper materializes that +profile entirely inside Keychain from the firmware-scoped source. The actual +secret never reaches the browser, API, argv, logs, manifests or evidence. The +bounded Python importer holds it only in a short-lived mutable buffer, sends it +through helper stdin and zeroizes the buffer. + Full UUIDs: - service: `00007f00-0000-1000-8000-00805f9b34fb`; @@ -38,6 +67,59 @@ There is no checksum, nonce, token, certificate, signature, or separate commit command in this production call path. The implementation must never print, persist, or accept the password as a command-line argument. +## Quick Connect AP-enable frame + +The separately reviewed Quick Connect device action writes exactly 100 bytes: + +| Offset | Length | Meaning | +| --- | ---: | --- | +| 0 | 99 | zero | +| 99 | 1 | enable device AP (`0x01`) | + +It contains no SSID, password, device identifier or user input. The reviewed +client maps response byte 51 of `7f02` to its AP-ready flag. Mission Core +therefore requires all three observations before host association: mode +`WIFI_AP`, address `192.168.56.1`, and non-zero byte 51. A failed or ambiguous +attempt is not automatically repeated. + +The first controlled AP attempt was physically accepted: one write-with-response +completed, `7f02` changed to `WIFI_AP / 192.168.56.1`, and a later exact +CoreWLAN scan found the SSID matching the selected BLE device. The Mac remained +on its previous LAN only because the former host adapter looked up an invalid +global profile. That profile inference and its APK importer were withdrawn. + +A later physical attempt established another boundary: `7f02` can continue to +report `WIFI_AP / 192.168.56.1` with byte 51 zero after the exact SSID is no +longer beaconing. Mode and address alone are therefore not an idempotency or +readiness signal. Like the reviewed LixelGO action, each new explicit Mission +Core Quick Connect intent emits one AP-enable frame even when the baseline mode +already says `WIFI_AP`, then polls for the byte-51 ready flag for at most 15 +seconds. It never retries the device write automatically. + +Static review of the original client also established a lifecycle requirement: +LixelGO keeps the same BLE manager connected after AP-ready and invokes native +Wi-Fi association from that live session. Mission Core now retains the same +`BleakClient` while CoreWLAN performs bounded exact-SSID discovery and one +association. The discovery window may contain multiple read-only scans; it does +not repeat the BLE write or Wi-Fi association. + +The next physical attempt exposed a CoreBluetooth lifecycle boundary before any +write: K1 appeared in the explicit six-second BLE scan, but a second lookup by +its macOS UUID failed moments later. The UUID is a transport-local selector, not +a durable rediscovery contract. The runtime now retains the live `BLEDevice` +handle from the operator's scan and connects that exact selected handle in the +following network action. A fallback lookup remains only for non-UI callers +that did not perform discovery first. + +The 2026-07-20 prepared-host acceptance installed the exact firmware provider, +found one expected K1 candidate, emitted one AP-enable write, observed AP-ready +and completed one CoreWLAN association without an iPhone or manual credential. +Mission Core admitted `192.168.56.1`; the operator disconnected afterward only +to restore the external chat route. Full redacted evidence and artifact hashes +are recorded in `docs/lab/004_K1_FW302_AP_CREDENTIAL_PROVIDER_20260720.redacted.md`. +This proves the mechanism on that Mac, not automatic credential acquisition by +a copied application on a clean host. + The Android application unequivocally requests a write without response and negotiates MTU 120, making the 99-byte frame one ATT command. A live read-only CoreBluetooth check reports MTU 256 and a maximum write-without-response size of @@ -53,11 +135,13 @@ mode. It never fragments or retries the payload automatically. ## Expected transition and evidence of acceptance A completed GATT write only proves transport completion. It does not prove that -the K1 joined Wi-Fi. The application polls `7f02`; the observed response frame -contains a fixed-width mode slot, an address slot, and a status byte at offset -50. The current AP baseline reports mode `WIFI_AP` and address `192.168.56.1`. +the K1 joined Wi-Fi or began beaconing. The application polls `7f02`; the +observed response frame contains a fixed-width mode slot, an address slot, a +status byte at offset 50 and the AP-ready flag at offset 51. The stale AP +baseline reports `WIFI_AP / 192.168.56.1 / byte51=0`; the physically observed +ready transition reports the same mode/address with `byte51=1`. -For the controlled experiment, acceptance required at least one of: +For Bridge/Direct Connect, acceptance requires at least one of: 1. `7f02` reports a non-AP IPv4 address; 2. the same address appears as a new router/ARP client after the write; @@ -66,10 +150,35 @@ For the controlled experiment, acceptance required at least one of: Do not infer success from a write callback alone. +The Bridge/Direct Connect address is a DHCP lease, not configuration and not +device identity. Mission Core re-reads `7f02` without writing before every new +LAN control session, implicit-host acquisition and factory-calibration read. +If the value changes, it rotates `device_session_id`; it never retargets an +active acquisition. A correlated MQTT `DeviceInfo` response supplies the live +model/firmware/serial identity barrier. + +The 2026-07-20 reboot/power-cycle check observed the startup race directly: +one read returned the earlier `.54` lease while that exact address had no ARP or +application endpoint; a later read returned `.52`, where exact probes found +MQTT 1883 and RTSP 8554. No subnet scan, route change, network-profile change or +VPN action was used. This is why no owner-LAN IPv4 value is a product constant +and why a BLE lease observation alone is not reported as live DeviceInfo. + +For Quick Connect, host association is not admitted until the canonical +byte-51 ready flag is observed. CoreWLAN then searches only for the exact +device-profile SSID for at most 15 seconds and performs at most one association. + ## Safety, recovery and stop conditions -- Perform one write per explicitly named attempt, using credentials for the LAN - already used by the Mac. Never retry automatically. +- Perform one write per explicitly named attempt. Never retry automatically. +- For Bridge/Direct Connect, use credentials for the operator-selected network. +- For Quick Connect, the exact `3.0.2` provider must already exist in the OS + secure store. Missing or mismatched firmware material fails before the AP + write. Never extrapolate this provider to another firmware or model. +- The macOS adapter materializes a device-scoped Keychain item from the exact + firmware source, then performs one association. Standard Wi-Fi Keychain and + native prompt paths remain compatibility fallbacks, not the reviewed + zero-touch path. It never asks the browser for a password. - Do not alter Deco settings, scan the subnet, or guess any credential. - If the status does not change, do not retry automatically. - If the supplied credentials are wrong, reconnect over BLE and overwrite them diff --git a/docs/09_OBSERVATION_SESSIONS.md b/docs/09_OBSERVATION_SESSIONS.md index ca90d23..378dd8b 100644 --- a/docs/09_OBSERVATION_SESSIONS.md +++ b/docs/09_OBSERVATION_SESSIONS.md @@ -15,6 +15,9 @@ fully usable with only their available modalities. 1. Enter the required project name and start a normal acquisition from **Парк → Локальное устройство**. The NFKC-normalized/trimmed value is local display metadata, not a filesystem path, and becomes the saved-session catalog name. + A normal acquisition has no duration deadline and runs until the operator + explicitly stops it. Compatibility clients may still request a positive + finite duration, without an application-level maximum. 2. Open **Наблюдение → Пространственная сцена**. Live point cloud, trajectory and the selected camera remain live-only while acquisition is running. 3. Stop acquisition normally, or allow the local service to recover an @@ -165,7 +168,8 @@ a separately attested storage root: export MISSIONCORE_DATA_DIR=/absolute/private/path/mission-core # Full K1 point-plus-camera evidence must currently remain below the checkout. export MISSIONCORE_EVIDENCE_DIR=/absolute/path/to/NODEDC_MISSION_CORE/.runtime/mission-core/evidence/sessions -export MISSIONCORE_RRD_CACHE_MAX_BYTES=8589934592 +# Optional operator retention quota; unset means no application byte quota. +# export MISSIONCORE_RRD_CACHE_MAX_BYTES=8589934592 export MISSIONCORE_RRD_FREE_SPACE_RESERVE_BYTES=2147483648 uv run k1link serve ``` @@ -226,13 +230,15 @@ keeps the current device scan generation and does not accumulate an earlier distance after the device resets scan time and route distance. These values are not reconstructed from pose integration or a browser timer. -Expensive cache misses run through the bounded preparation worker and one global -cross-process export gate to cap peak RAM, CPU and temporary-disk use. Crash -leftovers from candidates, exporter temporary files and staged replay prefixes -are scavenged under that lock before quota accounting. Ready cache hits and -active response leases do not wait behind that gate. The derived cache has an -8 GiB default quota, preserves a 2 GiB default filesystem reserve and evicts -least-recently-used RRDs only; it never deletes native evidence. +Expensive cache misses run through the single-worker preparation queue and one +global cross-process export gate to cap concurrent RAM, CPU and temporary-disk +use. Crash leftovers from candidates, exporter temporary files and staged replay +prefixes are scavenged under that lock before capacity accounting. Ready cache +hits and active response leases do not wait behind that gate. The derived cache +has no application byte quota by default, so a single multi-hour RRD is not +rejected at 8 GiB. It still preserves a 2 GiB default filesystem reserve. An +operator may set `MISSIONCORE_RRD_CACHE_MAX_BYTES` to enable LRU eviction of +derived RRDs only; native evidence is never deleted. ## Capture-clock envelope @@ -313,7 +319,9 @@ time are not proven to use a shared device clock. Do not infer frame-accurate calibration from the playback timeline. Finalized media is prepared once by the same process-owned background job that -materializes the RRD. The gateway records host time only after a complete +materializes the RRD. JSONL indexes are read incrementally and no total index, +segment-count or archive-byte ceiling is used. The gateway records host time +only after a complete `moof+mdat` fragment has arrived, so that timestamp is an availability/end anchor, never a fragment-start timestamp. Preparation reads and SHA-verifies every fragment, parses bounded ISO-BMFF timing tables (`mdhd`, `trex`, `tfhd`, @@ -332,7 +340,7 @@ coverage can be navigated. A missing, ambiguous, oversized or otherwise unparseable timing table fails preparation; the archive remains evidence but is never advertised as seekable media. -The prepared path-free v2 descriptor and full source stat identity (native raw +The durable path-free v2 descriptor and full source stat identity (native raw and timing metadata plus every camera summary, index, init and segment file) are written under the private derived cache with a schema, generation and checksum. Publication uses a private temporary file, file and directory `fsync`, and atomic @@ -379,8 +387,9 @@ camera acceptance run retained point/pose evidence only. provisional `transport` generation, but discovery will not use either to advertise camera coverage. A mismatched origin/envelope/summary fails closed. - A native capture with a missing final summary is accepted only when the raw - and metadata prefix is bounded, aligned and structurally valid. It is cataloged - as `interrupted`, never silently promoted to `ready`. + and metadata prefix is aligned and structurally valid. Recovery streams the + metadata JSONL one row at a time with no total-byte or message-count ceiling; + it is cataloged as `interrupted`, never silently promoted to `ready`. - A non-newline metadata crash tail can be ignored. Newline-terminated or mid-file corruption fails closed. - Camera recovery retains a contiguous valid segment prefix, quarantines @@ -426,6 +435,7 @@ POST /api/v1/observation-sessions/{id}/blueprint.rrd GET /api/v1/observation-sessions/{id}/media/{artifact}/manifest GET /api/v1/observation-sessions/{id}/media/{artifact}/epochs/{n}/init.mp4 GET /api/v1/observation-sessions/{id}/media/{artifact}/epochs/{n}/segments/{m}.m4s +GET /api/v1/observation-sessions/{id}/media/{artifact}/epochs/{n}/recording.mp4?generation= GET /api/v1/workspace-layouts/observation.spatial PUT /api/v1/workspace-layouts/observation.spatial @@ -461,40 +471,40 @@ revision in `If-Match`; stale writers receive HTTP 412 rather than overwriting another saved profile. Recorded media routes expose only opaque catalog identifiers and ordinal codec -epochs. The required `missioncore.observation-recorded-media/v2` manifest carries -a strong `generation_sha256`, exact JS-safe aggregate `byte_length`, and finite +epochs. The public compact +`missioncore.observation-recorded-media/v3` manifest carries a strong +`generation_sha256`, exact JS-safe aggregate `byte_length`, and finite `timeline_start_seconds` / `timeline_end_seconds` for every epoch. Epoch ends -participate in the generation digest. Every epoch also declares its init byte -length/digest and a complete contiguous segment list with sequence, URL, byte -length and digest. The launch source repeats the same aggregate `byte_length` -and uses exactly `max(epoch.timeline_end_seconds)` as its end; the spatial RRD -end must never pad camera coverage. The browser cross-checks launch, manifest and -component lengths. The current browser laboratory policy accepts at most 16 -camera sources, 128 MiB per source and 512 MiB across the session. This launch -preflight finishes before the first camera manifest/init/segment GET; admitted -cameras are then downloaded and decode-probed one at a time. Verified raw -buffers remain immutable so route changes and player remounts cannot append -emptied data. This bounded in-memory strategy is deliberate for the laboratory -milestone; an OPFS-backed sealed-generation cache is the next scaling step for -larger rigs and must preserve the same launch/manifest/hash admission contract. +participate in the generation digest. Each epoch declares one generation-bound +`stream_url`, media type and aggregate byte length; thousands of internal +segment rows never enter browser memory. The launch source repeats the same +aggregate `byte_length` and uses exactly `max(epoch.timeline_end_seconds)` as +its end; the spatial RRD end must never pad camera coverage. The browser +cross-checks launch and manifest identity, but applies no duration, per-source +byte or aggregate-session byte admission ceiling. -The manifest response ETag is the exact generation, and the manifest GET itself -requires that generation in `If-Match`. Init and media GETs likewise require the -descriptor's exact SHA `If-Match`, then open through a confined directory file -descriptor with no symlink following, verify the declared SHA-256 and serve -exact-length bytes with immutable private `no-transform` caching and byte-range -support. Physical source ids, RTSP addresses and storage paths never cross the -API boundary. +The `