4

Why does JS method replace() work incorrect in the latest version of Safari (11.1) with "$<" in the second argument?

Example:

"aaaXXXbbb".replace(/XXX/, '_before_$<_after_')

Actual result:

"aaa$<_after_bbb"

Expected result:

"aaa_before_$<_after_bbb"

PS: "$$" inserts a "$" and solves this problem

Joe Clay
  • 33,401
  • 4
  • 85
  • 85
  • Just tried this in Firefox 60 and it works fine. Inconsistent handling of [replacement patterns](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_string_as_a_parameter) between browsers, maybe? – Joe Clay Apr 14 '18 at 15:27
  • Its interesting. Somehow the string `$<` cuts everything in front of the replacement so that the following is true: `"a".replace(/a/, 'a$<') === "$<"`. But this happens only using a regex. When you use a string for the search it works fine. Maybe its some Safari internal thing? – Teemoh Apr 14 '18 at 15:35
  • 1
    It's maybe worth mentioning that `$<` in a replacement string [**does** have a defined meaning in the spec](https://tc39.github.io/ecma262/#sec-getsubstitution), but (assuming I'm interpreting the spec correctly) it should only apply when you're using named captures in your Regex. I'd consider [reporting this as a WebKit bug](https://webkit.org/reporting-bugs/). – Joe Clay Apr 14 '18 at 15:37
  • Especially given that @Teemoh's example evaluates to `false` for me in Firefox! – Joe Clay Apr 14 '18 at 15:39
  • Yes, in Firefox und Chrome its `false` but in Safari it is `true`. :D – Teemoh Apr 14 '18 at 15:41

1 Answers1

3

This behavior doesn't occur in Firefox or Chrome, and I think I understand why.

A new feature has been accepted for inclusion in the next version of the ECMAScript spec called 'Regex Named Capture Groups' which, as the name suggests, allows you to assign a name to a capture group in a regular expression. One of the things added by this feature is a new addition to the replacement string syntax which allows you to interpolate the value of a named capture group.

This syntax takes the form $<captureName> - note the $< at the beginning!

According to the latest iteration of the spec, if you haven't closed a $< with a corresponding >, it should be ignored and just treated as part of the text. The behavior being displayed in your browser doesn't line up with this, and therefore I think it's quite likely that you've discovered a bug!

I'd encoruage you to report it to WebKit via the process detailed on their website.

Joe Clay
  • 33,401
  • 4
  • 85
  • 85