fix(runtime): string.match() honors fancy-regex fallback (date-fns format)#975
Merged
Merged
Conversation
…te-fns format) date-fns 4.x format() crashed at `formatStr.match(formattingTokensRegExp).map(...)` because the format-token regex `(\w)\1*` uses a backreference that the Rust regex crate rejects. get_or_compile_regex already stashed the compiled fancy-regex in FANCY_CACHE and substituted a never-match `[^\s\S]` placeholder, but js_string_match never consulted FANCY_CACHE — so `string.match(re)` always returned null for backreferenced patterns, and the downstream `.map(...)` crashed with NULL_PTR_METHOD_CALL. Add lookup_fancy_regex() helper and have js_string_match check FANCY_CACHE before falling through to the standard regex.crate path, mirroring the same fallback that js_regexp_exec already had. Global flag uses fre.find_iter; non-global returns the full match + capture groups via fre.captures. Validation: format(new Date(2024,0,15), 'yyyy-MM-dd') -> 2024-01-15 (matches Node), plus 'HH:mm:ss', 'yyyy-MM-dd HH:mm:ss', 'MMM yyyy', 'EEEE, MMMM do yyyy' all byte-for-byte parity with `node --experimental-strip-types`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
date-fns4.xformat()got pastconstructFrom(PR feat(runtime): .constructor on Date/Array/Object instances #973) but immediately tripped onformatStr.match(/[yYQqMLwIdDecihHKkms]o|(\w)\1*|''|'(''|[^'])+('|$)|./g).map(...)because the regex contains a(\w)\1*backreference. The Rustregexcrate rejects backreferences, soget_or_compile_regexsubstituted a never-match[^\s\S]placeholder and stashed the real pattern inFANCY_CACHEfor fancy-regex to handle.RegExp.prototype.execalready wired up the fancy fallback (lookup before falling through), butString.prototype.matchdidn't.formatStr.match(...)therefore returnednull, and the chained.map(...)blew up withNULL_PTR_METHOD_CALL.lookup_fancy_regex(re)helper, havejs_string_matchconsultFANCY_CACHEfirst. Global flag walksfre.find_iter; non-global returns the full match + capture groups viafre.captures. Pattern + flags + array shape match the standard-regex path exactly.Validation:
format(new Date(2024, 0, 15), 'yyyy-MM-dd')→2024-01-15(matches Node).'HH:mm:ss','yyyy-MM-dd HH:mm:ss','MMM yyyy','EEEE, MMMM do yyyy'— byte-for-byte parity.test-files/test_date_fns_format.tscovers the underlying regex shape (global + non-global + no-match) without importing date-fns directly.Follow-ups (not in this PR):
js_string_match_all,js_regexp_test, andjs_string_search_regexstill consult only the placeholder for fancy patterns. None are on date-fns'format()hot path; the samelookup_fancy_regexhelper can be wired in when needed.Test plan
cargo build --release -p perry-runtime -p perry-stdlib -p perryformat(new Date(2024, 0, 15), 'yyyy-MM-dd')returns2024-01-15viacompilePackages: ["date-fns"]node --experimental-strip-typestest-files/test_date_fns_format.tsmatches Node for(\w)\1*global + non-global + no-matchlint,cargo-test,parity,compile-smoke,api-docs-drift,security-audit