UNPKG

6.32 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = convertFunctionParams;
7
8var _core = require("@babel/core");
9
10const buildDefaultParam = (0, _core.template)(`
11 let VARIABLE_NAME =
12 arguments.length > ARGUMENT_KEY && arguments[ARGUMENT_KEY] !== undefined ?
13 arguments[ARGUMENT_KEY]
14 :
15 DEFAULT_VALUE;
16`);
17const buildLooseDefaultParam = (0, _core.template)(`
18 if (ASSIGNMENT_IDENTIFIER === UNDEFINED) {
19 ASSIGNMENT_IDENTIFIER = DEFAULT_VALUE;
20 }
21`);
22const buildLooseDestructuredDefaultParam = (0, _core.template)(`
23 let ASSIGNMENT_IDENTIFIER = PARAMETER_NAME === UNDEFINED ? DEFAULT_VALUE : PARAMETER_NAME ;
24`);
25const buildSafeArgumentsAccess = (0, _core.template)(`
26 let $0 = arguments.length > $1 ? arguments[$1] : undefined;
27`);
28const iifeVisitor = {
29 "ReferencedIdentifier|BindingIdentifier"(path, state) {
30 const {
31 scope,
32 node
33 } = path;
34 const {
35 name
36 } = node;
37
38 if (name === "eval" || scope.getBinding(name) === state.scope.parent.getBinding(name) && state.scope.hasOwnBinding(name)) {
39 state.needsOuterBinding = true;
40 path.stop();
41 }
42 },
43
44 "TypeAnnotation|TSTypeAnnotation|TypeParameterDeclaration|TSTypeParameterDeclaration": path => path.skip()
45};
46
47function convertFunctionParams(path, ignoreFunctionLength, shouldTransformParam, replaceRestElement) {
48 const params = path.get("params");
49 const isSimpleParameterList = params.every(param => param.isIdentifier());
50 if (isSimpleParameterList) return false;
51 const {
52 node,
53 scope
54 } = path;
55 const state = {
56 stop: false,
57 needsOuterBinding: false,
58 scope
59 };
60 const body = [];
61 const shadowedParams = new Set();
62
63 for (const param of params) {
64 for (const name of Object.keys(param.getBindingIdentifiers())) {
65 var _scope$bindings$name;
66
67 const constantViolations = (_scope$bindings$name = scope.bindings[name]) == null ? void 0 : _scope$bindings$name.constantViolations;
68
69 if (constantViolations) {
70 for (const redeclarator of constantViolations) {
71 const node = redeclarator.node;
72
73 switch (node.type) {
74 case "VariableDeclarator":
75 {
76 if (node.init === null) {
77 const declaration = redeclarator.parentPath;
78
79 if (!declaration.parentPath.isFor() || declaration.parentPath.get("body") === declaration) {
80 redeclarator.remove();
81 break;
82 }
83 }
84
85 shadowedParams.add(name);
86 break;
87 }
88
89 case "FunctionDeclaration":
90 shadowedParams.add(name);
91 break;
92 }
93 }
94 }
95 }
96 }
97
98 if (shadowedParams.size === 0) {
99 for (const param of params) {
100 if (!param.isIdentifier()) param.traverse(iifeVisitor, state);
101 if (state.needsOuterBinding) break;
102 }
103 }
104
105 let firstOptionalIndex = null;
106
107 for (let i = 0; i < params.length; i++) {
108 const param = params[i];
109
110 if (shouldTransformParam && !shouldTransformParam(i)) {
111 continue;
112 }
113
114 const transformedRestNodes = [];
115
116 if (replaceRestElement) {
117 replaceRestElement(param.parentPath, param, transformedRestNodes);
118 }
119
120 const paramIsAssignmentPattern = param.isAssignmentPattern();
121
122 if (paramIsAssignmentPattern && (ignoreFunctionLength || node.kind === "set")) {
123 const left = param.get("left");
124 const right = param.get("right");
125 const undefinedNode = scope.buildUndefinedNode();
126
127 if (left.isIdentifier()) {
128 body.push(buildLooseDefaultParam({
129 ASSIGNMENT_IDENTIFIER: _core.types.cloneNode(left.node),
130 DEFAULT_VALUE: right.node,
131 UNDEFINED: undefinedNode
132 }));
133 param.replaceWith(left.node);
134 } else if (left.isObjectPattern() || left.isArrayPattern()) {
135 const paramName = scope.generateUidIdentifier();
136 body.push(buildLooseDestructuredDefaultParam({
137 ASSIGNMENT_IDENTIFIER: left.node,
138 DEFAULT_VALUE: right.node,
139 PARAMETER_NAME: _core.types.cloneNode(paramName),
140 UNDEFINED: undefinedNode
141 }));
142 param.replaceWith(paramName);
143 }
144 } else if (paramIsAssignmentPattern) {
145 if (firstOptionalIndex === null) firstOptionalIndex = i;
146 const left = param.get("left");
147 const right = param.get("right");
148 const defNode = buildDefaultParam({
149 VARIABLE_NAME: left.node,
150 DEFAULT_VALUE: right.node,
151 ARGUMENT_KEY: _core.types.numericLiteral(i)
152 });
153 body.push(defNode);
154 } else if (firstOptionalIndex !== null) {
155 const defNode = buildSafeArgumentsAccess([param.node, _core.types.numericLiteral(i)]);
156 body.push(defNode);
157 } else if (param.isObjectPattern() || param.isArrayPattern()) {
158 const uid = path.scope.generateUidIdentifier("ref");
159
160 const defNode = _core.types.variableDeclaration("let", [_core.types.variableDeclarator(param.node, uid)]);
161
162 body.push(defNode);
163 param.replaceWith(_core.types.cloneNode(uid));
164 }
165
166 if (transformedRestNodes) {
167 for (const transformedNode of transformedRestNodes) {
168 body.push(transformedNode);
169 }
170 }
171 }
172
173 if (firstOptionalIndex !== null) {
174 node.params = node.params.slice(0, firstOptionalIndex);
175 }
176
177 path.ensureBlock();
178
179 if (state.needsOuterBinding || shadowedParams.size > 0) {
180 body.push(buildScopeIIFE(shadowedParams, path.get("body").node));
181 path.set("body", _core.types.blockStatement(body));
182 const bodyPath = path.get("body.body");
183 const arrowPath = bodyPath[bodyPath.length - 1].get("argument.callee");
184 arrowPath.arrowFunctionToExpression();
185 arrowPath.node.generator = path.node.generator;
186 arrowPath.node.async = path.node.async;
187 path.node.generator = false;
188 } else {
189 path.get("body").unshiftContainer("body", body);
190 }
191
192 return true;
193}
194
195function buildScopeIIFE(shadowedParams, body) {
196 const args = [];
197 const params = [];
198
199 for (const name of shadowedParams) {
200 args.push(_core.types.identifier(name));
201 params.push(_core.types.identifier(name));
202 }
203
204 return _core.types.returnStatement(_core.types.callExpression(_core.types.arrowFunctionExpression(params, body), args));
205}
\No newline at end of file