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: add runtime plugin hooks #9084

Merged
merged 4 commits into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 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 @@ -28,6 +28,7 @@ rspack_napi = { workspace = true }
rspack_paths = { workspace = true }
rspack_plugin_html = { workspace = true }
rspack_plugin_javascript = { workspace = true }
rspack_plugin_runtime = { workspace = true }
rspack_util = { workspace = true }

rspack_tracing = { workspace = true }
Expand Down
23 changes: 22 additions & 1 deletion crates/node_binding/binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,11 @@ export interface JsCreateData {
resource: string
}

export interface JsCreateScriptData {
code: string
chunk: JsChunk
}

export interface JsDefaultObjectRedirectWarnObject {
ignore: boolean
}
Expand Down Expand Up @@ -719,6 +724,16 @@ export interface JsLibraryOptions {
amdContainer?: string
}

export interface JsLinkPrefetchData {
code: string
chunk: JsChunk
}

export interface JsLinkPreloadData {
code: string
chunk: JsChunk
}

export interface JsLoaderContext {
resourceData: Readonly<JsResourceData>
/** Will be deprecated. Use module.module_identifier instead */
Expand Down Expand Up @@ -2117,7 +2132,10 @@ export declare enum RegisterJsTapKind {
HtmlPluginAlterAssetTagGroups = 37,
HtmlPluginAfterTemplateExecution = 38,
HtmlPluginBeforeEmit = 39,
HtmlPluginAfterEmit = 40
HtmlPluginAfterEmit = 40,
RuntimePluginCreateScript = 41,
RuntimePluginLinkPreload = 42,
RuntimePluginLinkPrefetch = 43
}

export interface RegisterJsTaps {
Expand Down Expand Up @@ -2162,6 +2180,9 @@ export interface RegisterJsTaps {
registerHtmlPluginAfterTemplateExecutionTaps: (stages: Array<number>) => Array<{ function: ((arg: JsAfterTemplateExecutionData) => JsAfterTemplateExecutionData); stage: number; }>
registerHtmlPluginBeforeEmitTaps: (stages: Array<number>) => Array<{ function: ((arg: JsBeforeEmitData) => JsBeforeEmitData); stage: number; }>
registerHtmlPluginAfterEmitTaps: (stages: Array<number>) => Array<{ function: ((arg: JsAfterEmitData) => JsAfterEmitData); stage: number; }>
registerRuntimePluginCreateScriptTaps: (stages: Array<number>) => Array<{ function: ((arg: JsCreateScriptData) => String); stage: number; }>
registerRuntimePluginLinkPreloadTaps: (stages: Array<number>) => Array<{ function: ((arg: JsLinkPreloadData) => String); stage: number; }>
registerRuntimePluginLinkPrefetchTaps: (stages: Array<number>) => Array<{ function: ((arg: JsLinkPrefetchData) => String); stage: number; }>
}

export interface ThreadsafeNodeFS {
Expand Down
110 changes: 106 additions & 4 deletions crates/node_binding/src/plugins/interceptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ use rspack_binding_values::{
JsChunkAssetArgs, JsChunkWrapper, JsCompilationWrapper,
JsContextModuleFactoryAfterResolveDataWrapper, JsContextModuleFactoryAfterResolveResult,
JsContextModuleFactoryBeforeResolveDataWrapper, JsContextModuleFactoryBeforeResolveResult,
JsCreateData, JsExecuteModuleArg, JsFactorizeArgs, JsFactorizeOutput, JsModuleWrapper,
JsNormalModuleFactoryCreateModuleArgs, JsResolveArgs, JsResolveForSchemeArgs,
JsResolveForSchemeOutput, JsResolveOutput, JsRuntimeGlobals, JsRuntimeModule, JsRuntimeModuleArg,
JsRuntimeRequirementInTreeArg, JsRuntimeRequirementInTreeResult, ToJsCompatSourceOwned,
JsCreateData, JsCreateScriptData, JsExecuteModuleArg, JsFactorizeArgs, JsFactorizeOutput,
JsLinkPrefetchData, JsLinkPreloadData, JsModuleWrapper, JsNormalModuleFactoryCreateModuleArgs,
JsResolveArgs, JsResolveForSchemeArgs, JsResolveForSchemeOutput, JsResolveOutput,
JsRuntimeGlobals, JsRuntimeModule, JsRuntimeModuleArg, JsRuntimeRequirementInTreeArg,
JsRuntimeRequirementInTreeResult, ToJsCompatSourceOwned,
};
use rspack_collections::IdentifierSet;
use rspack_core::{
Expand Down Expand Up @@ -67,6 +68,11 @@ use rspack_plugin_html::{
HtmlPluginBeforeAssetTagGenerationHook, HtmlPluginBeforeEmit, HtmlPluginBeforeEmitHook,
};
use rspack_plugin_javascript::{JavascriptModulesChunkHash, JavascriptModulesChunkHashHook};
use rspack_plugin_runtime::{
CreateScriptData, LinkPrefetchData, LinkPreloadData, RuntimePluginCreateScript,
RuntimePluginCreateScriptHook, RuntimePluginLinkPrefetch, RuntimePluginLinkPrefetchHook,
RuntimePluginLinkPreload, RuntimePluginLinkPreloadHook,
};

#[napi(object)]
pub struct JsTap<'f> {
Expand Down Expand Up @@ -386,6 +392,9 @@ pub enum RegisterJsTapKind {
HtmlPluginAfterTemplateExecution,
HtmlPluginBeforeEmit,
HtmlPluginAfterEmit,
RuntimePluginCreateScript,
RuntimePluginLinkPreload,
RuntimePluginLinkPrefetch,
}

#[derive(Default, Clone)]
Expand Down Expand Up @@ -589,6 +598,21 @@ pub struct RegisterJsTaps {
)]
pub register_html_plugin_after_emit_taps:
RegisterFunction<JsAfterEmitData, Promise<JsAfterEmitData>>,
#[napi(
ts_type = "(stages: Array<number>) => Array<{ function: ((arg: JsCreateScriptData) => String); stage: number; }>"
)]
pub register_runtime_plugin_create_script_taps:
RegisterFunction<JsCreateScriptData, Option<String>>,
#[napi(
ts_type = "(stages: Array<number>) => Array<{ function: ((arg: JsLinkPreloadData) => String); stage: number; }>"
)]
pub register_runtime_plugin_link_preload_taps:
RegisterFunction<JsLinkPreloadData, Option<String>>,
#[napi(
ts_type = "(stages: Array<number>) => Array<{ function: ((arg: JsLinkPrefetchData) => String); stage: number; }>"
)]
pub register_runtime_plugin_link_prefetch_taps:
RegisterFunction<JsLinkPrefetchData, Option<String>>,
}

