Files
2026-07-30 16:48:46 +05:30
..
fix
2026-07-30 16:48:46 +05:30
fix
2026-07-30 16:48:46 +05:30
2026-06-22 15:18:47 +05:30
2026-06-22 15:18:47 +05:30
2026-06-22 15:18:47 +05:30
2026-06-22 15:18:47 +05:30

WASM (Emscripten)

Phase 0 task "WASM hello-world build (Emscripten)" lives here. The full engine-in-WASM build is Phase 2 work — see Phase 2 below.

Rule R5: WASM never blocks shipping. Server-side rendering is always the fallback. This Phase 0 deliverable is validation only — proves that the Emscripten toolchain end-to-end compiles a C++ function callable from JS. Do not gate Phase 1 on it.

What's here today

wasm/
  emsdk.pinned          # pinned Emscripten SDK version
  CMakeLists.txt        # builds the hello-world Emscripten target
  hello.cpp             # exports add() and hello_version() via EMSCRIPTEN_KEEPALIVE
  hello.test.mjs        # Node 20+ smoke test — loads the module, asserts return values
  package.json          # `npm test` shortcut for hello.test.mjs

Build output goes to out/build/wasm/bin/hello.{mjs,wasm}. The .mjs is an ES6 module that imports cleanly into Node 20+ and modern browsers.

Prerequisites

  1. Emscripten SDK at the version pinned in emsdk.pinned.

    git clone https://github.com/emscripten-core/emsdk
    cd emsdk
    ./emsdk install 3.1.74     # match emsdk.pinned
    ./emsdk activate 3.1.74
    source ./emsdk_env.sh      # Linux/macOS
    .\emsdk_env.bat            # Windows cmd.exe
    .\emsdk_env.ps1            # Windows PowerShell
    

    After emsdk_env runs in your shell, $EMSDK is set — that's what cmake/toolchains/wasm.cmake keys off. On Windows, install emsdk on a space-free path outside OneDrive (same rule as the PDFium build — see docs/phase0.md).

  2. Node 20+ for the smoke test (CI uses Node 20).

  3. CMake 3.25+ and Ninja — already required for the rest of the repo.

Build + run

cmake --preset wasm
cmake --build --preset wasm

node wasm/hello.test.mjs
# → [wasm-smoke] OK — add(2,3)=5, hello_version()=1, cwrap add(40,2)=42

CI does the same three commands on Ubuntu after installing the pinned emsdk.

Local build dir override (Windows / OneDrive)

The default binaryDir lives under the repo. On Windows the OneDrive + spaced-path constraint applies — drop a CMakeUserPresets.json next to this README's parent that overrides binaryDir to e.g. C:/Users/<you>/pdfeng-build/wasm, and set HELLO_MJS=C:/Users/<you>/pdfeng-build/wasm/bin/hello.mjs when running the smoke test.

What this proves (and what it does NOT)

Validated by Phase 0 hello-world Still TODO in Phase 2
emsdk install + version pin PDFium cross-compiled with Emscripten
cmake --preset wasm configures cleanly Skia / FreeType / HarfBuzz cross-compiled
C → JS export via ccall/cwrap Engine cross-compiled
ES6-module output usable from Node + web Web Worker + OffscreenCanvas integration
CI pipeline for the WASM artifact Page-render parity with the server path

Phase 2 — real engine-in-WASM

When that work begins, do not delete the hello-world target — keep it as a toolchain canary so a broken emsdk install fails fast and obviously. The real target will live alongside it (e.g. pdfengine_wasm) and consume the engine library via the standard CMake import path once the engine has Emscripten support in its vcpkg/build story.

Key flags to carry forward (engine blueprint §6): ALLOW_MEMORY_GROWTH=1, Web Worker + OffscreenCanvas for off-main-thread rendering, ES6 module output.