Stage 3 Draft / November 19, 2019

String.prototype.replaceAll

1StringIndexOf ( string, searchValue, fromIndex )

The abstract operation StringIndexOf performs the following steps:

  1. Assert: Type(string) is String.
  2. Assert: Type(searchValue) is String.
  3. Assert: fromIndex is a nonnegative integer.
  4. Let len be the length of string.
  5. If searchValue is the empty string, and fromIndex <= len, return fromIndex.
  6. Let searchLen be the length of searchValue.
  7. If there exists any integer k such that fromIndexklen - searchLen and for all nonnegative integers j less than searchLen, the code unit at index k + j within string is the same as the code unit at index j within searchValue, let pos be the smallest (closest to -∞) such integer. Otherwise, let pos be -1.
  8. Return pos.
Note

If searchValue is empty and fromIndex is less than or equal to the length of string, this algorithm returns fromIndex. An empty searchValue is effectively found at every position within a string, including after the last code unit.

2String.prototype.replaceAll ( searchValue, replaceValue )

When the replaceAll method is called with arguments searchValue and replaceValue, the following steps are taken:

  1. Let O be ? RequireObjectCoercible(this value).
  2. If searchValue is neither undefined nor null, then
    1. Let isRegExp be ? IsRegExp(searchValue).
    2. If isRegExp is true, then
      1. Let flags be ? Get(searchValue, "flags").
      2. Perform ? RequireObjectCoercible(flags).
      3. If ? ToString(flags) does not contain "g", throw a TypeError exception.
    3. Let replacer be ? GetMethod(searchValue, @@replace).
    4. If replacer is not undefined, then
      1. Return ? Call(replacer, searchValue, « O, replaceValue »).
  3. Let string be ? ToString(O).
  4. Let searchString be ? ToString(searchValue).
  5. Let functionalReplace be IsCallable(replaceValue).
  6. If functionalReplace is false, then
    1. Let replaceValue be ? ToString(replaceValue).
  7. Let searchLength be the length of searchString.
  8. Let advanceBy be max(1, searchLength).
  9. Let matchPositions be a new empty List.
  10. Let position be ! StringIndexOf(string, searchString, 0).
  11. Repeat, while position is not -1
    1. Append position to the end of matchPositions.
    2. Let position be ! StringIndexOf(string, searchString, position + advanceBy).
  12. Let endOfLastMatch be 0.
  13. Let result be the empty string value.
  14. For each position in matchPositions, do
    1. If functionalReplace is true, then
      1. Let replacement be ? ToString(? Call(replaceValue, undefined, « searchString, position, string »).
    2. Else,
      1. Assert: Type(replaceValue) is String.
      2. Let captures be a new empty List.
      3. Let replacement be GetSubstitution(searchString, string, position, captures, undefined, replaceValue).
    3. Let stringSlice be the substring of string consisting of the code units from endOfLastMatch (inclusive) up through position (exclusive).
    4. Let result be the string-concatenation of result, stringSlice, and replacement.
    5. Let endOfLastMatch be position + searchLength.
  15. If endOfLastMatch < the length of string, then
    1. Let result be the string-concatenation of result and the substring of string consisting of the code units from endOfLastMatch (inclusive) up through the final code unit of string (inclusive).
  16. Return result.

3String.prototype.matchAll ( regexp )

Performs a regular expression match of the String representing the this value against regexp and returns an iterator. Each iteration result's value is an Array object containing the results of the match, or null if the String did not match.

When the matchAll method is called, the following steps are taken:

  1. Let O be ? RequireObjectCoercible(this value).
  2. If regexp is neither undefined nor null, then
    1. Let isRegExp be ? IsRegExp(regexp).
    2. If isRegExp is true, then
      1. Let flags be ? Get(regexp, "flags").
      2. Perform ? RequireObjectCoercible(flags).
      3. If ? ToString(flags) does not contain "g", throw a TypeError exception.
    3. Let matcher be ? GetMethod(regexp, @@matchAll).
    4. If matcher is not undefined, then
      1. Return ? Call(matcher, regexp, « O »).
  3. Let S be ? ToString(O).
  4. Let rx be ? RegExpCreate(regexp, "g").
  5. Return ? Invoke(rx, @@matchAll, « S »).
Note 1
The matchAll function is intentionally generic, it does not require that its this value be a String object. Therefore, it can be transferred to other kinds of objects for use as a method.
Note 2
Similarly to String.prototype.split, String.prototype.matchAll is designed to typically act without mutating its inputs.

4String.prototype.indexOf ( searchString [ , position ] )

Note 1

If searchString appears as a substring of the result of converting this object to a String, at one or more indices that are greater than or equal to position, then the smallest such index is returned; otherwise, -1 is returned. If position is undefined, 0 is assumed, so as to search all of the String.

The indexOf method takes two arguments, searchString and position, and performs the following steps:

  1. Let O be ? RequireObjectCoercible(this value).
  2. Let S be ? ToString(O).
  3. Let searchStr be ? ToString(searchString).
  4. Let pos be ? ToInteger(position).
  5. Assert: If position is undefined, then pos is 0.
  6. Let len be the length of S.
  7. Let start be min(max(pos, 0), len).
  8. Let searchLen be the length of searchStr.
  9. Return the smallest possible integer k not smaller than start such that k + searchLen is not greater than len, and for all nonnegative integers j less than searchLen, the code unit at index k + j within S is the same as the code unit at index j within searchStr; but if there is no such integer k, return the value -1.
  10. Let position be ! StringIndexOf(S, searchString, start).
  11. Return position.
Note 2

The indexOf function is intentionally generic; it does not require that its this value be a String object. Therefore, it can be transferred to other kinds of objects for use as a method.