Stage 4 Draft / June 29, 2020

String.prototype.replaceAll

1 Static Semantics: StringIndexOf ( string, searchValue, fromIndex )

The abstract operation StringIndexOf takes arguments string (a String), searchValue (a String), and fromIndex (a non-negative integer). It performs the following steps when called:

  1. Assert: Type(string) is String.
  2. Assert: Type(searchValue) is String.
  3. Assert: ! IsNonNegativeInteger(fromIndex) is true.
  4. Let len be the length of string.
  5. If searchValue is the empty String, and fromIndexlen, 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 1

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.

Note 2

The above algorithm accepts out-of-bounds fromIndex values (where fromIndex ≥ the length of string).

2 String.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. Set replaceValue to ? 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. Set position to ! 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 to position (exclusive).
    4. Set result to the string-concatenation of result, stringSlice, and replacement.
    5. Set endOfLastMatch to position + searchLength.
  15. If endOfLastMatch < the length of string, then
    1. Set result to 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.

3 String.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.

4 String.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 index be ! StringIndexOf(S, searchStr, start).
  11. Return index.
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.