# Legacy Perl engine This engine uses the unmodified prebuilt WebPerl `v0.09-beta` distribution, which contains Perl `v5.28.1` compiled by Emscripten `1.38.28`. It is an explicitly legacy, beta compatibility target. It is not current desktop Perl. ## Trust boundary `regex_tools_bridge.pl` is fixed application source. The classic runtime worker writes each exact-key, byte-bounded request as JSON to a fixed MEMFS path and invokes only the constant Perl expression `RegexTools::run_request()`. The metadata-only response uses a second bounded JSON file. Successful replacement bytes use a third, fixed binary file; the worker checks its exact declared length, output bound and canonical UTF-8 before supplying the decoded string to the adapter. Pattern, subject, flags and replacement values are never interpolated into Perl or JavaScript source. The bridge: - compiles a scalar pattern with `no re 'eval'`; - independently rejects `(?{...})` and `(??{...})` outside escaped literals and character classes; - never imports the WebPerl JavaScript interoperability module; - pre-tokenizes a deliberately bounded replacement grammar consisting of literal text, `$$`, greedy `$n` and `${name}`; - streams unmatched spans, literals and native capture values to the binary output file in small UTF-8 chunks, stopping before a code point would cross the output-byte bound; - stops replacement at the match/capture-row result bound and preserves the remaining subject as an unchanged tail; - compares fixed named and numbered streaming fixtures with native Perl `s///` output during the identity self-test; - validates every request again inside Perl; and - reports native Perl character offsets as Unicode code-point offsets. Numbered capture participation and spans come from Perl's native `@-` and `@+` arrays. The legacy runtime does not expose a stable name-to-number table, so the adapter annotates those native capture rows with names from regex-tools' syntax metadata. Numbered replacement values are streamed directly from their native spans. Named replacement lookup itself uses Perl's native `%+`, and only names present in the pre-tokenized template are read. The prebuilt `emperl.js` contains one JavaScript `eval(code)` site in its optional Perl-to-JavaScript interoperability import. The fixed bridge does not load or call that facility. A Chromium CSP smoke succeeds with `script-src 'self' 'wasm-unsafe-eval'` and without `'unsafe-eval'`. The module worker remains responsive while the nested classic worker executes. Terminating the supervised module worker terminates its worker descendants, so catastrophic matching remains killable. ## Provenance - WebPerl release: `v0.09-beta` - Release commit: `6f2173d29a2c2e3536e1de75ff5d291ae96ab348` - Prebuilt archive: `https://github.com/haukex/webperl/releases/download/v0.09-beta/webperl_prebuilt_v0.09-beta.zip` - Archive SHA-256: `5f441249217e90ab378c666f473d4206ab4f44907f6bb0aa8d70834bc38c40dc` - Perl runtime identity: `v5.28.1` - Emscripten toolchain identified by the pinned upstream build configuration: `1.38.28` The deployed `emperl.js`, `emperl.wasm` and `emperl.data` files are copied byte-for-byte from that archive. See `public/engines/perl/engine-metadata.json`, `NOTICE.txt`, and the adjacent license files.