-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ecma-plugins): extract custom emotion transform (#4662)
### Description First step for WEB-940. Context: https://vercel.slack.com/archives/C03EWR7LGEN/p1681789689115509 Currently all of the ecma transforms are explicitly listed under EcmaInputTransform in turbopack-ecmascript. This makes enum verbose, we have to manually expand it each time adding new transform, as well as turbopack-ecmascript gets larger to contain all of the 3rd party transforms by default. PR extracts non-core transforms into a new crate, named as ecmascript-plugins then utilize EcmaInputTransform::Custom to invoke transforms instead. `EcmaInputTransform::Custom` is renamed to `EcmaInputTransform::Plugin` as well. Goal is extracting all of 3rd party / non-core transforms. This also reduces multiple steps to construct option value between caller (next-*) to actual transform (swcOptions). vercel/next.js#48671 have corresponding next.js changes.
- Loading branch information
Showing
19 changed files
with
226 additions
and
107 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
[package] | ||
name = "turbopack-ecmascript-plugins" | ||
version = "0.1.0" | ||
description = "TBD" | ||
license = "MPL-2.0" | ||
edition = "2021" | ||
autobenches = false | ||
|
||
[lib] | ||
bench = false | ||
|
||
[features] | ||
transform_emotion = [] | ||
|
||
[dependencies] | ||
anyhow = { workspace = true } | ||
serde = { workspace = true } | ||
|
||
turbo-tasks = { workspace = true } | ||
turbopack-ecmascript = { workspace = true } | ||
|
||
swc_core = { workspace = true, features = ["ecma_ast", "ecma_visit", "common"] } | ||
swc_emotion = { workspace = true } | ||
|
||
[build-dependencies] | ||
turbo-tasks-build = { workspace = true } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
use turbo_tasks_build::generate_register; | ||
|
||
fn main() { | ||
generate_register(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
pub mod transform; | ||
|
||
pub fn register() { | ||
turbo_tasks::register(); | ||
turbopack_ecmascript::register(); | ||
include!(concat!(env!("OUT_DIR"), "/register.rs")); | ||
} |
126 changes: 126 additions & 0 deletions
126
crates/turbopack-ecmascript-plugins/src/transform/emotion.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
#![allow(unused)] | ||
use std::{ | ||
hash::{Hash, Hasher}, | ||
path::Path, | ||
}; | ||
|
||
use anyhow::Result; | ||
use serde::{Deserialize, Serialize}; | ||
use swc_core::{ | ||
common::util::take::Take, | ||
ecma::{ | ||
ast::{Module, Program}, | ||
visit::FoldWith, | ||
}, | ||
}; | ||
use turbo_tasks::trace::TraceRawVcs; | ||
use turbopack_ecmascript::{CustomTransformer, TransformContext}; | ||
|
||
#[derive(Clone, PartialEq, Eq, Debug, TraceRawVcs, Serialize, Deserialize)] | ||
#[serde(rename_all = "kebab-case")] | ||
pub enum EmotionLabelKind { | ||
DevOnly, | ||
Always, | ||
Never, | ||
} | ||
|
||
#[turbo_tasks::value(transparent)] | ||
pub struct OptionEmotionTransformConfig(Option<EmotionTransformConfigVc>); | ||
|
||
//[TODO]: need to support importmap, there are type mismatch between | ||
//next.config.js to swc's emotion options | ||
#[turbo_tasks::value(shared)] | ||
#[derive(Default, Clone, Debug)] | ||
#[serde(rename_all = "camelCase")] | ||
pub struct EmotionTransformConfig { | ||
pub sourcemap: Option<bool>, | ||
pub label_format: Option<String>, | ||
pub auto_label: Option<EmotionLabelKind>, | ||
} | ||
|
||
#[turbo_tasks::value_impl] | ||
impl EmotionTransformConfigVc { | ||
#[turbo_tasks::function] | ||
pub fn default() -> Self { | ||
Self::cell(Default::default()) | ||
} | ||
} | ||
|
||
impl Default for EmotionTransformConfigVc { | ||
fn default() -> Self { | ||
Self::default() | ||
} | ||
} | ||
|
||
#[derive(Debug)] | ||
pub struct EmotionTransformer { | ||
#[cfg(feature = "transform_emotion")] | ||
config: swc_emotion::EmotionOptions, | ||
} | ||
|
||
#[cfg(feature = "transform_emotion")] | ||
impl EmotionTransformer { | ||
pub fn new(config: &EmotionTransformConfig) -> Option<Self> { | ||
let config = swc_emotion::EmotionOptions { | ||
// When you create a transformer structure, it is assumed that you are performing an | ||
// emotion transform. | ||
enabled: Some(true), | ||
sourcemap: config.sourcemap, | ||
label_format: config.label_format.clone(), | ||
auto_label: if let Some(auto_label) = config.auto_label.as_ref() { | ||
match auto_label { | ||
EmotionLabelKind::Always => Some(true), | ||
EmotionLabelKind::Never => Some(false), | ||
// [TODO]: this is not correct coerece, need to be fixed | ||
EmotionLabelKind::DevOnly => None, | ||
} | ||
} else { | ||
None | ||
}, | ||
..Default::default() | ||
}; | ||
|
||
Some(EmotionTransformer { config }) | ||
} | ||
} | ||
|
||
#[cfg(not(feature = "transform_emotion"))] | ||
impl EmotionTransformer { | ||
pub fn new(_config: &EmotionTransformConfig) -> Option<Self> { | ||
None | ||
} | ||
} | ||
|
||
impl CustomTransformer for EmotionTransformer { | ||
fn transform(&self, program: &mut Program, ctx: &TransformContext<'_>) -> Option<Program> { | ||
#[cfg(feature = "transform_emotion")] | ||
{ | ||
let p = std::mem::replace(program, Program::Module(Module::dummy())); | ||
let hash = { | ||
#[allow(clippy::disallowed_types)] | ||
let mut hasher = std::collections::hash_map::DefaultHasher::new(); | ||
p.hash(&mut hasher); | ||
hasher.finish() | ||
}; | ||
*program = p.fold_with(&mut swc_emotion::emotion( | ||
self.config.clone(), | ||
Path::new(ctx.file_name_str), | ||
hash as u32, | ||
ctx.source_map.clone(), | ||
ctx.comments.clone(), | ||
)); | ||
} | ||
|
||
None | ||
} | ||
} | ||
|
||
pub async fn build_emotion_transformer( | ||
config: &Option<EmotionTransformConfigVc>, | ||
) -> Result<Option<Box<EmotionTransformer>>> { | ||
Ok(if let Some(config) = config { | ||
EmotionTransformer::new(&*config.await?).map(Box::new) | ||
} else { | ||
None | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub mod emotion; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.