Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support contextModuleFactory beforeResolve hook #6420

Merged
merged 14 commits into from
May 10, 2024
Merged
1 change: 1 addition & 0 deletions 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/node_binding/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ rspack_hook = { path = "../rspack_hook" }
rspack_identifier = { path = "../rspack_identifier" }
rspack_napi = { path = "../rspack_napi" }
rspack_tracing = { path = "../rspack_tracing" }
rspack_regex = { path = "../rspack_regex" }
tokio = { workspace = true, features = ["rt", "rt-multi-thread"] }

async-trait = { workspace = true }
Expand Down
16 changes: 14 additions & 2 deletions crates/node_binding/binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,18 @@ export interface JsCompatSource {
map?: Buffer
}

export interface JsContextModuleFactoryAfterResolveData {
resource: string
context: string
request: string
regExp?: string
}

export interface JsContextModuleFactoryBeforeResolveData {
context: string
request?: string
}

export interface JsCreateData {
request: string
userRequest: string
Expand Down Expand Up @@ -1415,8 +1427,8 @@ export interface RegisterJsTaps {
registerNormalModuleFactoryResolveForSchemeTaps: (stages: Array<number>) => Array<{ function: ((arg: JsResolveForSchemeArgs) => Promise<[boolean | undefined, JsResolveForSchemeArgs]>); stage: number; }>
registerNormalModuleFactoryAfterResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: JsAfterResolveData) => Promise<[boolean | undefined, JsCreateData | undefined]>); stage: number; }>
registerNormalModuleFactoryCreateModuleTaps: (stages: Array<number>) => Array<{ function: ((arg: JsNormalModuleFactoryCreateModuleArgs) => Promise<void>); stage: number; }>
registerContextModuleFactoryBeforeResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: JsBeforeResolveArgs) => Promise<[boolean | undefined, JsBeforeResolveArgs]>); stage: number; }>
registerContextModuleFactoryAfterResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: JsAfterResolveData) => Promise<boolean | undefined>); stage: number; }>
registerContextModuleFactoryBeforeResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: false | JsContextModuleFactoryBeforeResolveData) => Promise<false | JsContextModuleFactoryBeforeResolveData>); stage: number; }>
registerContextModuleFactoryAfterResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: false | JsContextModuleFactoryAfterResolveData) => Promise<false | JsContextModuleFactoryAfterResolveData>); stage: number; }>
}

/** Builtin loader runner */
Expand Down
123 changes: 65 additions & 58 deletions crates/node_binding/src/plugins/interceptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@ use napi::{
};
use rspack_binding_values::{
CompatSource, JsAfterResolveData, JsAfterResolveOutput, JsAssetEmittedArgs, JsBeforeResolveArgs,
JsBeforeResolveOutput, JsChunk, JsChunkAssetArgs, JsCompilation, JsCreateData,
JsBeforeResolveOutput, JsChunk, JsChunkAssetArgs, JsCompilation,
JsContextModuleFactoryAfterResolveData, JsContextModuleFactoryAfterResolveResult,
JsContextModuleFactoryBeforeResolveData, JsContextModuleFactoryBeforeResolveResult, JsCreateData,
JsExecuteModuleArg, JsModule, JsNormalModuleFactoryCreateModuleArgs, JsResolveForSchemeArgs,
JsResolveForSchemeOutput, JsRuntimeModule, JsRuntimeModuleArg, ToJsCompatSource, ToJsModule,
};
use rspack_core::{
rspack_sources::SourceExt, AssetEmittedInfo, BoxModule, Chunk, ChunkUkey, CodeGenerationResults,
rspack_sources::SourceExt, AfterResolveData, AfterResolveResult, AssetEmittedInfo,
BeforeResolveData, BeforeResolveResult, BoxModule, Chunk, ChunkUkey, CodeGenerationResults,
Compilation, CompilationAfterOptimizeModules, CompilationAfterOptimizeModulesHook,
CompilationAfterProcessAssets, CompilationAfterProcessAssetsHook, CompilationAfterSeal,
CompilationAfterSealHook, CompilationBuildModule, CompilationBuildModuleHook,
Expand All @@ -42,6 +45,7 @@ use rspack_core::{
use rspack_hook::{Hook, Interceptor};
use rspack_identifier::IdentifierSet;
use rspack_napi::threadsafe_function::ThreadsafeFunction;
use rspack_regex::RspackRegex;

#[napi(object)]
pub struct JsTap {
Expand Down Expand Up @@ -434,15 +438,19 @@ pub struct RegisterJsTaps {
pub register_normal_module_factory_create_module_taps:
RegisterFunction<JsNormalModuleFactoryCreateModuleArgs, Promise<()>>,
#[napi(
ts_type = "(stages: Array<number>) => Array<{ function: ((arg: JsBeforeResolveArgs) => Promise<[boolean | undefined, JsBeforeResolveArgs]>); stage: number; }>"
ts_type = "(stages: Array<number>) => Array<{ function: ((arg: false | JsContextModuleFactoryBeforeResolveData) => Promise<false | JsContextModuleFactoryBeforeResolveData>); stage: number; }>"
)]
pub register_context_module_factory_before_resolve_taps:
RegisterFunction<JsBeforeResolveArgs, Promise<JsBeforeResolveOutput>>,
pub register_context_module_factory_before_resolve_taps: RegisterFunction<
JsContextModuleFactoryBeforeResolveResult,
Promise<JsContextModuleFactoryBeforeResolveResult>,
>,
#[napi(
ts_type = "(stages: Array<number>) => Array<{ function: ((arg: JsAfterResolveData) => Promise<boolean | undefined>); stage: number; }>"
ts_type = "(stages: Array<number>) => Array<{ function: ((arg: false | JsContextModuleFactoryAfterResolveData) => Promise<false | JsContextModuleFactoryAfterResolveData>); stage: number; }>"
)]
pub register_context_module_factory_after_resolve_taps:
RegisterFunction<JsAfterResolveData, Promise<Option<bool>>>,
pub register_context_module_factory_after_resolve_taps: RegisterFunction<
JsContextModuleFactoryAfterResolveResult,
Promise<JsContextModuleFactoryAfterResolveResult>,
>,
}

