From 894ef0b7be76b67d4c5de7848b7f5af1f04c50a0 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Wed, 8 Aug 2018 13:37:47 -0700 Subject: [PATCH] [spec] Adjust to committee feedback: - `String.prototype.matchAll`: - use `RegExpCreate` when `Symbol.prototype.matchAll` is not found - fall back to regex coercion otherwise - `RegExp.prototype[Symbol.matchAll]`: - receiver is assumed to be a regex implicitly - remove `MatchAllIterator` abstract operation Thus, `IsRegExp` call no longer exists. Addresses #21. Addresses #34. Closes #37. --- index.html | 96 ++++++++++++++++++++++-------------------------------- spec.emu | 42 ++++++++---------------- spec.md | 35 ++++++++------------ 3 files changed, 67 insertions(+), 106 deletions(-) diff --git a/index.html b/index.html index f241e72..cdf40e8 100644 --- a/index.html +++ b/index.html @@ -29,24 +29,6 @@ "location": "", "referencingIds": [], "key": "RegExp.prototype [ @@matchAll ] ( string )" - }, { - "type": "op", - "aoid": "MatchAllIterator", - "refId": "sec-matchalliterator", - "location": "", - "referencingIds": [], - "key": "MatchAllIterator" - }, { - "type": "clause", - "id": "sec-matchalliterator", - "aoid": "MatchAllIterator", - "title": "MatchAllIterator ( R, O )", - "titleHTML": "MatchAllIterator ( R, O )", - "number": "3", - "namespace": "", - "location": "", - "referencingIds": ["_ref_8", "_ref_10"], - "key": "MatchAllIterator ( R, O )" }, { "type": "op", "aoid": "CreateRegExpStringIterator", @@ -60,10 +42,10 @@ "aoid": "CreateRegExpStringIterator", "title": "CreateRegExpStringIterator ( R, S, global, fullUnicode )", "titleHTML": "CreateRegExpStringIterator ( R, S, global, fullUnicode )", - "number": "4", + "number": "3", "namespace": "", "location": "", - "referencingIds": ["_ref_26"], + "referencingIds": ["_ref_10", "_ref_24"], "key": "CreateRegExpStringIterator ( R, S, global, fullUnicode )" }, { "type": "clause", @@ -71,7 +53,7 @@ "aoid": null, "title": "%RegExpStringIteratorPrototype%.next ( )", "titleHTML": "%RegExpStringIteratorPrototype%.next ( )", - "number": "5.1", + "number": "4.1", "namespace": "", "location": "", "referencingIds": [], @@ -82,7 +64,7 @@ "aoid": null, "title": "%RegExpStringIteratorPrototype%[ @@toStringTag ]", "titleHTML": "%RegExpStringIteratorPrototype%[ @@toStringTag ]", - "number": "5.2", + "number": "4.2", "namespace": "", "location": "", "referencingIds": [], @@ -93,7 +75,7 @@ "aoid": null, "title": "Properties of RegExp String Iterator Instances", "titleHTML": "Properties of RegExp String Iterator Instances", - "number": "5.3", + "number": "4.3", "namespace": "", "location": "", "referencingIds": ["_ref_2"], @@ -104,7 +86,7 @@ "aoid": null, "title": "The %RegExpStringIteratorPrototype% Object", "titleHTML": "The %RegExpStringIteratorPrototype% Object", - "number": "5", + "number": "4", "namespace": "", "location": "", "referencingIds": ["_ref_0", "_ref_1", "_ref_3"], @@ -115,7 +97,7 @@ "aoid": null, "title": "Symbol.matchAll", "titleHTML": "Symbol.matchAll", - "number": "6", + "number": "5", "namespace": "", "location": "", "referencingIds": [], @@ -135,7 +117,7 @@ "aoid": null, "title": "Well-Known Symbols", "titleHTML": "Well-Known Symbols", - "number": "7", + "number": "6", "namespace": "", "location": "", "referencingIds": [], @@ -1699,6 +1681,11 @@ display: block; } + emu-rhs>ins, + emu-rhs>del { + display: inline; + } + tr.ins>td>ins { border-bottom: none; } @@ -2176,6 +2163,12 @@ text-align: right; padding-right: 5px; } + + @media print { + #menu-toggle { + display: none; + } + } @@ -2195,23 +2188,22 @@
  1. 1 String.prototype.matchAll ( regexp )
  2. 2 RegExp.prototype [ @@matchAll ] ( string )
  3. -
  4. 3 MatchAllIterator ( R, O )
  5. -
  6. 4 CreateRegExpStringIterator ( R, S, global, fullUnicode )
  7. -
  8. 5 The %RegExpStringIteratorPrototype% Object +
  9. 3 CreateRegExpStringIterator ( R, S, global, fullUnicode )
  10. +
  11. 4 The %RegExpStringIteratorPrototype% Object
      -
    1. 5.1 %RegExpStringIteratorPrototype%.next ( )
    2. -
    3. 5.2 %RegExpStringIteratorPrototype%[ @@toStringTag ]
    4. -
    5. 5.3 Properties of RegExp String Iterator Instances
    6. +
    7. 4.1 %RegExpStringIteratorPrototype%.next ( )
    8. +
    9. 4.2 %RegExpStringIteratorPrototype%[ @@toStringTag ]
    10. +
    11. 4.3 Properties of RegExp String Iterator Instances
  12. -
  13. 6 Symbol.matchAll
  14. -
  15. 7 Well-Known Symbols
  16. +
  17. 5 Symbol.matchAll
  18. +
  19. 6 Well-Known Symbols
  20. A Copyright & Software License
