UNPKG

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