diff --git a/README.md b/README.md index fbb66ce..e1edee9 100644 --- a/README.md +++ b/README.md @@ -44,15 +44,16 @@ It also removes the need to escape special regexp characters (note the unescaped The proposed signature is the same as the existing `String.prototype.replace` method: -``` +```js String.prototype.replaceAll(searchValue, replaceValue) ``` -Per the current TC39 consensus, `String.prototype.replaceAll` behaves identically to `String.prototype.replace` in all cases, **except** for the case where `searchValue` is a string. +Per the current TC39 consensus, `String.prototype.replaceAll` behaves identically to `String.prototype.replace` in all cases, **except** for the following two cases: -In that case, `String.prototype.replace` only replaces a single occurrence of the `searchValue`, whereas `String.prototype.replaceAll` replaces *all* occurrences of the `searchValue` (as if `.split(searchValue).join(replaceValue)` or a global & properly-escaped regular expression had been used). +1. If `searchValue` is a string, `String.prototype.replace` only replaces a single occurrence of the `searchValue`, whereas `String.prototype.replaceAll` replaces *all* occurrences of the `searchValue` (as if `.split(searchValue).join(replaceValue)` or a global & properly-escaped regular expression had been used). +1. If `searchValue` is a non-global regular expression, `String.prototype.replace` replaces a single match, whereas `String.prototype.replaceAll` throws an exception. This is done to avoid the inherent confusion between the lack of a global flag (which implies "do NOT replace all") and the name of the method being called (which strongly suggests "replace all"). -Notably, `String.prototype.replaceAll` behaves just like `String.prototype.replace` if `searchValue` is a regular expression, [including if it's a non-global regular expression](https://github.com/tc39/proposal-string-replaceall/issues/16). +Notably, `String.prototype.replaceAll` behaves just like `String.prototype.replace` if `searchValue` is a global regular expression. ## Comparison to other languages @@ -87,7 +88,7 @@ A: This is an awkward interface — because the default limit is 1, the user wou ## TC39 meeting notes - [November 2017](https://tc39.es/tc39-notes/2017-11_nov-28.html#10ih-stringprototypereplaceall-for-stage-1) -- [March 2019](https://github.com/rwaldron/tc39-notes/blob/master/meetings/2019-03/mar-26.md#stringprototypereplaceall-for-stage-2) +- [March 2019](https://github.com/tc39/tc39-notes/blob/master/meetings/2019-03/mar-26.md#stringprototypereplaceall-for-stage-2) - [July 2019](https://github.com/tc39/tc39-notes/blob/master/meetings/2019-07/july-24.md#stringprototypereplaceall) ## Specification diff --git a/spec.html b/spec.html index 3b3741d..2e2c932 100644 --- a/spec.html +++ b/spec.html @@ -42,8 +42,13 @@

String.prototype.replaceAll ( _searchValue_, _replaceValue_ )

1. Let _O_ be ? RequireObjectCoercible(*this* value). 1. If _searchValue_ is neither *undefined* nor *null*, then + 1. Let _isRegExp_ be ? IsRegExp(_searchString_). + 1. If _isRegExp_ is true, then + 1. Let _flags_ be ? Get(_searchValue_, *"flags"*). + 1. If _flags_ is not *undefined*, then + 1. If ? ToString(_flags_) does not contain *"g"*, throw a *TypeError* exception. 1. Let _replacer_ be ? GetMethod(_searchValue_, @@replace). - 2. If _replacer_ is not *undefined*, then + 1. If _replacer_ is not *undefined*, then 1. Return ? Call(_replacer_, _searchValue_, « _O_, _replaceValue_ »). 1. Let _string_ be ? ToString(_O_). 1. Let _searchString_ be ? ToString(_searchValue_). @@ -76,3 +81,26 @@

String.prototype.replaceAll ( _searchValue_, _replaceValue_ )

1. Return _result_.
+ + +

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). + 1. If _regexp_ is neither *undefined* nor *null*, then + 1. Let _isRegExp_ be ? IsRegExp(_regexp_). + 1. If _isRegExp_ is true, then + 1. Let _flags_ be ? Get(_regexp_, *"flags"*). + 1. If _flags_ is not *undefined*, then + 1. If ? ToString(_flags_) does not contain *"g"*, throw a *TypeError* exception. + 1. Let _matcher_ be ? GetMethod(_regexp_, @@matchAll). + 1. If _matcher_ is not *undefined*, then + 1. Return ? Call(_matcher_, _regexp_, « _O_ »). + 1. Let _S_ be ? ToString(_O_). + 1. Let _rx_ be ? RegExpCreate(_regexp_, `"g"`). + 1. Return ? Invoke(_rx_, @@matchAll, « _S_ »). + + 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. + Similarly to `String.prototype.split`, `String.prototype.matchAll` is designed to typically act without mutating its inputs. +