/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @format */ import {default as generate} from '@babel/generator'; import {parse, ParserPlugin} from '@babel/parser'; import {transformFromAstSync} from '@babel/core'; import {default as flipperEnv} from './flipper-env'; import {resolve} from 'path'; const jsParsePlugins: ParserPlugin[] = [ 'jsx', ['flow', {all: true}], 'classProperties', 'objectRestSpread', 'optionalChaining', 'nullishCoalescingOperator', ]; const tsParsePluins: ParserPlugin[] = [ 'jsx', 'typescript', 'classProperties', 'optionalChaining', 'nullishCoalescingOperator', ]; const commonJsPlugin = [ require('@babel/plugin-transform-modules-commonjs'), { strictMode: false, }, ]; const classPropertiesPlugin = require('@babel/plugin-proposal-class-properties'); const optionalChainingPlugin = require('@babel/plugin-proposal-optional-chaining'); const coalescingOperatorPlugin = require('@babel/plugin-proposal-nullish-coalescing-operator'); const objectRestSpreadPlugin = require('@babel/plugin-proposal-object-rest-spread'); const flowStripTypesPlugin = require('@babel/plugin-transform-flow-strip-types'); const dynamicRequiresPlugin = require('./dynamic-requires'); const typeScriptPlugin = require('@babel/plugin-transform-typescript'); const emotionPlugin = require('@emotion/babel-plugin'); const tsTransformPlugins = [ typeScriptPlugin, classPropertiesPlugin, commonJsPlugin, optionalChainingPlugin, coalescingOperatorPlugin, // Sourcemap disabled because // https://github.com/electron/electron/issues/17772#issuecomment-570795784 // https://github.com/emotion-js/emotion/issues/1838 [emotionPlugin, {autoLabel: 'always', sourceMap: false}], ]; const jsTransformPlugins = [ commonJsPlugin, objectRestSpreadPlugin, classPropertiesPlugin, flowStripTypesPlugin, optionalChainingPlugin, coalescingOperatorPlugin, dynamicRequiresPlugin, [emotionPlugin, {autoLabel: 'always', sourceMap: false}], ]; export default function transform({ filename, options, src, presets, plugins, }: { filename: string; options: any; src: string; presets?: any[]; plugins?: any[]; }) { filename = resolve(options.projectRoot, filename); presets = presets ?? [require('@babel/preset-react')]; plugins = plugins ?? []; const isTypeScript = filename.endsWith('.tsx') || filename.endsWith('.ts'); const ast = parse(src, { sourceFilename: filename, plugins: isTypeScript ? tsParsePluins : jsParsePlugins, sourceType: 'module', }); const transformed = transformFromAstSync(ast, src, { ast: true, babelrc: !filename.includes('node_modules'), code: false, comments: false, compact: false, root: options.projectRoot, filename, plugins: [ ...(isTypeScript ? tsTransformPlugins : jsTransformPlugins), ...plugins, ], presets, sourceMaps: true, retainLines: !!flipperEnv.FLIPPER_TEST_RUNNER, }); if (!transformed) { throw new Error('Failed to transform'); } const result = generate( transformed.ast!, { filename, sourceFileName: filename, sourceMaps: true, retainLines: !!flipperEnv.FLIPPER_TEST_RUNNER, }, src, ); return { ast: transformed.ast, code: result.code, filename, map: result.map, }; }