UNPKG

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