You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					205 lines
				
				6.2 KiB
			
		
		
			
		
	
	
					205 lines
				
				6.2 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								"use strict";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Object.defineProperty(exports, "__esModule", {
							 | 
						||
| 
								 | 
							
								  value: true
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								exports.default = convertFunctionParams;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _core = require("@babel/core");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const buildDefaultParam = (0, _core.template)(`
							 | 
						||
| 
								 | 
							
								  let VARIABLE_NAME =
							 | 
						||
| 
								 | 
							
								    arguments.length > ARGUMENT_KEY && arguments[ARGUMENT_KEY] !== undefined ?
							 | 
						||
| 
								 | 
							
								      arguments[ARGUMENT_KEY]
							 | 
						||
| 
								 | 
							
								    :
							 | 
						||
| 
								 | 
							
								      DEFAULT_VALUE;
							 | 
						||
| 
								 | 
							
								`);
							 | 
						||
| 
								 | 
							
								const buildLooseDefaultParam = (0, _core.template)(`
							 | 
						||
| 
								 | 
							
								  if (ASSIGNMENT_IDENTIFIER === UNDEFINED) {
							 | 
						||
| 
								 | 
							
								    ASSIGNMENT_IDENTIFIER = DEFAULT_VALUE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								`);
							 | 
						||
| 
								 | 
							
								const buildLooseDestructuredDefaultParam = (0, _core.template)(`
							 | 
						||
| 
								 | 
							
								  let ASSIGNMENT_IDENTIFIER = PARAMETER_NAME === UNDEFINED ? DEFAULT_VALUE : PARAMETER_NAME ;
							 | 
						||
| 
								 | 
							
								`);
							 | 
						||
| 
								 | 
							
								const buildSafeArgumentsAccess = (0, _core.template)(`
							 | 
						||
| 
								 | 
							
								  let $0 = arguments.length > $1 ? arguments[$1] : undefined;
							 | 
						||
| 
								 | 
							
								`);
							 | 
						||
| 
								 | 
							
								const iifeVisitor = {
							 | 
						||
| 
								 | 
							
								  "ReferencedIdentifier|BindingIdentifier"(path, state) {
							 | 
						||
| 
								 | 
							
								    const {
							 | 
						||
| 
								 | 
							
								      scope,
							 | 
						||
| 
								 | 
							
								      node
							 | 
						||
| 
								 | 
							
								    } = path;
							 | 
						||
| 
								 | 
							
								    const {
							 | 
						||
| 
								 | 
							
								      name
							 | 
						||
| 
								 | 
							
								    } = node;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (name === "eval" || scope.getBinding(name) === state.scope.parent.getBinding(name) && state.scope.hasOwnBinding(name)) {
							 | 
						||
| 
								 | 
							
								      state.needsOuterBinding = true;
							 | 
						||
| 
								 | 
							
								      path.stop();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  "TypeAnnotation|TSTypeAnnotation|TypeParameterDeclaration|TSTypeParameterDeclaration": path => path.skip()
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function convertFunctionParams(path, ignoreFunctionLength, shouldTransformParam, replaceRestElement) {
							 | 
						||
| 
								 | 
							
								  const params = path.get("params");
							 | 
						||
| 
								 | 
							
								  const isSimpleParameterList = params.every(param => param.isIdentifier());
							 | 
						||
| 
								 | 
							
								  if (isSimpleParameterList) return false;
							 | 
						||
| 
								 | 
							
								  const {
							 | 
						||
| 
								 | 
							
								    node,
							 | 
						||
| 
								 | 
							
								    scope
							 | 
						||
| 
								 | 
							
								  } = path;
							 | 
						||
| 
								 | 
							
								  const state = {
							 | 
						||
| 
								 | 
							
								    stop: false,
							 | 
						||
| 
								 | 
							
								    needsOuterBinding: false,
							 | 
						||
| 
								 | 
							
								    scope
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								  const body = [];
							 | 
						||
| 
								 | 
							
								  const shadowedParams = new Set();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (const param of params) {
							 | 
						||
| 
								 | 
							
								    for (const name of Object.keys(param.getBindingIdentifiers())) {
							 | 
						||
| 
								 | 
							
								      var _scope$bindings$name;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const constantViolations = (_scope$bindings$name = scope.bindings[name]) == null ? void 0 : _scope$bindings$name.constantViolations;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (constantViolations) {
							 | 
						||
| 
								 | 
							
								        for (const redeclarator of constantViolations) {
							 | 
						||
| 
								 | 
							
								          const node = redeclarator.node;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          switch (node.type) {
							 | 
						||
| 
								 | 
							
								            case "VariableDeclarator":
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								                if (node.init === null) {
							 | 
						||
| 
								 | 
							
								                  const declaration = redeclarator.parentPath;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                  if (!declaration.parentPath.isFor() || declaration.parentPath.get("body") === declaration) {
							 | 
						||
| 
								 | 
							
								                    redeclarator.remove();
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                  }
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                shadowedParams.add(name);
							 | 
						||
| 
								 | 
							
								                break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case "FunctionDeclaration":
							 | 
						||
| 
								 | 
							
								              shadowedParams.add(name);
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (shadowedParams.size === 0) {
							 | 
						||
| 
								 | 
							
								    for (const param of params) {
							 | 
						||
| 
								 | 
							
								      if (!param.isIdentifier()) param.traverse(iifeVisitor, state);
							 | 
						||
| 
								 | 
							
								      if (state.needsOuterBinding) break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  let firstOptionalIndex = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (let i = 0; i < params.length; i++) {
							 | 
						||
| 
								 | 
							
								    const param = params[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (shouldTransformParam && !shouldTransformParam(i)) {
							 | 
						||
| 
								 | 
							
								      continue;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const transformedRestNodes = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (replaceRestElement) {
							 | 
						||
| 
								 | 
							
								      replaceRestElement(param.parentPath, param, transformedRestNodes);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const paramIsAssignmentPattern = param.isAssignmentPattern();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (paramIsAssignmentPattern && (ignoreFunctionLength || node.kind === "set")) {
							 | 
						||
| 
								 | 
							
								      const left = param.get("left");
							 | 
						||
| 
								 | 
							
								      const right = param.get("right");
							 | 
						||
| 
								 | 
							
								      const undefinedNode = scope.buildUndefinedNode();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (left.isIdentifier()) {
							 | 
						||
| 
								 | 
							
								        body.push(buildLooseDefaultParam({
							 | 
						||
| 
								 | 
							
								          ASSIGNMENT_IDENTIFIER: _core.types.cloneNode(left.node),
							 | 
						||
| 
								 | 
							
								          DEFAULT_VALUE: right.node,
							 | 
						||
| 
								 | 
							
								          UNDEFINED: undefinedNode
							 | 
						||
| 
								 | 
							
								        }));
							 | 
						||
| 
								 | 
							
								        param.replaceWith(left.node);
							 | 
						||
| 
								 | 
							
								      } else if (left.isObjectPattern() || left.isArrayPattern()) {
							 | 
						||
| 
								 | 
							
								        const paramName = scope.generateUidIdentifier();
							 | 
						||
| 
								 | 
							
								        body.push(buildLooseDestructuredDefaultParam({
							 | 
						||
| 
								 | 
							
								          ASSIGNMENT_IDENTIFIER: left.node,
							 | 
						||
| 
								 | 
							
								          DEFAULT_VALUE: right.node,
							 | 
						||
| 
								 | 
							
								          PARAMETER_NAME: _core.types.cloneNode(paramName),
							 | 
						||
| 
								 | 
							
								          UNDEFINED: undefinedNode
							 | 
						||
| 
								 | 
							
								        }));
							 | 
						||
| 
								 | 
							
								        param.replaceWith(paramName);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } else if (paramIsAssignmentPattern) {
							 | 
						||
| 
								 | 
							
								      if (firstOptionalIndex === null) firstOptionalIndex = i;
							 | 
						||
| 
								 | 
							
								      const left = param.get("left");
							 | 
						||
| 
								 | 
							
								      const right = param.get("right");
							 | 
						||
| 
								 | 
							
								      const defNode = buildDefaultParam({
							 | 
						||
| 
								 | 
							
								        VARIABLE_NAME: left.node,
							 | 
						||
| 
								 | 
							
								        DEFAULT_VALUE: right.node,
							 | 
						||
| 
								 | 
							
								        ARGUMENT_KEY: _core.types.numericLiteral(i)
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								      body.push(defNode);
							 | 
						||
| 
								 | 
							
								    } else if (firstOptionalIndex !== null) {
							 | 
						||
| 
								 | 
							
								      const defNode = buildSafeArgumentsAccess([param.node, _core.types.numericLiteral(i)]);
							 | 
						||
| 
								 | 
							
								      body.push(defNode);
							 | 
						||
| 
								 | 
							
								    } else if (param.isObjectPattern() || param.isArrayPattern()) {
							 | 
						||
| 
								 | 
							
								      const uid = path.scope.generateUidIdentifier("ref");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const defNode = _core.types.variableDeclaration("let", [_core.types.variableDeclarator(param.node, uid)]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      body.push(defNode);
							 | 
						||
| 
								 | 
							
								      param.replaceWith(_core.types.cloneNode(uid));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (transformedRestNodes) {
							 | 
						||
| 
								 | 
							
								      for (const transformedNode of transformedRestNodes) {
							 | 
						||
| 
								 | 
							
								        body.push(transformedNode);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (firstOptionalIndex !== null) {
							 | 
						||
| 
								 | 
							
								    node.params = node.params.slice(0, firstOptionalIndex);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  path.ensureBlock();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (state.needsOuterBinding || shadowedParams.size > 0) {
							 | 
						||
| 
								 | 
							
								    body.push(buildScopeIIFE(shadowedParams, path.get("body").node));
							 | 
						||
| 
								 | 
							
								    path.set("body", _core.types.blockStatement(body));
							 | 
						||
| 
								 | 
							
								    const bodyPath = path.get("body.body");
							 | 
						||
| 
								 | 
							
								    const arrowPath = bodyPath[bodyPath.length - 1].get("argument.callee");
							 | 
						||
| 
								 | 
							
								    arrowPath.arrowFunctionToExpression();
							 | 
						||
| 
								 | 
							
								    arrowPath.node.generator = path.node.generator;
							 | 
						||
| 
								 | 
							
								    arrowPath.node.async = path.node.async;
							 | 
						||
| 
								 | 
							
								    path.node.generator = false;
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    path.get("body").unshiftContainer("body", body);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function buildScopeIIFE(shadowedParams, body) {
							 | 
						||
| 
								 | 
							
								  const args = [];
							 | 
						||
| 
								 | 
							
								  const params = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (const name of shadowedParams) {
							 | 
						||
| 
								 | 
							
								    args.push(_core.types.identifier(name));
							 | 
						||
| 
								 | 
							
								    params.push(_core.types.identifier(name));
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return _core.types.returnStatement(_core.types.callExpression(_core.types.arrowFunctionExpression(params, body), args));
							 | 
						||
| 
								 | 
							
								}
							 |