regexp-exec.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. 'use strict';
  2. /* eslint-disable regexp/no-assertion-capturing-group, regexp/no-empty-group, regexp/no-lazy-ends -- testing */
  3. /* eslint-disable regexp/no-useless-quantifier -- testing */
  4. var regexpFlags = require('./regexp-flags');
  5. var stickyHelpers = require('./regexp-sticky-helpers');
  6. var shared = require('./shared');
  7. var nativeExec = RegExp.prototype.exec;
  8. var nativeReplace = shared('native-string-replace', String.prototype.replace);
  9. var patchedExec = nativeExec;
  10. var UPDATES_LAST_INDEX_WRONG = (function () {
  11. var re1 = /a/;
  12. var re2 = /b*/g;
  13. nativeExec.call(re1, 'a');
  14. nativeExec.call(re2, 'a');
  15. return re1.lastIndex !== 0 || re2.lastIndex !== 0;
  16. })();
  17. var UNSUPPORTED_Y = stickyHelpers.UNSUPPORTED_Y || stickyHelpers.BROKEN_CARET;
  18. // nonparticipating capturing group, copied from es5-shim's String#split patch.
  19. var NPCG_INCLUDED = /()??/.exec('')[1] !== undefined;
  20. var PATCH = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED || UNSUPPORTED_Y;
  21. if (PATCH) {
  22. patchedExec = function exec(str) {
  23. var re = this;
  24. var lastIndex, reCopy, match, i;
  25. var sticky = UNSUPPORTED_Y && re.sticky;
  26. var flags = regexpFlags.call(re);
  27. var source = re.source;
  28. var charsAdded = 0;
  29. var strCopy = str;
  30. if (sticky) {
  31. flags = flags.replace('y', '');
  32. if (flags.indexOf('g') === -1) {
  33. flags += 'g';
  34. }
  35. strCopy = String(str).slice(re.lastIndex);
  36. // Support anchored sticky behavior.
  37. if (re.lastIndex > 0 && (!re.multiline || re.multiline && str[re.lastIndex - 1] !== '\n')) {
  38. source = '(?: ' + source + ')';
  39. strCopy = ' ' + strCopy;
  40. charsAdded++;
  41. }
  42. // ^(? + rx + ) is needed, in combination with some str slicing, to
  43. // simulate the 'y' flag.
  44. reCopy = new RegExp('^(?:' + source + ')', flags);
  45. }
  46. if (NPCG_INCLUDED) {
  47. reCopy = new RegExp('^' + source + '$(?!\\s)', flags);
  48. }
  49. if (UPDATES_LAST_INDEX_WRONG) lastIndex = re.lastIndex;
  50. match = nativeExec.call(sticky ? reCopy : re, strCopy);
  51. if (sticky) {
  52. if (match) {
  53. match.input = match.input.slice(charsAdded);
  54. match[0] = match[0].slice(charsAdded);
  55. match.index = re.lastIndex;
  56. re.lastIndex += match[0].length;
  57. } else re.lastIndex = 0;
  58. } else if (UPDATES_LAST_INDEX_WRONG && match) {
  59. re.lastIndex = re.global ? match.index + match[0].length : lastIndex;
  60. }
  61. if (NPCG_INCLUDED && match && match.length > 1) {
  62. // Fix browsers whose `exec` methods don't consistently return `undefined`
  63. // for NPCG, like IE8. NOTE: This doesn' work for /(.?)?/
  64. nativeReplace.call(match[0], reCopy, function () {
  65. for (i = 1; i < arguments.length - 2; i++) {
  66. if (arguments[i] === undefined) match[i] = undefined;
  67. }
  68. });
  69. }
  70. return match;
  71. };
  72. }
  73. module.exports = patchedExec;