Skip to content

Commit

Permalink
refactor webpack loader execution (#4880)
Browse files Browse the repository at this point in the history
### Description

* [fix error propagation in
ContextCondition](e0a8a54)
* [improve JSON deserialization error
message](b032330)
* [fix glob
matching](d868be4)
* allow to rename assets and apply pipeline on renamed asset

vercel/next.js#49535
  • Loading branch information
sokra committed May 23, 2023
1 parent d35811f commit 2a0256b
Show file tree
Hide file tree
Showing 12 changed files with 254 additions and 183 deletions.
13 changes: 11 additions & 2 deletions crates/turbo-tasks-fs/src/glob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ impl Glob {
pub fn execute(&self, path: &str) -> bool {
let match_partial = path.ends_with('/');
self.iter_matches(path, true, match_partial)
.next()
.is_some()
.any(|result| matches!(result, ("", _)))
}

fn iter_matches<'a>(
Expand Down Expand Up @@ -416,4 +415,14 @@ mod tests {

assert!(glob.execute(path));
}

#[rstest]
#[case::early_end("*.raw", "hello.raw.js")]
fn glob_not_matching(#[case] glob: &str, #[case] path: &str) {
let glob = Glob::parse(glob).unwrap();

println!("{glob:?} {path}");

assert!(!glob.execute(path));
}
}
7 changes: 2 additions & 5 deletions crates/turbopack-cli/src/dev/web_entry_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,8 @@ use turbopack_dev_server::{
source::{asset_graph::AssetGraphContentSourceVc, ContentSourceVc},
};
use turbopack_ecmascript_plugins::transform::{
emotion::{EmotionTransformConfig, EmotionTransformConfigVc, EmotionTransformer},
styled_components::{
StyledComponentsTransformConfig, StyledComponentsTransformConfigVc,
StyledComponentsTransformer,
},
emotion::{EmotionTransformConfig, EmotionTransformer},
styled_components::{StyledComponentsTransformConfig, StyledComponentsTransformer},
styled_jsx::StyledJsxTransformer,
};
use turbopack_node::execution_context::ExecutionContextVc;
Expand Down
17 changes: 17 additions & 0 deletions crates/turbopack-core/src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ impl AssetIdent {
pub fn add_asset(&mut self, key: StringVc, asset: AssetIdentVc) {
self.assets.push((key, asset));
}

pub async fn rename_as(&mut self, pattern: &str) -> Result<()> {
let root = self.path.root();
let path = self.path.await?;
self.path = root
.join(&pattern.replace("*", &path.path))
.resolve()
.await?;
Ok(())
}
}

#[turbo_tasks::value_impl]
Expand Down Expand Up @@ -95,6 +105,13 @@ impl AssetIdentVc {
Ok(Self::new(Value::new(this)))
}

#[turbo_tasks::function]
pub async fn rename_as(self, pattern: &str) -> Result<Self> {
let mut this = self.await?.clone_value();
this.rename_as(pattern).await?;
Ok(Self::new(Value::new(this)))
}

#[turbo_tasks::function]
pub async fn path(self) -> Result<FileSystemPathVc> {
Ok(self.await?.path)
Expand Down
3 changes: 2 additions & 1 deletion crates/turbopack-node/js/src/ipc/evaluate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ export const run = async (
const value = await getValue(ipc, ...msg.args);
await ipc.send({
type: "end",
data: value === undefined ? undefined : JSON.stringify(value),
data:
value === undefined ? undefined : JSON.stringify(value, null, 2),
});
} catch (e) {
await ipc.sendError(e as Error);
Expand Down
48 changes: 25 additions & 23 deletions crates/turbopack-node/src/transforms/webpack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,22 @@ struct WebpackLoadersProcessingResult {
}

#[derive(Clone, PartialEq, Eq, Debug, TraceRawVcs, Serialize, Deserialize)]
#[serde(untagged)]
pub enum WebpackLoaderConfigItem {
LoaderName(String),
LoaderNameWithOptions {
loader: String,
#[turbo_tasks(trace_ignore)]
options: serde_json::Map<String, serde_json::Value>,
},
pub struct WebpackLoaderItem {
pub loader: String,
#[turbo_tasks(trace_ignore)]
pub options: serde_json::Map<String, serde_json::Value>,
}

#[derive(Debug, Clone)]
#[turbo_tasks::value(shared, transparent)]
pub struct WebpackLoaderConfigItems(pub Vec<WebpackLoaderConfigItem>);
pub struct WebpackLoaderItems(pub Vec<WebpackLoaderItem>);

#[turbo_tasks::value]
pub struct WebpackLoaders {
evaluate_context: AssetContextVc,
execution_context: ExecutionContextVc,
loaders: WebpackLoaderConfigItemsVc,
loaders: WebpackLoaderItemsVc,
rename_as: Option<String>,
}

#[turbo_tasks::value_impl]
Expand All @@ -62,12 +59,14 @@ impl WebpackLoadersVc {
pub fn new(
evaluate_context: AssetContextVc,
execution_context: ExecutionContextVc,
loaders: WebpackLoaderConfigItemsVc,
loaders: WebpackLoaderItemsVc,
rename_as: Option<String>,
) -> Self {
WebpackLoaders {
evaluate_context,
execution_context,
loaders,
rename_as,
}
.cell()
}
Expand All @@ -76,11 +75,9 @@ impl WebpackLoadersVc {
#[turbo_tasks::value_impl]
impl SourceTransform for WebpackLoaders {
#[turbo_tasks::function]
fn transform(&self, source: AssetVc) -> AssetVc {
fn transform(self_vc: WebpackLoadersVc, source: AssetVc) -> AssetVc {
WebpackLoadersProcessedAsset {
evaluate_context: self.evaluate_context,
execution_context: self.execution_context,
loaders: self.loaders,
transform: self_vc,
source,
}
.cell()
Expand All @@ -90,17 +87,21 @@ impl SourceTransform for WebpackLoaders {

#[turbo_tasks::value]
struct WebpackLoadersProcessedAsset {
evaluate_context: AssetContextVc,
execution_context: ExecutionContextVc,
loaders: WebpackLoaderConfigItemsVc,
transform: WebpackLoadersVc,
source: AssetVc,
}

#[turbo_tasks::value_impl]
impl Asset for WebpackLoadersProcessedAsset {
#[turbo_tasks::function]
fn ident(&self) -> AssetIdentVc {
self.source.ident()
async fn ident(&self) -> Result<AssetIdentVc> {
Ok(
if let Some(rename_as) = self.transform.await?.rename_as.as_deref() {
self.source.ident().rename_as(rename_as)
} else {
self.source.ident()
},
)
}

#[turbo_tasks::function]
Expand Down Expand Up @@ -135,12 +136,13 @@ impl WebpackLoadersProcessedAssetVc {
#[turbo_tasks::function]
async fn process(self) -> Result<ProcessWebpackLoadersResultVc> {
let this = self.await?;
let transform = this.transform.await?;

let ExecutionContext {
project_path,
chunking_context,
env,
} = *this.execution_context.await?;
} = *transform.execution_context.await?;
let source_content = this.source.content();
let AssetContent::File(file) = *source_content.await? else {
bail!("Webpack Loaders transform only support transforming files");
Expand All @@ -152,12 +154,12 @@ impl WebpackLoadersProcessedAssetVc {
}.cell());
};
let content = content.content().to_str()?;
let context = this.evaluate_context;
let context = transform.evaluate_context;

let webpack_loaders_executor = webpack_loaders_executor(context);
let resource_fs_path = this.source.ident().path().await?;
let resource_path = resource_fs_path.path.as_str();
let loaders = this.loaders.await?;
let loaders = transform.loaders.await?;
let config_value = evaluate(
webpack_loaders_executor,
project_path,
Expand Down
31 changes: 14 additions & 17 deletions crates/turbopack/src/condition.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use anyhow::Result;
use async_recursion::async_recursion;
use futures::{stream, StreamExt};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -32,32 +33,28 @@ impl ContextCondition {

#[async_recursion]
/// Returns true if the condition matches the context.
pub async fn matches(&self, context: &FileSystemPath) -> bool {
pub async fn matches(&self, context: &FileSystemPath) -> Result<bool> {
match self {
ContextCondition::All(conditions) => {
stream::iter(conditions)
.all(|c| async move { c.matches(context).await })
.fold(Ok(true), |acc, c| async move {
Ok(acc? && c.matches(context).await?)
})
.await
}
ContextCondition::Any(conditions) => {
stream::iter(conditions)
.any(|c| async move { c.matches(context).await })
.fold(Ok(true), |acc, c| async move {
Ok(acc? || c.matches(context).await?)
})
.await
}
ContextCondition::Not(condition) => !condition.matches(context).await,
ContextCondition::InPath(path) => {
if let Ok(path) = path.await {
context.is_inside(&path)
} else {
false
}
}
ContextCondition::InDirectory(dir) => {
context.path.starts_with(&format!("{dir}/"))
|| context.path.contains(&format!("/{dir}/"))
|| context.path.ends_with(&format!("/{dir}"))
|| context.path == *dir
}
ContextCondition::Not(condition) => condition.matches(context).await.map(|b| !b),
ContextCondition::InPath(path) => Ok(context.is_inside(&*path.await?)),
ContextCondition::InDirectory(dir) => Ok(context.path.starts_with(&format!("{dir}/"))
|| context.path.contains(&format!("/{dir}/"))
|| context.path.ends_with(&format!("/{dir}"))
|| context.path == *dir),
}
}
}

0 comments on commit 2a0256b

Please sign in to comment.