ktecma262 0.1.0
Caution
Deprecated — parser bug.
\0 inside a character class was rejected as a SyntaxError under the u and v flags, where ECMA-262 keeps it valid as the NUL escape. Patterns such as [\0] and [+\0d] failed to compile. Fixed in 0.1.1.
Use 0.1.4 instead.
Warning
Superseded by 0.1.1.
This release rejects \0 inside a character class under the u and v
flags, where it is the NUL escape in every mode — so patterns such as
[\0] and [+\0d] fail to compile. Use 0.1.1.
An ECMA-262 (JavaScript) regular expression engine in pure Kotlin, for Kotlin
Multiplatform. Patterns and match results behave as they do in JavaScript: the
same flags, Annex B syntax, capture semantics and UTF-16 offsets.
Highlights
- Flags
i g m s u v y d; Annex B by default, strict ECMA-262 opt-in - Named groups including ES2022 duplicates; backreferences including forward
references; lookahead and lookbehind, including variable-length lookbehind
with right-to-left capture semantics v(UnicodeSets): nested classes,&&and--,\q{…}string literals, and
properties of strings (\p{RGI_Emoji}and its constituents)- Regexp modifiers
(?i:…)andRegExp.escape(ES2025) - Unicode 17.0.0 compiled in, so
\p{…}does not vary with the host JDK - JVM output is Java 17 bytecode, checked by reading the emitted class files
Safety and performance
Backtracking runs on an explicit stack with an undo log, so deep backtracking
cannot overflow the call stack — java.util.regex throws StackOverflowError
on inputs this engine handles. Matching is bounded by RegExp.maxSteps
(default 1,000,000, as PCRE's backtrack limit), and the budget spans a whole
operation rather than each match, so cost cannot scale with a match count the
input controls.
On a Ryzen 9 6900HX: literal scan over 100k chars 41 µs (vs 81 µs for
java.util.regex), a three-capture date match 174 ns (vs 170 ns).
How correctness was established
Differential testing against a real JavaScript engine rather than readings of
the specification:
- ~40,000 recorded node results replayed on JVM and JS on every build
- Millions of live fuzz cases covering
exec,findAll,replaceandsplit,
including unstructured patterns the generator's own grammar cannot produce - Test262's generated
v-flag conformance cases - All 439 Unicode properties verified against node code point by code point, and
RegExp.escapeverified over all 1,114,112 code points
Deliberate divergences from V8
Three, each documented in the README with a test pinning the specified
behaviour: match positions that split a surrogate pair under /u,
single-character \q{} folding under /vi, and modifier scoping leaking into
\w. Each was confirmed as a V8 inconsistency rather than a reading of the
grammar.
Installing
Maven Central publication is pending namespace verification. Until then, build
from source:
git clone https://github.com/mgilbir/ktecma262 && cd ktecma262
./gradlew publishToMavenLocalthen add mavenLocal() to your repositories and
implementation("io.github.mgilbir:ktecma262:0.1.0") — or take the jars below.
The -sources jars carry the KDoc; the artifacts here are the same ones
publishToMavenLocal produces.