UNPKG

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