Files
regex-tools/docs/ENGINE_BUILDS.md

3.2 KiB

Engine builds

The production application uses the browser's native RegExp for ECMAScript and bundles a verified PCRE2 10.47 WebAssembly pack. Normal application builds never download or compile an engine: the reviewed files under public/engines/pcre2/ are copied into dist/ and verified there.

Rebuilding PCRE2

The reproducible build accepts only:

  • PCRE2 tag pcre2-10.47, signed tag object cd007b4466798f66d479d1442a407099e7c40050, peeled commit f454e231fe5006dd7ff8f4693fd2b8eb94333429 and tree 81a83a3552bd68d0ea7b7004f8bb6e7892f583ba;
  • Emscripten 6.0.4, compiler revision fe5be6afdff43ad58860d821fcc8572a23f92d19, from emsdk commit 224ec5f9f2f72f09f9ce0e26d66bae7dbd8b692f;
  • CMake 4.3.4 and Ninja 1.13.2;
  • 8-bit PCRE2 with Unicode enabled and JIT, threads and filesystem disabled.

The source and compiler checkouts must already exist locally and be completely clean. No command clones, downloads or updates them:

npm run engines:pcre2:build -- \
  --source-dir /absolute/path/to/pcre2 \
  --emcc /absolute/path/to/emscripten/emcc
npm run engines:pcre2:verify
npm run engines:pcre2:install

Use --force only to replace the exact ignored .engine-build/pcre2 output. The explicit install command first re-verifies that pack and then atomically replaces only public/engines/pcre2.

The builder verifies Git objects and critical source/compiler hashes, sanitizes build flags, sets SOURCE_DATE_EPOCH=1760997684, builds serially and emits exactly:

  • pcre2.mjs and pcre2.wasm;
  • deterministic engine-metadata.json;
  • the exact upstream LICENSE.txt;
  • SHA256SUMS.

The verifier checks the closed file set, metadata, source bridge hashes and all checksums. It validates and instantiates WebAssembly, checks ABI/engine/config identity, then executes native Unicode compile, bounded match and bounded substitution smoke cases plus normal and cap-stopped automatic-callout traces.

The immutable signed-tag object is pinned. OpenPGP trust validation remains a release-operator step because the offline builder does not install or trust a key.

Runtime boundary

ABI version 3 has no retained native handles. Each call compiles, obtains capture names, matches/substitutes or traces and releases its code, match data and match context before returning. The caller supplies fixed-capacity result/name/output/event/mark buffers. Hard maxima are 1 MiB pattern, 16 MiB subject, 1,000 captures, 10,000 matches, 100,000 capture rows, 50,000 trace events, 10 MiB serialized trace data and 128 MiB PCRE2 heap limit; the workbench uses stricter pattern and replacement input limits where applicable.

PCRE2 always runs with UTF and UCP. Native UTF-8 byte offsets are retained in DTOs and converted only at valid code-point boundaries to half-open editor UTF-16 ranges. Lone UTF-16 surrogates are rejected before encoding.

Normal execution lives only in pcre2.worker. Instrumented PCRE2_AUTO_CALLOUT collection is a separate ABI operation loaded only by pcre2-trace.worker; normal match, replacement, tests, corpus and benchmarks never call it. Each supervisor terminates its worker on timeout, crash, cancellation or supersession and lazily creates a clean generation for the next request.