source: trip-planner-front/node_modules/@babel/traverse/lib/path/conversion.js@ 6a3a178

Last change on this file since 6a3a178 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 13.8 KB
Line 
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.toComputedKey = toComputedKey;
7exports.ensureBlock = ensureBlock;
8exports.arrowFunctionToShadowed = arrowFunctionToShadowed;
9exports.unwrapFunctionEnvironment = unwrapFunctionEnvironment;
10exports.arrowFunctionToExpression = arrowFunctionToExpression;
11
12var _t = require("@babel/types");
13
14var _helperFunctionName = require("@babel/helper-function-name");
15
16const {
17 arrowFunctionExpression,
18 assignmentExpression,
19 binaryExpression,
20 blockStatement,
21 callExpression,
22 conditionalExpression,
23 expressionStatement,
24 identifier,
25 isIdentifier,
26 jsxIdentifier,
27 memberExpression,
28 metaProperty,
29 numericLiteral,
30 objectExpression,
31 restElement,
32 returnStatement,
33 sequenceExpression,
34 spreadElement,
35 stringLiteral,
36 super: _super,
37 thisExpression,
38 unaryExpression
39} = _t;
40
41function toComputedKey() {
42 let key;
43
44 if (this.isMemberExpression()) {
45 key = this.node.property;
46 } else if (this.isProperty() || this.isMethod()) {
47 key = this.node.key;
48 } else {
49 throw new ReferenceError("todo");
50 }
51
52 if (!this.node.computed) {
53 if (isIdentifier(key)) key = stringLiteral(key.name);
54 }
55
56 return key;
57}
58
59function ensureBlock() {
60 const body = this.get("body");
61 const bodyNode = body.node;
62
63 if (Array.isArray(body)) {
64 throw new Error("Can't convert array path to a block statement");
65 }
66
67 if (!bodyNode) {
68 throw new Error("Can't convert node without a body");
69 }
70
71 if (body.isBlockStatement()) {
72 return bodyNode;
73 }
74
75 const statements = [];
76 let stringPath = "body";
77 let key;
78 let listKey;
79
80 if (body.isStatement()) {
81 listKey = "body";
82 key = 0;
83 statements.push(body.node);
84 } else {
85 stringPath += ".body.0";
86
87 if (this.isFunction()) {
88 key = "argument";
89 statements.push(returnStatement(body.node));
90 } else {
91 key = "expression";
92 statements.push(expressionStatement(body.node));
93 }
94 }
95
96 this.node.body = blockStatement(statements);
97 const parentPath = this.get(stringPath);
98 body.setup(parentPath, listKey ? parentPath.node[listKey] : parentPath.node, listKey, key);
99 return this.node;
100}
101
102function arrowFunctionToShadowed() {
103 if (!this.isArrowFunctionExpression()) return;
104 this.arrowFunctionToExpression();
105}
106
107function unwrapFunctionEnvironment() {
108 if (!this.isArrowFunctionExpression() && !this.isFunctionExpression() && !this.isFunctionDeclaration()) {
109 throw this.buildCodeFrameError("Can only unwrap the environment of a function.");
110 }
111
112 hoistFunctionEnvironment(this);
113}
114
115function arrowFunctionToExpression({
116 allowInsertArrow = true,
117 specCompliant = false,
118 noNewArrows = !specCompliant
119} = {}) {
120 if (!this.isArrowFunctionExpression()) {
121 throw this.buildCodeFrameError("Cannot convert non-arrow function to a function expression.");
122 }
123
124 const thisBinding = hoistFunctionEnvironment(this, noNewArrows, allowInsertArrow);
125 this.ensureBlock();
126 this.node.type = "FunctionExpression";
127
128 if (!noNewArrows) {
129 const checkBinding = thisBinding ? null : this.parentPath.scope.generateUidIdentifier("arrowCheckId");
130
131 if (checkBinding) {
132 this.parentPath.scope.push({
133 id: checkBinding,
134 init: objectExpression([])
135 });
136 }
137
138 this.get("body").unshiftContainer("body", expressionStatement(callExpression(this.hub.addHelper("newArrowCheck"), [thisExpression(), checkBinding ? identifier(checkBinding.name) : identifier(thisBinding)])));
139 this.replaceWith(callExpression(memberExpression((0, _helperFunctionName.default)(this, true) || this.node, identifier("bind")), [checkBinding ? identifier(checkBinding.name) : thisExpression()]));
140 }
141}
142
143function hoistFunctionEnvironment(fnPath, noNewArrows = true, allowInsertArrow = true) {
144 const thisEnvFn = fnPath.findParent(p => {
145 return p.isFunction() && !p.isArrowFunctionExpression() || p.isProgram() || p.isClassProperty({
146 static: false
147 });
148 });
149 const inConstructor = (thisEnvFn == null ? void 0 : thisEnvFn.node.kind) === "constructor";
150
151 if (thisEnvFn.isClassProperty()) {
152 throw fnPath.buildCodeFrameError("Unable to transform arrow inside class property");
153 }
154
155 const {
156 thisPaths,
157 argumentsPaths,
158 newTargetPaths,
159 superProps,
160 superCalls
161 } = getScopeInformation(fnPath);
162
163 if (inConstructor && superCalls.length > 0) {
164 if (!allowInsertArrow) {
165 throw superCalls[0].buildCodeFrameError("Unable to handle nested super() usage in arrow");
166 }
167
168 const allSuperCalls = [];
169 thisEnvFn.traverse({
170 Function(child) {
171 if (child.isArrowFunctionExpression()) return;
172 child.skip();
173 },
174
175 ClassProperty(child) {
176 child.skip();
177 },
178
179 CallExpression(child) {
180 if (!child.get("callee").isSuper()) return;
181 allSuperCalls.push(child);
182 }
183
184 });
185 const superBinding = getSuperBinding(thisEnvFn);
186 allSuperCalls.forEach(superCall => {
187 const callee = identifier(superBinding);
188 callee.loc = superCall.node.callee.loc;
189 superCall.get("callee").replaceWith(callee);
190 });
191 }
192
193 if (argumentsPaths.length > 0) {
194 const argumentsBinding = getBinding(thisEnvFn, "arguments", () => {
195 const args = () => identifier("arguments");
196
197 if (thisEnvFn.scope.path.isProgram()) {
198 return conditionalExpression(binaryExpression("===", unaryExpression("typeof", args()), stringLiteral("undefined")), thisEnvFn.scope.buildUndefinedNode(), args());
199 } else {
200 return args();
201 }
202 });
203 argumentsPaths.forEach(argumentsChild => {
204 const argsRef = identifier(argumentsBinding);
205 argsRef.loc = argumentsChild.node.loc;
206 argumentsChild.replaceWith(argsRef);
207 });
208 }
209
210 if (newTargetPaths.length > 0) {
211 const newTargetBinding = getBinding(thisEnvFn, "newtarget", () => metaProperty(identifier("new"), identifier("target")));
212 newTargetPaths.forEach(targetChild => {
213 const targetRef = identifier(newTargetBinding);
214 targetRef.loc = targetChild.node.loc;
215 targetChild.replaceWith(targetRef);
216 });
217 }
218
219 if (superProps.length > 0) {
220 if (!allowInsertArrow) {
221 throw superProps[0].buildCodeFrameError("Unable to handle nested super.prop usage");
222 }
223
224 const flatSuperProps = superProps.reduce((acc, superProp) => acc.concat(standardizeSuperProperty(superProp)), []);
225 flatSuperProps.forEach(superProp => {
226 const key = superProp.node.computed ? "" : superProp.get("property").node.name;
227 const isAssignment = superProp.parentPath.isAssignmentExpression({
228 left: superProp.node
229 });
230 const isCall = superProp.parentPath.isCallExpression({
231 callee: superProp.node
232 });
233 const superBinding = getSuperPropBinding(thisEnvFn, isAssignment, key);
234 const args = [];
235
236 if (superProp.node.computed) {
237 args.push(superProp.get("property").node);
238 }
239
240 if (isAssignment) {
241 const value = superProp.parentPath.node.right;
242 args.push(value);
243 }
244
245 const call = callExpression(identifier(superBinding), args);
246
247 if (isCall) {
248 superProp.parentPath.unshiftContainer("arguments", thisExpression());
249 superProp.replaceWith(memberExpression(call, identifier("call")));
250 thisPaths.push(superProp.parentPath.get("arguments.0"));
251 } else if (isAssignment) {
252 superProp.parentPath.replaceWith(call);
253 } else {
254 superProp.replaceWith(call);
255 }
256 });
257 }
258
259 let thisBinding;
260
261 if (thisPaths.length > 0 || !noNewArrows) {
262 thisBinding = getThisBinding(thisEnvFn, inConstructor);
263
264 if (noNewArrows || inConstructor && hasSuperClass(thisEnvFn)) {
265 thisPaths.forEach(thisChild => {
266 const thisRef = thisChild.isJSX() ? jsxIdentifier(thisBinding) : identifier(thisBinding);
267 thisRef.loc = thisChild.node.loc;
268 thisChild.replaceWith(thisRef);
269 });
270 if (!noNewArrows) thisBinding = null;
271 }
272 }
273
274 return thisBinding;
275}
276
277function standardizeSuperProperty(superProp) {
278 if (superProp.parentPath.isAssignmentExpression() && superProp.parentPath.node.operator !== "=") {
279 const assignmentPath = superProp.parentPath;
280 const op = assignmentPath.node.operator.slice(0, -1);
281 const value = assignmentPath.node.right;
282 assignmentPath.node.operator = "=";
283
284 if (superProp.node.computed) {
285 const tmp = superProp.scope.generateDeclaredUidIdentifier("tmp");
286 assignmentPath.get("left").replaceWith(memberExpression(superProp.node.object, assignmentExpression("=", tmp, superProp.node.property), true));
287 assignmentPath.get("right").replaceWith(binaryExpression(op, memberExpression(superProp.node.object, identifier(tmp.name), true), value));
288 } else {
289 assignmentPath.get("left").replaceWith(memberExpression(superProp.node.object, superProp.node.property));
290 assignmentPath.get("right").replaceWith(binaryExpression(op, memberExpression(superProp.node.object, identifier(superProp.node.property.name)), value));
291 }
292
293 return [assignmentPath.get("left"), assignmentPath.get("right").get("left")];
294 } else if (superProp.parentPath.isUpdateExpression()) {
295 const updateExpr = superProp.parentPath;
296 const tmp = superProp.scope.generateDeclaredUidIdentifier("tmp");
297 const computedKey = superProp.node.computed ? superProp.scope.generateDeclaredUidIdentifier("prop") : null;
298 const parts = [assignmentExpression("=", tmp, memberExpression(superProp.node.object, computedKey ? assignmentExpression("=", computedKey, superProp.node.property) : superProp.node.property, superProp.node.computed)), assignmentExpression("=", memberExpression(superProp.node.object, computedKey ? identifier(computedKey.name) : superProp.node.property, superProp.node.computed), binaryExpression("+", identifier(tmp.name), numericLiteral(1)))];
299
300 if (!superProp.parentPath.node.prefix) {
301 parts.push(identifier(tmp.name));
302 }
303
304 updateExpr.replaceWith(sequenceExpression(parts));
305 const left = updateExpr.get("expressions.0.right");
306 const right = updateExpr.get("expressions.1.left");
307 return [left, right];
308 }
309
310 return [superProp];
311}
312
313function hasSuperClass(thisEnvFn) {
314 return thisEnvFn.isClassMethod() && !!thisEnvFn.parentPath.parentPath.node.superClass;
315}
316
317function getThisBinding(thisEnvFn, inConstructor) {
318 return getBinding(thisEnvFn, "this", thisBinding => {
319 if (!inConstructor || !hasSuperClass(thisEnvFn)) return thisExpression();
320 const supers = new WeakSet();
321 thisEnvFn.traverse({
322 Function(child) {
323 if (child.isArrowFunctionExpression()) return;
324 child.skip();
325 },
326
327 ClassProperty(child) {
328 child.skip();
329 },
330
331 CallExpression(child) {
332 if (!child.get("callee").isSuper()) return;
333 if (supers.has(child.node)) return;
334 supers.add(child.node);
335 child.replaceWithMultiple([child.node, assignmentExpression("=", identifier(thisBinding), identifier("this"))]);
336 }
337
338 });
339 });
340}
341
342function getSuperBinding(thisEnvFn) {
343 return getBinding(thisEnvFn, "supercall", () => {
344 const argsBinding = thisEnvFn.scope.generateUidIdentifier("args");
345 return arrowFunctionExpression([restElement(argsBinding)], callExpression(_super(), [spreadElement(identifier(argsBinding.name))]));
346 });
347}
348
349function getSuperPropBinding(thisEnvFn, isAssignment, propName) {
350 const op = isAssignment ? "set" : "get";
351 return getBinding(thisEnvFn, `superprop_${op}:${propName || ""}`, () => {
352 const argsList = [];
353 let fnBody;
354
355 if (propName) {
356 fnBody = memberExpression(_super(), identifier(propName));
357 } else {
358 const method = thisEnvFn.scope.generateUidIdentifier("prop");
359 argsList.unshift(method);
360 fnBody = memberExpression(_super(), identifier(method.name), true);
361 }
362
363 if (isAssignment) {
364 const valueIdent = thisEnvFn.scope.generateUidIdentifier("value");
365 argsList.push(valueIdent);
366 fnBody = assignmentExpression("=", fnBody, identifier(valueIdent.name));
367 }
368
369 return arrowFunctionExpression(argsList, fnBody);
370 });
371}
372
373function getBinding(thisEnvFn, key, init) {
374 const cacheKey = "binding:" + key;
375 let data = thisEnvFn.getData(cacheKey);
376
377 if (!data) {
378 const id = thisEnvFn.scope.generateUidIdentifier(key);
379 data = id.name;
380 thisEnvFn.setData(cacheKey, data);
381 thisEnvFn.scope.push({
382 id: id,
383 init: init(data)
384 });
385 }
386
387 return data;
388}
389
390function getScopeInformation(fnPath) {
391 const thisPaths = [];
392 const argumentsPaths = [];
393 const newTargetPaths = [];
394 const superProps = [];
395 const superCalls = [];
396 fnPath.traverse({
397 ClassProperty(child) {
398 child.skip();
399 },
400
401 Function(child) {
402 if (child.isArrowFunctionExpression()) return;
403 child.skip();
404 },
405
406 ThisExpression(child) {
407 thisPaths.push(child);
408 },
409
410 JSXIdentifier(child) {
411 if (child.node.name !== "this") return;
412
413 if (!child.parentPath.isJSXMemberExpression({
414 object: child.node
415 }) && !child.parentPath.isJSXOpeningElement({
416 name: child.node
417 })) {
418 return;
419 }
420
421 thisPaths.push(child);
422 },
423
424 CallExpression(child) {
425 if (child.get("callee").isSuper()) superCalls.push(child);
426 },
427
428 MemberExpression(child) {
429 if (child.get("object").isSuper()) superProps.push(child);
430 },
431
432 ReferencedIdentifier(child) {
433 if (child.node.name !== "arguments") return;
434 let curr = child.scope;
435
436 do {
437 if (curr.hasOwnBinding("arguments")) {
438 curr.rename("arguments");
439 return;
440 }
441
442 if (curr.path.isFunction() && !curr.path.isArrowFunctionExpression()) {
443 break;
444 }
445 } while (curr = curr.parent);
446
447 argumentsPaths.push(child);
448 },
449
450 MetaProperty(child) {
451 if (!child.get("meta").isIdentifier({
452 name: "new"
453 })) return;
454 if (!child.get("property").isIdentifier({
455 name: "target"
456 })) return;
457 newTargetPaths.push(child);
458 }
459
460 });
461 return {
462 thisPaths,
463 argumentsPaths,
464 newTargetPaths,
465 superProps,
466 superCalls
467 };
468}
Note: See TracBrowser for help on using the repository browser.