| 1 | /** |
| 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. |
| 3 | * |
| 4 | * This source code is licensed under the MIT license found in the |
| 5 | * LICENSE file in the root directory of this source tree. |
| 6 | */ |
| 7 | |
| 8 | import babelJest from 'babel-jest'; |
| 9 | import { |
| 10 | validateEnvironmentConfig, |
| 11 | EnvironmentConfig, |
| 12 | } from 'babel-plugin-react-compiler'; |
| 13 | import {execSync} from 'child_process'; |
| 14 | |
| 15 | import type {NodePath, Visitor} from '@babel/traverse'; |
| 16 | import type {CallExpression} from '@babel/types'; |
| 17 | import BabelPluginReactCompiler from 'babel-plugin-react-compiler'; |
| 18 | |
| 19 | /** |
| 20 | * -- IMPORTANT -- |
| 21 | * When making changes to any babel plugins defined this file |
| 22 | * (e.g. `ReactForgetFunctionTransform`), make sure to bump e2eTransformerCacheKey |
| 23 | * as our script files are currently not used for babel cache breaking!! |
| 24 | */ |
| 25 | const e2eTransformerCacheKey = 1; |
| 26 | const forgetOptions: EnvironmentConfig = validateEnvironmentConfig({ |
| 27 | enableAssumeHooksFollowRulesOfReact: true, |
| 28 | }); |
| 29 | const debugMode = process.env['DEBUG_FORGET_COMPILER'] != null; |
| 30 | |
| 31 | const compilerCacheKey = execSync( |
| 32 | 'yarn --silent --cwd ../.. hash packages/babel-plugin-react-compiler/dist', |
| 33 | ) |
| 34 | .toString() |
| 35 | .trim(); |
| 36 | |
| 37 | if (debugMode) { |
| 38 | console.log('cachebreaker', compilerCacheKey); |
| 39 | } |
| 40 | |
| 41 | module.exports = (useForget: boolean) => { |
| 42 | function createTransformer() { |
| 43 | return babelJest.createTransformer({ |
| 44 | passPerPreset: true, |
| 45 | presets: [ |
| 46 | '@babel/preset-typescript', |
| 47 | { |
| 48 | plugins: [ |
| 49 | useForget |
| 50 | ? [ |
| 51 | BabelPluginReactCompiler, |
| 52 | { |
| 53 | environment: forgetOptions, |
| 54 | /* |
| 55 | * Jest hashes the babel config as a cache breaker. |
| 56 | * (see https://github.com/jestjs/jest/blob/v29.6.2/packages/babel-jest/src/index.ts#L84) |
| 57 | */ |
| 58 | compilerCacheKey, |
| 59 | transformOptionsCacheKey: forgetOptions, |
| 60 | e2eTransformerCacheKey, |
| 61 | }, |
| 62 | ] |
| 63 | : '@babel/plugin-syntax-jsx', |
| 64 | ], |
| 65 | }, |
| 66 | '@babel/preset-react', |
| 67 | { |
| 68 | plugins: [ |
| 69 | [ |
| 70 | function BabelPluginRewriteRequirePath(): {visitor: Visitor} { |
| 71 | return { |
| 72 | visitor: { |
| 73 | CallExpression(path: NodePath<CallExpression>): void { |
| 74 | const {callee} = path.node; |
| 75 | if ( |
| 76 | callee.type === 'Identifier' && |
| 77 | callee.name === 'require' |
| 78 | ) { |
| 79 | const arg = path.node.arguments[0]; |
| 80 | if (arg.type === 'StringLiteral') { |
| 81 | /* |
| 82 | * The compiler adds requires of "React", which is expected to be a wrapper |
| 83 | * around the "react" package. For tests, we just rewrite the require. |
| 84 | */ |
| 85 | if (arg.value === 'React') { |
| 86 | arg.value = 'react'; |
| 87 | } |
| 88 | } |
| 89 | } |
| 90 | }, |
| 91 | }, |
| 92 | }; |
| 93 | }, |
| 94 | ], |
| 95 | '@babel/plugin-transform-modules-commonjs', |
| 96 | ], |
| 97 | }, |
| 98 | ], |
| 99 | targets: { |
| 100 | esmodules: true, |
| 101 | }, |
| 102 | } as any); |
| 103 | /* |
| 104 | * typecast needed as DefinitelyTyped does not have updated Babel configs types yet |
| 105 | * (missing passPerPreset and targets). |
| 106 | */ |
| 107 | } |
| 108 | |
| 109 | return { |
| 110 | createTransformer, |
| 111 | }; |
| 112 | }; |