CreateRegExpStringIterator.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. 'use strict';
  2. var GetIntrinsic = require('get-intrinsic');
  3. var hasSymbols = require('has-symbols')();
  4. var $TypeError = require('es-errors/type');
  5. var IteratorPrototype = GetIntrinsic('%IteratorPrototype%', true);
  6. var AdvanceStringIndex = require('./AdvanceStringIndex');
  7. var CreateIterResultObject = require('./CreateIterResultObject');
  8. var CreateMethodProperty = require('./CreateMethodProperty');
  9. var Get = require('./Get');
  10. var OrdinaryObjectCreate = require('./OrdinaryObjectCreate');
  11. var RegExpExec = require('./RegExpExec');
  12. var Set = require('./Set');
  13. var ToLength = require('./ToLength');
  14. var ToString = require('./ToString');
  15. var Type = require('./Type');
  16. var SLOT = require('internal-slot');
  17. var setToStringTag = require('es-set-tostringtag');
  18. var RegExpStringIterator = function RegExpStringIterator(R, S, global, fullUnicode) {
  19. if (typeof S !== 'string') {
  20. throw new $TypeError('`S` must be a string');
  21. }
  22. if (typeof global !== 'boolean') {
  23. throw new $TypeError('`global` must be a boolean');
  24. }
  25. if (typeof 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. setToStringTag(RegExpStringIterator.prototype, 'RegExp String Iterator');
  79. if (Symbol.iterator && typeof RegExpStringIterator.prototype[Symbol.iterator] !== 'function') {
  80. var iteratorFn = function SymbolIterator() {
  81. return this;
  82. };
  83. CreateMethodProperty(RegExpStringIterator.prototype, Symbol.iterator, iteratorFn);
  84. }
  85. }
  86. // https://262.ecma-international.org/11.0/#sec-createregexpstringiterator
  87. module.exports = function CreateRegExpStringIterator(R, S, global, fullUnicode) {
  88. // assert R.global === global && R.unicode === fullUnicode?
  89. return new RegExpStringIterator(R, S, global, fullUnicode);
  90. };