Skip to content

Build And Test

Build the WebAssembly package from the repository root:

npm run wasm:build

The build requires Docker and pulls emscripten/emsdk:3.1.74 on first use. It writes packages/wasm/dist/muhammara-wasm.js and packages/wasm/dist/muhammara-wasm.wasm.

Docker is the only supported build toolchain. Start its daemon before running the command; the build intentionally has no local-Emscripten fallback so release artifacts use the pinned image. Release CI builds dist/ first and publishes the validated result with npm lifecycle scripts disabled. The npm package is a precompiled runtime distribution and does not include these development inputs.

Compiler Cache

The pinned Emscripten image ships no ccache, so the build adds it in a thin layer on top of that image and tags the result with the pinned digest. The layer is built once per digest and reused afterwards; when it cannot be built, for example without network access, the build falls back to the pinned image and compiles without a cache.

Compiled objects are kept in packages/wasm/.ccache/<configuration> and the CMake tree in packages/wasm/build/<configuration>, where the configuration is derived from the build type and the sanitizer setting (release-sanitize-off, release-sanitize-on). Sanitizer and normal builds therefore never share objects. Wasm CI restores the cache per configuration through .github/actions/setup-wasm-build-cache, keyed on the Emscripten image digest, the build script, CMakeLists.txt, and the Wasm and shared C++ sources. Cached and uncached builds produce identical dist/ bytes.

These environment variables adjust the build:

Variable Default Effect
MUHAMMARA_WASM_SANITIZE OFF ON builds with Emscripten LeakSanitizer; address with AddressSanitizer and stack overflow checks, for fuzzing.
MUHAMMARA_WASM_BUILD_TYPE Release CMAKE_BUILD_TYPE for the build.
MUHAMMARA_WASM_CCACHE ON Set to OFF to build straight from the pinned image.
MUHAMMARA_WASM_CCACHE_DIR packages/wasm/.ccache Root directory holding the per-configuration caches.
MUHAMMARA_WASM_CCACHE_MAXSIZE 1G Upper bound for one configuration's cache.

./packages/wasm/build.sh --print-cache-directory and --print-build-directory report the directories for the current settings without touching Docker; CI uses the first one so the workflow never repeats the layout the script owns.

After a build, run the focused checks:

npm run wasm:verify
npm run wasm:test
npm run wasm:test:types
npm run wasm:test:paths
npm run wasm:test:exports
npm run wasm:test:manifests
npm run wasm:test:browser

The manifest check compares the native GYP and Wasm CMake PDFWriter translation units without changing either vendored manifest. The export check requires the CMake export list to match the symbols used by the package runtime exactly.

The browser test starts a local server and uses puppeteer-core. Set CHROME_BIN to a Chrome executable or FIREFOX_BIN to a Firefox executable; CI provisions Chrome with browser-actions/setup-chrome. Wasm tests share native test fixtures under packages/native-with-source/tests/TestMaterials.

Wasm documentation sources are package-local and are not published in the npm package. The standalone WebAssembly documentation site is configured by packages/wasm/.readthedocs.yaml; configure its Read the Docs project to use that file. Native documentation is maintained separately in packages/native/docs/.

Fuzzing

npm run fuzz --workspace=@muhammara/wasm runs a mutation fuzzer against the built package; build with MUHAMMARA_WASM_SANITIZE=address first so memory errors are reported where they happen. See tests/fuzz/README.md for targets, options, and how to turn a finding into a regression test. The Wasm Fuzzing workflow runs it weekly and on demand.

Documentation

Create a Python virtual environment and install the WebAssembly site's pinned documentation dependencies:

python -m venv .docs-venv
source .docs-venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r packages/wasm/docs/requirements.txt

Build the site strictly before opening a pull request:

npm run docs:check --workspace=@muhammara/wasm

After Wasm tests pass on develop, CI stages the browser example with that run's Wasm artifact and updates its dev version under wasm/browser-example on GitHub Pages. Release tags deploy immutable versions and update their alpha, beta, rc, or latest alias. mike stores the generated examples on the gh-pages branch; pull requests create no preview versions that require cleanup. Wasm reference documentation remains on Read the Docs.

Serve a local preview with:

mkdocs serve --config-file packages/wasm/mkdocs.yml

Never commit generated packages/wasm/docs/reference.md or packages/wasm/site/ output.

Release Tags

WebAssembly package tags trigger validation and publication. The package version must match the version in the tag. Wasm releases use npm trusted publishing through GitHub Actions OIDC and do not require an npm token. The workflow checks the runtime package contents and an npm publish dry run, publishes to npm, and only then creates the GitHub release.

Before the first Wasm release, configure an npm trusted publisher for @muhammara/wasm that trusts this repository's Wasm release workflow and release environment.

# WebAssembly release example.
git tag wasm-v1.0.0
git push origin wasm-v1.0.0

The release body is generated at build time by .github/scripts/release-notes.mjs. It copies the ## [<version>] section of packages/wasm/CHANGELOG.md, so that section must exist before the tag is pushed; the workflow fails before anything is published when it is missing. Below the changelog, the notes list the pull requests merged since the previous wasm-v tag with the issues they close, every contributor, the contributors whose first commit on the default branch is part of the release, and a compare link. Documentation tags and the tags of the other package are never picked as the previous tag. The same notes can be reproduced for a published release:

# Print the release notes of a tag. GITHUB_TOKEN raises the API rate limit.
node .github/scripts/release-notes.mjs packages/wasm/CHANGELOG.md wasm-v wasm-v1.0.0

After successful publication, the workflow automatically creates a matching wasm-doc-v<version> documentation tag. A later documentation-only correction can be tagged without rebuilding or publishing the package:

git tag wasm-doc-v1.0.0.1
git push origin wasm-doc-v1.0.0.1

Documentation tags trigger only the documentation workflow.