/* Compiler Hooks */
Expand Down Expand Up @@ -935,6 +959,30 @@ define_register!(
kind = RegisterJsTapKind::HtmlPluginAfterEmit,
skip = true,
);
define_register!(
RegisterRuntimePluginCreateScriptTaps,
tap = RuntimePluginCreateScriptTap<JsCreateScriptData, Option<String>> @ RuntimePluginCreateScriptHook,
cache = true,
sync = false,
kind = RegisterJsTapKind::RuntimePluginCreateScript,
skip = true,
);
define_register!(
RegisterRuntimePluginLinkPreloadTaps,
tap = RuntimePluginLinkPreloadTap<JsLinkPreloadData, Option<String>> @ RuntimePluginLinkPreloadHook,
cache = true,
sync = false,
kind = RegisterJsTapKind::RuntimePluginLinkPreload,
skip = true,
);
define_register!(
RegisterRuntimePluginLinkPrefetchTaps,
tap = RuntimePluginLinkPrefetchTap<JsLinkPrefetchData, Option<String>> @ RuntimePluginLinkPrefetchHook,
cache = true,
sync = false,
kind = RegisterJsTapKind::RuntimePluginLinkPrefetch,
skip = true,
);

#[async_trait]
impl CompilerThisCompilation for CompilerThisCompilationTap {
Expand Down Expand Up @@ -1768,3 +1816,57 @@ impl HtmlPluginAfterEmit for HtmlPluginAfterEmitTap {
self.stage
}
}

#[async_trait]
impl RuntimePluginCreateScript for RuntimePluginCreateScriptTap {
async fn run(&self, mut data: CreateScriptData) -> rspack_error::Result<CreateScriptData> {
if let Some(code) = self
.function
.call_with_sync(JsCreateScriptData::from(data.clone()))
.await?
{
data.code = code;
}
Ok(data)
}

fn stage(&self) -> i32 {
self.stage
}
}

#[async_trait]
impl RuntimePluginLinkPreload for RuntimePluginLinkPreloadTap {
async fn run(&self, mut data: LinkPreloadData) -> rspack_error::Result<LinkPreloadData> {
if let Some(code) = self
.function
.call_with_sync(JsLinkPreloadData::from(data.clone()))
.await?
{
data.code = code;
}
Ok(data)
}

fn stage(&self) -> i32 {
self.stage
}
}

