Skip to content
Draft
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
2 changes: 2 additions & 0 deletions Cargo.lock

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

88 changes: 73 additions & 15 deletions crates/node_binding/napi-binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,37 @@ export declare class JsLoaderCache {
store(loaderIndex: number, output: JsLoaderCacheEntry): Promise<void>
}

/**
* Owns the boxed native context while JavaScript executes. Returning the class
* moves the context back to Rust and leaves the cached JavaScript instance empty.
* The same instance is reattached on the next entry for this native lifetime.
*/
export declare class JsLoaderContext {
/**
* Snapshot the mutable execution state in one crossing. Output remains lazy:
* leaving it absent on writeback preserves native content and source maps.
*/
get state(): JsLoaderContextState
get resource(): string
get _module(): Module
/** Content may be empty in the pitching stage. */
get content(): string | Buffer | null
get additionalData(): any
get sourceMap(): Buffer | null
get loaderItems(): Array<JsLoaderMetadata>
get __internal__loaderCache(): JsLoaderCache | undefined
/**
* Commit the JavaScript wrapper's state in one crossing. An absent output
* preserves native content and source maps when pitching produces no output.
*/
set state(result: JsLoaderContextState)
/**
* Return unexpected JavaScript failures together with the owned context,
* even when reading or converting the state object itself failed.
*/
set __internal__error(error: RspackError)
}

