Skip to content

Commit

Permalink
refactor: move hook filter related logic to rolldown_binding (rolld…
Browse files Browse the repository at this point in the history
…own#3265)

### Description

closes rolldown#3255
  • Loading branch information
shulaoda authored Dec 31, 2024
1 parent f1c6bdf commit ed3c822
Show file tree
Hide file tree
Showing 14 changed files with 161 additions and 323 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/rolldown_binding/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ rolldown_sourcemap = { workspace = true }
rolldown_tracing = { workspace = true }
rolldown_utils = { workspace = true }
rustc-hash = { workspace = true }
sugar_path = { workspace = true }
tracing = { workspace = true }

[target.'cfg(all(not(target_os = "linux"), not(target_os = "freebsd"), not(target_family = "wasm")))'.dependencies]
Expand Down
220 changes: 151 additions & 69 deletions crates/rolldown_binding/src/options/plugin/js_plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,24 @@ use crate::types::{
binding_outputs::{to_js_diagnostic, update_outputs},
js_callback::MaybeAsyncJsCallbackExt,
};
use rolldown_plugin::{
Plugin, __inner::SharedPluginable, typedmap::TypedMapKey, LoadHookFilter, ResolvedIdHookFilter,
TransformHookFilter,
use anyhow::Ok;
use rolldown::ModuleType;
use rolldown_plugin::{Plugin, __inner::SharedPluginable, typedmap::TypedMapKey};
use rolldown_utils::pattern_filter::{self, FilterResult};
use std::{
borrow::Cow,
ops::Deref,
path::{Path, PathBuf},
sync::Arc,
};
use std::{borrow::Cow, ops::Deref, sync::Arc};
use sugar_path::SugarPath;

use super::{
binding_transform_context::BindingTransformPluginContext,
types::{
binding_hook_filter::BindingTransformHookFilter,
binding_hook_resolve_id_extra_args::BindingHookResolveIdExtraArgs,
binding_js_or_regex::bindingify_string_or_regex_array,
binding_plugin_transform_extra_args::BindingTransformHookExtraArgs,
},
BindingPluginOptions,
Expand Down Expand Up @@ -78,28 +86,49 @@ impl Plugin for JsPlugin {
ctx: &rolldown_plugin::PluginContext,
args: &rolldown_plugin::HookResolveIdArgs<'_>,
) -> rolldown_plugin::HookResolveIdReturn {
if let Some(cb) = &self.resolve_id {
let custom = args
.custom
.get::<JsPluginContextResolveCustomArgId>(&JsPluginContextResolveCustomArgId)
.map(|v| *v);
Ok(
cb.await_call((
ctx.clone().into(),
args.specifier.to_string(),
args.importer.map(str::to_string),
BindingHookResolveIdExtraArgs {
is_entry: args.is_entry,
kind: args.kind.to_string(),
custom,
},
))
.await?
.map(Into::into),
let Some(cb) = &self.resolve_id else { return Ok(None) };

if let Some(resolve_id_filter) = &self.inner.resolve_id_filter {
let stabilized_path = Path::new(args.specifier).relative(ctx.cwd());
let normalized_id = stabilized_path.to_string_lossy();

let exclude =
resolve_id_filter.exclude.clone().map(bindingify_string_or_regex_array).transpose()?;
let include =
resolve_id_filter.include.clone().map(bindingify_string_or_regex_array).transpose()?;

let matched = pattern_filter::filter(
exclude.as_deref(),
include.as_deref(),
args.specifier,
&normalized_id,
)
} else {
Ok(None)
.inner();

if !matched {
return Ok(None);
}
}

let extra_args = BindingHookResolveIdExtraArgs {
is_entry: args.is_entry,
kind: args.kind.to_string(),
custom: args
.custom
.get::<JsPluginContextResolveCustomArgId>(&JsPluginContextResolveCustomArgId)
.map(|v| *v),
};

Ok(
cb.await_call((
ctx.clone().into(),
args.specifier.to_string(),
args.importer.map(str::to_string),
extra_args,
))
.await?
.map(Into::into),
)
}

fn resolve_id_meta(&self) -> Option<rolldown_plugin::PluginHookMeta> {
Expand Down Expand Up @@ -135,16 +164,30 @@ impl Plugin for JsPlugin {
ctx: &rolldown_plugin::PluginContext,
args: &rolldown_plugin::HookLoadArgs<'_>,
) -> rolldown_plugin::HookLoadReturn {
if let Some(cb) = &self.load {
Ok(
cb.await_call((ctx.clone().into(), args.id.to_string()))
.await?
.map(TryInto::try_into)
.transpose()?,
)
} else {
Ok(None)
let Some(cb) = &self.load else { return Ok(None) };

if let Some(load_filter) = &self.load_filter {
let stabilized_path = Path::new(args.id).relative(ctx.cwd());
let normalized_id = stabilized_path.to_string_lossy();

let exclude =
load_filter.exclude.clone().map(bindingify_string_or_regex_array).transpose()?;
let include =
load_filter.include.clone().map(bindingify_string_or_regex_array).transpose()?;

let matched =
pattern_filter::filter(exclude.as_deref(), include.as_deref(), args.id, &normalized_id)
.inner();

if !matched {
return Ok(None);
}
}

cb.await_call((ctx.clone().into(), args.id.to_string()))
.await?
.map(TryInto::try_into)
.transpose()
}

fn load_meta(&self) -> Option<rolldown_plugin::PluginHookMeta> {
Expand All @@ -156,21 +199,29 @@ impl Plugin for JsPlugin {
ctx: rolldown_plugin::SharedTransformPluginContext,
args: &rolldown_plugin::HookTransformArgs<'_>,
) -> rolldown_plugin::HookTransformReturn {
if let Some(cb) = &self.transform {
Ok(
cb.await_call((
BindingTransformPluginContext::new(Arc::clone(&ctx)),
args.code.to_string(),
args.id.to_string(),
BindingTransformHookExtraArgs { module_type: args.module_type.to_string() },
))
.await?
.map(TryInto::try_into)
.transpose()?,
)
} else {
Ok(None)
let Some(cb) = &self.transform else { return Ok(None) };

if !filter_transform(
self.transform_filter.as_ref(),
args.id,
ctx.inner.cwd(),
args.module_type,
args.code,
)? {
return Ok(None);
}

let extra_args = BindingTransformHookExtraArgs { module_type: args.module_type.to_string() };

cb.await_call((
BindingTransformPluginContext::new(Arc::clone(&ctx)),
args.code.to_string(),
args.id.to_string(),
extra_args,
))
.await?
.map(TryInto::try_into)
.transpose()
}

fn transform_meta(&self) -> Option<rolldown_plugin::PluginHookMeta> {
Expand Down Expand Up @@ -472,34 +523,65 @@ impl Plugin for JsPlugin {
fn close_watcher_meta(&self) -> Option<rolldown_plugin::PluginHookMeta> {
self.close_watcher_meta.as_ref().map(Into::into)
}
}

fn transform_filter(&self) -> anyhow::Result<Option<TransformHookFilter>> {
match self.inner.transform_filter {
Some(ref item) => {
let filter = TransformHookFilter::try_from(item.clone())?;
Ok(Some(filter))
/// If the transform hook is filtered out and need to be skipped.
/// Using `Option<bool>` for better programming experience.
/// return `None` means it is early return, should not be skipped.
/// return `Some(false)` means it should be skipped.
/// return `Some(true)` means it should not be skipped.
/// Since transform has three different filter, so we need to check all of them.
fn filter_transform(
transform_filter: Option<&BindingTransformHookFilter>,
id: &str,
cwd: &PathBuf,
module_type: &ModuleType,
code: &str,
) -> anyhow::Result<bool> {
let Some(transform_hook_filter_options) = transform_filter else {
return Ok(true);
};

let mut fallback_ret =
if let Some(ref module_type_filter) = transform_hook_filter_options.module_type {
if module_type_filter
.iter()
.map(ModuleType::from_str_with_fallback)
.any(|ty| ty == *module_type)
{
return Ok(true);
}
None => Ok(None),
}
}
false
} else {
true
};

fn resolve_id_filter(&self) -> anyhow::Result<Option<ResolvedIdHookFilter>> {
match self.inner.resolve_id_filter {
Some(ref item) => {
let filter = ResolvedIdHookFilter::try_from(item.clone())?;
Ok(Some(filter))
}
None => Ok(None),
if let Some(ref id_filter) = transform_hook_filter_options.id {
let stabilized_path = Path::new(id).relative(cwd);
let normalized_id = stabilized_path.to_string_lossy();

let exclude = id_filter.exclude.clone().map(bindingify_string_or_regex_array).transpose()?;
let include = id_filter.include.clone().map(bindingify_string_or_regex_array).transpose()?;

let id_res = pattern_filter::filter(exclude.as_deref(), include.as_deref(), id, &normalized_id);
// it matched by `exclude` or `include`, early return
if let FilterResult::Match(id_res) = id_res {
return Ok(id_res);
}
fallback_ret = fallback_ret && id_res.inner();
}

fn load_filter(&self) -> anyhow::Result<Option<LoadHookFilter>> {
match self.inner.load_filter {
Some(ref item) => {
let filter = LoadHookFilter::try_from(item.clone())?;
Ok(Some(filter))
}
None => Ok(None),
if let Some(ref code_filter) = transform_hook_filter_options.code {
let exclude = code_filter.exclude.clone().map(bindingify_string_or_regex_array).transpose()?;
let include = code_filter.include.clone().map(bindingify_string_or_regex_array).transpose()?;

let code_res = pattern_filter::filter_code(exclude.as_deref(), include.as_deref(), code);
// it matched by `exclude` or `include`, early return
if let FilterResult::Match(code_res) = code_res {
return Ok(code_res);
}
fallback_ret = fallback_ret && code_res.inner();
}

Ok(fallback_ret)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use rolldown::ModuleType;
use rolldown_plugin::{GeneralHookFilter, ResolvedIdHookFilter, TransformHookFilter};

use super::binding_js_or_regex::{bindingify_string_or_regex_array, BindingStringOrRegex};
use super::binding_js_or_regex::BindingStringOrRegex;

#[napi_derive::napi(object, object_to_js = false)]
#[derive(Clone, Debug)]
Expand All @@ -10,53 +7,10 @@ pub struct BindingGeneralHookFilter {
pub exclude: Option<Vec<BindingStringOrRegex>>,
}

impl TryFrom<BindingGeneralHookFilter> for GeneralHookFilter {
type Error = anyhow::Error;

fn try_from(value: BindingGeneralHookFilter) -> Result<Self, Self::Error> {
Ok(Self {
include: value.include.map(bindingify_string_or_regex_array).transpose()?,
exclude: value.exclude.map(bindingify_string_or_regex_array).transpose()?,
})
}
}

impl TryFrom<BindingGeneralHookFilter> for ResolvedIdHookFilter {
type Error = anyhow::Error;

fn try_from(value: BindingGeneralHookFilter) -> Result<Self, Self::Error> {
let mut ret = Self::default();
let id_filter = value.try_into()?;
ret.id = Some(id_filter);
Ok(ret)
}
}

#[napi_derive::napi(object, object_to_js = false)]
#[derive(Default, Clone)]
pub struct BindingTransformHookFilter {
pub code: Option<BindingGeneralHookFilter>,
pub module_type: Option<Vec<String>>,
pub id: Option<BindingGeneralHookFilter>,
}

impl TryFrom<BindingTransformHookFilter> for TransformHookFilter {
type Error = anyhow::Error;

fn try_from(value: BindingTransformHookFilter) -> Result<Self, Self::Error> {
let mut default = Self::default();
if let Some(code_filter) = value.code {
let ret = code_filter.try_into()?;
default.code = Some(ret);
}
if let Some(id_filter) = value.id {
let ret = id_filter.try_into()?;
default.id = Some(ret);
}
if let Some(module_type) = value.module_type {
default.module_type =
Some(module_type.into_iter().map(ModuleType::from_str_with_fallback).collect());
}
Ok(default)
}
}
1 change: 0 additions & 1 deletion crates/rolldown_plugin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ rolldown_sourcemap = { workspace = true }
rolldown_utils = { workspace = true }
rustc-hash = { workspace = true }
string_wizard = { workspace = true }
sugar_path = { workspace = true }
tokio = { workspace = true, features = ["sync"] }
tracing = { workspace = true }
typedmap = { workspace = true, features = ["dashmap"] }
3 changes: 0 additions & 3 deletions crates/rolldown_plugin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ pub use crate::{
types::hook_addon_args::HookAddonArgs,
types::hook_build_end_args::HookBuildEndArgs,
types::hook_build_start_args::HookBuildStartArgs,
types::hook_filter::{
GeneralHookFilter, LoadHookFilter, ResolvedIdHookFilter, TransformHookFilter,
},
types::hook_generate_bundle_args::HookGenerateBundleArgs,
types::hook_load_args::HookLoadArgs,
types::hook_load_output::HookLoadOutput,
Expand Down
Loading

0 comments on commit ed3c822

Please sign in to comment.