459 lines
22 KiB
Markdown
459 lines
22 KiB
Markdown
# Engine builds
|
|
|
|
The production application uses the browser's native `RegExp` for ECMAScript
|
|
and bundles ten verified runtime packs for standalone PCRE2, PHP, Perl, Python,
|
|
Ruby, Java, C++, Go, Rust and .NET. The Scala/JVM compatibility profile shares
|
|
the Java pack and contains no Scala runtime. Normal application builds never
|
|
download or compile an engine: reviewed files under `public/engines/` 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:
|
|
|
|
```sh
|
|
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.
|
|
|
|
## Installing the Python pack
|
|
|
|
The Python pack is derived from the exact `pyodide@314.0.3` npm package locked
|
|
with integrity:
|
|
|
|
```text
|
|
sha512-sK40My6m8tmBUYtYH9au9rXUeh9x0wfahtHdOlGmJxZDsKBGKtP6KznyFB2+u/klbQTdDionR0uaVd176zVQzQ==
|
|
```
|
|
|
|
That Pyodide release is tag/commit
|
|
`ac57031be7564f864d061cb37c5c152e59f83ad4`. Direct executable identity
|
|
verification reports CPython 3.14.2; the shipped `pyodide-lock.json`
|
|
independently reports `info.python` as 3.14.0, and the verifier records rather
|
|
than conflates those two upstream identities. The pack copies only the reviewed
|
|
loader, WebAssembly runtime, Python standard library and lock metadata required
|
|
for a local CPython `re` worker. It adds deterministic engine metadata, a
|
|
closed-file-set checksum manifest and a complete `SOURCE-MANIFEST.json`.
|
|
|
|
The source manifest records immutable Git commit/tree identities or primary
|
|
release-archive SHA-256 values for Pyodide, its `pyodide-build` submodule, its
|
|
vendored Error Stack Parser 2.1.4 and StackFrame 1.3.4 ports, CPython, libffi,
|
|
Hiwire, XZ/liblzma, Zstandard, SQLite, the Emscripten bzip2 and zlib ports,
|
|
Emscripten itself and HACL* preferred source. It hashes both vendored
|
|
JavaScript ports, all nine CPython patches, all five Emscripten patches, and
|
|
the Pyodide Makefiles that select those inputs. That is the
|
|
preferred-form/patch route for the upstream MPL source; the exact npm package
|
|
remains the binary-distribution reference, not a claim that arbitrary future
|
|
host SDK packaging will reproduce identical bytes.
|
|
|
|
The linked-component inventory is derived from the exact Pyodide recipe and
|
|
checked against executable identities where the libraries expose one. Besides
|
|
Pyodide and CPython, the base module contains CPython-vendored Expat 2.7.3,
|
|
libmpdec 2.5.1 and HACL*, plus libffi, Hiwire 1.0.1, liblzma 5.2.2,
|
|
Zstandard 1.5.7, SQLite 3.39.0, bzip2 1.0.6 and zlib 1.3.1. The conservative
|
|
Emscripten 5.0.3 runtime notice closure covers musl, compiler-rt, libc++,
|
|
libc++abi, libunwind, dlmalloc and the MiniLZ4 source selected by the pinned
|
|
link flags. The upstream stripped module contains no link map, so retaining the
|
|
complete potentially selected Emscripten runtime notice set is intentional.
|
|
|
|
The install operation reads from the already installed pinned npm package. It
|
|
does not contact a CDN or package index. It verifies source package identity,
|
|
file hashes, runtime metadata, every independently fetched legal-source hash,
|
|
the generated source manifest and licence inputs before atomically replacing
|
|
only `public/engines/python/`. The distribution verifier checks the same closed
|
|
set under `dist/`, validates WebAssembly and native component identities and
|
|
confirms that all runtime references remain relative and self-hosted.
|
|
|
|
```sh
|
|
node scripts/python-engine-pack.mjs \
|
|
node_modules/pyodide \
|
|
.engine-build/python
|
|
node scripts/install-python-engine.mjs .engine-build/python
|
|
```
|
|
|
|
The installed closed set is:
|
|
|
|
- `pyodide.mjs`, `pyodide.asm.mjs` and `pyodide.asm.wasm`;
|
|
- `python_stdlib.zip` and `pyodide-lock.json`;
|
|
- `engine-metadata.json`, `SOURCE-MANIFEST.json` and `SHA256SUMS`; and
|
|
- 22 exact `LICENSE.*`/`NOTICE.*` files enumerated and source-anchored by that
|
|
manifest.
|
|
|
|
`pyodide-lock.json` is the upstream catalogue of optional packages. Regex
|
|
Tools does not ship the catalogue's wheels; `externalPackagesIncluded: false`
|
|
and the closed pack file set make that boundary machine-verifiable.
|
|
|
|
## Building the Java pack
|
|
|
|
The Java bridge under `engines/java/` wraps TeaVM 0.15.0
|
|
`java.util.regex.Pattern` and `Matcher`. TeaVM tag/commit
|
|
`ee91b03e616c4b45401cd11fb0cd7eb0daf6649b` is pinned through the Maven build.
|
|
The build produces a minified ES2015 module without source maps, source files,
|
|
remote imports or an OpenJDK runtime.
|
|
|
|
The pack gate verifies the Maven coordinates, bridge source identity, TeaVM
|
|
engine identity and self-test, generated module, deterministic metadata,
|
|
checksums, Apache-2.0 licence and TeaVM NOTICE. Only the verified pack is
|
|
installed under `public/engines/java/`.
|
|
|
|
```sh
|
|
node scripts/java-engine-pack.mjs
|
|
node scripts/install-java-engine.mjs
|
|
```
|
|
|
|
The pack command performs two clean offline Maven builds and requires identical
|
|
output. The installed closed set is `java-regex.mjs`,
|
|
`engine-metadata.json`, `SHA256SUMS`, `LICENSE.txt` and `NOTICE.txt`.
|
|
|
|
TeaVM supplies its own Apache Harmony-derived class-library implementation.
|
|
The resulting engine is therefore identified as
|
|
`TeaVM java.util.regex 0.15.0`, not OpenJDK. TeaVM 0.15.0 does not implement
|
|
OpenJDK's `Pattern.UNICODE_CHARACTER_CLASS`; the bridge treats the application
|
|
`U` flag as a compatibility request, implies Unicode case folding and reports
|
|
that predefined-character classes and word boundaries retain TeaVM behaviour.
|
|
|
|
## Building the PHP pack
|
|
|
|
The PHP bridge under `engines/php/` executes actual PHP 8.5.8 `preg_*`.
|
|
`@php-wasm/web-8-5` and `@php-wasm/universal` 3.1.46 plus their pinned support
|
|
packages supply the Asyncify WebAssembly runtime and host API. Direct identity
|
|
verification reports PCRE2 10.44; this pack is not the standalone PCRE2 10.47
|
|
build.
|
|
|
|
```sh
|
|
node scripts/php-engine-pack.mjs
|
|
node scripts/install-php-engine.mjs
|
|
```
|
|
|
|
The builder copies only the pinned npm runtime files, changes the
|
|
bundler-specific WebAssembly import into a same-directory URL, records the
|
|
original and transformed hashes, and runs real identity, match, bounded
|
|
replacement and native-component positive/negative audits before installation.
|
|
`native-components.json` binds the exact WebAssembly hash to WordPress
|
|
Playground `v3.1.46` commit
|
|
`581c7c172428159eb4e6c5309054a568cd39a97a`, PHP tag `php-8.5.8` commit
|
|
`26b97507444c4fbda072f57dda1820f7b7d5e467`, Emscripten 4.0.19 commit
|
|
`08e2de1031913e4ba7963b1c56f35f036a7d4d56` and all 32 linked native/source
|
|
surfaces. It carries exact archive hashes or Git identities where upstream
|
|
recorded them and honestly bounds the one unpinned Oniguruma clone using the
|
|
committed archive/header identities and upstream source interval.
|
|
|
|
The pack elects PHP License version 4 (`BSD-3-Clause`) for PHP 8.5.8 through
|
|
PHP's later-version option and includes the complete PCRE2 and PHP-vendored,
|
|
external-library, patent and Emscripten/LLVM/musl legal set. This includes the
|
|
exact Zend Engine licence, official php-src binary redistribution notice, CLI
|
|
HTTP parser MIT terms, and the public-domain, CC0 and FNV permission notices for
|
|
linked hash implementations. The WordPress Playground `@php-wasm` packages
|
|
retain GPL-2.0-or-later; JavaScript support-package licences remain separate.
|
|
All 42 legal assets and the native inventory are independently SHA-256-pinned
|
|
by the builder, then covered again by the closed file set, `SHA256SUMS`, release
|
|
requirements and metadata.
|
|
|
|
## Building the legacy Perl pack
|
|
|
|
The Perl bridge under `engines/perl/` uses the unmodified WebPerl 0.09-beta
|
|
prebuilt archive, SHA-256
|
|
`5f441249217e90ab378c666f473d4206ab4f44907f6bb0aa8d70834bc38c40dc`.
|
|
That 2019 beta contains Perl 5.28.1 and Emscripten 1.38.28 output. It is
|
|
intentionally a legacy compatibility target, not a current Perl distribution.
|
|
|
|
The builder accepts only a local copy of that exact official archive; it never
|
|
downloads. An already extracted release root can be supplied with `--prebuilt`
|
|
instead of `--archive`.
|
|
|
|
```sh
|
|
node scripts/perl-engine-pack.mjs \
|
|
--archive /absolute/path/webperl_prebuilt_v0.09-beta.zip
|
|
node scripts/perl-engine-pack.mjs --verify .engine-build/perl
|
|
node scripts/install-perl-engine.mjs .engine-build/perl
|
|
```
|
|
|
|
The installed pack retains upstream `emperl.js`, `emperl.wasm` and
|
|
`emperl.data` byte-for-byte. Application-owned fixed worker and Perl bridge
|
|
files carry values through an exact-key, byte-bounded JSON request path; they do
|
|
not splice patterns or replacements into source. The metadata response remains
|
|
bounded JSON, while successful replacement UTF-8 bytes stream into a separate
|
|
fixed MEMFS binary file and receive exact worker-side byte, size and encoding
|
|
validation. Exact WebPerl/Perl, Emscripten and bundled-CPAN notices travel with
|
|
the pack.
|
|
|
|
The legacy generated loader contains one `eval(code)` site in an optional
|
|
Perl-to-JavaScript interoperability import. The application bridge never loads
|
|
that facility. Its browser CSP smoke passes with `'wasm-unsafe-eval'` and
|
|
without broad `'unsafe-eval'`; that dormant upstream site remains documented
|
|
rather than removed from the checksummed asset.
|
|
|
|
## Building the Ruby pack
|
|
|
|
The Ruby pack copies the minimal runtime from pinned
|
|
`@ruby/4.0-wasm-wasi@2.9.3-2.9.4` and uses
|
|
`@ruby/wasm-wasi@2.9.3-2.9.4` as its host. It verifies the CRuby 4.0.0
|
|
`wasm32-wasi` identity and actual `Regexp`/replacement behavior before
|
|
installation.
|
|
|
|
```sh
|
|
node scripts/ruby-engine-pack.mjs
|
|
node scripts/install-ruby-engine.mjs
|
|
```
|
|
|
|
The closed set contains the runtime WebAssembly file, deterministic metadata
|
|
and checksums, ruby.wasm licence/complete NOTICE and the exact browser WASI
|
|
shim and `tslib` licence texts needed by the host bundle. The production worker
|
|
passes each request through a bounded length-prefixed file in its private WASI
|
|
memory filesystem. It receives bounded inert JSON metadata and reads bounded
|
|
UTF-8 replacement output from a separate private file, rather than amplifying
|
|
that output through JSON or using `RubyVM.wrap`/`toJS` and their
|
|
JavaScript-eval conversion path. Ruby cold startup passes the release's
|
|
strict-CSP browser gate.
|
|
|
|
## Building the C++ pack
|
|
|
|
The C++ bridge under `engines/cpp/` is compiled with Emscripten 6.0.4 at
|
|
compiler revision `fe5be6afdff43ad58860d821fcc8572a23f92d19`. It uses libc++
|
|
`std::wregex`, 32-bit `wchar_t`, fixed structured Embind entry points and
|
|
`-sDYNAMIC_EXECUTION=0`.
|
|
|
|
```sh
|
|
node scripts/cpp-engine-pack.mjs --empp /absolute/path/to/em++
|
|
node scripts/install-cpp-engine.mjs
|
|
```
|
|
|
|
The verifier checks exact Emscripten, emsdk and LLVM identities, bridge hashes,
|
|
WebAssembly/module structure, absence of dynamic-execution constructs in the
|
|
generated module, runtime identity, code-point ranges and bounded replacement
|
|
parity. The build also enables `wasm-ld --trace` and accepts only the reviewed
|
|
linked archive set: Emscripten runtime support, musl `libc`, emmalloc,
|
|
compiler-rt builtins, libc++ and libc++abi.
|
|
|
|
`SOURCE-MANIFEST.json` ties the exact module hash to Emscripten tag/commit
|
|
`6.0.4`/`fe5be6afdff43ad58860d821fcc8572a23f92d19`, emsdk commit
|
|
`224ec5f9f2f72f09f9ce0e26d66bae7dbd8b692f`, the official release commit and
|
|
LLVM compiler commit. It records preferred-source paths and independently
|
|
pinned legal files for musl 1.2.6, emmalloc, compiler-rt 22.1.8, libc++ 21.1.8
|
|
and libc++abi 21.1.8. The current JavaScript-exception link selects no
|
|
`libunwind.a` member; libunwind 22.1.8 and its legal text remain as an explicit
|
|
audited exclusion. Any added, removed or newly selected archive fails the pack
|
|
build.
|
|
|
|
## Building the Go pack
|
|
|
|
Go 1.26.5 standard-library `regexp` is built with the official linux/amd64
|
|
archive, SHA-256
|
|
`5c2c3b16caefa1d968a94c1daca04a7ca301a496d9b086e17ad77bb81393f053`,
|
|
for `GOOS=js GOARCH=wasm`.
|
|
|
|
```sh
|
|
node scripts/build-go-engine.mjs /absolute/path/to/go
|
|
node scripts/install-go-engine.mjs
|
|
node scripts/verify-go-engine.mjs
|
|
```
|
|
|
|
The pack pins the source commit, official archive, `wasm_exec.mjs`, bridge
|
|
source, build flags and Go licence. Verification executes real Unicode
|
|
matching and `regexp.ExpandString` cases.
|
|
|
|
## Building the Rust pack
|
|
|
|
The Rust bridge pins `regex` crate 1.13.1 and its complete Cargo graph, rustc
|
|
1.97.1, the matching `wasm32-unknown-unknown` standard library and wasm-bindgen
|
|
0.2.126.
|
|
|
|
```sh
|
|
node scripts/build-rust-engine.mjs /absolute/path/to/rust-toolchain
|
|
node scripts/install-rust-engine.mjs
|
|
node scripts/verify-rust-engine.mjs
|
|
```
|
|
|
|
The pack records the distribution manifest/archive hashes, crate checksums,
|
|
compiler and LLVM identities, bridge sources, exact bindings and complete
|
|
Rust/crate licence material. Runtime verification covers identity, Unicode
|
|
byte ranges, limits and `Captures::expand`.
|
|
|
|
## Building the .NET pack
|
|
|
|
The fixed `[JSExport]` bridge under `engines/dotnet/` is published by .NET SDK
|
|
10.0.302 with runtime 10.0.10 and its `wasm-tools` workload.
|
|
|
|
```sh
|
|
node scripts/dotnet-engine-pack.mjs --dotnet /absolute/path/to/dotnet
|
|
node scripts/install-dotnet-engine.mjs
|
|
```
|
|
|
|
The pack gate checks SDK/runtime/workload and bridge identities, removes
|
|
compressed/debug outputs, records every `_framework` file, and includes the
|
|
.NET MIT licence and third-party notices. The release browser gate executes
|
|
the browser-WASM identity, Unicode-range and native-replacement smoke. There
|
|
is no separate Scala pack.
|
|
|
|
## Runtime boundaries
|
|
|
|
### PCRE2
|
|
|
|
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.
|
|
|
|
### Python
|
|
|
|
The Python worker loads the self-hosted Pyodide pack and verifies Pyodide,
|
|
CPython and `re` identities before accepting work. The application bridge is
|
|
evaluated inside that interpreter and exposes bounded compile, match and native
|
|
replacement operations. It reports CPython's Unicode code-point positions;
|
|
the TypeScript adapter retains them and converts only valid boundaries to
|
|
half-open editor UTF-16 ranges. Replacement output is byte-bounded in Python,
|
|
encoded as canonical base64 in the JSON envelope and decoded only after its
|
|
declared size, request cap and UTF-8 are validated. Runtime load has a separate
|
|
startup deadline. Execution timeout, cancellation or crash terminates the
|
|
worker and its complete Python/WebAssembly heap.
|
|
|
|
### Java
|
|
|
|
The Java worker imports the self-hosted TeaVM ES module and checks the bridge
|
|
ABI, declared engine identity and compiled self-test before accepting work.
|
|
Every request compiles a `Pattern`, obtains bounded `Matcher` results or native
|
|
replacement output, and returns native half-open UTF-16 ranges. No Java virtual
|
|
machine, OpenJDK classes, remote service or ECMAScript regex fallback is
|
|
involved. Runtime load has a separate startup deadline; termination discards
|
|
the complete worker module state.
|
|
|
|
### PHP
|
|
|
|
The PHP worker starts the same-origin Asyncify runtime, installs the fixed
|
|
`bridge.php` in its private virtual filesystem and verifies PHP 8.5.8 plus
|
|
PCRE2 10.44 before accepting work. User values cross only as JSON data. The
|
|
bridge selects its own safe delimiter, permits only registered modifiers and
|
|
calls native `preg_match()`. `PREG_OFFSET_CAPTURE` byte offsets are retained;
|
|
byte matches that split an encoded character are rejected because they cannot
|
|
map losslessly to a browser string. Bounded replacement mirrors PHP 8.5.8's
|
|
`preg_get_backref()` syntax over those native records and clips every append
|
|
before allocation crosses the requested byte cap. `preg_replace()` is used
|
|
only by the fixed identity parity self-test. Replacement bytes cross the JSON
|
|
envelope as size-predictable base64 and are decoded with a fatal UTF-8 check.
|
|
|
|
### Perl
|
|
|
|
The supervised module worker owns a nested classic worker required by the
|
|
legacy WebPerl loader. Terminating the supervisor also terminates that
|
|
descendant and the complete Perl heap. The fixed bridge uses `no re 'eval'`,
|
|
rejects code assertions independently and exposes only literal text, `$$`,
|
|
greedy `$n` and `${name}` replacement expansion. It pre-tokenizes that grammar,
|
|
streams small bounded UTF-8 pieces from native spans without constructing a
|
|
complete expansion or JSON output, and preserves the unmatched tail when the
|
|
match/capture-row bound stops replacement. Fixed named and numbered fixtures
|
|
are checked against native Perl `s///` during the identity self-test. Perl
|
|
character offsets are returned as Unicode code points. This containment does
|
|
not make WebPerl current software; the UI continues to report its legacy beta
|
|
identity.
|
|
|
|
### Ruby
|
|
|
|
The Ruby worker starts the minimal WASI runtime, evaluates only the fixed
|
|
application bridge and verifies CRuby 4.0.0 identity. User values travel as
|
|
bounded length-prefixed data in the worker-local memory filesystem; the bridge
|
|
returns inert metadata JSON and never sends a user-controlled value through
|
|
ruby.wasm's JavaScript-eval object-conversion path. CRuby compiles and matches.
|
|
Native `String#gsub`/`String#sub` block iteration selects replacement matches;
|
|
a fixed streaming implementation of CRuby 4.0.0's `rb_reg_regsub` grammar
|
|
writes only the configured UTF-8 prefix to a separate private file. A
|
|
load-time parity check compares the fixed expander with CRuby on bounded
|
|
fixtures. Native character offsets are retained as Unicode code points.
|
|
Worker termination discards the Ruby VM and both private files.
|
|
|
|
### C++
|
|
|
|
The C++ worker loads fixed Embind exports whose generated module was built with
|
|
dynamic execution disabled. Each request constructs `std::wregex`, iterates
|
|
under central result limits and streams a fixed implementation of libc++'s
|
|
`match_results::format` default grammar through the output byte cap. Load-time
|
|
fixtures compare it with the native formatter. The adapter exposes 32-bit
|
|
`wchar_t` positions as Unicode code points. The default grammar is C++'s
|
|
modified ECMAScript grammar, not the browser's current ECMAScript grammar.
|
|
|
|
### Go and Rust
|
|
|
|
The Go and Rust workers load their own fixed JSON bridges and verify the exact
|
|
runtime/crate identities before work. Both return UTF-8 byte ranges and reject
|
|
lone surrogates before encoding. Go uses standard-library `regexp` and
|
|
`ExpandString`; Rust uses `regex` crate iteration and `Captures::expand`.
|
|
Their fixed streaming expanders reproduce those native replacement grammars
|
|
under the output byte cap and compare bounded fixtures with the native APIs at
|
|
load. The adapters measure exact request JSON bytes, while matching native caps
|
|
include the worst-case sixfold escaping of every accepted string field. Output
|
|
bytes use fixed 4:3 base64 JSON envelopes instead of content-dependent JSON
|
|
escaping. Neither runtime supports look-around or backreferences. Each module
|
|
also enforces its own pattern, result and output bounds; Rust adds
|
|
compiled-regex and DFA-size limits.
|
|
|
|
### .NET
|
|
|
|
The .NET worker loads the browser-WASM runtime and calls only fixed
|
|
`[JSExport]` methods with bounded JSON. It verifies runtime 10.0.10,
|
|
`System.Text.RegularExpressions`, UTF-16 offsets and invariant culture. A
|
|
nine-second native regex timeout complements the shorter supervisor deadline;
|
|
terminating the worker discards the managed runtime. The adapter currently
|
|
returns the final retained capture only, not .NET capture history. Replacement
|
|
templates are parsed once by a fixed streaming implementation of .NET's
|
|
numbered, named and special substitution tokens. A load-time oracle compares
|
|
the fixed implementation with native `Match.Result`; bounded UTF-8 output is
|
|
transported as canonical base64 rather than JSON-escaped user text.
|
|
|
|
### Scala/JVM compatibility
|
|
|
|
Scala requests deliberately delegate to the same verified TeaVM adapter and
|
|
module described under Java. Result metadata says “no Scala runtime”. The
|
|
profile covers Java-compatible pattern/replacement semantics only and does not
|
|
claim Scala `Regex` wrappers, extractors, compiler/runtime code or OpenJDK
|
|
behavior.
|