main
ts 104 lines 3.34 KB
Raw
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 type * as BabelCore from '@babel/core';
9 import {compileProgram, Logger, parsePluginOptions} from '../Entrypoint';
10 import {
11 injectReanimatedFlag,
12 pipelineUsesReanimatedPlugin,
13 } from '../Entrypoint/Reanimated';
14 import {CompilerError} from '..';
15
16 const ENABLE_REACT_COMPILER_TIMINGS =
17 process.env['ENABLE_REACT_COMPILER_TIMINGS'] === '1';
18
19 /*
20 * The React Forget Babel Plugin
21 * @param {*} _babel
22 * @returns
23 */
24 export default function BabelPluginReactCompiler(
25 _babel: typeof BabelCore,
26 ): BabelCore.PluginObj {
27 return {
28 name: 'react-forget',
29 visitor: {
30 /*
31 * Note: Babel does some "smart" merging of visitors across plugins, so even if A is inserted
32 * prior to B, if A does not have a Program visitor and B does, B will run first. We always
33 * want Forget to run true to source as possible.
34 */
35 Program: {
36 enter(prog, pass): void {
37 try {
38 const filename = pass.filename ?? 'unknown';
39 if (ENABLE_REACT_COMPILER_TIMINGS === true) {
40 performance.mark(`${filename}:start`, {
41 detail: 'BabelPlugin:Program:start',
42 });
43 }
44 let opts = parsePluginOptions(pass.opts);
45 const isDev =
46 (typeof __DEV__ !== 'undefined' && __DEV__ === true) ||
47 process.env['NODE_ENV'] === 'development';
48 if (
49 opts.enableReanimatedCheck === true &&
50 pipelineUsesReanimatedPlugin(pass.file.opts.plugins)
51 ) {
52 opts = injectReanimatedFlag(opts);
53 }
54 if (
55 opts.environment.enableResetCacheOnSourceFileChanges !== false &&
56 isDev
57 ) {
58 opts = {
59 ...opts,
60 environment: {
61 ...opts.environment,
62 enableResetCacheOnSourceFileChanges: true,
63 },
64 };
65 }
66 compileProgram(prog, {
67 opts,
68 filename: pass.filename ?? null,
69 comments: pass.file.ast.comments ?? [],
70 code: pass.file.code,
71 });
72 if (ENABLE_REACT_COMPILER_TIMINGS === true) {
73 performance.mark(`${filename}:end`, {
74 detail: 'BabelPlugin:Program:end',
75 });
76 }
77 } catch (e) {
78 if (e instanceof CompilerError) {
79 throw e.withPrintedMessage(pass.file.code, {eslint: false});
80 }
81 throw e;
82 }
83 },
84 exit(_, pass): void {
85 if (ENABLE_REACT_COMPILER_TIMINGS === true) {
86 const filename = pass.filename ?? 'unknown';
87 const measurement = performance.measure(filename, {
88 start: `${filename}:start`,
89 end: `${filename}:end`,
90 detail: 'BabelPlugin:Program',
91 });
92 if ('logger' in pass.opts && pass.opts.logger != null) {
93 const logger: Logger = pass.opts.logger as Logger;
94 logger.logEvent(filename, {
95 kind: 'Timing',
96 measurement,
97 });
98 }
99 }
100 },
101 },
102 },
103 };
104 }