Skip to content

fix(regex): dynamic regex.test()/exec() dispatch on untyped receiver (#1731) - #1734

Merged
proggeramlug merged 1 commit into
mainfrom
fix-1731-regex-test-method
May 25, 2026
Merged

fix(regex): dynamic regex.test()/exec() dispatch on untyped receiver (#1731)#1734
proggeramlug merged 1 commit into
mainfrom
fix-1731-regex-test-method

Conversation

@proggeramlug

Copy link
Copy Markdown
Contributor

Fixes #1731.

Root cause

hono's RegExpRouter matches wildcard middleware with buildWildcardRegExp(k).test(path) — a method call on the untyped result of a function call. Codegen's Expr::RegExpTest / Expr::RegExpExec fast path only fires when the receiver's static type is provably a RegExp (const re = /…/; re.test(x)). The dynamic-receiver form fell through to js_native_call_method, which had arms for string.match/search/replace(regex) (regex as argument) but none for a regex receiver with test/exec — so it hit the catch-all and threw TypeError: test is not a function.

That broke every Hono app.use('*', …) wildcard middleware — including logger(), which was the last line blocking the #1655 acceptance program.

Fix

A regex-receiver arm in js_native_call_method: when method ∈ {test, exec} and the receiver is a live regex (is_regex_pointer), dispatch to js_regexp_test / js_regexp_exec (argument coerced to a string; exec returns null on no match, per spec). The body lives in regex::dispatch_regex_receiver_method; it returns None for non-regex receivers so the generic dispatch continues unchanged.

Testing

  • Minimal repro app.use('*', async (c,next)=>{await next()}) + app.get('/') now returns status 200.
  • The complete literal Tracker: Hono on Perry — runtime-agnostic app.fetch contract working end-to-end #1655 acceptance program (real hono@4.10 + @hono/perry-server, app.use('*', logger()) included) now serves all routes end-to-end through serve() + live curl:
    • GET /<html>…<h1>hello</h1>…</html>
    • GET /api/echo?k=v&a=b{"q":{"k":"v","a":"b"}}
    • POST /api/echo{"body":{"x":1}}
    • logger() logs --> GET / 200 0ms (with color)
  • cargo test -p perry-runtime: 560 passed, 0 failed. cargo fmt --all --check clean; file-size gate clean.

Note (out of scope)

typeof re.test on a regex value still reports undefined (the method-as-value form via the property-get path) — hono doesn't rely on it. Left for a separate follow-up if needed.

…1731)

hono's RegExpRouter does `buildWildcardRegExp(k).test(path)` — a method call
on the (untyped) result of a function call. Codegen's Expr::RegExpTest fast
path only fires for statically-typed receivers, so this fell through to
js_native_call_method, which had no regex-receiver arm and threw
`TypeError: test is not a function` — breaking every Hono `app.use('*', …)`
wildcard middleware (logger included). Adds a regex-receiver arm dispatching
test/exec (arg coerced to string; exec returns null on no match), with the
body in regex::dispatch_regex_receiver_method. Verified: the full #1655
acceptance (incl. `app.use('*', logger())`) now serves all routes end-to-end.
@proggeramlug
proggeramlug merged commit 1ed27b5 into main May 25, 2026
10 checks passed
@proggeramlug
proggeramlug deleted the fix-1731-regex-test-method branch May 25, 2026 04:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

hono logger() throws 'TypeError: test is not a function' at runtime inside the middleware path (follow-up to #1725)

1 participant