1{"version":3,"file":"createMultiRuleTransformer.js","names":["debug","Debug","babelCore","getBabelCoreFromProject","projectRoot","require","resolveFrom","babelParser","getBabelParserFromProject","sucrase","args","transforms","src","filename","options","dev","transform","results","filePath","production","code","functionMap","getExpensiveSucraseTransforms","test","parseAst","sourceCode","babylon","parse","sourceType","createMultiRuleTransformer","getRuleType","rules","OLD_BABEL_ENV","process","env","BABEL_ENV","ruleType","rule","type","isMatched","_ruleName","name","ast","Error","loaders","app","plugins","babelConfig","getBabelConfig","caller","platform","Object","defineProperty","enumerable","writable","value","onWarning","msg","console","warn","chalk","bold","yellow","parseSync","transformFromAstSync","sourceAst","result","generateFunctionMap","reactNativeModule","expoModule","filter","Boolean","untranspiledModule","passthroughModule"],"sources":["../../src/transformer/createMultiRuleTransformer.ts"],"sourcesContent":["// Copyright 2021-present 650 Industries (Expo). All rights reserved.\n\nimport chalk from 'chalk';\nimport Debug from 'debug';\nimport type { BabelTransformer, BabelTransformerArgs } from 'metro-babel-transformer';\nimport resolveFrom from 'resolve-from';\n\nimport { generateFunctionMap } from './generateFunctionMap';\nimport { getBabelConfig } from './getBabelConfig';\n\nconst debug = Debug('expo:metro:exotic-babel-transformer');\n\nlet babelCore: typeof import('@babel/core') | undefined;\n\nfunction getBabelCoreFromProject(projectRoot: string) {\n  if (babelCore) return babelCore;\n  babelCore = require(resolveFrom(projectRoot, '@babel/core'));\n  return babelCore!;\n}\n\nlet babelParser: typeof import('@babel/parser') | undefined;\n\nfunction getBabelParserFromProject(projectRoot: string) {\n  if (babelParser) return babelParser;\n  babelParser = require(resolveFrom(projectRoot, '@babel/parser'));\n  return babelParser!;\n}\n\nfunction sucrase(\n  args: BabelTransformerArgs,\n  {\n    transforms,\n  }: {\n    transforms: string[];\n  }\n): Partial<ReturnType<BabelTransformer['transform']>> {\n  const {\n    src,\n    filename,\n    options: { dev },\n  } = args;\n  const { transform } = require('sucrase');\n\n  const results = transform(src, {\n    filePath: filename,\n    production: !dev,\n    transforms,\n  });\n\n  return {\n    code: results.code,\n    functionMap: null,\n  };\n}\n\nconst getExpensiveSucraseTransforms = (filename: string) => [\n  'jsx',\n  'imports',\n  /\\.tsx?$/.test(filename) ? 'typescript' : 'flow',\n];\n\nfunction parseAst(projectRoot: string, sourceCode: string) {\n  const babylon = getBabelParserFromProject(projectRoot);\n\n  return babylon.parse(sourceCode, {\n    sourceType: 'unambiguous',\n  });\n}\n\nexport type Rule = {\n  warn?: boolean;\n  type?: 'module' | 'app';\n  name?: string;\n  test: ((args: BabelTransformerArgs) => boolean) | RegExp;\n  transform: BabelTransformer['transform'];\n};\n\n/** Create a transformer that emulates Webpack's loader system. */\nexport function createMultiRuleTransformer({\n  getRuleType,\n  rules,\n}: {\n  getRuleType: (args: BabelTransformerArgs) => string;\n  rules: Rule[];\n}): BabelTransformer['transform'] {\n  // const warnings: string[] = [];\n  return function transform(args: BabelTransformerArgs) {\n    const { filename, options } = args;\n    const OLD_BABEL_ENV = process.env.BABEL_ENV;\n    process.env.BABEL_ENV = options?.dev ? 'development' : process.env.BABEL_ENV || 'production';\n\n    try {\n      const ruleType = getRuleType(args);\n\n      for (const rule of rules) {\n        // optimization for checking node modules\n        if (rule.type && rule.type !== ruleType) {\n          continue;\n        }\n\n        const isMatched =\n          typeof rule.test === 'function' ? rule.test(args) : rule.test.test(args.filename);\n        if (isMatched) {\n          const results = rule.transform(args);\n          // @ts-ignore: Add extra property for testing\n          results._ruleName = rule.name;\n          // Perform a basic parse if none exists, this enables us to control the output, but only if it changed.\n          if (results.code && !results.ast) {\n            // Parse AST with babel otherwise Metro transformer will throw away the returned results.\n            results.ast = parseAst(options?.projectRoot, results.code);\n          }\n\n          // TODO: Suboptimal warnings\n          // if (rule.warn) {\n          //   const matchName =\n          //     filename.match(/node_modules\\/((:?@[\\w\\d-]+\\/[\\w\\d-]+)|(:?[\\w\\d-]+))\\/?/)?.[1] ??\n          //     filename;\n          //   if (matchName && !warnings.includes(matchName)) {\n          //     warnings.push(matchName);\n          //     console.warn(chalk.yellow.bold`warn `, matchName);\n          //     console.warn(\n          //       chalk.yellow`untranspiled module is potentially causing bundler slowdown, using modules that support commonjs will make your dev server much faster.`\n          //     );\n          //   }\n          // }\n\n          return results;\n        }\n      }\n      throw new Error('no loader rule to handle file: ' + filename);\n    } finally {\n      if (OLD_BABEL_ENV) {\n        process.env.BABEL_ENV = OLD_BABEL_ENV;\n      }\n    }\n  };\n}\n\nexport const loaders: Record<string, (args: BabelTransformerArgs) => any> = {\n  // Perform the standard, and most expensive transpilation sequence.\n  app(args) {\n    debug('app:', args.filename);\n\n    const { filename, options, src, plugins } = args;\n    const babelConfig = {\n      // ES modules require sourceType='module' but OSS may not always want that\n      sourceType: 'unambiguous',\n      ...getBabelConfig(filename, options, plugins),\n      // Variables that are exposed to the user's babel preset.\n      caller: {\n        name: 'metro',\n\n        platform: options.platform,\n      },\n      ast: true,\n    };\n\n    // Surface a warning function so babel linters can be used.\n    Object.defineProperty(babelConfig.caller, 'onWarning', {\n      enumerable: false,\n      writable: false,\n      value: (babelConfig.caller.onWarning = function (msg: any) {\n        // Format the file path first so users know where the warning came from.\n        console.warn(chalk.bold.yellow`warn ` + args.filename);\n        console.warn(msg);\n      }),\n    });\n\n    const { parseSync, transformFromAstSync } = getBabelCoreFromProject(options.projectRoot);\n    const sourceAst = parseSync(src, babelConfig);\n\n    // Should never happen.\n    if (!sourceAst) return { ast: null };\n\n    const result = transformFromAstSync(sourceAst, src, babelConfig);\n\n    // TODO: Disable by default\n    const functionMap = generateFunctionMap(options.projectRoot, sourceAst, { filename });\n    // The result from `transformFromAstSync` can be null (if the file is ignored)\n    if (!result) {\n      return { ast: null, functionMap };\n    }\n\n    return { ast: result.ast, functionMap };\n  },\n\n  // Transpile react-native with sucrase.\n  reactNativeModule(args) {\n    debug('rn:', args.filename);\n    return sucrase(args, {\n      transforms: ['jsx', 'flow', 'imports'],\n    });\n  },\n\n  // Transpile expo modules with sucrase.\n  expoModule(args) {\n    debug('expo:', args.filename);\n    // TODO: Fix all expo packages\n    return sucrase(args, {\n      transforms: [\n        'imports',\n        // TODO: fix expo-processing, expo/vector-icons\n        /(expo-processing|expo\\/vector-icons)/.test(args.filename) && 'jsx',\n        // TODO: fix expo-asset-utils\n        /(expo-asset-utils)/.test(args.filename) && 'flow',\n      ].filter(Boolean) as string[],\n    });\n  },\n\n  // Transpile known community modules with the most expensive sucrase\n  untranspiledModule(args) {\n    debug('known issues:', args.filename);\n    return sucrase(args, {\n      transforms: getExpensiveSucraseTransforms(args.filename),\n    });\n  },\n\n  // Pass all modules through without transpiling them.\n  passthroughModule(args) {\n    const { filename, options, src } = args;\n    debug('passthrough:', filename);\n\n    // Perform a basic ast parse, this doesn't matter since the worker will parse and ignore anyways.\n    const ast = parseAst(options.projectRoot, src);\n\n    // TODO: Disable by default\n    const functionMap = generateFunctionMap(options.projectRoot, ast, { filename });\n\n    return {\n      code: src,\n      functionMap,\n      ast,\n    };\n  },\n};\n"],"mappings":"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"}