/* Compiler Hooks */
Expand Down Expand Up @@ -662,15 +670,15 @@ define_register!(
/* ContextModuleFactory Hooks */
define_register!(
RegisterContextModuleFactoryBeforeResolveTaps,
tap = ContextModuleFactoryBeforeResolveTap<JsBeforeResolveArgs, Promise<JsBeforeResolveOutput>> @ ContextModuleFactoryBeforeResolveHook,
tap = ContextModuleFactoryBeforeResolveTap<JsContextModuleFactoryBeforeResolveResult, Promise<JsContextModuleFactoryBeforeResolveResult>> @ ContextModuleFactoryBeforeResolveHook,
cache = true,
sync = false,
kind = RegisterJsTapKind::ContextModuleFactoryBeforeResolve,
skip = true,
);
define_register!(
RegisterContextModuleFactoryAfterResolveTaps,
tap = ContextModuleFactoryAfterResolveTap<JsAfterResolveData, Promise<Option<bool>>> @ ContextModuleFactoryAfterResolveHook,
tap = ContextModuleFactoryAfterResolveTap<JsContextModuleFactoryAfterResolveResult, Promise<JsContextModuleFactoryAfterResolveResult>> @ ContextModuleFactoryAfterResolveHook,
cache = true,
sync = false,
kind = RegisterJsTapKind::ContextModuleFactoryAfterResolve,
Expand Down Expand Up @@ -1198,24 +1206,27 @@ impl NormalModuleFactoryCreateModule for NormalModuleFactoryCreateModuleTap {

#[async_trait]
impl ContextModuleFactoryBeforeResolve for ContextModuleFactoryBeforeResolveTap {
async fn run(&self, data: &mut ModuleFactoryCreateData) -> rspack_error::Result<Option<bool>> {
let dependency = data
.dependency
.as_context_dependency_mut()
.expect("should be context dependency");
match self
.function
.call_with_promise(JsBeforeResolveArgs {
request: dependency.request().to_string(),
context: data.context.to_string(),
})
.await
{
Ok((ret, resolve_data)) => {
dependency.set_request(resolve_data.request);
data.context = resolve_data.context.into();
Ok(ret)
async fn run(&self, result: BeforeResolveResult) -> rspack_error::Result<BeforeResolveResult> {
let js_result = match result {
BeforeResolveResult::Ignored => JsContextModuleFactoryBeforeResolveResult::A(false),
BeforeResolveResult::Data(d) => {
JsContextModuleFactoryBeforeResolveResult::B(JsContextModuleFactoryBeforeResolveData {
context: d.context,
request: d.request,
})
}
};
match self.function.call_with_promise(js_result).await {
Ok(js_result) => match js_result {
napi::bindgen_prelude::Either::A(_) => Ok(BeforeResolveResult::Ignored),
napi::bindgen_prelude::Either::B(d) => {
let data = BeforeResolveData {
context: d.context,
request: d.request,
};
Ok(BeforeResolveResult::Data(Box::new(data)))
}
},
Err(err) => Err(err),
}
}
Expand All @@ -1227,37 +1238,33 @@ impl ContextModuleFactoryBeforeResolve for ContextModuleFactoryBeforeResolveTap

#[async_trait]
impl ContextModuleFactoryAfterResolve for ContextModuleFactoryAfterResolveTap {
async fn run(&self, data: &mut ModuleFactoryCreateData) -> rspack_error::Result<Option<bool>> {
let dependency = data
.dependency
.as_context_dependency_mut()
.expect("should be context dependency");
self
.function
.call_with_promise(JsAfterResolveData {
request: dependency.request().to_string(),
context: data.context.to_string(),
file_dependencies: data
.file_dependencies
.clone()
.into_iter()
.map(|item| item.to_string_lossy().to_string())
.collect::<Vec<_>>(),
context_dependencies: data
.context_dependencies
.clone()
.into_iter()
.map(|item| item.to_string_lossy().to_string())
.collect::<Vec<_>>(),
missing_dependencies: data
.missing_dependencies
.clone()
.into_iter()
.map(|item| item.to_string_lossy().to_string())
.collect::<Vec<_>>(),
create_data: None,
})
.await
async fn run(&self, result: AfterResolveResult) -> rspack_error::Result<AfterResolveResult> {
let js_result = match result {
AfterResolveResult::Ignored => JsContextModuleFactoryAfterResolveResult::A(false),
AfterResolveResult::Data(d) => {
JsContextModuleFactoryAfterResolveResult::B(JsContextModuleFactoryAfterResolveData {
resource: d.resource.to_owned(),
context: d.context.to_owned(),
request: d.request.to_owned(),
reg_exp: d.reg_exp.clone().map(|r| r.to_string()),
})
}
};
match self.function.call_with_promise(js_result).await? {
napi::Either::A(_) => Ok(AfterResolveResult::Ignored),
napi::Either::B(d) => {
let data = AfterResolveData {
resource: d.resource,
context: d.context,
request: d.request,
reg_exp: match d.reg_exp {
Some(r) => Some(RspackRegex::new(&r)?),
None => None,
},
};
Ok(AfterResolveResult::Data(Box::new(data)))
}
}
}

fn stage(&self) -> i32 {
Expand Down
22 changes: 22 additions & 0 deletions crates/rspack_binding_values/src/context_module_factory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use napi::bindgen_prelude::Either;
use napi_derive::napi;

#[napi(object)]
pub struct JsContextModuleFactoryBeforeResolveData {
pub context: String,
pub request: Option<String>,
}

pub type JsContextModuleFactoryBeforeResolveResult =
Either<bool, JsContextModuleFactoryBeforeResolveData>;

#[napi(object)]
pub struct JsContextModuleFactoryAfterResolveData {
pub resource: String,
pub context: String,
pub request: String,
pub reg_exp: Option<String>,
}

pub type JsContextModuleFactoryAfterResolveResult =
Either<bool, JsContextModuleFactoryAfterResolveData>;
2 changes: 2 additions & 0 deletions crates/rspack_binding_values/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod chunk_graph;
mod chunk_group;
mod codegen_result;
mod compilation;
mod context_module_factory;
mod filename;
mod module;
mod normal_module_factory;
Expand All @@ -19,6 +20,7 @@ pub use chunk_graph::*;
pub use chunk_group::*;
pub use codegen_result::*;
pub use compilation::*;
pub use context_module_factory::*;
pub use filename::*;
pub use module::*;
pub use normal_module_factory::*;
Expand Down
2 changes: 1 addition & 1 deletion crates/rspack_core/src/context_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ pub struct ContextOptions {
pub end: u32,
}

#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Clone)]
pub struct ContextModuleOptions {
pub addon: String,
pub resource: String,
Expand Down
Loading
Loading