WebAssembly i workery
Build C++23 do WASM, publiczne API instancji, Dedicated Worker z zero-copy transferami i anulowaniem przez AbortSignal.
Build#
Kompilacja natywnego rdzenia C++23 do zoptymalizowanego -O3 WASM:
npm run wasm:build
npm run verify:wasm
scripts/build-wasm.mjs kompiluje wszystkie jednostki translacji z flagami:
-std=c++23 -O3 -ffunction-sections -fdata-sections
-Wl,--gc-sections -Wl,--strip-all
Target: wasm32-wasi reactor mode. Artefakty:
apps/web/public/wasm/vector_engine.wasmapps/web/public/wasm/vector_engine.js(loader zgodny z CSP)
Publiczne API instancji#
| Funkcja | Co robi |
|---|---|
validateJson(source) | Walidacja schemy, unikalnych ID, gradientów, warstw, workspace'ów i limitów |
measureBounds(source, optionsJson) | Dokładne analityczne bounding boxy przez złożone transformacje i stroke |
renderScopedSvg(source, optionsJson) | Ekstrakcja scope, viewport/margin/clip/fit, zwraca SVG + metadane |
exportScopedMeta(source, optionsJson) + takeLastBytes() | Rasteryzacja i enkodowanie; bajty kopiowane raz przez pamięć liniową |
renderSvg(...), exportBinary(...) | Legacy convenience entrypoints |
Dedicated Worker#
WorkerBackend uruchamia exportWorker.ts poza głównym wątkiem UI:
UI thread Worker thread
│ export(source, opts) │
│ ─────────────────────────▶ │ WASM render + encode
│ │
│ Transferable ArrayBuffer │
│ ◀───────────────────────── │ zero-copy transfer
│ │
│ abort() │
│ ─────────────────────────▶ │ terminate() natychmiast
│ nowy worker przy next op │
- Zakodowane bufory wracają przez zero-copy
TransferableArrayBuffer— bez kopiowania megabajtów PNG między wątkami. AbortSignal.abort()terminuje workera natychmiast, bez blokowania UI.- Następna operacja transparentnie inicjuje czystego workera.
Przykład: adapter#
import { WorkerBackend } from '@/engine/workerBackend'
const backend = new WorkerBackend()
const validation = await backend.validateJson(source)
if (!validation.valid) throw new Error(validation.errors[0].message)
const meta = await backend.exportScopedMeta(source, JSON.stringify({
format: 'png',
width: 2400,
height: 1600,
background: 'transparent'
}))
const bytes = backend.takeLastBytes()
const blob = new Blob([bytes], { type: 'image/png' })
Anulowanie w locie#
const controller = new AbortController()
const promise = backend.exportScopedMeta(source, options, controller.signal)
setTimeout(() => controller.abort(), 5000)
try {
await promise
} catch (e) {
if (e.name === 'AbortError') {
status.value = 'Eksport anulowany'
}
}
Fallback przeglądarkowy#
Gdy artefaktów WASM nie ma (świeży checkout bez builda), development używa BrowserBackend — implementacji zgodnej API w TypeScripcie. UI działa, ale produkcyjnie zawsze weryfikuj rdzeń:
npm run verify:wasm
Weryfikacja sprawdza fabrykę JavaScript i magic header WebAssembly przed buildem Vite.
Dostarczanie WASM#
Deployment serwuje:
/wasm/vector_engine.js
/wasm/vector_engine.wasm
z Content-Type: application/wasm, same-origin resource policy i revalidation caching dla stabilnych nazw plików. Szczegóły: Wdrożenie na Vercel.
Jeden rdzeń, trzy wyjścia
Ta sama implementacja C++23 zasila natywną bibliotekę, CLI i WASM. Nie ma osobnego „renderera przeglądarkowego” do utrzymania — fallback dev to jedyny wyjątek i jest jawnie oznaczony.