File size: 14,880 Bytes
1df763a
1
{"version":3,"names":["_template","require","_t","NOT_LOCAL_BINDING","cloneNode","identifier","isAssignmentExpression","isAssignmentPattern","isFunction","isIdentifier","isLiteral","isNullLiteral","isObjectMethod","isObjectProperty","isRegExpLiteral","isRestElement","isTemplateLiteral","isVariableDeclarator","toBindingIdentifierName","getFunctionArity","node","count","params","findIndex","param","length","buildPropertyMethodAssignmentWrapper","template","statement","buildGeneratorPropertyMethodAssignmentWrapper","visitor","ReferencedIdentifier|BindingIdentifier","path","state","name","localDeclar","scope","getBindingIdentifier","outerDeclar","selfReference","stop","getNameFromLiteralId","id","pattern","flags","quasis","map","quasi","value","raw","join","undefined","wrap","method","hasBinding","hasGlobal","rename","build","generator","FUNCTION","FUNCTION_ID","FUNCTION_KEY","generateUidIdentifier","expression","callee","body","i","len","push","getProgramParent","references","visit","selfAssignment","binding","getOwnBinding","kind","traverse","_default","parent","localBinding","supportUnicodeId","computed","key","getBinding","constant","operator","left","test","newId"],"sources":["../src/index.ts"],"sourcesContent":["import template from \"@babel/template\";\nimport {\n  NOT_LOCAL_BINDING,\n  cloneNode,\n  identifier,\n  isAssignmentExpression,\n  isAssignmentPattern,\n  isFunction,\n  isIdentifier,\n  isLiteral,\n  isNullLiteral,\n  isObjectMethod,\n  isObjectProperty,\n  isRegExpLiteral,\n  isRestElement,\n  isTemplateLiteral,\n  isVariableDeclarator,\n  toBindingIdentifierName,\n} from \"@babel/types\";\nimport type * as t from \"@babel/types\";\nimport type { NodePath, Scope, Visitor } from \"@babel/traverse\";\n\nfunction getFunctionArity(node: t.Function): number {\n  const count = node.params.findIndex(\n    param => isAssignmentPattern(param) || isRestElement(param),\n  );\n  return count === -1 ? node.params.length : count;\n}\n\nconst buildPropertyMethodAssignmentWrapper = template.statement(`\n  (function (FUNCTION_KEY) {\n    function FUNCTION_ID() {\n      return FUNCTION_KEY.apply(this, arguments);\n    }\n\n    FUNCTION_ID.toString = function () {\n      return FUNCTION_KEY.toString();\n    }\n\n    return FUNCTION_ID;\n  })(FUNCTION)\n`);\n\nconst buildGeneratorPropertyMethodAssignmentWrapper = template.statement(`\n  (function (FUNCTION_KEY) {\n    function* FUNCTION_ID() {\n      return yield* FUNCTION_KEY.apply(this, arguments);\n    }\n\n    FUNCTION_ID.toString = function () {\n      return FUNCTION_KEY.toString();\n    };\n\n    return FUNCTION_ID;\n  })(FUNCTION)\n`);\n\ntype State = {\n  name: string;\n  outerDeclar: t.Identifier;\n  selfAssignment: boolean;\n  selfReference: boolean;\n};\n\nconst visitor: Visitor<State> = {\n  \"ReferencedIdentifier|BindingIdentifier\"(\n    path: NodePath<t.Identifier>,\n    state,\n  ) {\n    // check if this node matches our function id\n    if (path.node.name !== state.name) return;\n\n    // check that we don't have a local variable declared as that removes the need\n    // for the wrapper\n    const localDeclar = path.scope.getBindingIdentifier(state.name);\n    if (localDeclar !== state.outerDeclar) return;\n\n    state.selfReference = true;\n    path.stop();\n  },\n};\n\nfunction getNameFromLiteralId(id: t.Literal) {\n  if (isNullLiteral(id)) {\n    return \"null\";\n  }\n\n  if (isRegExpLiteral(id)) {\n    return `_${id.pattern}_${id.flags}`;\n  }\n\n  if (isTemplateLiteral(id)) {\n    return id.quasis.map(quasi => quasi.value.raw).join(\"\");\n  }\n\n  if (id.value !== undefined) {\n    return id.value + \"\";\n  }\n\n  return \"\";\n}\n\nfunction wrap(\n  state: State,\n  method: t.FunctionExpression | t.Class,\n  id: t.Identifier,\n  scope: Scope,\n) {\n  if (state.selfReference) {\n    if (scope.hasBinding(id.name) && !scope.hasGlobal(id.name)) {\n      // we can just munge the local binding\n      scope.rename(id.name);\n    } else {\n      // we don't currently support wrapping class expressions\n      if (!isFunction(method)) return;\n\n      // need to add a wrapper since we can't change the references\n      let build = buildPropertyMethodAssignmentWrapper;\n      if (method.generator) {\n        build = buildGeneratorPropertyMethodAssignmentWrapper;\n      }\n\n      const template = (\n        build({\n          FUNCTION: method,\n          FUNCTION_ID: id,\n          FUNCTION_KEY: scope.generateUidIdentifier(id.name),\n        }) as t.ExpressionStatement\n      ).expression as t.CallExpression;\n\n      // shim in dummy params to retain function arity, if you try to read the\n      // source then you'll get the original since it's proxied so it's all good\n      const params = (\n        (template.callee as t.FunctionExpression).body\n          .body[0] as any as t.FunctionExpression\n      ).params;\n\n      for (let i = 0, len = getFunctionArity(method); i < len; i++) {\n        params.push(scope.generateUidIdentifier(\"x\"));\n      }\n\n      return template;\n    }\n  }\n\n  method.id = id;\n  scope.getProgramParent().references[id.name] = true;\n}\n\nfunction visit(\n  node: t.FunctionExpression | t.Class,\n  name: string,\n  scope: Scope,\n) {\n  const state: State = {\n    selfAssignment: false,\n    selfReference: false,\n    outerDeclar: scope.getBindingIdentifier(name),\n    name: name,\n  };\n\n  // check to see if we have a local binding of the id we're setting inside of\n  // the function, this is important as there are caveats associated\n\n  const binding = scope.getOwnBinding(name);\n\n  if (binding) {\n    if (binding.kind === \"param\") {\n      // safari will blow up in strict mode with code like:\n      //\n      //   let t = function t(t) {};\n      //\n      // with the error:\n      //\n      //   Cannot declare a parameter named 't' as it shadows the name of a\n      //   strict mode function.\n      //\n      // this isn't to the spec and they've invented this behaviour which is\n      // **extremely** annoying so we avoid setting the name if it has a param\n      // with the same id\n      state.selfReference = true;\n    } else {\n      // otherwise it's defined somewhere in scope like:\n      //\n      //   let t = function () {\n      //     let t = 2;\n      //   };\n      //\n      // so we can safely just set the id and move along as it shadows the\n      // bound function id\n    }\n  } else if (state.outerDeclar || scope.hasGlobal(name)) {\n    scope.traverse(node, visitor, state);\n  }\n\n  return state;\n}\n\n/**\n * Add id to function/class expression inferred from the AST\n *\n * @export\n * @template N The unnamed expression type\n * @param {Object} nodePathLike The NodePath-like input\n * @param {N} nodePathLike.node an AST node\n * @param {NodePath<N>[\"parent\"]} [nodePathLike.parent] The parent of the AST node\n * @param {Scope} nodePathLike.scope The scope associated to the AST node\n * @param {t.LVal | t.StringLiteral | t.NumericLiteral | t.BigIntLiteral} [nodePathLike.id] the fallback naming source when the helper\n * can not infer the function name from the AST\n * @param {boolean} [localBinding=false] whether a name could shadow a self-reference (e.g. converting arrow function)\n * @param {boolean} [supportUnicodeId=false] whether the compilation target supports unicodeId (non-BMP characters) or not\n * @returns {(N | t.CallExpression | void)}\n * - modified node when name can be inferred,\n * - an IIFE when `node` contains a binding shadowing the inferred function name (e.g. `let f = function (f) {}`),\n * - `void` when `node` has `id` property or the helper can not inferred the name or the inferred name contains non-BMP characters that is not supported by current target\n */\nexport default function <N extends t.FunctionExpression | t.Class>(\n  {\n    node,\n    parent,\n    scope,\n    id,\n  }: {\n    node: N;\n    parent?: NodePath<N>[\"parent\"];\n    scope: Scope;\n    id?:\n      | t.AssignmentExpression[\"left\"]\n      | t.StringLiteral\n      | t.NumericLiteral\n      | t.BigIntLiteral;\n  },\n  localBinding = false,\n  supportUnicodeId = false,\n): N | t.CallExpression | void {\n  // has an `id` so we don't need to infer one\n  if (node.id) return;\n\n  if (\n    (isObjectProperty(parent) || isObjectMethod(parent, { kind: \"method\" })) &&\n    (!parent.computed || isLiteral(parent.key))\n  ) {\n    // { foo() {} };\n    id = parent.key as\n      | t.Identifier\n      | t.StringLiteral\n      | t.NumericLiteral\n      | t.BigIntLiteral;\n  } else if (isVariableDeclarator(parent)) {\n    // let foo = function () {};\n    id = parent.id;\n\n    // but not \"let foo = () => {};\" being converted to function expression\n    if (isIdentifier(id) && !localBinding) {\n      const binding = scope.parent.getBinding(id.name);\n      if (\n        binding &&\n        binding.constant &&\n        scope.getBinding(id.name) === binding\n      ) {\n        // always going to reference this method\n        node.id = cloneNode(id);\n        // @ts-expect-error Fixme: avoid mutating AST nodes\n        node.id[NOT_LOCAL_BINDING] = true;\n        return;\n      }\n    }\n  } else if (isAssignmentExpression(parent, { operator: \"=\" })) {\n    // foo = function () {};\n    id = parent.left;\n  } else if (!id) {\n    return;\n  }\n\n  let name;\n  if (id && isLiteral(id)) {\n    name = getNameFromLiteralId(id);\n  } else if (id && isIdentifier(id)) {\n    name = id.name;\n  }\n\n  if (name === undefined) {\n    return;\n  }\n\n  if (!supportUnicodeId && isFunction(node) && /[\\uD800-\\uDFFF]/.test(name)) {\n    return;\n  }\n\n  name = toBindingIdentifierName(name);\n  const newId = identifier(name);\n\n  // The id shouldn't be considered a local binding to the function because\n  // we are simply trying to set the function name and not actually create\n  // a local binding.\n  // @ts-expect-error Fixme: avoid mutating AST nodes\n  newId[NOT_LOCAL_BINDING] = true;\n\n  const state = visit(node, name, scope);\n  return wrap(state, node, newId, scope) || node;\n}\n"],"mappings":"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"}