1 | 'use strict';
|
---|
2 | /* eslint-disable es/no-string-prototype-matchall -- safe */
|
---|
3 | var $ = require('../internals/export');
|
---|
4 | var call = require('../internals/function-call');
|
---|
5 | var uncurryThis = require('../internals/function-uncurry-this-clause');
|
---|
6 | var createIteratorConstructor = require('../internals/iterator-create-constructor');
|
---|
7 | var createIterResultObject = require('../internals/create-iter-result-object');
|
---|
8 | var requireObjectCoercible = require('../internals/require-object-coercible');
|
---|
9 | var toLength = require('../internals/to-length');
|
---|
10 | var toString = require('../internals/to-string');
|
---|
11 | var anObject = require('../internals/an-object');
|
---|
12 | var isNullOrUndefined = require('../internals/is-null-or-undefined');
|
---|
13 | var classof = require('../internals/classof-raw');
|
---|
14 | var isRegExp = require('../internals/is-regexp');
|
---|
15 | var getRegExpFlags = require('../internals/regexp-get-flags');
|
---|
16 | var getMethod = require('../internals/get-method');
|
---|
17 | var defineBuiltIn = require('../internals/define-built-in');
|
---|
18 | var fails = require('../internals/fails');
|
---|
19 | var wellKnownSymbol = require('../internals/well-known-symbol');
|
---|
20 | var speciesConstructor = require('../internals/species-constructor');
|
---|
21 | var advanceStringIndex = require('../internals/advance-string-index');
|
---|
22 | var regExpExec = require('../internals/regexp-exec-abstract');
|
---|
23 | var InternalStateModule = require('../internals/internal-state');
|
---|
24 | var IS_PURE = require('../internals/is-pure');
|
---|
25 |
|
---|
26 | var MATCH_ALL = wellKnownSymbol('matchAll');
|
---|
27 | var REGEXP_STRING = 'RegExp String';
|
---|
28 | var REGEXP_STRING_ITERATOR = REGEXP_STRING + ' Iterator';
|
---|
29 | var setInternalState = InternalStateModule.set;
|
---|
30 | var getInternalState = InternalStateModule.getterFor(REGEXP_STRING_ITERATOR);
|
---|
31 | var RegExpPrototype = RegExp.prototype;
|
---|
32 | var $TypeError = TypeError;
|
---|
33 | var stringIndexOf = uncurryThis(''.indexOf);
|
---|
34 | var nativeMatchAll = uncurryThis(''.matchAll);
|
---|
35 |
|
---|
36 | var WORKS_WITH_NON_GLOBAL_REGEX = !!nativeMatchAll && !fails(function () {
|
---|
37 | nativeMatchAll('a', /./);
|
---|
38 | });
|
---|
39 |
|
---|
40 | var $RegExpStringIterator = createIteratorConstructor(function RegExpStringIterator(regexp, string, $global, fullUnicode) {
|
---|
41 | setInternalState(this, {
|
---|
42 | type: REGEXP_STRING_ITERATOR,
|
---|
43 | regexp: regexp,
|
---|
44 | string: string,
|
---|
45 | global: $global,
|
---|
46 | unicode: fullUnicode,
|
---|
47 | done: false
|
---|
48 | });
|
---|
49 | }, REGEXP_STRING, function next() {
|
---|
50 | var state = getInternalState(this);
|
---|
51 | if (state.done) return createIterResultObject(undefined, true);
|
---|
52 | var R = state.regexp;
|
---|
53 | var S = state.string;
|
---|
54 | var match = regExpExec(R, S);
|
---|
55 | if (match === null) {
|
---|
56 | state.done = true;
|
---|
57 | return createIterResultObject(undefined, true);
|
---|
58 | }
|
---|
59 | if (state.global) {
|
---|
60 | if (toString(match[0]) === '') R.lastIndex = advanceStringIndex(S, toLength(R.lastIndex), state.unicode);
|
---|
61 | return createIterResultObject(match, false);
|
---|
62 | }
|
---|
63 | state.done = true;
|
---|
64 | return createIterResultObject(match, false);
|
---|
65 | });
|
---|
66 |
|
---|
67 | var $matchAll = function (string) {
|
---|
68 | var R = anObject(this);
|
---|
69 | var S = toString(string);
|
---|
70 | var C = speciesConstructor(R, RegExp);
|
---|
71 | var flags = toString(getRegExpFlags(R));
|
---|
72 | var matcher, $global, fullUnicode;
|
---|
73 | matcher = new C(C === RegExp ? R.source : R, flags);
|
---|
74 | $global = !!~stringIndexOf(flags, 'g');
|
---|
75 | fullUnicode = !!~stringIndexOf(flags, 'u');
|
---|
76 | matcher.lastIndex = toLength(R.lastIndex);
|
---|
77 | return new $RegExpStringIterator(matcher, S, $global, fullUnicode);
|
---|
78 | };
|
---|
79 |
|
---|
80 | // `String.prototype.matchAll` method
|
---|
81 | // https://tc39.es/ecma262/#sec-string.prototype.matchall
|
---|
82 | $({ target: 'String', proto: true, forced: WORKS_WITH_NON_GLOBAL_REGEX }, {
|
---|
83 | matchAll: function matchAll(regexp) {
|
---|
84 | var O = requireObjectCoercible(this);
|
---|
85 | var flags, S, matcher, rx;
|
---|
86 | if (!isNullOrUndefined(regexp)) {
|
---|
87 | if (isRegExp(regexp)) {
|
---|
88 | flags = toString(requireObjectCoercible(getRegExpFlags(regexp)));
|
---|
89 | if (!~stringIndexOf(flags, 'g')) throw new $TypeError('`.matchAll` does not allow non-global regexes');
|
---|
90 | }
|
---|
91 | if (WORKS_WITH_NON_GLOBAL_REGEX) return nativeMatchAll(O, regexp);
|
---|
92 | matcher = getMethod(regexp, MATCH_ALL);
|
---|
93 | if (matcher === undefined && IS_PURE && classof(regexp) === 'RegExp') matcher = $matchAll;
|
---|
94 | if (matcher) return call(matcher, regexp, O);
|
---|
95 | } else if (WORKS_WITH_NON_GLOBAL_REGEX) return nativeMatchAll(O, regexp);
|
---|
96 | S = toString(O);
|
---|
97 | rx = new RegExp(regexp, 'g');
|
---|
98 | return IS_PURE ? call($matchAll, rx, S) : rx[MATCH_ALL](S);
|
---|
99 | }
|
---|
100 | });
|
---|
101 |
|
---|
102 | IS_PURE || MATCH_ALL in RegExpPrototype || defineBuiltIn(RegExpPrototype, MATCH_ALL, $matchAll);
|
---|