Comparison
Default Manifold
Stock OpenCascade
context.signal, context.feature,
context.tolerance, and every low-level STEP export option from own data
properties only. An accessor-backed field, or one supplied by a
caller-defined prototype such as a class getter, fails with TypeError
instead of being ignored, so a class-based cancellation signal is never
silently dropped. A field reachable only through the intrinsic
Object.prototype is ignored, so prototype pollution cannot relabel feature
lineage or change kernel tolerances. feature must be a string and
tolerance a number when present. Each operation captures these values once
when it is called: changing or reusing the context object afterwards does not
change the lineage that later topology() calls report for shapes it already
created.
The profile is stronger than checking representation === "brep": creation
also requires the documented primitive and feature baseline, native exchange
methods, exactness, face/edge/vertex topology with semantic roles, sketch
sources, geometry, and adjacency, and a callable topology() snapshot method.
inspectEvaluatorProfile(kernel, "mechanical-exact") lists each missing
requirement as a stable path such as topology:adjacency or
topology:snapshot. For custom loading, create the kernel explicitly and
request the same preflight:
createOcctKernel() receives an explicit wasm source or
moduleFactory and the loaded module does not expose the owned facade ABI,
the kernel is not the qualified zero-override stock runtime, even when it
loads the identical stock occt-wasm.wasm bytes. It omits the persistent
topology signature declaration (capabilities.topology.signatures and
signatureProfiles), so evaluating a document that stores a persistent
topology reference fails with KERNEL_CAPABILITY_MISSING for capability
persistent-topology-signatures. It also omits the
deterministic stepExport envelope and keeps weak raw STEP export. The
mechanical-exact preflight still passes, because it does not require
signatures. Prefer letting the bundler place occt-wasm.wasm next to its
JavaScript glue so the zero-override createOcctKernel() call can load it.
Owned OCCT facade
Capability preflight
The evaluator treats capabilities as data contracts. Before executing a feature, it checks:- protocol version
- primitive or feature name
- exact composite-sweep refinements
- native import/export format
- strong single-body import format and unit mode
- topology evidence surfaces and signature fingerprint
- exact indexed topology evolution when a stronger contract is required
- versioned measurement semantics such as exact or unsupported genus
- body-result classification protocol and a callable classifier whenever a staged product solid graph contains a Boolean
- deterministic single-shape STEP metadata, bounds, and byte scope
inspectKernelMeasurementCapabilities(...) or
kernelSupports(capabilities, "measurement", "genus") for discovery. A numeric
measurement is exact for the backend representation; null means unsupported.
The following strong STEP envelope was added in 0.2.0 and is not in 0.1.1.
Use inspectKernelStepExportCapabilities(...) for the optional strong STEP
envelope. nativeExports containing "step" promises only that bytes can be
written. Calling output.export("step") without a second argument remains
compatible with weak kernels; supporting kernels use their deterministic
defaults, and fall back to weak native bytes for an output they can write only
as several STEP products. Passing any second argument, including {},
requires a valid stepExport envelope or throws CadError with
KERNEL_CAPABILITY_MISSING.
nativeImports is the weak exchange declaration. Document-backed imported
bodies require the separate versioned documentBodyImport envelope and a
callable importDocumentBody(...) method. Stock OCCT currently makes only
these stronger promises:
The strong path rejects multiple solids, shells, and wrappers containing loose
topology. It unwraps a pure one-solid compound, normalizes reversed orientation,
uses fatal UTF-8 for text BREP, and releases provisional native handles on
failure or cancellation. It does not claim healing, assembly import, stable
feature lineage, or containment of an untrusted native parser.
The public
ImportedBodyDocument workflow composes this kernel
contract with a caller-supplied SHA-256/byte-length commitment and resolver.
It accepts only STEP + model/step + file units, text BREP + text/plain +
declared units, or binary BREP + application/octet-stream + declared units.
Its explicit format chooses the reader; the media type is provenance rather
than inference. The high-level workflow fails before native parsing when
resolution or commitment verification fails and never falls back to
importShape(...) or Manifold. See Import and export.
Body-result classification
Body-result classification was added in 0.2.0 and is not in 0.1.1.
bodyResultClassification: { protocolVersion: 1 } implements
classifyBodyResult(shape, context?). The call borrows one shape and returns
exactly one classification of its retained representation:
Use
inspectKernelBodyResultClassificationCapabilities(...) for discovery. It
reads only own data properties, never invokes accessors, returns an immutable
snapshot, and reports uninspectable-metadata, not-object, or
unsupported-protocol-version separately from absent support.
The result describes the kernel’s declared representation, so it inherits that
representation’s exactness:
- Manifold classifies connected components of its approximate mesh. Each component with strictly positive native volume is a body. Manifold separates a hollow solid’s cavity boundary into a negative-volume component, so that boundary bounds a void rather than adding a body. A zero-volume component is non-body topology. Its native decomposition is one synchronous WASM call: cancellation is checked before and after it, not during it. Every temporary component is deleted on success, failure, and cancellation.
- OCCT classifies exact B-Rep contents. It traverses compound and compsolid occurrences, counts each solid occurrence as one body without reinterpreting that solid’s shells, and treats any other occurrence as loose topology. Repeated occurrences of the same solid count separately. Cancellation is checked before each traversal step and after traversal. Visited plus queued occurrences, including the root and every compound or compsolid wrapper, are bounded at 1,000,000: the pinned runtime has no non-allocating child count, so one native call materializes a wrapper’s direct children, which are charged to the bound immediately and released when it rejects them. Every traversal handle is released on success, failure, and cancellation.
abort()
scheduled from elsewhere on the same thread cannot run until the call returns.
context must be a plain object, and context.signal, when present, must be
an own data property; an accessor-backed signal or one supplied by a
caller-defined prototype fails with TypeError instead of being ignored, while
one reachable only through Object.prototype is ignored as pollution. Context and cancellation are checked
before the shape is validated.
Classification is structural. It does not validate the bodies it counts:
check status(...) separately, as the staged evaluator does before
classifying.
The two classifications are not a cross-backend equivalence claim. For
example, Manifold reports two boxes that touch only along an edge as two
components of its mesh; near-contact geometry can classify differently on
another backend.
The staged Document v7 evaluator uses this contract to require that every
Boolean result is exactly one body. It never splits a disconnected Boolean
into invented body-set members, retries another backend, or converts exact
geometry to mesh. Authors who need separate bodies list them explicitly in a
bodySet.
Do not equate these guarantees
- A B-Rep kernel is not automatically exact for every authored feature.
- Construction support does not imply complete topology history.
- STEP/BREP exchange does not imply safe backend-owned shape artifact caching.
- Native STEP export does not imply deterministic metadata or byte equality.
- Weak native import does not imply the strong document-body import contract.
- A topology snapshot does not imply persistent signature support.
- Successful tessellation does not make mesh coordinates analytically exact.
- A
single-bodyclassification is only as exact as the kernel representation it classifies.