== Why is this an issue?

In JavaScript, the ``++String.prototype.replace()++`` method is used to replace parts of a string with new substrings. It allows you to perform simple to complex string replacements based on either a static string or a regular expression pattern.

When the first argument is a regular expression, the method will use the regular expression to search for matches within the original string and then replace those matches with the specified replacement. If the second argument is a string, the method will use it as the static replacement for the matched substrings found by the regular expression.

Within the replacement string, the function supports special placeholders to insert the matched values of capturing groups from the regular expression:

* The ``++$n++`` syntax allows you to reference capturing groups by their numerical index. The number ``++n++`` corresponds to the order in which the capturing group appears in the regular expression, starting from 1 for the first capturing group.
* The ``++$<Name>++`` syntax allows you to reference capturing groups by their name. Instead of using numerical indices, you can assign a name to a capturing group using ``++?<Name>++`` within the regular expression.

If the second argument of ``++String.prototype.replace()++`` references non-existing groups (capturing groups that do not exist in the regular expression), the behavior of the replacement will depend on the specific references made. It won't cause an error, but the replacement will not be based on any captured values, potentially leading to unexpected results in the replaced string:

* If the replacement string contains references like ``++$1++``, ``++$2++``, etc., to capturing groups that don't exist in the regular expression, those references will be treated as literals. In other words, the ``++$n++`` will be replaced with the literal text ``++$n++`` itself.
* If the replacement string contains references like ``++$<Name>++``, they will also be treated as literals, but only if there are no named captures in the regular expression; otherwise, they will be replaced with the empty string.

This rule checks that all referenced groups exist when replacing a pattern with a replacement string using ``++String.prototype.replace()++`` or ``++String.prototype.replaceAll()++`` methods.

[source,javascript,diff-id=1,diff-type=noncompliant]
----
const str = 'John Doe';
console.log(str.replace(/(\w+)\s(\w+)/, '$1, $0 $1')); // Noncompliant: index is 1-based, '$0' does not exist, prints 'John, $0 John'
console.log(str.replace(/(?<firstName>\w+)\s(?<lastName>\w+)/, '$<surname>, $<firstName> $<surname>')); // Noncompliant: '$<surname>' does not exist but there are named captures, prints ', John '
----

Always check your regular expression and replacement string to ensure they properly reference existing capturing groups, most specifically, the latter references capturing groups existing in the former.

[source,javascript,diff-id=1,diff-type=compliant]
----
const str = 'John Doe';
console.log(str.replace(/(\w+)\s(\w+)/, '$2, $1 $2'));
console.log(str.replace(/(?<firstName>\w+)\s(?<lastName>\w+)/, '$<lastName>, $<firstName> $<lastName>'));
----

== Resources
=== Documentation

* MDN web docs - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace[``++String.prototype.replace()++``]
* MDN web docs - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll[``++String.prototype.replaceAll()++``]
* MDN web docs - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions[Regular expressions]
* MDN web docs - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Capturing_group[Capturing group: ``++(...)++``]
