regexp-exec.js 3.7 KB

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