{"version":3,"names":["_helperPluginUtils","require","_core","_default","exports","default","declare","api","options","assertVersion","allowMutablePropsOnTags","Array","isArray","Error","HOISTED","WeakMap","declares","node","scope","t","isJSXIdentifier","name","path","isFunctionParent","isArrowFunctionExpression","hasOwnBinding","isHoistingScope","isLoop","isProgram","getHoistingScope","parent","targetScopeVisitor","ReferencedIdentifier","state","jsxScope","targetScope","immutabilityVisitor","enter","_expressionResult$deo","stop","isImmutable","skip","isJSXClosingElement","parentPath","isJSXAttribute","isJSXMemberExpression","isJSXNamespacedName","isIdentifier","binding","getBinding","constant","mutablePropsAllowed","isFunction","traverse","isPure","expressionResult","evaluate","confident","value","deopt","hoistingVisitor","Object","assign","visitor","JSXElement|JSXFragment","_jsxScope","has","isJSXElement","openingElement","lastSegment","property","elementName","includes","current","isJSX","get","set","visitorState","getProgramParent","currentScope","id","generateUidBasedOnNode","push","identifier","replacement","template","expression","ast","isJSXFragment","jsxExpressionContainer","replaceWith"],"sources":["../src/index.ts"],"sourcesContent":["import { declare } from \"@babel/helper-plugin-utils\";\nimport { types as t, template } from \"@babel/core\";\nimport type { Visitor, Scope, NodePath } from \"@babel/core\";\n\nexport interface Options {\n  allowMutablePropsOnTags?: null | string[];\n}\n\ninterface VisitorState {\n  isImmutable: boolean;\n  mutablePropsAllowed: boolean;\n  jsxScope: Scope;\n  targetScope: Scope;\n}\nexport default declare((api, options: Options) => {\n  api.assertVersion(REQUIRED_VERSION(7));\n\n  const { allowMutablePropsOnTags } = options;\n\n  if (\n    allowMutablePropsOnTags != null &&\n    !Array.isArray(allowMutablePropsOnTags)\n  ) {\n    throw new Error(\n      \".allowMutablePropsOnTags must be an array, null, or undefined.\",\n    );\n  }\n\n  // Element -> Target scope\n  const HOISTED = new WeakMap();\n\n  function declares(node: t.Identifier | t.JSXIdentifier, scope: Scope) {\n    if (\n      t.isJSXIdentifier(node, { name: \"this\" }) ||\n      t.isJSXIdentifier(node, { name: \"arguments\" }) ||\n      t.isJSXIdentifier(node, { name: \"super\" }) ||\n      t.isJSXIdentifier(node, { name: \"new\" })\n    ) {\n      const { path } = scope;\n      return path.isFunctionParent() && !path.isArrowFunctionExpression();\n    }\n\n    return scope.hasOwnBinding(node.name);\n  }\n\n  function isHoistingScope({ path }: Scope) {\n    return path.isFunctionParent() || path.isLoop() || path.isProgram();\n  }\n\n  function getHoistingScope(scope: Scope) {\n    while (!isHoistingScope(scope)) scope = scope.parent;\n    return scope;\n  }\n\n  const targetScopeVisitor: Visitor<VisitorState> = {\n    ReferencedIdentifier(path, state) {\n      const { node } = path;\n      let { scope } = path;\n\n      while (scope !== state.jsxScope) {\n        // If a binding is declared in an inner function, it doesn't affect hoisting.\n        if (declares(node, scope)) return;\n\n        scope = scope.parent;\n      }\n\n      while (scope) {\n        // We cannot hoist outside of the previous hoisting target\n        // scope, so we return early and we don't update it.\n        if (scope === state.targetScope) return;\n\n        // If the scope declares this identifier (or we're at the function\n        // providing the lexical env binding), we can't hoist the var any\n        // higher.\n        if (declares(node, scope)) break;\n\n        scope = scope.parent;\n      }\n\n      state.targetScope = getHoistingScope(scope);\n    },\n  };\n\n  const immutabilityVisitor: Visitor<VisitorState> = {\n    enter(path, state) {\n      const stop = () => {\n        state.isImmutable = false;\n        path.stop();\n      };\n\n      const skip = () => {\n        path.skip();\n      };\n\n      if (path.isJSXClosingElement()) {\n        skip();\n        return;\n      }\n\n      // Elements with refs are not safe to hoist.\n      if (\n        path.isJSXIdentifier({ name: \"ref\" }) &&\n        path.parentPath.isJSXAttribute({ name: path.node })\n      ) {\n        stop();\n        return;\n      }\n\n      // Ignore JSX expressions and immutable values.\n      if (\n        path.isJSXIdentifier() ||\n        path.isJSXMemberExpression() ||\n        path.isJSXNamespacedName() ||\n        path.isImmutable()\n      ) {\n        return;\n      }\n\n      // Ignore constant bindings.\n      if (path.isIdentifier()) {\n        const binding = path.scope.getBinding(path.node.name);\n        if (binding?.constant) return;\n      }\n\n      // If we allow mutable props, tags with function expressions can be\n      // safely hoisted.\n      const { mutablePropsAllowed } = state;\n      if (mutablePropsAllowed && path.isFunction()) {\n        path.traverse(targetScopeVisitor, state);\n        skip();\n        return;\n      }\n\n      if (!path.isPure()) {\n        stop();\n        return;\n      }\n\n      // If it's not immutable, it may still be a pure expression, such as string concatenation.\n      // It is still safe to hoist that, so long as its result is immutable.\n      // If not, it is not safe to replace as mutable values (like objects) could be mutated after render.\n      // https://github.com/facebook/react/issues/3226\n      const expressionResult = path.evaluate();\n      if (expressionResult.confident) {\n        // We know the result; check its mutability.\n        const { value } = expressionResult;\n        if (\n          mutablePropsAllowed ||\n          value === null ||\n          (typeof value !== \"object\" && typeof value !== \"function\")\n        ) {\n          // It evaluated to an immutable value, so we can hoist it.\n          skip();\n          return;\n        }\n      } else if (expressionResult.deopt?.isIdentifier()) {\n        // It's safe to hoist here if the deopt reason is an identifier (e.g. func param).\n        // The hoister will take care of how high up it can be hoisted.\n        return;\n      }\n\n      stop();\n    },\n  };\n\n  // We cannot use traverse.visitors.merge because it doesn't support\n  // immutabilityVisitor's bare `enter` visitor.\n  // It's safe to just use ... because the two visitors don't share any key.\n  const hoistingVisitor = { ...immutabilityVisitor, ...targetScopeVisitor };\n\n  return {\n    name: \"transform-react-constant-elements\",\n\n    visitor: {\n      \"JSXElement|JSXFragment\"(path: NodePath<t.JSXElement | t.JSXFragment>) {\n        if (HOISTED.has(path.node)) return;\n        let mutablePropsAllowed = false;\n        let name: t.JSXOpeningElement[\"name\"] | t.JSXFragment;\n        if (path.isJSXElement()) {\n          name = path.node.openingElement.name;\n\n          // This transform takes the option `allowMutablePropsOnTags`, which is an array\n          // of JSX tags to allow mutable props (such as objects, functions) on. Use sparingly\n          // and only on tags you know will never modify their own props.\n          if (allowMutablePropsOnTags != null) {\n            // Get the element's name. If it's a member expression, we use the last part of the path.\n            // So the option [\"FormattedMessage\"] would match \"Intl.FormattedMessage\".\n            let lastSegment = name;\n            while (t.isJSXMemberExpression(lastSegment)) {\n              lastSegment = lastSegment.property;\n            }\n\n            const elementName = lastSegment.name;\n            // @ts-expect-error Fixme: allowMutablePropsOnTags should handle JSXNamespacedName\n            mutablePropsAllowed = allowMutablePropsOnTags.includes(elementName);\n          }\n        } else {\n          name = path.node;\n        }\n\n        // In order to avoid hoisting unnecessarily, we need to know which is\n        // the scope containing the current JSX element. If a parent of the\n        // current element has already been hoisted, we can consider its target\n        // scope as the base scope for the current element.\n        let jsxScope;\n        let current: NodePath<t.JSX> = path;\n        while (!jsxScope && current.parentPath.isJSX()) {\n          current = current.parentPath;\n          jsxScope = HOISTED.get(current.node);\n        }\n        jsxScope ??= path.scope;\n        // The initial HOISTED is set to jsxScope, s.t.\n        // if the element's JSX ancestor has been hoisted, it will be skipped\n        HOISTED.set(path.node, jsxScope);\n\n        const visitorState: VisitorState = {\n          isImmutable: true,\n          mutablePropsAllowed,\n          jsxScope,\n          targetScope: path.scope.getProgramParent(),\n        };\n        path.traverse(hoistingVisitor, visitorState);\n        if (!visitorState.isImmutable) return;\n\n        const { targetScope } = visitorState;\n        // Only hoist if it would give us an advantage.\n        for (let currentScope = jsxScope; ; ) {\n          if (targetScope === currentScope) return;\n          if (isHoistingScope(currentScope)) break;\n\n          currentScope = currentScope.parent;\n          if (!currentScope) {\n            throw new Error(\n              \"Internal @babel/plugin-transform-react-constant-elements error: \" +\n                \"targetScope must be an ancestor of jsxScope. \" +\n                \"This is a Babel bug, please report it.\",\n            );\n          }\n        }\n\n        const id = path.scope.generateUidBasedOnNode(name);\n        targetScope.push({ id: t.identifier(id) });\n        // If the element is to be hoisted, update HOISTED to be the target scope\n        HOISTED.set(path.node, targetScope);\n\n        let replacement: t.Expression | t.JSXExpressionContainer = template\n          .expression.ast`\n          ${t.identifier(id)} || (${t.identifier(id)} = ${path.node})\n        `;\n        if (\n          path.parentPath.isJSXElement() ||\n          path.parentPath.isJSXAttribute() ||\n          path.parentPath.isJSXFragment()\n        ) {\n          replacement = t.jsxExpressionContainer(replacement);\n        }\n\n        path.replaceWith(replacement);\n      },\n    },\n  };\n});\n"],"mappings":"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","ignoreList":[]}