Add custom JavaScript regex engine (QuickJS libregexp port)#2380
Conversation
This Claude is quite optimistic about those no regressions.. |
5c9a41c to
8b0b235
Compare
There was a problem hiding this comment.
Pull request overview
Adds a QuickJS libregexp-ported regex engine to Jint and integrates it as a runtime fallback when Acornima/.NET Regex cannot represent JavaScript RegExp semantics (notably v-flag, unicode property escapes, forward backrefs, and other semantic mismatches). This shifts regex handling toward “parse-time validation, runtime compilation” to preserve correctness while retaining .NET Regex as a fast path when safe.
Changes:
- Introduces a custom regex compiler + bytecode interpreter (QuickJS port) and Unicode property support.
- Routes RegExp initialization/execution to either .NET
Regexor the custom engine via detection + fallback. - Updates parsing defaults/Prepare* flow to validate regex syntax without requiring conversion at parse time; enables additional test262 RegExp coverage.
Reviewed changes
Copilot reviewed 22 out of 24 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| Jint/Runtime/RegExp/Unicode/UnicodeProperties.cs | Adds Unicode property lookup, case folding, and set operations used by the custom engine. |
| Jint/Runtime/RegExp/RegExpSyntaxException.cs | Adds a dedicated exception type for custom engine compilation failures. |
| Jint/Runtime/RegExp/RegExpOpcode.cs | Defines custom-engine bytecode opcodes, sizes, and header layout. |
| Jint/Runtime/RegExp/RegExpMatchResult.cs | Adds match/capture result structs for the custom engine execution path. |
| Jint/Runtime/RegExp/RegExpInterpreter.cs | Implements the QuickJS-style bytecode interpreter with backtracking and timeout support. |
| Jint/Runtime/RegExp/RegExpCompiler.cs | Implements the QuickJS-style regex compiler (parsing → bytecode), including /v unicode-sets support. |
| Jint/Runtime/RegExp/JintRegExpEngine.cs | Wraps compilation/execution of the custom engine and builds match results. |
| Jint/Runtime/RegExp/DotNetRegExpEngine.cs | Wraps .NET Regex + Acornima parse metadata for the fast path. |
| Jint/Runtime/Interpreter/Expressions/JintLiteralExpression.cs | Updates RegExp literal evaluation to cache runtime-compiled .NET/custom engines. |
| Jint/ParsingOptions.cs | Stops overriding RegExp parse mode to AdaptToInterpreted; relies on base Validate mode. |
| Jint/Native/RegExp/RegExpPrototype.cs | Integrates custom-engine execution into exec and adjusts fast paths for engine type and v semantics. |
| Jint/Native/RegExp/RegExpConstructor.cs | Adds flag validation, custom-engine routing/fallback, and constructors for cached custom-engine instances. |
| Jint/Native/JsRegExp.cs | Adds CustomEngine, separates unicode vs FullUnicode semantics, and exposes UsesDotNetEngine. |
| Jint/Native/Iterator/IteratorInstance.cs | Uses AdvanceStringIndex for Unicode-aware advancement during regexp iteration. |
| Jint/Jint.csproj | Switches Acornima dependency from package to external project reference (fork). |
| Jint/Engine.Defaults.cs | Bumps default ECMAScript version and sets RegExpParseMode to Validate by default. |
| Jint/Engine.Ast.cs | Adds fallback to Validate mode when RegExp conversion fails during PrepareScript/PrepareModule. |
| Jint.Tests/Jint.Tests.csproj | Switches Acornima.Extras dependency to external project reference (fork). |
| Jint.Tests.Test262/Test262Harness.settings.json | Re-enables previously excluded regexp features/tests in test262 settings. |
| Jint.Tests.Test262/Jint.Tests.Test262.csproj | Switches Acornima.Extras dependency to external project reference (fork). |
| Jint.Tests.PublicInterface/Jint.Tests.PublicInterface.csproj | Switches Acornima.Extras dependency to external project reference (fork). |
| Jint.Tests.CommonScripts/Jint.Tests.CommonScripts.csproj | Switches Acornima.Extras dependency to external project reference (fork). |
| Directory.Packages.props | Comments out Acornima/Acornima.Extras central package versions (no longer used). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 22 out of 24 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 22 out of 24 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 22 out of 24 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 22 out of 24 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 22 out of 24 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 22 out of 24 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 22 out of 24 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@lahma FYI, I just released flag v validation and the Unicode 17 upgrade. Hopefully, this will unblock this PR. But let me know if you need any further changes on the parser side. Some remarks: As planned, the regexp conversion-related APIs have been deprecated, so you will get a lot of deprecation warnings. These can just be ignored for now. However, if you want to get ahead of the wave, you can switch to using the new |
|
@adams85 congratulations on the release, great leap forward. Big thanks for cleaning up and polishing my AI slop 😅 I'll integrate the new version and then check your feedback, much appreciated! |
b1c734f to
d416626
Compare
Port of QuickJS libregexp to C# for patterns where .NET Regex diverges from ECMAScript semantics. Three-tier architecture: direct .NET Regex for simple patterns, Jint's converter for patterns needing rewriting, and custom bytecode engine for ECMAScript-specific semantics. 97,638 test262 passed, 0 failures (+1,624 from baseline). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
72f558a to
6acaba7
Compare
Summary
Port of QuickJS's libregexp engine to C# as a custom regex engine for patterns where .NET's
System.Text.RegularExpressionsproduces incorrect results. Uses a three-tier architecture: direct .NET Regex for simple patterns, Jint's converter for patterns needing rewriting, and custom bytecode engine for ECMAScript-specific semantics.97,638 test262 passed, 0 failures (+1,624 from 96,014 baseline on main)
Architecture
Why the hybrid approach matters
The custom bytecode interpreter is 13-17x slower than .NET's JIT-compiled Regex on heavy workloads. Benchmarked with
dromaeo-object-regexp(40 regex tests — split/match/test/replace on 64KB strings), the branch shows no meaningful regression on existing workloads (confidence intervals overlap with main across all scenarios).The three-tier routing keeps .NET Regex on the fast path for compatible patterns while the custom engine handles the categories of .NET divergence from ECMAScript spec.
What's included
Custom regex engine (
Jint/Runtime/RegExp/)libregexp.c\p{}), case folding, set operations for v-flagPattern routing (
NeedCustomEngine)Routes to custom engine for:
/uand/vflags, named groups, scoped modifiers ((?i:...)), forward backreferences, lookbehind with backrefs, nullable quantifier captures, case-insensitive with non-ASCII content, duplicate named groups.Converter (
JsRegExpConverter)Lightweight JS-to-.NET converter handling
.→[^\n\r\u2028\u2029],\s/\S→ JS whitespace sets,\b/\B→ lookaround expansions, multiline^/$→ anchors, and more. Falls back to custom engine on rejection.Safety
RegexTimeoutRegexTimeoutpropagated from engine options through preparation handlersAPI compatibility
[Obsolete]ParseResultshim onJsRegExpfor backward compatibilityregExpParseResultparameter removed fromConstructAcornima dependency
Requires Acornima 1.4.0 which adds v-flag syntax validation and Unicode 17 script names.
Benchmark results (vs main)
Test plan
🤖 Generated with Claude Code