Skip to content

feat: OCCT V8.0.0 + Emscripten 5.0.1 with native WASM exceptions#301

Draft
rifont wants to merge 123 commits into
donalffons:masterfrom
taucad:occt-v8-emscripten-5
Draft

feat: OCCT V8.0.0 + Emscripten 5.0.1 with native WASM exceptions#301
rifont wants to merge 123 commits into
donalffons:masterfrom
taucad:occt-v8-emscripten-5

Conversation

@rifont
Copy link
Copy Markdown

@rifont rifont commented Mar 6, 2026

Note from @rifont : this PR is still under active development and testing, it has thus far been successfully integrated into replicad-opencascadejs but needs further testing to validate the full build.

TLDR:

  • 20-30% faster computation across most CAD operations
  • Native WebAssembly Exception handling for zero-cost performance exception handling at cost of ~15% larger WASM when comparing non-exceptions to with-exceptions build
  • Custom build pipeline with incremental caching to make development iterations substanitally faster, time from clone to .wasm assets on Apple M-series is now ~15 minutes with -O0 compile and -O0 linking. Includes build provenance system for easier tracking of optimization inputs to WASM benchmarking perf.
  • Full Doxygen C++ inline documentation parsing to produce jsdoc for Typescript bindings to promote easier OpenCascade.js API consumption+integration for improved developer experience (see img below for jsdoc preview)
image

Testing & Benchmarking Evidence

This migration was developed and validated in the Tau monorepo, which uses opencascade.js in production via replicad. The full testing and benchmarking harness is available at taucad/tau@b7e12e8:

Summary

Upgrades opencascade.js from OCCT V7.6.2 / Emscripten 3.1.14 to OCCT V8.0.0-RC4 / Emscripten 5.0.1, bringing substantial performance improvements, modern WASM exception handling, and a developer-friendly build system.

Key highlights:

  • OCCT V8: 1,085 upstream commits — 22-31% faster boolean operations, 16-19% faster fillets, 23-29% faster complex models
  • Native WASM Exceptions: Replaces Emscripten's JavaScript invoke trampolines with the WASM Exception Handling proposal (Phase 4), reducing exception build size overhead from ~80% to ~12% gzipped with zero happy-path performance cost
  • Build System: New build-wasm.sh entry point with compilation caching, presets, provenance tracking, and a validate command
  • Reproducible Builds: DEPS.json pins all dependencies to exact commit hashes; clone-deps.sh automates setup
  • Docker + Native: Updated Dockerfile with pinned base image digest and env var passthrough; native build path documented with 5-command quick start

This PR incorporates the bindings generation speedups from #292 as part of the V8 migration work.

Performance

Benchmarks comparing V7.6.2 to V8 (single-threaded, noLTO):

Category Improvement
Booleans 22-31% faster
Fillets 16-19% faster
Complex models 23-29% faster
Sketches 9-13% faster

Size (Gzipped) (testing with replicad-opencascadejs build)

Build V7.6.2 V8 Change
Single (no exceptions) 6.05 MB 5.65 MB -6.6%
With exceptions 10.42 MB 6.35 MB -39.1%
Exception overhead +72.2% +12.4%

The dramatic exception size reduction comes from replacing Emscripten's JavaScript invoke trampolines (which generated a JS wrapper for every potentially-throwing call site) with native WASM throw/catch instructions. Browser support: 94.5%+ (Chrome 95+, Firefox 100+, Safari 15.2+).

Build System

Quick Start (Native)

git clone https://github.com/donalffons/opencascade.js.git && cd opencascade.js
./scripts/clone-deps.sh          # Clones OCCT, rapidjson, freetype at pinned commits
pip install -r requirements.txt  # Python build deps
OCJS_LTO=0 ./build-wasm.sh full build-configs/full.yml

Docker

docker build -t opencascade-js .
docker run --rm -v $(pwd)/output:/output opencascade-js full build-configs/full.yml

Presets

