UNPKG

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