#[async_trait]
impl RuntimePluginLinkPrefetch for RuntimePluginLinkPrefetchTap {
async fn run(&self, mut data: LinkPrefetchData) -> rspack_error::Result<LinkPrefetchData> {
if let Some(code) = self
.function
.call_with_sync(JsLinkPrefetchData::from(data.clone()))
.await?
{
data.code = code;
}
Ok(data)
}

fn stage(&self) -> i32 {
self.stage
}
}
48 changes: 48 additions & 0 deletions crates/node_binding/src/plugins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use rspack_hook::plugin_hook;
use rspack_hook::Hook as _;
use rspack_plugin_html::HtmlRspackPlugin;
use rspack_plugin_javascript::JsPlugin;
use rspack_plugin_runtime::RuntimePlugin;

use self::interceptor::*;

Expand Down Expand Up @@ -67,6 +68,9 @@ pub struct JsHooksAdapterPlugin {
register_html_plugin_after_template_execution_taps: RegisterHtmlPluginAfterTemplateExecutionTaps,
register_html_plugin_before_emit_taps: RegisterHtmlPluginBeforeEmitTaps,
register_html_plugin_after_emit_taps: RegisterHtmlPluginAfterEmitTaps,
register_runtime_plugin_create_script_taps: RegisterRuntimePluginCreateScriptTaps,
register_runtime_plugin_link_preload_taps: RegisterRuntimePluginLinkPreloadTaps,
register_runtime_plugin_link_prefetch_taps: RegisterRuntimePluginLinkPrefetchTaps,
}

impl fmt::Debug for JsHooksAdapterPlugin {
Expand Down Expand Up @@ -311,6 +315,12 @@ impl rspack_core::Plugin for JsHooksAdapterPlugin {
.compilation
.tap(html_hooks_adapter_compilation::new(self));

ctx
.context
.compiler_hooks
.compilation
.tap(runtime_hooks_adapter_compilation::new(self));

Ok(())
}

Expand Down Expand Up @@ -396,6 +406,13 @@ impl rspack_core::Plugin for JsHooksAdapterPlugin {
.clear_cache();
self.register_html_plugin_before_emit_taps.clear_cache();
self.register_html_plugin_after_emit_taps.clear_cache();
self
.register_runtime_plugin_create_script_taps
.clear_cache();
self.register_runtime_plugin_link_preload_taps.clear_cache();
self
.register_runtime_plugin_link_prefetch_taps
.clear_cache();
}
}

Expand Down Expand Up @@ -448,6 +465,25 @@ async fn html_hooks_adapter_compilation(
Ok(())
}

#[plugin_hook(CompilerCompilation for JsHooksAdapterPlugin)]
async fn runtime_hooks_adapter_compilation(
&self,
compilation: &mut Compilation,
_params: &mut CompilationParams,
) -> rspack_error::Result<()> {
let mut hooks = RuntimePlugin::get_compilation_hooks_mut(compilation);
hooks
.create_script
.intercept(self.register_runtime_plugin_create_script_taps.clone());
hooks
.link_preload
.intercept(self.register_runtime_plugin_link_preload_taps.clone());
hooks
.link_prefetch
.intercept(self.register_runtime_plugin_link_prefetch_taps.clone());
Ok(())
}

impl JsHooksAdapterPlugin {
pub fn from_js_hooks(_env: Env, register_js_taps: RegisterJsTaps) -> Result<Self> {
let non_skippable_registers = NonSkippableRegisters::default();
Expand Down Expand Up @@ -632,6 +668,18 @@ impl JsHooksAdapterPlugin {
register_js_taps.register_html_plugin_after_emit_taps,
non_skippable_registers.clone(),
),
register_runtime_plugin_create_script_taps: RegisterRuntimePluginCreateScriptTaps::new(
register_js_taps.register_runtime_plugin_create_script_taps,
non_skippable_registers.clone(),
),
register_runtime_plugin_link_preload_taps: RegisterRuntimePluginLinkPreloadTaps::new(
register_js_taps.register_runtime_plugin_link_preload_taps,
non_skippable_registers.clone(),
),
register_runtime_plugin_link_prefetch_taps: RegisterRuntimePluginLinkPrefetchTaps::new(
register_js_taps.register_runtime_plugin_link_prefetch_taps,
non_skippable_registers.clone(),
),
non_skippable_registers,
}
.into(),
Expand Down
6 changes: 3 additions & 3 deletions crates/rspack_binding_values/src/chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,9 +241,9 @@ thread_local! {
}

pub struct JsChunkWrapper {
chunk_ukey: ChunkUkey,
compilation_id: CompilationId,
compilation: NonNull<Compilation>,
pub chunk_ukey: ChunkUkey,
pub compilation_id: CompilationId,
pub compilation: NonNull<Compilation>,
}

unsafe impl Send for JsChunkWrapper {}
Expand Down
Loading
Loading