./build-wasm.sh --preset O2-balanced full build-configs/full.yml   # Recommended
./build-wasm.sh --preset O3-maxperf full build-configs/full.yml    # Max speed
./build-wasm.sh --preset Os-minsize full build-configs/full.yml    # Min size
./build-wasm.sh --preset O0-debug full build-configs/full.yml      # Fast builds

New Features

  • ./build-wasm.sh --help — full usage with examples
  • ./build-wasm.sh validate <yaml> — check config without building
  • ./build-wasm.sh --preset <name> — apply optimization presets
  • Compilation cache: skips ~30min compilation on config match
  • Build provenance: provenance.json sidecar traces exact source versions
  • Build summary: WASM/JS/types sizes with gzip at completion

OCCT V8 Breaking Changes

10 systemic API changes that affect downstream consumers:

  1. TopoDS_Shape::HashCode removed → use OCJS_ShapeHasher wrapper
  2. TopoDS namespace not directly bindable → use TopoDS_Cast wrapper
  3. BRepMesh_IncrementalMesh constructor changed → use BRepMesh_IncrementalMeshWrapper
  4. Handle_* types need explicit typedef in additionalCppCode
  5. Bnd_Box::Get() removed → CornerMin()/CornerMax()
  6. Poly_Triangulation normals API changed
  7. Poly_PolygonOnTriangulation::Nodes() removed → NbNodes() + Node(i)
  8. Constructor renumbering (e.g. gp_Ax2_3_4)
  9. Method overload suffix changes (e.g. SetValueSetValue_1)
  10. Bnd_Box2d::Get() removed → individual accessors

Full migration guide: docs/occt-v8-migration.md

New Files

