feat: RegexCapability - #196
Conversation
01e092e to
fa8c15a
Compare
80d8df4 to
81d4a77
Compare
Overall package sizeSelf size: 30.29 MB Dependency sizes| name | version | self size | total size | |------|---------|-----------|------------|🤖 This report was automatically generated by heaviest-objects-in-the-universe |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 81d4a77fc2
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| // `g` is required to iterate all matches with exec; `d` is required for the | ||
| // per-group indices used by `capturesAll`. | ||
| module.exports.compile = function (pattern) { | ||
| return new RegExp(pattern, 'gd') |
There was a problem hiding this comment.
Keep regex matches on UTF-8 boundaries
When callers use a pattern that can consume one UTF-16 code unit, such as ., against non-BMP input like "😀", this regex is not in Unicode mode, so exec matches only the high surrogate and findFirst reports [0, 2]. Those values are returned to Rust as UTF-8 byte offsets, but byte 2 is inside the four-byte character; consumers that slice strings or expect Rust regex-style match boundaries will get incorrect results or panic. Compile/iterate with Unicode-aware semantics, or otherwise prevent matches from splitting surrogate pairs.
Useful? React with 👍 / 👎.
| for (let g = 0; g < groupCount; g++) { | ||
| const idx = m.indices[g] | ||
| if (idx === undefined) out.push(-1, -1) | ||
| else out.push(local[idx[0] - matchStart], local[idx[1] - matchStart]) |
There was a problem hiding this comment.
Map capture offsets outside the overall match
For JS patterns with captures in lookahead/lookbehind, a capture group's indices can fall outside the overall match span; for example (?=(a)) on "a" has match [0, 0] but group [0, 1]. Because the local byte-offset map only covers matchStart..matchEnd, local[idx[1] - matchStart] is undefined and is later converted to 0 in the returned Int32Array, so Rust receives incorrect capture ranges. Build the offset map over the full min/max range of all present group indices, or fall back to walking from the haystack start for out-of-span groups.
Useful? React with 👍 / 👎.
| } | ||
|
|
||
| fn captures(handle: &Self::Handle, haystack: &str) -> Option<Captures> { | ||
| decode_captures(js_captures_all(&handle.re, haystack)) |
There was a problem hiding this comment.
Stop captures() after the first match
When callers ask for only the first capture set, this still invokes capturesAll, which runs the global regexp over the entire haystack and allocates/decodes every match before discarding all but the first. On large trace payloads or broad patterns this makes captures() scale with total match count instead of the first match; add a JS helper that performs a single exec and decodes only that result.
Useful? React with 👍 / 👎.
| // `g` is required to iterate all matches with exec; `d` is required for the | ||
| // per-group indices used by `capturesAll`. | ||
| module.exports.compile = function (pattern) { | ||
| return new RegExp(pattern, 'gd') |
There was a problem hiding this comment.
Avoid backtracking regexes in trace filtering
When the agent's /info filters include a pathological pattern such as (a+)+$, this compiles it into V8's backtracking RegExp; evaluating it against a non-matching resource like a long run of as plus ! can block the Node event loop for seconds, whereas the native capability uses Rust's linear-time regex engine. Since these filters are applied while processing trace payloads, a configured filter can stall trace flushing; use the Rust/wasm regex engine or otherwise reject patterns that can trigger catastrophic backtracking.
Useful? React with 👍 / 👎.
Wasm still gets compiled and is in the dependancy tree through libdd-common, but wasm-ld trims it out for it is not used