next_swc_napi/
react_compiler.rs1use std::{path::PathBuf, sync::Arc};
2
3use napi::bindgen_prelude::*;
4use next_custom_transforms::react_compiler;
5use swc_core::{
6 common::{GLOBALS, SourceMap},
7 ecma::{
8 ast::EsVersion,
9 parser::{Syntax, TsSyntax, parse_file_as_program},
10 },
11};
12
13pub struct CheckTask {
14 pub filename: PathBuf,
15}
16
17#[napi]
18impl Task for CheckTask {
19 type Output = bool;
20 type JsValue = bool;
21
22 fn compute(&mut self) -> napi::Result<Self::Output> {
23 GLOBALS.set(&Default::default(), || {
24 let cm = Arc::new(SourceMap::default());
26 let Ok(fm) = cm.load_file(&self.filename.clone()) else {
27 return Ok(false);
28 };
29 let mut errors = vec![];
30 let Ok(program) = parse_file_as_program(
31 &fm,
32 Syntax::Typescript(TsSyntax {
33 tsx: true,
34 ..Default::default()
35 }),
36 EsVersion::EsNext,
37 None,
38 &mut errors,
39 ) else {
40 return Ok(false);
41 };
42 if !errors.is_empty() {
43 return Ok(false);
44 }
45
46 Ok(react_compiler::is_required(&program))
47 })
48 }
49
50 fn resolve(&mut self, _env: Env, result: Self::Output) -> napi::Result<Self::JsValue> {
51 Ok(result)
52 }
53}
54
55#[napi]
56pub fn is_react_compiler_required(
57 filename: String,
58 signal: Option<AbortSignal>,
59) -> AsyncTask<CheckTask> {
60 let filename = PathBuf::from(filename);
61 AsyncTask::with_optional_signal(CheckTask { filename }, signal)
62}