export declare class JsModuleGraph {
getModule(dependency: Dependency): Module | null
getResolvedModule(dependency: Dependency): Module | null
Expand Down Expand Up @@ -972,23 +1003,18 @@ export interface JsLoaderCacheEntry {
parseMeta: Record<string, string>
}

export interface JsLoaderContext {
loaderContextState?: object | undefined
resource: string
_module: Module
hot: Readonly<boolean>
/** Content maybe empty in pitching stage */
content: string | Buffer | null
additionalData?: any
__internal__parseMeta: Record<string, string>
sourceMap?: Buffer
export interface JsLoaderContextState {
cacheable: boolean
dependencies: JsLoaderDependencies
loaderItems: Array<JsLoaderItem>
hot: boolean
/** The native scheduler owns phase transitions; writeback does not change it. */
loaderState: JsLoaderState
loaderItemStates: Array<JsLoaderItemState>
loaderIndex: number
loaderState: Readonly<JsLoaderState>
__internal__error?: RspackError
__internal__loaderCache?: JsLoaderCache | undefined
/** JavaScript additions, merged into the native typed parse metadata. */
parseMeta: Record<string, string>
output?: JsLoaderOutput
error?: RspackError
}

export interface JsLoaderDependencies {
Expand All @@ -998,6 +1024,18 @@ export interface JsLoaderDependencies {
buildDependencies: Array<string>
}

/**
* The before-loaders hook borrows the native context and exchanges only owned
* snapshots. It neither moves the Box nor materializes source content/maps.
*/
export interface JsLoaderHookContext {
identity: JsLoaderContext
state: JsLoaderContextState
resource: string
_module: Module
loaderItems?: Array<JsLoaderMetadata>
}

export interface JsLoaderItem {
loader: string
type: string
Expand All @@ -1008,6 +1046,26 @@ export interface JsLoaderItem {
noPitch: boolean
}

export interface JsLoaderItemState {
data: any
normalExecuted: boolean
pitchExecuted: boolean
noPitch: boolean
}

/** Immutable loader metadata, materialized once for the JavaScript facade. */
export interface JsLoaderMetadata {
loader: string
type: string
cache: boolean
}

export interface JsLoaderOutput {
content: string | Buffer | null
sourceMap?: Buffer
additionalData?: any
}

export declare enum JsLoaderState {
Pitching = 'Pitching',
Normal = 'Normal'
Expand Down Expand Up @@ -3335,7 +3393,7 @@ export interface RegisterJsTaps {
registerCompilationAfterProcessAssetsTaps: (stages: Array<number>) => Array<{ function: ((arg: JsCompilation) => void); stage: number; }>
registerCompilationSealTaps: (stages: Array<number>) => Array<{ function: (() => void); stage: number; }>
registerCompilationAfterSealTaps: (stages: Array<number>) => Array<{ function: (() => Promise<void>); stage: number; }>
registerNormalModuleLoaderTaps: (stages: Array<number>) => Array<{ function: ((arg: JsLoaderContext) => JsLoaderContext); stage: number; }>
registerNormalModuleLoaderTaps: (stages: Array<number>) => Array<{ function: ((arg: JsLoaderHookContext) => JsLoaderContextState); stage: number; }>
registerNormalModuleFactoryBeforeResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: JsResolveData) => Promise<[boolean | undefined, JsResolveData]>); stage: number; }>
registerNormalModuleFactoryFactorizeTaps: (stages: Array<number>) => Array<{ function: ((arg: JsResolveData) => Promise<JsResolveData>); stage: number; }>
registerNormalModuleFactoryResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: JsResolveData) => Promise<JsResolveData>); stage: number; }>
Expand Down
1 change: 1 addition & 0 deletions crates/node_binding/rspack.wasi-browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export const JsContextModuleFactoryBeforeResolveData = __napiModule.exports.JsCo
export const JsCoordinator = __napiModule.exports.JsCoordinator
export const JsDependencies = __napiModule.exports.JsDependencies
export const JsEntries = __napiModule.exports.JsEntries
export const JsLoaderContext = __napiModule.exports.JsLoaderContext
export const JsExportsInfo = __napiModule.exports.JsExportsInfo
export const JsModuleGraph = __napiModule.exports.JsModuleGraph
export const JsResolver = __napiModule.exports.JsResolver
Expand Down
1 change: 1 addition & 0 deletions crates/node_binding/rspack.wasi.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ module.exports.JsContextModuleFactoryBeforeResolveData = __napiModule.exports.Js
module.exports.JsCoordinator = __napiModule.exports.JsCoordinator
module.exports.JsDependencies = __napiModule.exports.JsDependencies
module.exports.JsEntries = __napiModule.exports.JsEntries
module.exports.JsLoaderContext = __napiModule.exports.JsLoaderContext
module.exports.JsExportsInfo = __napiModule.exports.JsExportsInfo
module.exports.JsModuleGraph = __napiModule.exports.JsModuleGraph
module.exports.JsResolver = __napiModule.exports.JsResolver
Expand Down
2 changes: 1 addition & 1 deletion crates/rspack_binding_api/src/modules/normal_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl NormalModule {
module
.loaders()
.iter()
.map(JsLoaderItem::from)
.map(|resolved| JsLoaderItem::from(&resolved.loader))
.collect::<Vec<_>>(),
)?
});
Expand Down
18 changes: 12 additions & 6 deletions crates/rspack_binding_api/src/plugins/interceptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,10 @@ use crate::{
JsCreateData, JsNormalModuleFactoryCreateModuleArgs, JsResolveData, JsResolveForSchemeArgs,
JsResolveForSchemeOutput,
},
plugins::js_loader::{JsLoaderContext, merge_loader_context},
plugins::js_loader::{
JsLoaderContextState, JsLoaderHookContext,
context::{JsLoaderHookContextObject, check_loader_error},
},
rsdoctor::{
JsRsdoctorAssetPatch, JsRsdoctorChunkGraph, JsRsdoctorModuleGraph, JsRsdoctorModuleIdsPatch,
JsRsdoctorModuleSourcesPatch,
Expand Down Expand Up @@ -626,7 +629,7 @@ pub struct RegisterJsTaps {
)]
pub register_compilation_after_seal_taps: RegisterFunction,
#[napi(
ts_type = "(stages: Array<number>) => Array<{ function: ((arg: JsLoaderContext) => JsLoaderContext); stage: number; }>"
ts_type = "(stages: Array<number>) => Array<{ function: ((arg: JsLoaderHookContext) => JsLoaderContextState); stage: number; }>"
)]
pub register_normal_module_loader_taps: RegisterFunction,
#[napi(
Expand Down Expand Up @@ -942,7 +945,7 @@ define_register!(
/* NormalModule Hooks */
define_register!(
RegisterNormalModuleLoaderTaps,
tap = NormalModuleLoaderTap<JsLoaderContext, JsLoaderContext> @ NormalModuleLoaderHook,
tap = NormalModuleLoaderTap<JsLoaderHookContextObject, JsLoaderContextState> @ NormalModuleLoaderHook,
cache = true,
kind = RegisterJsTapKind::NormalModuleLoader,
skip = true,
Expand Down Expand Up @@ -1705,11 +1708,14 @@ impl CompilationAfterSeal for CompilationAfterSealTap {
#[async_trait]
impl NormalModuleLoader for NormalModuleLoaderTap {
async fn run(&self, context: &mut LoaderContext<RunnerContext>) -> rspack_error::Result<()> {
let data = self
let state = self
.function
.call_with_sync(JsLoaderContext::try_from(&mut *context)?)
.call_with_sync(JsLoaderHookContextObject(JsLoaderHookContext::new(context)))
.await?;
merge_loader_context(context, data)
let (error, _) = state
.apply(context)
.map_err(|error| rspack_error::error!("{error}"))?;
check_loader_error(error)
}

fn stage(&self) -> i32 {
Expand Down
Loading
Loading