CreateRegExpStringIterator.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. 'use strict';
  2. var GetIntrinsic = require('get-intrinsic');
  3. var hasSymbols = require('has-symbols')();
  4. var $TypeError = GetIntrinsic('%TypeError%');
  5. var IteratorPrototype = GetIntrinsic('%IteratorPrototype%', true);
  6. var $defineProperty = GetIntrinsic('%Object.defineProperty%', true);
  7. var AdvanceStringIndex = require('./AdvanceStringIndex');
  8. var CreateIterResultObject = require('./CreateIterResultObject');
  9. var CreateMethodProperty = require('./CreateMethodProperty');
  10. var Get = require('./Get');
  11. var OrdinaryObjectCreate = require('./OrdinaryObjectCreate');
  12. var RegExpExec = require('./RegExpExec');
  13. var Set = require('./Set');
  14. var ToLength = require('./ToLength');
  15. var ToString = require('./ToString');
  16. var Type = require('./Type');
  17. var SLOT = require('internal-slot');
  18. var RegExpStringIterator = function RegExpStringIterator(R, S, global, fullUnicode) {
  19. if (Type(S) !== 'String') {
  20. throw new $TypeError('`S` must be a string');
  21. }
  22. if (Type(global) !== 'Boolean') {
  23. throw new $TypeError('`global` must be a boolean');
  24. }
  25. if (Type(fullUnicode) !== 'Boolean') {
  26. throw new $TypeError('`fullUnicode` must be a boolean');
  27. }
  28. SLOT.set(this, '[[IteratingRegExp]]', R);
  29. SLOT.set(this, '[[IteratedString]]', S);
  30. SLOT.set(this, '[[Global]]', global);
  31. SLOT.set(this, '[[Unicode]]', fullUnicode);
  32. SLOT.set(this, '[[Done]]', false);
  33. };
  34. if (IteratorPrototype) {
  35. RegExpStringIterator.prototype = OrdinaryObjectCreate(IteratorPrototype);
  36. }
  37. var RegExpStringIteratorNext = function next() {
  38. var O = this; // eslint-disable-line no-invalid-this
  39. if (Type(O) !== 'Object') {
  40. throw new $TypeError('receiver must be an object');
  41. }
  42. if (
  43. !(O instanceof RegExpStringIterator)
  44. || !SLOT.has(O, '[[IteratingRegExp]]')
  45. || !SLOT.has(O, '[[IteratedString]]')
  46. || !SLOT.has(O, '[[Global]]')
  47. || !SLOT.has(O, '[[Unicode]]')
  48. || !SLOT.has(O, '[[Done]]')
  49. ) {
  50. throw new $TypeError('"this" value must be a RegExpStringIterator instance');
  51. }
  52. if (SLOT.get(O, '[[Done]]')) {
  53. return CreateIterResultObject(undefined, true);
  54. }
  55. var R = SLOT.get(O, '[[IteratingRegExp]]');
  56. var S = SLOT.get(O, '[[IteratedString]]');
  57. var global = SLOT.get(O, '[[Global]]');
  58. var fullUnicode = SLOT.get(O, '[[Unicode]]');
  59. var match = RegExpExec(R, S);
  60. if (match === null) {
  61. SLOT.set(O, '[[Done]]', true);
  62. return CreateIterResultObject(undefined, true);
  63. }
  64. if (global) {
  65. var matchStr = ToString(Get(match, '0'));
  66. if (matchStr === '') {
  67. var thisIndex = ToLength(Get(R, 'lastIndex'));
  68. var nextIndex = AdvanceStringIndex(S, thisIndex, fullUnicode);
  69. Set(R, 'lastIndex', nextIndex, true);
  70. }
  71. return CreateIterResultObject(match, false);
  72. }
  73. SLOT.set(O, '[[Done]]', true);
  74. return CreateIterResultObject(match, false);
  75. };
  76. CreateMethodProperty(RegExpStringIterator.prototype, 'next', RegExpStringIteratorNext);
  77. if (hasSymbols) {
  78. if (Symbol.toStringTag) {
  79. if ($defineProperty) {
  80. $defineProperty(RegExpStringIterator.prototype, Symbol.toStringTag, {
  81. configurable: true,
  82. enumerable: false,
  83. value: 'RegExp String Iterator',
  84. writable: false
  85. });
  86. } else {
  87. RegExpStringIterator.prototype[Symbol.toStringTag] = 'RegExp String Iterator';
  88. }
  89. }
  90. if (Symbol.iterator && typeof RegExpStringIterator.prototype[Symbol.iterator] !== 'function') {
  91. var iteratorFn = function SymbolIterator() {
  92. return this;
  93. };
  94. CreateMethodProperty(RegExpStringIterator.prototype, Symbol.iterator, iteratorFn);
  95. }
  96. }
  97. // https://262.ecma-international.org/11.0/#sec-createregexpstringiterator
  98. module.exports = function CreateRegExpStringIterator(R, S, global, fullUnicode) {
  99. // assert R.global === global && R.unicode === fullUnicode?
  100. return new RegExpStringIterator(R, S, global, fullUnicode);
  101. };