-

Stage 3 Draft / April 13, 2018

+

Stage 3 Draft / August 8, 2018

String.prototype.matchAll

@@ -2221,7 +2213,7 @@

1String.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 matcher be ? GetMethod(regexp, @@matchAll).
    2. If matcher is not undefined, then
      1. Return ? Call(matcher, regexp, « O »).
  3. Return ? MatchAllIterator(regexp, O). +
    1. Let O be ? RequireObjectCoercible(this value).
    2. If regexp is neither undefined nor null, then
      1. Let matcher be ? GetMethod(regexp, @@matchAll).
      2. If matcher is not undefined, then
        1. Return ? Call(matcher, regexp, « O »).
    3. Let S be ? ToString(O).
    4. Let matcher be ? RegExpCreate(R, "g").
    5. Let global be true.
    6. Let fullUnicode be false.
    7. Return ! CreateRegExpStringIterator(matcher, S, global, fullUnicode).
    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.
    @@ -2233,52 +2225,42 @@

    1String.prototype.matchAll ( regexp )

    2RegExp.prototype [ @@matchAll ] ( string )

    When the @@matchAll method is called with argument string, the following steps are taken:

    -
    1. Let R be the this value.
    2. If Type(R) is not Object, throw a TypeError exception.
    3. Return ? MatchAllIterator(R, string). +
      1. Let R be the this value.
      2. If Type(R) is not Object, throw a TypeError exception.
      3. Let S be ? ToString(string).
      4. Let C be ? SpeciesConstructor(R, %RegExp%).
      5. Let flags be ? ToString(? Get(R, "flags")).
      6. Let matcher be ? Construct(C, « R, flags »).
      7. Let lastIndex be ? ToLength(? Get(R, "lastIndex")).
      8. Perform ? Set(matcher, "lastIndex", lastIndex, true).
      9. Let global be ? ToBoolean(? Get(matcher, "global")).
      10. Let fullUnicode be ? ToBoolean(? Get(matcher, "unicode").
      11. Return ! CreateRegExpStringIterator(matcher, S, global, fullUnicode).

      The value of the name property of this function is "[Symbol.matchAll]".

      - - - - -

      3MatchAllIterator ( R, O )

      - -

      The abstract operation MatchAllIterator performs the following steps:

      -
      1. Let S be ? ToString(O).
      2. If ? IsRegExp(R) is true, then
        1. Let C be ? SpeciesConstructor(R, %RegExp%).
        2. Let flags be ? ToString(? Get(R, "flags")).
        3. Let matcher be ? Construct(C, « R, flags »).
        4. Let global be ? ToBoolean(? Get(matcher, "global")).
        5. Let fullUnicode be ? ToBoolean(? Get(matcher, "unicode").
        6. Let lastIndex be ? ToLength(? Get(R, "lastIndex")).
        7. Perform ? Set(matcher, "lastIndex", lastIndex, true).
      3. Else,
        1. Let flags be "g".
        2. Let matcher be ? RegExpCreate(R, flags).
        3. Let global be true.
        4. Let fullUnicode be false.
        5. Assert: ! Get(matcher, "lastIndex") is 0.
      4. Return ! CreateRegExpStringIterator(matcher, S, global, fullUnicode). -
      -
      -

      4CreateRegExpStringIterator ( R, S, global, fullUnicode )

      +

      3CreateRegExpStringIterator ( R, S, global, fullUnicode )

      The abstract operation CreateRegExpStringIterator is used to create such iterator objects. It performs the following steps:

      -
      1. Assert: Type(S) is String.
      2. Assert: Type(global) is Boolean.
      3. Assert: Type(fullUnicode) is Boolean.
      4. Let iterator be ObjectCreate(%RegExpStringIteratorPrototype%, « [[IteratingRegExp]], [[IteratedString]], [[Global]], [[Unicode]], [[Done]] »).
      5. Set iterator.[[IteratingRegExp]] to R.
      6. Set iterator.[[IteratedString]] to S.
      7. Set iterator.[[Global]] to global.
      8. Set iterator.[[Unicode]] to fullUnicode.
      9. Set iterator.[[Done]] to false.
      10. Return iterator. +
        1. Assert: Type(S) is String.
        2. Assert: Type(global) is Boolean.
        3. Assert: Type(fullUnicode) is Boolean.
        4. Let iterator be ObjectCreate(%RegExpStringIteratorPrototype%, « [[IteratingRegExp]], [[IteratedString]], [[Global]], [[Unicode]], [[Done]] »).
        5. Set iterator.[[IteratingRegExp]] to R.
        6. Set iterator.[[IteratedString]] to S.
        7. Set iterator.[[Global]] to global.
        8. Set iterator.[[Unicode]] to fullUnicode.
        9. Set iterator.[[Done]] to false.
        10. Return iterator.
        -

        5The %RegExpStringIteratorPrototype% Object

        +

        4The %RegExpStringIteratorPrototype% Object

        All RegExp String Iterator Objects inherit properties from the %RegExpStringIteratorPrototype% intrinsic object. The %RegExpStringIteratorPrototype% object is an ordinary object and its [[Prototype]] internal slot is the %IteratorPrototype% intrinsic object. In addition, %RegExpStringIteratorPrototype% has the following properties:

        -

        5.1%RegExpStringIteratorPrototype%.next ( )

        -
        1. Let O be the this value.
        2. If Type(O) is not Object, throw a TypeError exception.
        3. If O does not have all of the internal slots of a RegExp String Iterator Object Instance (see 5.3), throw a TypeError exception.
        4. If O.[[Done]] is true, then
          1. Return ! CreateIterResultObject(undefined, true).
        5. Let R be O.[[IteratingRegExp]].
        6. Let S be O.[[IteratedString]].
        7. Let global be O.[[Global]].
        8. Let fullUnicode be O.[[Unicode]].
        9. Let match be ? RegExpExec(R, S).
        10. If match is null, then
          1. Set O.[[Done]] to true.
          2. Return ! CreateIterResultObject(undefined, true).
        11. Else,
          1. If global is true,
            1. Let matchStr be ? ToString(? Get(match, "0")).
            2. If matchStr is the empty string,
              1. Let thisIndex be ? ToLength(? Get(R, "lastIndex")).
              2. Let nextIndex be ! AdvanceStringIndex(S, thisIndex, fullUnicode).
              3. Perform ? Set(R, "lastIndex", nextIndex, true).
            3. Return ! CreateIterResultObject(match, false).
          2. Else,
            1. Set O.[[Done]] to true.
            2. Return ! CreateIterResultObject(match, false). +

              4.1%RegExpStringIteratorPrototype%.next ( )

              +
              1. Let O be the this value.
              2. If Type(O) is not Object, throw a TypeError exception.
              3. If O does not have all of the internal slots of a RegExp String Iterator Object Instance (see 4.3), throw a TypeError exception.
              4. If O.[[Done]] is true, then
                1. Return ! CreateIterResultObject(undefined, true).
              5. Let R be O.[[IteratingRegExp]].
              6. Let S be O.[[IteratedString]].
              7. Let global be O.[[Global]].
              8. Let fullUnicode be O.[[Unicode]].
              9. Let match be ? RegExpExec(R, S).
              10. If match is null, then
                1. Set O.[[Done]] to true.
                2. Return ! CreateIterResultObject(undefined, true).
              11. Else,
                1. If global is true,
                  1. Let matchStr be ? ToString(? Get(match, "0")).
                  2. If matchStr is the empty string,
                    1. Let thisIndex be ? ToLength(? Get(R, "lastIndex")).
                    2. Let nextIndex be ! AdvanceStringIndex(S, thisIndex, fullUnicode).
                    3. Perform ? Set(R, "lastIndex", nextIndex, true).
                  3. Return ! CreateIterResultObject(match, false).
                2. Else,
                  1. Set O.[[Done]] to true.
                  2. Return ! CreateIterResultObject(match, false).
              -

              5.2%RegExpStringIteratorPrototype%[ @@toStringTag ]

              +

              4.2%RegExpStringIteratorPrototype%[ @@toStringTag ]

              The initial value of the @@toStringTag property is the String value "RegExp String Iterator".

              This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

              -

              5.3Properties of RegExp String Iterator Instances

              +

              4.3Properties of RegExp String Iterator Instances

              RegExp String Iterator instances are ordinary objects that inherit properties from the %RegExpStringIteratorPrototype% intrinsic object. RegExp String Iterator instances are initially created with the internal slots listed in Table 1.

              Table 1 – Internal Slots of RegExp String Iterator Instances
              @@ -2290,7 +2272,7 @@

              5.3Properties of RegExp String Iterator Instance [[IteratingRegExp]] - The regular expression used for iteration. IsRegExp([[IteratingRegExp]]) is always initially true. + The regular expression used for iteration. IsRegExp([[IteratingRegExp]]) is always initially true. [[IteratedString]] @@ -2318,14 +2300,14 @@

              5.3Properties of RegExp String Iterator Instance -

              6Symbol.matchAll

              +

              5Symbol.matchAll

              The initial value of Symbol.matchAll is the well-known symbol @@matchAll (Table 1).

              This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

              -

              7Well-Known Symbols

              +

              6Well-Known Symbols

              Editor's Note
              insert after @@match; before @@replace
              diff --git a/spec.emu b/spec.emu index f9b2518..bff5b7d 100644 --- a/spec.emu +++ b/spec.emu @@ -20,7 +20,11 @@ contributors: Jordan Harband 1. Let _matcher_ be ? GetMethod(_regexp_, @@matchAll). 1. If _matcher_ is not *undefined*, then 1. Return ? Call(_matcher_, _regexp_, « _O_ »). - 1. Return ? MatchAllIterator(_regexp_, _O_). + 1. Let _S_ be ? ToString(_O_). + 1. Let _matcher_ be ? RegExpCreate(_R_, `"g"`). + 1. Let _global_ be *true*. + 1. Let _fullUnicode_ be *false*. + 1. Return ! CreateRegExpStringIterator(_matcher_, _S_, _global_, _fullUnicode_). 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. @@ -35,35 +39,17 @@ contributors: Jordan Harband 1. Let _R_ be the *this* value. 1. If Type(_R_) is not Object, throw a *TypeError* exception. - 1. Return ? MatchAllIterator(_R_, _string_). - -

              The value of the *name* property of this function is *"[Symbol.matchAll]"*.

              -
              - - - - -

              MatchAllIterator ( _R_, _O_ )

              - -

              The abstract operation _MatchAllIterator_ performs the following steps:

              - - 1. Let _S_ be ? ToString(_O_). - 1. If ? IsRegExp(_R_) is `true`, then - 1. Let _C_ be ? SpeciesConstructor(_R_, %RegExp%). - 1. Let _flags_ be ? ToString(? Get(_R_, `"flags"`)). - 1. Let _matcher_ be ? Construct(_C_, « _R_, _flags_ »). - 1. Let _global_ be ? ToBoolean(? Get(_matcher_, `"global"`)). - 1. Let _fullUnicode_ be ? ToBoolean(? Get(_matcher_, `"unicode"`). - 1. Let _lastIndex_ be ? ToLength(? Get(_R_, `"lastIndex"`)). - 1. Perform ? Set(_matcher_, `"lastIndex"`, _lastIndex_, *true*). - 1. Else, - 1. Let _flags_ be `"g"`. - 1. Let _matcher_ be ? RegExpCreate(_R_, _flags_). - 1. Let _global_ be *true*. - 1. Let _fullUnicode_ be *false*. - 1. Assert: ! Get(_matcher_, `"lastIndex"`) is *0*. + 1. Let _S_ be ? ToString(_string_). + 1. Let _C_ be ? SpeciesConstructor(_R_, %RegExp%). + 1. Let _flags_ be ? ToString(? Get(_R_, `"flags"`)). + 1. Let _matcher_ be ? Construct(_C_, « _R_, _flags_ »). + 1. Let _lastIndex_ be ? ToLength(? Get(_R_, `"lastIndex"`)). + 1. Perform ? Set(_matcher_, `"lastIndex"`, _lastIndex_, *true*). + 1. Let _global_ be ? ToBoolean(? Get(_matcher_, `"global"`)). + 1. Let _fullUnicode_ be ? ToBoolean(? Get(_matcher_, `"unicode"`). 1. Return ! CreateRegExpStringIterator(_matcher_, _S_, _global_, _fullUnicode_). +

              The value of the *name* property of this function is *"[Symbol.matchAll]"*.

              diff --git a/spec.md b/spec.md index e7f3ea9..5dc7844 100644 --- a/spec.md +++ b/spec.md @@ -8,7 +8,11 @@ When the `matchAll` method is called, the following steps are taken: 1. Let *matcher* be ? [GetMethod][getmethod](*regexp*, @@matchAll). 1. If *matcher* is not **undefined**, then 1. Return ? [Call](call)(*matcher*, *regexp*, « *O* »). - 1. Return ? [MatchAllIterator](#matchalliterator)(*regexp*, *O*). + 1. Let *S* be ? [ToString][tostring](*O*). + 1. Let *matcher* be ? [RegExpCreate][regexp-create](*R*, `"g"`). + 1. Let *global* be **true**. + 1. Let *fullUnicode* be **false**. + 1. Return ! [CreateRegExpStringIterator](#createregexpstringiterator-abstract-operation)(*matcher*, *S*, *global*, *fullUnicode*). 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. @@ -18,29 +22,18 @@ Note 2: Similarly to `String.prototype.split`, `String.prototype.matchAll` is de When the `@@matchAll` method is called with argument *string*, the following steps are taken: 1. Let *R* be the **this** value. 1. If [Type][type](_R_) is not Object, throw a **TypeError** exception. - 1. Return ? [MatchAllIterator](#matchalliterator)(*R*, *string*). + 1. Let *S* be ? [ToString][tostring](*string*). + 1. Let *C* be ? [SpeciesConstructor][species-constructor](*R*, %RegExp%). + 1. Let *flags* be ? [ToString][tostring](? [Get][get](*R*, `"flags"`)). + 1. Let *matcher* be ? [Construct][construct](*C*, « *R*, *flags* »). + 1. Let *lastIndex* be ? [ToLength][tolength](? [Get][get](*R*, `"lastIndex"`)). + 1. Perform ? [Set][set](*matcher*, **"lastIndex"**, *lastIndex*, **true**). + 1. Let *global* be ? [ToBoolean][to-boolean](? [Get][get](*matcher*, `"global"`)). + 1. Let *fullUnicode* be ? [ToBoolean][to-boolean](? [Get][get](*matcher*, `"unicode"`)). + 1. Return ! [CreateRegExpStringIterator](#createregexpstringiterator-abstract-operation)(*matcher*, *S*, *global*, *fullUnicode*). The value of the name property of this function is "[Symbol.matchAll]". -# MatchAllIterator ( *R*, *O* ) - -The abstract operation *MatchAllIterator* performs the following steps: - 1. Let *S* be ? [ToString][to-string](*O*). - 1. If ? [IsRegExp][isregexp](*R*) is **true**, then - 1. Let *C* be ? [SpeciesConstructor][species-constructor](*R*, %RegExp%). - 1. Let *flags* be ? [ToString][tostring](? [Get][get](*R*, `"flags"`)). - 1. Let *matcher* be ? [Construct][construct](*C*, « *R*, *flags* »). - 1. Let *global* be ? [ToBoolean][to-boolean](? [Get][get](*matcher*, `"global"`)). - 1. Let *fullUnicode* be ? [ToBoolean][to-boolean](? [Get][get](*matcher*, `"unicode"`)). - 1. Let *lastIndex* be ? [ToLength][tolength](? [Get][get](*R*, `"lastIndex"`)). - 1. Perform ? [Set][set](*matcher*, **"lastIndex"**, *lastIndex*, **true**). - 1. Else, - 1. Let *matcher* be [RegExpCreate][regexp-create](*R*, `"g"`). - 1. Let *global* be **true**. - 1. Let *fullUnicode* be **false**. - 1. Assert: ! [Get][get](*matcher*, `"lastIndex"`) is `0`. - 1. Return ! [CreateRegExpStringIterator](#createregexpstringiterator-abstract-operation)(*matcher*, *S*, *global*, *fullUnicode*). - ## CreateRegExpStringIterator( *R*, *S*, *global*, *fullUnicode* ) The abstract operation *CreateRegExpStringIterator* is used to create such iterator objects. It performs the following steps: