index.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _helperPluginUtils = require("@babel/helper-plugin-utils");
  7. var _core = require("@babel/core");
  8. var _noHelperImplementation = require("./no-helper-implementation");
  9. function buildLoopBody(path, declar, newBody) {
  10. let block;
  11. const bodyPath = path.get("body");
  12. const body = newBody != null ? newBody : bodyPath.node;
  13. if (_core.types.isBlockStatement(body) && Object.keys(path.getBindingIdentifiers()).some(id => bodyPath.scope.hasOwnBinding(id))) {
  14. block = _core.types.blockStatement([declar, body]);
  15. } else {
  16. block = _core.types.toBlock(body);
  17. block.body.unshift(declar);
  18. }
  19. return block;
  20. }
  21. var _default = (0, _helperPluginUtils.declare)((api, options) => {
  22. var _options$assumeArray, _options$allowArrayLi, _api$assumption;
  23. api.assertVersion(7);
  24. {
  25. const {
  26. assumeArray,
  27. allowArrayLike,
  28. loose
  29. } = options;
  30. if (loose === true && assumeArray === true) {
  31. throw new Error(`The loose and assumeArray options cannot be used together in @babel/plugin-transform-for-of`);
  32. }
  33. if (assumeArray === true && allowArrayLike === true) {
  34. throw new Error(`The assumeArray and allowArrayLike options cannot be used together in @babel/plugin-transform-for-of`);
  35. }
  36. if (allowArrayLike && /^7\.\d\./.test(api.version)) {
  37. throw new Error(`The allowArrayLike is only supported when using @babel/core@^7.10.0`);
  38. }
  39. }
  40. const iterableIsArray = (_options$assumeArray = options.assumeArray) != null ? _options$assumeArray : !options.loose && api.assumption("iterableIsArray");
  41. const arrayLikeIsIterable = (_options$allowArrayLi = options.allowArrayLike) != null ? _options$allowArrayLi : api.assumption("arrayLikeIsIterable");
  42. const skipteratorClosing = (_api$assumption = api.assumption("skipForOfIteratorClosing")) != null ? _api$assumption : options.loose;
  43. if (iterableIsArray && arrayLikeIsIterable) {
  44. throw new Error(`The "iterableIsArray" and "arrayLikeIsIterable" assumptions are not compatible.`);
  45. }
  46. if (iterableIsArray) {
  47. return {
  48. name: "transform-for-of",
  49. visitor: {
  50. ForOfStatement(path) {
  51. const {
  52. scope
  53. } = path;
  54. const {
  55. left,
  56. right,
  57. await: isAwait
  58. } = path.node;
  59. if (isAwait) {
  60. return;
  61. }
  62. const i = scope.generateUidIdentifier("i");
  63. let array = scope.maybeGenerateMemoised(right, true);
  64. const inits = [_core.types.variableDeclarator(i, _core.types.numericLiteral(0))];
  65. if (array) {
  66. inits.push(_core.types.variableDeclarator(array, right));
  67. } else {
  68. array = right;
  69. }
  70. const item = _core.types.memberExpression(_core.types.cloneNode(array), _core.types.cloneNode(i), true);
  71. let assignment;
  72. if (_core.types.isVariableDeclaration(left)) {
  73. assignment = left;
  74. assignment.declarations[0].init = item;
  75. } else {
  76. assignment = _core.types.expressionStatement(_core.types.assignmentExpression("=", left, item));
  77. }
  78. path.replaceWith(_core.types.forStatement(_core.types.variableDeclaration("let", inits), _core.types.binaryExpression("<", _core.types.cloneNode(i), _core.types.memberExpression(_core.types.cloneNode(array), _core.types.identifier("length"))), _core.types.updateExpression("++", _core.types.cloneNode(i)), buildLoopBody(path, assignment)));
  79. }
  80. }
  81. };
  82. }
  83. const buildForOfArray = (0, _core.template)`
  84. for (var KEY = 0, NAME = ARR; KEY < NAME.length; KEY++) BODY;
  85. `;
  86. const buildForOfNoIteratorClosing = _core.template.statements`
  87. for (var ITERATOR_HELPER = CREATE_ITERATOR_HELPER(OBJECT, ARRAY_LIKE_IS_ITERABLE), STEP_KEY;
  88. !(STEP_KEY = ITERATOR_HELPER()).done;) BODY;
  89. `;
  90. const buildForOf = _core.template.statements`
  91. var ITERATOR_HELPER = CREATE_ITERATOR_HELPER(OBJECT, ARRAY_LIKE_IS_ITERABLE), STEP_KEY;
  92. try {
  93. for (ITERATOR_HELPER.s(); !(STEP_KEY = ITERATOR_HELPER.n()).done;) BODY;
  94. } catch (err) {
  95. ITERATOR_HELPER.e(err);
  96. } finally {
  97. ITERATOR_HELPER.f();
  98. }
  99. `;
  100. const builder = skipteratorClosing ? {
  101. build: buildForOfNoIteratorClosing,
  102. helper: "createForOfIteratorHelperLoose",
  103. getContainer: nodes => nodes
  104. } : {
  105. build: buildForOf,
  106. helper: "createForOfIteratorHelper",
  107. getContainer: nodes => nodes[1].block.body
  108. };
  109. function _ForOfStatementArray(path) {
  110. const {
  111. node,
  112. scope
  113. } = path;
  114. const right = scope.generateUidIdentifierBasedOnNode(node.right, "arr");
  115. const iterationKey = scope.generateUidIdentifier("i");
  116. const loop = buildForOfArray({
  117. BODY: node.body,
  118. KEY: iterationKey,
  119. NAME: right,
  120. ARR: node.right
  121. });
  122. _core.types.inherits(loop, node);
  123. const iterationValue = _core.types.memberExpression(_core.types.cloneNode(right), _core.types.cloneNode(iterationKey), true);
  124. let declar;
  125. const left = node.left;
  126. if (_core.types.isVariableDeclaration(left)) {
  127. left.declarations[0].init = iterationValue;
  128. declar = left;
  129. } else {
  130. declar = _core.types.expressionStatement(_core.types.assignmentExpression("=", left, iterationValue));
  131. }
  132. loop.body = buildLoopBody(path, declar, loop.body);
  133. return loop;
  134. }
  135. return {
  136. name: "transform-for-of",
  137. visitor: {
  138. ForOfStatement(path, state) {
  139. const right = path.get("right");
  140. if (right.isArrayExpression() || right.isGenericType("Array") || _core.types.isArrayTypeAnnotation(right.getTypeAnnotation())) {
  141. path.replaceWith(_ForOfStatementArray(path));
  142. return;
  143. }
  144. if (!state.availableHelper(builder.helper)) {
  145. (0, _noHelperImplementation.default)(skipteratorClosing, path, state);
  146. return;
  147. }
  148. const {
  149. node,
  150. parent,
  151. scope
  152. } = path;
  153. const left = node.left;
  154. let declar;
  155. const stepKey = scope.generateUid("step");
  156. const stepValue = _core.types.memberExpression(_core.types.identifier(stepKey), _core.types.identifier("value"));
  157. if (_core.types.isVariableDeclaration(left)) {
  158. declar = _core.types.variableDeclaration(left.kind, [_core.types.variableDeclarator(left.declarations[0].id, stepValue)]);
  159. } else {
  160. declar = _core.types.expressionStatement(_core.types.assignmentExpression("=", left, stepValue));
  161. }
  162. const nodes = builder.build({
  163. CREATE_ITERATOR_HELPER: state.addHelper(builder.helper),
  164. ITERATOR_HELPER: scope.generateUidIdentifier("iterator"),
  165. ARRAY_LIKE_IS_ITERABLE: arrayLikeIsIterable ? _core.types.booleanLiteral(true) : null,
  166. STEP_KEY: _core.types.identifier(stepKey),
  167. OBJECT: node.right,
  168. BODY: buildLoopBody(path, declar)
  169. });
  170. const container = builder.getContainer(nodes);
  171. _core.types.inherits(container[0], node);
  172. _core.types.inherits(container[0].body, node.body);
  173. if (_core.types.isLabeledStatement(parent)) {
  174. container[0] = _core.types.labeledStatement(parent.label, container[0]);
  175. path.parentPath.replaceWithMultiple(nodes);
  176. path.skip();
  177. } else {
  178. path.replaceWithMultiple(nodes);
  179. }
  180. }
  181. }
  182. };
  183. });
  184. exports.default = _default;