feat: add multi-engine regex flavour support

This commit is contained in:
2026-07-27 11:43:51 +02:00
parent 7079cde15f
commit 7f3a91ad37
340 changed files with 643286 additions and 483 deletions

66
engines/perl/README.md Normal file
View File

@@ -0,0 +1,66 @@
# 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.