You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
the ToString coercion path — js_jsvalue_to_string, reached from String(x), template literals, + string concat, and every other implicit ToString. It maps a regex straight back to its /source/flags literal and never consults own properties.
So an override is honoured on one path and silently ignored on the other, which is worse than being wrong on both — the same regex stringifies two different ways depending on how you ask.
Scope to check when fixing
Per spec this is ordinary ToPrimitive -> OrdinaryToPrimitive -> [[Get]]("toString"), so the receiver's own property (data or accessor) must win over RegExp.prototype.toString on every coercion site, not just String():
String(re), `${re}`, "" + re
re + "", [re].join(""), console.log(re) (inspect may differ — check node)
and the same question for the other exotics that use the exotic_expando side table (Error, and anything else ExoticKind covers), not only RegExp.
Also worth checking whether an own Symbol.toPrimitive is honoured on these paths.
Summary
String(re)and`${re}`ignore an owntoStringoverride on a RegExp — both data and accessor forms. Only the explicitre.toString()call honours it.Repro
Reproduces identically on
mainand on the branch for #5897 — pre-existing, not introduced by that work.Why
There are two distinct paths:
.toString()fold —js_jsvalue_to_string_method(value/to_string.rs). Codegen rewritesx.toString()straight into it, bypassing method dispatch. fix(regex,hir): UTF-16 indices, own-property method shadowing, RegExp static inheritance (#5897) #6358 taught it to consult the receiver's owntoString(data), and a follow-up made that lookup accessor-aware.js_jsvalue_to_string, reached fromString(x), template literals,+string concat, and every other implicit ToString. It maps a regex straight back to its/source/flagsliteral and never consults own properties.So an override is honoured on one path and silently ignored on the other, which is worse than being wrong on both — the same regex stringifies two different ways depending on how you ask.
Scope to check when fixing
Per spec this is ordinary
ToPrimitive->OrdinaryToPrimitive->[[Get]]("toString"), so the receiver's own property (data or accessor) must win overRegExp.prototype.toStringon every coercion site, not justString():String(re),`${re}`,"" + rere + "",[re].join(""),console.log(re)(inspect may differ — check node)exotic_expandoside table (Error, and anything elseExoticKindcovers), not only RegExp.Also worth checking whether an own
Symbol.toPrimitiveis honoured on these paths.