| 1 | 'use strict';
|
|---|
| 2 | /* eslint-disable regexp/no-empty-capturing-group, regexp/no-empty-group, regexp/no-lazy-ends -- testing */
|
|---|
| 3 | /* eslint-disable regexp/no-useless-quantifier -- testing */
|
|---|
| 4 | var call = require('../internals/function-call');
|
|---|
| 5 | var uncurryThis = require('../internals/function-uncurry-this');
|
|---|
| 6 | var toString = require('../internals/to-string');
|
|---|
| 7 | var regexpFlags = require('../internals/regexp-flags');
|
|---|
| 8 | var stickyHelpers = require('../internals/regexp-sticky-helpers');
|
|---|
| 9 | var shared = require('../internals/shared');
|
|---|
| 10 | var create = require('../internals/object-create');
|
|---|
| 11 | var getInternalState = require('../internals/internal-state').get;
|
|---|
| 12 | var UNSUPPORTED_DOT_ALL = require('../internals/regexp-unsupported-dot-all');
|
|---|
| 13 | var UNSUPPORTED_NCG = require('../internals/regexp-unsupported-ncg');
|
|---|
| 14 |
|
|---|
| 15 | var nativeReplace = shared('native-string-replace', String.prototype.replace);
|
|---|
| 16 | var nativeExec = RegExp.prototype.exec;
|
|---|
| 17 | var patchedExec = nativeExec;
|
|---|
| 18 | var charAt = uncurryThis(''.charAt);
|
|---|
| 19 | var indexOf = uncurryThis(''.indexOf);
|
|---|
| 20 | var replace = uncurryThis(''.replace);
|
|---|
| 21 | var stringSlice = uncurryThis(''.slice);
|
|---|
| 22 |
|
|---|
| 23 | var UPDATES_LAST_INDEX_WRONG = (function () {
|
|---|
| 24 | var re1 = /a/;
|
|---|
| 25 | var re2 = /b*/g;
|
|---|
| 26 | call(nativeExec, re1, 'a');
|
|---|
| 27 | call(nativeExec, re2, 'a');
|
|---|
| 28 | return re1.lastIndex !== 0 || re2.lastIndex !== 0;
|
|---|
| 29 | })();
|
|---|
| 30 |
|
|---|
| 31 | var UNSUPPORTED_Y = stickyHelpers.BROKEN_CARET;
|
|---|
| 32 |
|
|---|
| 33 | // nonparticipating capturing group, copied from es5-shim's String#split patch.
|
|---|
| 34 | var NPCG_INCLUDED = /()??/.exec('')[1] !== undefined;
|
|---|
| 35 |
|
|---|
| 36 | var PATCH = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED || UNSUPPORTED_Y || UNSUPPORTED_DOT_ALL || UNSUPPORTED_NCG;
|
|---|
| 37 |
|
|---|
| 38 | var setGroups = function (re, groups) {
|
|---|
| 39 | var object = re.groups = create(null);
|
|---|
| 40 | for (var i = 0; i < groups.length; i++) {
|
|---|
| 41 | var group = groups[i];
|
|---|
| 42 | object[group[0]] = re[group[1]];
|
|---|
| 43 | }
|
|---|
| 44 | };
|
|---|
| 45 |
|
|---|
| 46 | if (PATCH) {
|
|---|
| 47 | patchedExec = function exec(string) {
|
|---|
| 48 | var re = this;
|
|---|
| 49 | var state = getInternalState(re);
|
|---|
| 50 | var str = toString(string);
|
|---|
| 51 | var raw = state.raw;
|
|---|
| 52 | var result, reCopy, lastIndex;
|
|---|
| 53 |
|
|---|
| 54 | if (raw) {
|
|---|
| 55 | raw.lastIndex = re.lastIndex;
|
|---|
| 56 | result = call(patchedExec, raw, str);
|
|---|
| 57 | re.lastIndex = raw.lastIndex;
|
|---|
| 58 |
|
|---|
| 59 | if (result && state.groups) setGroups(result, state.groups);
|
|---|
| 60 |
|
|---|
| 61 | return result;
|
|---|
| 62 | }
|
|---|
| 63 |
|
|---|
| 64 | var groups = state.groups;
|
|---|
| 65 | var sticky = UNSUPPORTED_Y && re.sticky;
|
|---|
| 66 | var flags = call(regexpFlags, re);
|
|---|
| 67 | var source = re.source;
|
|---|
| 68 | var charsAdded = 0;
|
|---|
| 69 | var strCopy = str;
|
|---|
| 70 |
|
|---|
| 71 | if (sticky) {
|
|---|
| 72 | flags = replace(flags, 'y', '');
|
|---|
| 73 | if (indexOf(flags, 'g') === -1) {
|
|---|
| 74 | flags += 'g';
|
|---|
| 75 | }
|
|---|
| 76 |
|
|---|
| 77 | strCopy = stringSlice(str, re.lastIndex);
|
|---|
| 78 | // Support anchored sticky behavior.
|
|---|
| 79 | var prevChar = re.lastIndex > 0 && charAt(str, re.lastIndex - 1);
|
|---|
| 80 | if (re.lastIndex > 0 &&
|
|---|
| 81 | (!re.multiline || re.multiline && prevChar !== '\n' && prevChar !== '\r' && prevChar !== '\u2028' && prevChar !== '\u2029')) {
|
|---|
| 82 | source = '(?: (?:' + source + '))';
|
|---|
| 83 | strCopy = ' ' + strCopy;
|
|---|
| 84 | charsAdded++;
|
|---|
| 85 | }
|
|---|
| 86 | // ^(? + rx + ) is needed, in combination with some str slicing, to
|
|---|
| 87 | // simulate the 'y' flag.
|
|---|
| 88 | reCopy = new RegExp('^(?:' + source + ')', flags);
|
|---|
| 89 | }
|
|---|
| 90 |
|
|---|
| 91 | if (NPCG_INCLUDED) {
|
|---|
| 92 | reCopy = new RegExp('^' + source + '$(?!\\s)', flags);
|
|---|
| 93 | }
|
|---|
| 94 | if (UPDATES_LAST_INDEX_WRONG) lastIndex = re.lastIndex;
|
|---|
| 95 |
|
|---|
| 96 | var match = call(nativeExec, sticky ? reCopy : re, strCopy);
|
|---|
| 97 |
|
|---|
| 98 | if (sticky) {
|
|---|
| 99 | if (match) {
|
|---|
| 100 | match.input = str;
|
|---|
| 101 | match[0] = stringSlice(match[0], charsAdded);
|
|---|
| 102 | match.index = re.lastIndex;
|
|---|
| 103 | re.lastIndex += match[0].length;
|
|---|
| 104 | } else re.lastIndex = 0;
|
|---|
| 105 | } else if (UPDATES_LAST_INDEX_WRONG && match) {
|
|---|
| 106 | re.lastIndex = re.global ? match.index + match[0].length : lastIndex;
|
|---|
| 107 | }
|
|---|
| 108 | if (NPCG_INCLUDED && match && match.length > 1) {
|
|---|
| 109 | // Fix browsers whose `exec` methods don't consistently return `undefined`
|
|---|
| 110 | // for NPCG, like IE8. NOTE: This doesn't work for /(.?)?/
|
|---|
| 111 | call(nativeReplace, match[0], reCopy, function () {
|
|---|
| 112 | for (var i = 1; i < arguments.length - 2; i++) {
|
|---|
| 113 | if (arguments[i] === undefined) match[i] = undefined;
|
|---|
| 114 | }
|
|---|
| 115 | });
|
|---|
| 116 | }
|
|---|
| 117 |
|
|---|
| 118 | if (match && groups) setGroups(match, groups);
|
|---|
| 119 |
|
|---|
| 120 | return match;
|
|---|
| 121 | };
|
|---|
| 122 | }
|
|---|
| 123 |
|
|---|
| 124 | module.exports = patchedExec;
|
|---|