1 | "use strict";
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 | exports.DestructuringTransformer = void 0;
|
7 | exports.buildObjectExcludingKeys = buildObjectExcludingKeys;
|
8 | exports.convertAssignmentExpression = convertAssignmentExpression;
|
9 | exports.convertVariableDeclaration = convertVariableDeclaration;
|
10 | exports.unshiftForXStatementBody = unshiftForXStatementBody;
|
11 | var _core = require("@babel/core");
|
12 | function isPureVoid(node) {
|
13 | return _core.types.isUnaryExpression(node) && node.operator === "void" && _core.types.isPureish(node.argument);
|
14 | }
|
15 | function unshiftForXStatementBody(statementPath, newStatements) {
|
16 | statementPath.ensureBlock();
|
17 | const {
|
18 | scope,
|
19 | node
|
20 | } = statementPath;
|
21 | const bodyScopeBindings = statementPath.get("body").scope.bindings;
|
22 | const hasShadowedBlockScopedBindings = Object.keys(bodyScopeBindings).some(name => scope.hasBinding(name));
|
23 | if (hasShadowedBlockScopedBindings) {
|
24 | node.body = _core.types.blockStatement([...newStatements, node.body]);
|
25 | } else {
|
26 | node.body.body.unshift(...newStatements);
|
27 | }
|
28 | }
|
29 | function hasArrayRest(pattern) {
|
30 | return pattern.elements.some(elem => _core.types.isRestElement(elem));
|
31 | }
|
32 | function hasObjectRest(pattern) {
|
33 | return pattern.properties.some(prop => _core.types.isRestElement(prop));
|
34 | }
|
35 | const STOP_TRAVERSAL = {};
|
36 | const arrayUnpackVisitor = (node, ancestors, state) => {
|
37 | if (!ancestors.length) {
|
38 | return;
|
39 | }
|
40 | if (_core.types.isIdentifier(node) && _core.types.isReferenced(node, ancestors[ancestors.length - 1].node) && state.bindings[node.name]) {
|
41 | state.deopt = true;
|
42 | throw STOP_TRAVERSAL;
|
43 | }
|
44 | };
|
45 | class DestructuringTransformer {
|
46 | constructor(opts) {
|
47 | this.blockHoist = void 0;
|
48 | this.operator = void 0;
|
49 | this.arrayRefSet = void 0;
|
50 | this.nodes = void 0;
|
51 | this.scope = void 0;
|
52 | this.kind = void 0;
|
53 | this.iterableIsArray = void 0;
|
54 | this.arrayLikeIsIterable = void 0;
|
55 | this.objectRestNoSymbols = void 0;
|
56 | this.useBuiltIns = void 0;
|
57 | this.addHelper = void 0;
|
58 | this.blockHoist = opts.blockHoist;
|
59 | this.operator = opts.operator;
|
60 | this.arrayRefSet = new Set();
|
61 | this.nodes = opts.nodes || [];
|
62 | this.scope = opts.scope;
|
63 | this.kind = opts.kind;
|
64 | this.iterableIsArray = opts.iterableIsArray;
|
65 | this.arrayLikeIsIterable = opts.arrayLikeIsIterable;
|
66 | this.objectRestNoSymbols = opts.objectRestNoSymbols;
|
67 | this.useBuiltIns = opts.useBuiltIns;
|
68 | this.addHelper = opts.addHelper;
|
69 | }
|
70 | getExtendsHelper() {
|
71 | return this.useBuiltIns ? _core.types.memberExpression(_core.types.identifier("Object"), _core.types.identifier("assign")) : this.addHelper("extends");
|
72 | }
|
73 | buildVariableAssignment(id, init) {
|
74 | let op = this.operator;
|
75 | if (_core.types.isMemberExpression(id)) op = "=";
|
76 | let node;
|
77 | if (op) {
|
78 | node = _core.types.expressionStatement(_core.types.assignmentExpression(op, id, _core.types.cloneNode(init) || this.scope.buildUndefinedNode()));
|
79 | } else {
|
80 | let nodeInit;
|
81 | if ((this.kind === "const" || this.kind === "using") && init === null) {
|
82 | nodeInit = this.scope.buildUndefinedNode();
|
83 | } else {
|
84 | nodeInit = _core.types.cloneNode(init);
|
85 | }
|
86 | node = _core.types.variableDeclaration(this.kind, [_core.types.variableDeclarator(id, nodeInit)]);
|
87 | }
|
88 | node._blockHoist = this.blockHoist;
|
89 | return node;
|
90 | }
|
91 | buildVariableDeclaration(id, init) {
|
92 | const declar = _core.types.variableDeclaration("var", [_core.types.variableDeclarator(_core.types.cloneNode(id), _core.types.cloneNode(init))]);
|
93 | declar._blockHoist = this.blockHoist;
|
94 | return declar;
|
95 | }
|
96 | push(id, _init) {
|
97 | const init = _core.types.cloneNode(_init);
|
98 | if (_core.types.isObjectPattern(id)) {
|
99 | this.pushObjectPattern(id, init);
|
100 | } else if (_core.types.isArrayPattern(id)) {
|
101 | this.pushArrayPattern(id, init);
|
102 | } else if (_core.types.isAssignmentPattern(id)) {
|
103 | this.pushAssignmentPattern(id, init);
|
104 | } else {
|
105 | this.nodes.push(this.buildVariableAssignment(id, init));
|
106 | }
|
107 | }
|
108 | toArray(node, count) {
|
109 | if (this.iterableIsArray || _core.types.isIdentifier(node) && this.arrayRefSet.has(node.name)) {
|
110 | return node;
|
111 | } else {
|
112 | return this.scope.toArray(node, count, this.arrayLikeIsIterable);
|
113 | }
|
114 | }
|
115 | pushAssignmentPattern({
|
116 | left,
|
117 | right
|
118 | }, valueRef) {
|
119 | if (isPureVoid(valueRef)) {
|
120 | this.push(left, right);
|
121 | return;
|
122 | }
|
123 | const tempId = this.scope.generateUidIdentifierBasedOnNode(valueRef);
|
124 | this.nodes.push(this.buildVariableDeclaration(tempId, valueRef));
|
125 | const tempConditional = _core.types.conditionalExpression(_core.types.binaryExpression("===", _core.types.cloneNode(tempId), this.scope.buildUndefinedNode()), right, _core.types.cloneNode(tempId));
|
126 | if (_core.types.isPattern(left)) {
|
127 | let patternId;
|
128 | let node;
|
129 | if (this.kind === "const" || this.kind === "let" || this.kind === "using") {
|
130 | patternId = this.scope.generateUidIdentifier(tempId.name);
|
131 | node = this.buildVariableDeclaration(patternId, tempConditional);
|
132 | } else {
|
133 | patternId = tempId;
|
134 | node = _core.types.expressionStatement(_core.types.assignmentExpression("=", _core.types.cloneNode(tempId), tempConditional));
|
135 | }
|
136 | this.nodes.push(node);
|
137 | this.push(left, patternId);
|
138 | } else {
|
139 | this.nodes.push(this.buildVariableAssignment(left, tempConditional));
|
140 | }
|
141 | }
|
142 | pushObjectRest(pattern, objRef, spreadProp, spreadPropIndex) {
|
143 | const value = buildObjectExcludingKeys(pattern.properties.slice(0, spreadPropIndex), objRef, this.scope, name => this.addHelper(name), this.objectRestNoSymbols, this.useBuiltIns);
|
144 | this.nodes.push(this.buildVariableAssignment(spreadProp.argument, value));
|
145 | }
|
146 | pushObjectProperty(prop, propRef) {
|
147 | if (_core.types.isLiteral(prop.key)) prop.computed = true;
|
148 | const pattern = prop.value;
|
149 | const objRef = _core.types.memberExpression(_core.types.cloneNode(propRef), prop.key, prop.computed);
|
150 | if (_core.types.isPattern(pattern)) {
|
151 | this.push(pattern, objRef);
|
152 | } else {
|
153 | this.nodes.push(this.buildVariableAssignment(pattern, objRef));
|
154 | }
|
155 | }
|
156 | pushObjectPattern(pattern, objRef) {
|
157 | if (!pattern.properties.length) {
|
158 | this.nodes.push(_core.types.expressionStatement(_core.types.callExpression(this.addHelper("objectDestructuringEmpty"), isPureVoid(objRef) ? [] : [objRef])));
|
159 | return;
|
160 | }
|
161 | if (pattern.properties.length > 1 && !this.scope.isStatic(objRef)) {
|
162 | const temp = this.scope.generateUidIdentifierBasedOnNode(objRef);
|
163 | this.nodes.push(this.buildVariableDeclaration(temp, objRef));
|
164 | objRef = temp;
|
165 | }
|
166 | if (hasObjectRest(pattern)) {
|
167 | let copiedPattern;
|
168 | for (let i = 0; i < pattern.properties.length; i++) {
|
169 | const prop = pattern.properties[i];
|
170 | if (_core.types.isRestElement(prop)) {
|
171 | break;
|
172 | }
|
173 | const key = prop.key;
|
174 | if (prop.computed && !this.scope.isPure(key)) {
|
175 | const name = this.scope.generateUidIdentifierBasedOnNode(key);
|
176 | this.nodes.push(this.buildVariableDeclaration(name, key));
|
177 | if (!copiedPattern) {
|
178 | copiedPattern = pattern = Object.assign({}, pattern, {
|
179 | properties: pattern.properties.slice()
|
180 | });
|
181 | }
|
182 | copiedPattern.properties[i] = Object.assign({}, prop, {
|
183 | key: name
|
184 | });
|
185 | }
|
186 | }
|
187 | }
|
188 | for (let i = 0; i < pattern.properties.length; i++) {
|
189 | const prop = pattern.properties[i];
|
190 | if (_core.types.isRestElement(prop)) {
|
191 | this.pushObjectRest(pattern, objRef, prop, i);
|
192 | } else {
|
193 | this.pushObjectProperty(prop, objRef);
|
194 | }
|
195 | }
|
196 | }
|
197 | canUnpackArrayPattern(pattern, arr) {
|
198 | if (!_core.types.isArrayExpression(arr)) return false;
|
199 | if (pattern.elements.length > arr.elements.length) return;
|
200 | if (pattern.elements.length < arr.elements.length && !hasArrayRest(pattern)) {
|
201 | return false;
|
202 | }
|
203 | for (const elem of pattern.elements) {
|
204 | if (!elem) return false;
|
205 | if (_core.types.isMemberExpression(elem)) return false;
|
206 | }
|
207 | for (const elem of arr.elements) {
|
208 | if (_core.types.isSpreadElement(elem)) return false;
|
209 | if (_core.types.isCallExpression(elem)) return false;
|
210 | if (_core.types.isMemberExpression(elem)) return false;
|
211 | }
|
212 | const bindings = _core.types.getBindingIdentifiers(pattern);
|
213 | const state = {
|
214 | deopt: false,
|
215 | bindings
|
216 | };
|
217 | try {
|
218 | _core.types.traverse(arr, arrayUnpackVisitor, state);
|
219 | } catch (e) {
|
220 | if (e !== STOP_TRAVERSAL) throw e;
|
221 | }
|
222 | return !state.deopt;
|
223 | }
|
224 | pushUnpackedArrayPattern(pattern, arr) {
|
225 | const holeToUndefined = el => el != null ? el : this.scope.buildUndefinedNode();
|
226 | for (let i = 0; i < pattern.elements.length; i++) {
|
227 | const elem = pattern.elements[i];
|
228 | if (_core.types.isRestElement(elem)) {
|
229 | this.push(elem.argument, _core.types.arrayExpression(arr.elements.slice(i).map(holeToUndefined)));
|
230 | } else {
|
231 | this.push(elem, holeToUndefined(arr.elements[i]));
|
232 | }
|
233 | }
|
234 | }
|
235 | pushArrayPattern(pattern, arrayRef) {
|
236 | if (arrayRef === null) {
|
237 | this.nodes.push(_core.types.expressionStatement(_core.types.callExpression(this.addHelper("objectDestructuringEmpty"), [])));
|
238 | return;
|
239 | }
|
240 | if (!pattern.elements) return;
|
241 | if (this.canUnpackArrayPattern(pattern, arrayRef)) {
|
242 | this.pushUnpackedArrayPattern(pattern, arrayRef);
|
243 | return;
|
244 | }
|
245 | const count = !hasArrayRest(pattern) && pattern.elements.length;
|
246 | const toArray = this.toArray(arrayRef, count);
|
247 | if (_core.types.isIdentifier(toArray)) {
|
248 | arrayRef = toArray;
|
249 | } else {
|
250 | arrayRef = this.scope.generateUidIdentifierBasedOnNode(arrayRef);
|
251 | this.arrayRefSet.add(arrayRef.name);
|
252 | this.nodes.push(this.buildVariableDeclaration(arrayRef, toArray));
|
253 | }
|
254 | for (let i = 0; i < pattern.elements.length; i++) {
|
255 | const elem = pattern.elements[i];
|
256 | if (!elem) continue;
|
257 | let elemRef;
|
258 | if (_core.types.isRestElement(elem)) {
|
259 | elemRef = this.toArray(arrayRef);
|
260 | elemRef = _core.types.callExpression(_core.types.memberExpression(elemRef, _core.types.identifier("slice")), [_core.types.numericLiteral(i)]);
|
261 | this.push(elem.argument, elemRef);
|
262 | } else {
|
263 | elemRef = _core.types.memberExpression(arrayRef, _core.types.numericLiteral(i), true);
|
264 | this.push(elem, elemRef);
|
265 | }
|
266 | }
|
267 | }
|
268 | init(pattern, ref) {
|
269 | if (!_core.types.isArrayExpression(ref) && !_core.types.isMemberExpression(ref)) {
|
270 | const memo = this.scope.maybeGenerateMemoised(ref, true);
|
271 | if (memo) {
|
272 | this.nodes.push(this.buildVariableDeclaration(memo, _core.types.cloneNode(ref)));
|
273 | ref = memo;
|
274 | }
|
275 | }
|
276 | this.push(pattern, ref);
|
277 | return this.nodes;
|
278 | }
|
279 | }
|
280 | exports.DestructuringTransformer = DestructuringTransformer;
|
281 | function buildObjectExcludingKeys(excludedKeys, objRef, scope, addHelper, objectRestNoSymbols, useBuiltIns) {
|
282 | const keys = [];
|
283 | let allLiteral = true;
|
284 | let hasTemplateLiteral = false;
|
285 | for (let i = 0; i < excludedKeys.length; i++) {
|
286 | const prop = excludedKeys[i];
|
287 | const key = prop.key;
|
288 | if (_core.types.isIdentifier(key) && !prop.computed) {
|
289 | keys.push(_core.types.stringLiteral(key.name));
|
290 | } else if (_core.types.isTemplateLiteral(key)) {
|
291 | keys.push(_core.types.cloneNode(key));
|
292 | hasTemplateLiteral = true;
|
293 | } else if (_core.types.isLiteral(key)) {
|
294 | keys.push(_core.types.stringLiteral(String(key.value)));
|
295 | } else if (_core.types.isPrivateName(key)) {} else {
|
296 | keys.push(_core.types.cloneNode(key));
|
297 | allLiteral = false;
|
298 | }
|
299 | }
|
300 | let value;
|
301 | if (keys.length === 0) {
|
302 | const extendsHelper = useBuiltIns ? _core.types.memberExpression(_core.types.identifier("Object"), _core.types.identifier("assign")) : addHelper("extends");
|
303 | value = _core.types.callExpression(extendsHelper, [_core.types.objectExpression([]), _core.types.sequenceExpression([_core.types.callExpression(addHelper("objectDestructuringEmpty"), [_core.types.cloneNode(objRef)]), _core.types.cloneNode(objRef)])]);
|
304 | } else {
|
305 | let keyExpression = _core.types.arrayExpression(keys);
|
306 | if (!allLiteral) {
|
307 | keyExpression = _core.types.callExpression(_core.types.memberExpression(keyExpression, _core.types.identifier("map")), [addHelper("toPropertyKey")]);
|
308 | } else if (!hasTemplateLiteral && !_core.types.isProgram(scope.block)) {
|
309 | const programScope = scope.getProgramParent();
|
310 | const id = programScope.generateUidIdentifier("excluded");
|
311 | programScope.push({
|
312 | id,
|
313 | init: keyExpression,
|
314 | kind: "const"
|
315 | });
|
316 | keyExpression = _core.types.cloneNode(id);
|
317 | }
|
318 | value = _core.types.callExpression(addHelper(`objectWithoutProperties${objectRestNoSymbols ? "Loose" : ""}`), [_core.types.cloneNode(objRef), keyExpression]);
|
319 | }
|
320 | return value;
|
321 | }
|
322 | function convertVariableDeclaration(path, addHelper, arrayLikeIsIterable, iterableIsArray, objectRestNoSymbols, useBuiltIns) {
|
323 | const {
|
324 | node,
|
325 | scope
|
326 | } = path;
|
327 | const nodeKind = node.kind;
|
328 | const nodeLoc = node.loc;
|
329 | const nodes = [];
|
330 | for (let i = 0; i < node.declarations.length; i++) {
|
331 | const declar = node.declarations[i];
|
332 | const patternId = declar.init;
|
333 | const pattern = declar.id;
|
334 | const destructuring = new DestructuringTransformer({
|
335 | blockHoist: node._blockHoist,
|
336 | nodes: nodes,
|
337 | scope: scope,
|
338 | kind: node.kind,
|
339 | iterableIsArray,
|
340 | arrayLikeIsIterable,
|
341 | useBuiltIns,
|
342 | objectRestNoSymbols,
|
343 | addHelper
|
344 | });
|
345 | if (_core.types.isPattern(pattern)) {
|
346 | destructuring.init(pattern, patternId);
|
347 | if (+i !== node.declarations.length - 1) {
|
348 | _core.types.inherits(nodes[nodes.length - 1], declar);
|
349 | }
|
350 | } else {
|
351 | nodes.push(_core.types.inherits(destructuring.buildVariableAssignment(pattern, patternId), declar));
|
352 | }
|
353 | }
|
354 | let tail = null;
|
355 | let nodesOut = [];
|
356 | for (const node of nodes) {
|
357 | if (_core.types.isVariableDeclaration(node)) {
|
358 | if (tail !== null) {
|
359 | tail.declarations.push(...node.declarations);
|
360 | continue;
|
361 | } else {
|
362 | node.kind = nodeKind;
|
363 | tail = node;
|
364 | }
|
365 | } else {
|
366 | tail = null;
|
367 | }
|
368 | if (!node.loc) {
|
369 | node.loc = nodeLoc;
|
370 | }
|
371 | nodesOut.push(node);
|
372 | }
|
373 | if (nodesOut.length === 2 && _core.types.isVariableDeclaration(nodesOut[0]) && _core.types.isExpressionStatement(nodesOut[1]) && _core.types.isCallExpression(nodesOut[1].expression) && nodesOut[0].declarations.length === 1) {
|
374 | const expr = nodesOut[1].expression;
|
375 | expr.arguments = [nodesOut[0].declarations[0].init];
|
376 | nodesOut = [expr];
|
377 | } else {
|
378 | if (_core.types.isForStatement(path.parent, {
|
379 | init: node
|
380 | }) && !nodesOut.some(v => _core.types.isVariableDeclaration(v))) {
|
381 | for (let i = 0; i < nodesOut.length; i++) {
|
382 | const node = nodesOut[i];
|
383 | if (_core.types.isExpressionStatement(node)) {
|
384 | nodesOut[i] = node.expression;
|
385 | }
|
386 | }
|
387 | }
|
388 | }
|
389 | if (nodesOut.length === 1) {
|
390 | path.replaceWith(nodesOut[0]);
|
391 | } else {
|
392 | path.replaceWithMultiple(nodesOut);
|
393 | }
|
394 | scope.crawl();
|
395 | }
|
396 | function convertAssignmentExpression(path, addHelper, arrayLikeIsIterable, iterableIsArray, objectRestNoSymbols, useBuiltIns) {
|
397 | const {
|
398 | node,
|
399 | scope,
|
400 | parentPath
|
401 | } = path;
|
402 | const nodes = [];
|
403 | const destructuring = new DestructuringTransformer({
|
404 | operator: node.operator,
|
405 | scope: scope,
|
406 | nodes: nodes,
|
407 | arrayLikeIsIterable,
|
408 | iterableIsArray,
|
409 | objectRestNoSymbols,
|
410 | useBuiltIns,
|
411 | addHelper
|
412 | });
|
413 | let ref;
|
414 | if (!parentPath.isExpressionStatement() && !parentPath.isSequenceExpression() || path.isCompletionRecord()) {
|
415 | ref = scope.generateUidIdentifierBasedOnNode(node.right, "ref");
|
416 | nodes.push(_core.types.variableDeclaration("var", [_core.types.variableDeclarator(ref, node.right)]));
|
417 | if (_core.types.isArrayExpression(node.right)) {
|
418 | destructuring.arrayRefSet.add(ref.name);
|
419 | }
|
420 | }
|
421 | destructuring.init(node.left, ref || node.right);
|
422 | if (ref) {
|
423 | if (parentPath.isArrowFunctionExpression()) {
|
424 | path.replaceWith(_core.types.blockStatement([]));
|
425 | nodes.push(_core.types.returnStatement(_core.types.cloneNode(ref)));
|
426 | } else {
|
427 | nodes.push(_core.types.expressionStatement(_core.types.cloneNode(ref)));
|
428 | }
|
429 | }
|
430 | path.replaceWithMultiple(nodes);
|
431 | scope.crawl();
|
432 | }
|
433 |
|
434 |
|