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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"}