@swifttui/web 0.1.11 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -30,6 +30,7 @@ function resolveWasmEngineCapabilities(signals = collectWasmEngineProbeSignals()
|
|
|
30
30
|
* `SWIFTTUI_STACK_LEAN_PROFILE` (or a tuning override) always wins.
|
|
31
31
|
*/
|
|
32
32
|
function stackProfileEnvironmentDefaults(capabilities) {
|
|
33
|
+
if (capabilities.engine === "v8") return { SWIFTTUI_STACK_LEAN_PROFILE: "0" };
|
|
33
34
|
return {};
|
|
34
35
|
}
|
|
35
36
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WasmEngineCapabilities.js","names":[],"sources":["../../../src/wasi/WasmEngineCapabilities.ts"],"sourcesContent":["// Runtime detection of the browser's JS/wasm engine family and the wasm\n// capabilities that decide how the SwiftTUI WASI runtime should execute.\n//\n// JavaScriptCore runs wasm calls on the host thread's native stack, and\n// Darwin worker threads get ~1/16 of the main-thread stack budget, so\n// SwiftTUI's WASI build defaults to its stack-lean resolve profile\n// (`SWIFTTUI_STACK_LEAN_PROFILE`, depth-capped chunked resolve). That profile\n// costs steady-state pipeline time, and engines with roomy worker stacks\n// don't need it. Detection is deliberately asymmetric: a wrongly applied lean\n// profile only costs speed, while wrongly disabling it on a small-stack\n// engine overflows the wasm stack and kills the app — so lean stays\n// recommended unless the engine is confidently V8, the only family with a\n// measured, comfortable worker budget. Gecko is measured (Firefox, live,\n// 2026-07) to NOT fit the non-lean shape in its worker: it must keep the\n// lean profile in worker mode.\n//\n// Engine classification reads Error mechanics rather than user-agent\n// strings: V8 formats stack frames as ` at fn (url)`, JSC and Gecko as\n// `fn@url`, and the two are split by engine-specific Error instance\n// properties (Gecko `fileName`, JSC `sourceURL`). Trunk WebKit (STP ≥ 238)\n// no longer exposes `sourceURL` on constructed Errors, so JSC\n// classification there rides the `fn@url` stack-shape fallback. Non-browser\n// JSC hosts that emulate V8 stack frames for Node compatibility (e.g. Bun)\n// classify as \"v8\"; the probe targets browser engines, where the formats\n// don't cross.\n\nexport type WasmEngineFamily = \"v8\" | \"jsc\" | \"gecko\" | \"unknown\";\n\nexport interface WasmEngineProbeSignals {\n errorStack: string;\n errorHasGeckoFileName: boolean;\n errorHasJSCSourceURL: boolean;\n wasmSuspendingType: string;\n wasmPromisingType: string;\n}\n\nexport interface WasmEngineCapabilities {\n engine: WasmEngineFamily;\n /**\n * WebAssembly JavaScript Promise Integration (`WebAssembly.Suspending` +\n * `WebAssembly.promising`). When true, the main-thread execution mode\n * (`MainThreadWasmExecutor`) can suspend on stdin/timers instead of\n * blocking a worker on `Atomics.wait`.\n */\n supportsJSPI: boolean;\n /**\n * Whether the SwiftTUI WASI build should keep its stack-lean resolve\n * profile on this engine.\n */\n stackLeanRecommended: boolean;\n}\n\nexport function collectWasmEngineProbeSignals(): WasmEngineProbeSignals {\n const probe = new Error(\"wasm-engine-probe\");\n const wasm = (\n globalThis as {\n WebAssembly?: { Suspending?: unknown; promising?: unknown };\n }\n ).WebAssembly;\n return {\n errorStack: typeof probe.stack === \"string\" ? probe.stack : \"\",\n errorHasGeckoFileName: \"fileName\" in probe,\n errorHasJSCSourceURL: \"sourceURL\" in probe,\n wasmSuspendingType: typeof wasm?.Suspending,\n wasmPromisingType: typeof wasm?.promising,\n };\n}\n\nexport function classifyWasmEngineFamily(\n signals: WasmEngineProbeSignals\n): WasmEngineFamily {\n if (/^\\s*at /m.test(signals.errorStack)) {\n return \"v8\";\n }\n if (signals.errorHasGeckoFileName) {\n return \"gecko\";\n }\n if (signals.errorHasJSCSourceURL || /^[^\\n]*@/m.test(signals.errorStack)) {\n return \"jsc\";\n }\n return \"unknown\";\n}\n\nexport function resolveWasmEngineCapabilities(\n signals: WasmEngineProbeSignals = collectWasmEngineProbeSignals()\n): WasmEngineCapabilities {\n const engine = classifyWasmEngineFamily(signals);\n return {\n engine,\n supportsJSPI:\n signals.wasmSuspendingType === \"function\" &&\n signals.wasmPromisingType === \"function\",\n stackLeanRecommended: engine !== \"v8\",\n };\n}\n\n/**\n * WASI environment defaults implied by the engine capabilities. Spread these\n * *before* caller-provided environment entries so an explicit\n * `SWIFTTUI_STACK_LEAN_PROFILE` (or a tuning override) always wins.\n */\nexport function stackProfileEnvironmentDefaults(\n capabilities: WasmEngineCapabilities\n): Record<string, string> {\n //
|
|
1
|
+
{"version":3,"file":"WasmEngineCapabilities.js","names":[],"sources":["../../../src/wasi/WasmEngineCapabilities.ts"],"sourcesContent":["// Runtime detection of the browser's JS/wasm engine family and the wasm\n// capabilities that decide how the SwiftTUI WASI runtime should execute.\n//\n// JavaScriptCore runs wasm calls on the host thread's native stack, and\n// Darwin worker threads get ~1/16 of the main-thread stack budget, so\n// SwiftTUI's WASI build defaults to its stack-lean resolve profile\n// (`SWIFTTUI_STACK_LEAN_PROFILE`, depth-capped chunked resolve). That profile\n// costs steady-state pipeline time, and engines with roomy worker stacks\n// don't need it. Detection is deliberately asymmetric: a wrongly applied lean\n// profile only costs speed, while wrongly disabling it on a small-stack\n// engine overflows the wasm stack and kills the app — so lean stays\n// recommended unless the engine is confidently V8, the only family with a\n// measured, comfortable worker budget. Gecko is measured (Firefox, live,\n// 2026-07) to NOT fit the non-lean shape in its worker: it must keep the\n// lean profile in worker mode.\n//\n// Engine classification reads Error mechanics rather than user-agent\n// strings: V8 formats stack frames as ` at fn (url)`, JSC and Gecko as\n// `fn@url`, and the two are split by engine-specific Error instance\n// properties (Gecko `fileName`, JSC `sourceURL`). Trunk WebKit (STP ≥ 238)\n// no longer exposes `sourceURL` on constructed Errors, so JSC\n// classification there rides the `fn@url` stack-shape fallback. Non-browser\n// JSC hosts that emulate V8 stack frames for Node compatibility (e.g. Bun)\n// classify as \"v8\"; the probe targets browser engines, where the formats\n// don't cross.\n\nexport type WasmEngineFamily = \"v8\" | \"jsc\" | \"gecko\" | \"unknown\";\n\nexport interface WasmEngineProbeSignals {\n errorStack: string;\n errorHasGeckoFileName: boolean;\n errorHasJSCSourceURL: boolean;\n wasmSuspendingType: string;\n wasmPromisingType: string;\n}\n\nexport interface WasmEngineCapabilities {\n engine: WasmEngineFamily;\n /**\n * WebAssembly JavaScript Promise Integration (`WebAssembly.Suspending` +\n * `WebAssembly.promising`). When true, the main-thread execution mode\n * (`MainThreadWasmExecutor`) can suspend on stdin/timers instead of\n * blocking a worker on `Atomics.wait`.\n */\n supportsJSPI: boolean;\n /**\n * Whether the SwiftTUI WASI build should keep its stack-lean resolve\n * profile on this engine.\n */\n stackLeanRecommended: boolean;\n}\n\nexport function collectWasmEngineProbeSignals(): WasmEngineProbeSignals {\n const probe = new Error(\"wasm-engine-probe\");\n const wasm = (\n globalThis as {\n WebAssembly?: { Suspending?: unknown; promising?: unknown };\n }\n ).WebAssembly;\n return {\n errorStack: typeof probe.stack === \"string\" ? probe.stack : \"\",\n errorHasGeckoFileName: \"fileName\" in probe,\n errorHasJSCSourceURL: \"sourceURL\" in probe,\n wasmSuspendingType: typeof wasm?.Suspending,\n wasmPromisingType: typeof wasm?.promising,\n };\n}\n\nexport function classifyWasmEngineFamily(\n signals: WasmEngineProbeSignals\n): WasmEngineFamily {\n if (/^\\s*at /m.test(signals.errorStack)) {\n return \"v8\";\n }\n if (signals.errorHasGeckoFileName) {\n return \"gecko\";\n }\n if (signals.errorHasJSCSourceURL || /^[^\\n]*@/m.test(signals.errorStack)) {\n return \"jsc\";\n }\n return \"unknown\";\n}\n\nexport function resolveWasmEngineCapabilities(\n signals: WasmEngineProbeSignals = collectWasmEngineProbeSignals()\n): WasmEngineCapabilities {\n const engine = classifyWasmEngineFamily(signals);\n return {\n engine,\n supportsJSPI:\n signals.wasmSuspendingType === \"function\" &&\n signals.wasmPromisingType === \"function\",\n stackLeanRecommended: engine !== \"v8\",\n };\n}\n\n/**\n * WASI environment defaults implied by the engine capabilities. Spread these\n * *before* caller-provided environment entries so an explicit\n * `SWIFTTUI_STACK_LEAN_PROFILE` (or a tuning override) always wins.\n */\nexport function stackProfileEnvironmentDefaults(\n capabilities: WasmEngineCapabilities\n): Record<string, string> {\n // V8 workers run non-lean by default: the measured worker stack budget\n // fits the full-depth resolve, and per-frame pipeline cost roughly\n // halves versus the lean profile. The 0.1.9 regression that forced the\n // lean-everywhere hold was NOT lean-vs-non-lean publication behavior —\n // it was completed-frame *disposal* under supersession (visual-only\n // drops + pre-start cancels saturating at the starvation floor), fixed\n // by the `async-no-cancel` render-mode default in `BrowserWASIBridge`;\n // live non-lean + async-no-cancel measures the same distinct-generation\n // coverage as lean at ~2x less per-frame CPU.\n //\n // JSC stays lean (Darwin worker threads get ~1/16 of the main-thread\n // stack). Gecko stays lean by *measurement*, not caution: Firefox live\n // (2026-07) overflows the non-lean shape in its worker.\n if (capabilities.engine === \"v8\") {\n return { SWIFTTUI_STACK_LEAN_PROFILE: \"0\" };\n }\n return {};\n}\n\n/**\n * Environment defaults for the main-thread (JSPI) execution mode, where the\n * wasm runs on the page's thread and gets its far larger stack budget\n * (measured ~12.7× the worker's on trunk WebKit).\n */\nexport function mainThreadStackProfileEnvironmentDefaults(\n capabilities: WasmEngineCapabilities\n): Record<string, string> {\n // HOLD: the main-thread (JSPI) stack budget fits non-lean on JSC and V8\n // (measured), but the JSC main-thread lane has not been soaked non-lean\n // in production, and JSPI slices the native stack — Safari 27's depth\n // budgets must be re-measured per release before this default can flip.\n // Callers can still force the profile via `SWIFTTUI_STACK_LEAN_PROFILE`.\n void capabilities;\n return {};\n}\n\nexport interface JSPIConstructors {\n Suspending: new (fn: (...args: never[]) => unknown) => unknown;\n promising: (fn: unknown) => (...args: unknown[]) => Promise<unknown>;\n}\n\n/** Typed access to the JSPI surface, or undefined where unsupported. */\nexport function jspiConstructors(): JSPIConstructors | undefined {\n const wasm = globalThis.WebAssembly as unknown as Partial<JSPIConstructors> | undefined;\n if (\n typeof wasm?.Suspending === \"function\" &&\n typeof wasm?.promising === \"function\"\n ) {\n return wasm as JSPIConstructors;\n }\n return undefined;\n}\n"],"mappings":";AAoDA,SAAgB,gCAAwD;CACtE,MAAM,wBAAQ,IAAI,MAAM,mBAAmB;CAC3C,MAAM,OACJ,WAGA;CACF,OAAO;EACL,YAAY,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ;EAC5D,uBAAuB,cAAc;EACrC,sBAAsB,eAAe;EACrC,oBAAoB,OAAO,MAAM;EACjC,mBAAmB,OAAO,MAAM;CAClC;AACF;AAEA,SAAgB,yBACd,SACkB;CAClB,IAAI,WAAW,KAAK,QAAQ,UAAU,GACpC,OAAO;CAET,IAAI,QAAQ,uBACV,OAAO;CAET,IAAI,QAAQ,wBAAwB,YAAY,KAAK,QAAQ,UAAU,GACrE,OAAO;CAET,OAAO;AACT;AAEA,SAAgB,8BACd,UAAkC,8BAA8B,GACxC;CACxB,MAAM,SAAS,yBAAyB,OAAO;CAC/C,OAAO;EACL;EACA,cACE,QAAQ,uBAAuB,cAC/B,QAAQ,sBAAsB;EAChC,sBAAsB,WAAW;CACnC;AACF;;;;;;AAOA,SAAgB,gCACd,cACwB;CAcxB,IAAI,aAAa,WAAW,MAC1B,OAAO,EAAE,6BAA6B,IAAI;CAE5C,OAAO,CAAC;AACV;;;;;;AAOA,SAAgB,0CACd,cACwB;CAOxB,OAAO,CAAC;AACV;;AAQA,SAAgB,mBAAiD;CAC/D,MAAM,OAAO,WAAW;CACxB,IACE,OAAO,MAAM,eAAe,cAC5B,OAAO,MAAM,cAAc,YAE3B,OAAO;AAGX"}
|