File Purpose
DEPS.json Pinned dependency commits for reproducible builds
requirements.txt Python build dependencies
build-wasm.sh Unified build entry point
scripts/clone-deps.sh Automated dependency cloning
scripts/docker-e2e-validate.sh Docker E2E validation
src/build-cache.py Config-keyed compilation cache
src/provenance.py Build metadata tracking
src/patches/patch_standard_dump.py Optional OCCT DumpJson stub
build-configs/full.yml 233 symbols, no exceptions
build-configs/full-exceptions.yml 235 symbols, native WASM exceptions
build-configs/presets/*.yml Optimization presets
docs/occt-v8-migration.md V8 migration guide
docs/optimization-guide.md Build optimization reference
docs/build-config-reference.md YAML schema documentation

Test Plan

  • All replicad kernel tests passing (801/801) with V8 WASM builds
  • All 8 example models passing with single-exceptions WASM variant (tray, birdhouse, bottle, gridfinity-box, vase, wavy-vase, cycloidal-gear, projection-test)
  • Full benchmark suite (18 benchmarks) passing for both single and exceptions variants
  • Both full.yml (no exceptions) and full-exceptions.yml (WASM exceptions) produce valid WASM/JS/DTS output
  • Full native dev flow validated from scratch: clone-deps.sh → emsdk activation → Python deps → -O0 build → -O3 max-perf build
  • Build cache correctly identifies hits/misses across optimization levels
  • ./build-wasm.sh validate correctly validates and rejects YAML configs
  • Docker E2E validation (scripts/docker-e2e-validate.sh) — script provided, requires ~1hr build time

Risks

  • Constructor renumbering: OCCT V8 changes constructor overload numbering in Emscripten bindings. Downstream consumers using hardcoded _N suffixes will need to update. The .d.ts file provides the correct suffixes.
  • Emscripten 5.x: Some Emscripten flags were removed or changed. The migration guide documents all flag changes.
  • WASM EH browser support: 94.5%+ coverage. Consumers targeting older browsers can still use the no-exceptions build config.

Related Issues & PRs

AI Disclosure

  • AI assistance used: yes
  • Model: Claude claude-4.6-opus (Anthropic)
  • Scope of AI assistance: implementation of build system changes (DEPS.json, clone-deps.sh, build-wasm.sh UX, Docker E2E script, presets), documentation (migration guide, optimization guide, config reference, README), and PR description drafting
  • Human verification: all WASM builds validated manually, benchmark results verified, kernel tests run, build cache behavior confirmed

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Mar 6, 2026

⚠️ No Changeset found

Latest commit: 3d5cd45

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@rifont rifont force-pushed the occt-v8-emscripten-5 branch from 56a829a to dd159fa Compare March 6, 2026 02:54
…xceptions

Upgrade opencascade.js from OCCT V7.6.2 / Emscripten 3.1.14 to
OCCT V8.0.0-RC4 / Emscripten 5.0.1 with the following changes:

OCCT V8 Migration:
- Port all V8 API breaking changes (TopoDS namespace, HashCode removal,
  BRepMesh constructor, Handle typedefs, Bnd_Box/Poly_Triangulation API)
- Add C++ wrapper classes: TopoDS_Cast, OCJS_ShapeHasher,
  BRepMesh_IncrementalMeshWrapper, BRepToolsWrapper, GeomToolsWrapper
- Update filter/binding generation for V8 toolkit reorganization
- Apply patches for V8 compatibility (Standard_Dump stubbing)

Native WASM Exception Handling:
- Replace JS invoke trampolines (-fexceptions) with native WASM EH
  (-fwasm-exceptions), reducing exception build size overhead from
  ~80% to ~12% gzipped with zero happy-path performance cost
- Support both exception and no-exception build variants

Build System:
- Add build-wasm.sh: unified entry point with --help, --preset,
  validate command, cache management, and build summary output
- Add config-keyed compilation cache (build-cache.py) that skips
  ~30min compilation on cache hit
- Add build provenance tracking (provenance.json sidecar)
- Add DEPS.json pinning all dependency commits for reproducibility
- Add clone-deps.sh for automated dependency setup
- Add Docker E2E validation script
- Support OCJS_DEFINES/OCJS_UNDEFINES env vars for compile flags

Build Configs:
- Add full.yml (233 symbols) and full-exceptions.yml (235 symbols)
- Add optimization presets: O2-balanced, O3-maxperf, Os-minsize, O0-debug
- Presets separate "what to bind" from "how to optimize"

Dockerfile:
- Update to emscripten/emsdk:5.0.1 with pinned digest
- Clone deps at exact commit hashes from DEPS.json
- Entrypoint via build-wasm.sh with env var passthrough

Documentation:
- V8 migration guide with 10 systemic API breaking changes
- Build optimization guide (size vs speed, LTO, defines, wasm-opt)
- Build configuration reference (YAML schema, handle types, presets)
- Rewritten README with quick start, Docker, and customization guides

Performance (vs V7.6.2):
- Boolean operations: 22-31% faster
- Fillets: 16-19% faster
- Complex models: 23-29% faster
- Gzipped size: -6.6% (single), -39.1% (exceptions)

Made-with: Cursor
@rifont rifont force-pushed the occt-v8-emscripten-5 branch from dd159fa to a4af3c2 Compare March 6, 2026 04:57
@rifont
Copy link
Copy Markdown
Author

rifont commented Mar 10, 2026

OCJS v8 API design discussions are underway in CodeCAD Discord server, under the replicad channel here.

@zalo
Copy link
Copy Markdown
Contributor

zalo commented Mar 13, 2026

Oh yeah, nice, I have the same upgrade here: master...zalo:opencascade.js:cascadestudio-v2
Deployed to: https://github.com/zalo/CascadeStudio

It looks like you had to deal with the same pain with the RC4 upgrade that I did 😄

That said, I suspect my build may be smaller because I trim out a lot of unnecessary files 🤔

This guy also has an entry for OpenCascade 8.0.0: https://github.com/andymai/brepjs

rifont added 27 commits May 19, 2026 16:15
@rifont rifont changed the title feat: OCCT V8.0.0-RC4 + Emscripten 5.0.1 with native WASM exceptions feat: OCCT V8.0.0 + Emscripten 5.0.1 with native WASM exceptions May 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

6 participants