Skip to content

Commit 1e88e6b

Browse files
authored
feat(es/react-compiler): Initialize support crate (#10422)
**Description:** Currently, it only provides a way to check if a file is interesting target for the React Compiler
1 parent edbeb49 commit 1e88e6b

File tree

7 files changed

+118
-0
lines changed

7 files changed

+118
-0
lines changed

.changeset/eight-pens-relax.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
swc_core: minor
3+
swc_ecma_react_compiler: minor
4+
---
5+
6+
feat(es/react-compiler): Initialize support crate

Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/swc_core/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ ecma_transforms_typescript = [
117117
"swc_ecma_transforms_typescript",
118118
]
119119

120+
ecma_react_compiler = ["swc_ecma_react_compiler"]
121+
122+
120123
# Enable swc_bundler
121124
bundler = ["__bundler"]
122125
bundler_node_v1 = ["__bundler", "swc_node_bundler/swc_v1"]
@@ -373,6 +376,7 @@ swc_ecma_minifier = { optional = true, version = "16.1.1", path =
373376
swc_ecma_parser = { optional = true, version = "11.1.4", path = "../swc_ecma_parser" }
374377
swc_ecma_preset_env = { optional = true, version = "16.0.0", path = "../swc_ecma_preset_env" }
375378
swc_ecma_quote_macros = { optional = true, version = "11.0.0", path = "../swc_ecma_quote_macros" }
379+
swc_ecma_react_compiler = { optional = true, version = "1.0.0", path = "../swc_ecma_react_compiler" }
376380
swc_ecma_transforms_base = { optional = true, version = "12.2.0", path = "../swc_ecma_transforms_base" }
377381
swc_ecma_transforms_compat = { optional = true, version = "13.0.0", path = "../swc_ecma_transforms_compat" }
378382
swc_ecma_transforms_module = { optional = true, version = "13.0.0", path = "../swc_ecma_transforms_module" }

crates/swc_core/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@ pub mod ecma {
154154
pub mod utils {
155155
pub use swc_ecma_utils::*;
156156
}
157+
158+
#[cfg(feature = "swc_ecma_react_compiler")]
159+
#[cfg_attr(docsrs, doc(cfg(feature = "swc_ecma_react_compiler")))]
160+
pub extern crate swc_ecma_react_compiler as react_compiler;
157161
}
158162

159163
// swc features
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[package]
2+
description = "SWC helpers for the React Compiler"
3+
documentation = "https://rustdoc.swc.rs/swc_ecma_react_compiler/"
4+
edition = { workspace = true }
5+
license = { workspace = true }
6+
name = "swc_ecma_react_compiler"
7+
repository = { workspace = true }
8+
version = "1.0.0"
9+
10+
11+
[package.metadata.docs.rs]
12+
all-features = true
13+
rustdoc-args = ["--cfg", "docsrs"]
14+
15+
[dependencies]
16+
swc_atoms = { version = "5.0.0", path = "../swc_atoms" }
17+
swc_common = { version = "8.1.1", path = "../swc_common" }
18+
swc_ecma_ast = { version = "8.1.2", path = "../swc_ecma_ast" }
19+
swc_ecma_visit = { version = "8.0.0", path = "../swc_ecma_visit" }
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
use swc_ecma_ast::{Callee, Expr, FnDecl, FnExpr, Program, ReturnStmt};
2+
use swc_ecma_visit::{Visit, VisitWith};
3+
4+
/// Returns true if the `program` is a good target for the react compiler.
5+
///
6+
/// If this function returns false, it means that it does not worth to apply the
7+
/// React Compiler to the file.
8+
pub fn is_required(program: &Program) -> bool {
9+
let mut finder = Finder::default();
10+
finder.visit_program(program);
11+
finder.found
12+
}
13+
14+
#[derive(Default)]
15+
struct Finder {
16+
found: bool,
17+
18+
/// We are in a function that starts with a capital letter or it's a
19+
/// function that starts with `use`
20+
is_interested: bool,
21+
}
22+
23+
impl Visit for Finder {
24+
fn visit_callee(&mut self, node: &Callee) {
25+
if self.is_interested {
26+
if let Callee::Expr(e) = node {
27+
if let Expr::Ident(c) = &**e {
28+
if c.sym.starts_with("use") {
29+
self.found = true;
30+
return;
31+
}
32+
}
33+
}
34+
}
35+
36+
node.visit_children_with(self);
37+
}
38+
39+
fn visit_fn_decl(&mut self, node: &FnDecl) {
40+
let old = self.is_interested;
41+
self.is_interested = node.ident.sym.starts_with("use")
42+
|| node.ident.sym.starts_with(|c: char| c.is_ascii_uppercase());
43+
44+
node.visit_children_with(self);
45+
46+
self.is_interested = old;
47+
}
48+
49+
fn visit_fn_expr(&mut self, node: &FnExpr) {
50+
let old = self.is_interested;
51+
52+
self.is_interested = node.ident.as_ref().is_some_and(|ident| {
53+
ident.sym.starts_with("use") || ident.sym.starts_with(|c: char| c.is_ascii_uppercase())
54+
});
55+
56+
node.visit_children_with(self);
57+
58+
self.is_interested = old;
59+
}
60+
61+
fn visit_return_stmt(&mut self, node: &ReturnStmt) {
62+
if self.is_interested {
63+
if let Some(Expr::JSXElement(..) | Expr::JSXEmpty(..) | Expr::JSXFragment(..)) =
64+
node.arg.as_deref()
65+
{
66+
self.found = true;
67+
return;
68+
}
69+
}
70+
71+
node.visit_children_with(self);
72+
}
73+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod fast_check;

0 commit comments

Comments
 (0)