diff --git a/crates/node_binding/napi-binding.d.ts b/crates/node_binding/napi-binding.d.ts index 7125ee39f0fb..b072c61cd319 100644 --- a/crates/node_binding/napi-binding.d.ts +++ b/crates/node_binding/napi-binding.d.ts @@ -1205,6 +1205,8 @@ export interface JsRuntimeModule { moduleIdentifier: string constructorName: string name: string + stage: number + isolate: boolean } export interface JsRuntimeModuleArg { diff --git a/crates/rspack_binding_api/src/module.rs b/crates/rspack_binding_api/src/module.rs index 6d90c053ad8e..0448865d1b0e 100644 --- a/crates/rspack_binding_api/src/module.rs +++ b/crates/rspack_binding_api/src/module.rs @@ -745,6 +745,8 @@ pub struct JsRuntimeModule { pub module_identifier: String, pub constructor_name: String, pub name: String, + pub stage: u32, + pub isolate: bool, } #[napi(object, object_from_js = false)] diff --git a/crates/rspack_binding_api/src/plugins/interceptor.rs b/crates/rspack_binding_api/src/plugins/interceptor.rs index e8e2c55ce5f6..04f1b501504d 100644 --- a/crates/rspack_binding_api/src/plugins/interceptor.rs +++ b/crates/rspack_binding_api/src/plugins/interceptor.rs @@ -1358,6 +1358,8 @@ impl CompilationRuntimeModule for CompilationRuntimeModuleTap { .as_str() .cow_replace(compilation.runtime_template.runtime_module_prefix(), "") .into_owned(), + stage: module.stage().into(), + isolate: module.should_isolate(), }, chunk: ChunkWrapper::new(*chunk_ukey, compilation), }; diff --git a/crates/rspack_core/src/runtime_module.rs b/crates/rspack_core/src/runtime_module.rs index 64088d66b37d..43f0d27d5de3 100644 --- a/crates/rspack_core/src/runtime_module.rs +++ b/crates/rspack_core/src/runtime_module.rs @@ -67,6 +67,17 @@ impl From for RuntimeModuleStage { } } +impl From for u32 { + fn from(value: RuntimeModuleStage) -> Self { + match value { + RuntimeModuleStage::Normal => 0, + RuntimeModuleStage::Basic => 5, + RuntimeModuleStage::Attach => 10, + RuntimeModuleStage::Trigger => 20, + } + } +} + pub trait RuntimeModuleExt { fn boxed(self) -> Box; } diff --git a/packages/rspack-test-tools/src/helper/hot-update/plugin.ts b/packages/rspack-test-tools/src/helper/hot-update/plugin.ts index f8d19f439eeb..3f7a8065246b 100644 --- a/packages/rspack-test-tools/src/helper/hot-update/plugin.ts +++ b/packages/rspack-test-tools/src/helper/hot-update/plugin.ts @@ -167,7 +167,9 @@ export class HotUpdatePlugin { compilation.hooks.runtimeModule.tap( PLUGIN_NAME, (module: any, _set: any) => { - if (module.constructorName === 'DefinePropertyGettersRuntimeModule') { + if ( + module.constructor.name === 'DefinePropertyGettersRuntimeModule' + ) { module.source.source = Buffer.from( ` ${RuntimeGlobals.definePropertyGetters} = function (exports, definition) { diff --git a/packages/rspack/etc/core.api.md b/packages/rspack/etc/core.api.md index 6f256d593af6..1238e9baa238 100644 --- a/packages/rspack/etc/core.api.md +++ b/packages/rspack/etc/core.api.md @@ -53,7 +53,6 @@ import { JsRsdoctorChunkGraph } from '@rspack/binding'; import { JsRsdoctorModuleGraph } from '@rspack/binding'; import { JsRsdoctorModuleIdsPatch } from '@rspack/binding'; import { JsRsdoctorModuleSourcesPatch } from '@rspack/binding'; -import type { JsRuntimeModule } from '@rspack/binding'; import type { JsStats } from '@rspack/binding'; import type { JsStatsCompilation } from '@rspack/binding'; import type { JsStatsError } from '@rspack/binding'; @@ -1026,7 +1025,7 @@ export class Compilation { Set ]>; runtimeRequirementInTree: liteTapable.HookMap], void>>; - runtimeModule: liteTapable.SyncHook<[JsRuntimeModule, Chunk]>; + runtimeModule: liteTapable.SyncHook<[RuntimeModule, Chunk]>; seal: liteTapable.SyncHook<[]>; afterSeal: liteTapable.AsyncSeriesHook<[], void>; needAdditionalPass: liteTapable.SyncBailHook<[], boolean>; diff --git a/packages/rspack/src/Compilation.ts b/packages/rspack/src/Compilation.ts index 3d4140158bc6..7ee225efa277 100644 --- a/packages/rspack/src/Compilation.ts +++ b/packages/rspack/src/Compilation.ts @@ -15,7 +15,6 @@ import type { ExternalObject, JsCompilation, JsPathData, - JsRuntimeModule, JsSource, } from '@rspack/binding'; import binding from '@rspack/binding'; @@ -252,7 +251,7 @@ export class Compilation { runtimeRequirementInTree: liteTapable.HookMap< liteTapable.SyncBailHook<[Chunk, Set], void> >; - runtimeModule: liteTapable.SyncHook<[JsRuntimeModule, Chunk]>; + runtimeModule: liteTapable.SyncHook<[RuntimeModule, Chunk]>; seal: liteTapable.SyncHook<[]>; afterSeal: liteTapable.AsyncSeriesHook<[], void>; needAdditionalPass: liteTapable.SyncBailHook<[], boolean>; diff --git a/packages/rspack/src/RuntimeModule.ts b/packages/rspack/src/RuntimeModule.ts index dfe97ad096f4..c349b3cae727 100644 --- a/packages/rspack/src/RuntimeModule.ts +++ b/packages/rspack/src/RuntimeModule.ts @@ -1,4 +1,8 @@ -import type { JsAddingRuntimeModule } from '@rspack/binding'; +import type { + JsAddingRuntimeModule, + JsRuntimeModule, + JsSource, +} from '@rspack/binding'; import type { Chunk } from './Chunk'; import type { ChunkGraph } from './ChunkGraph'; import type { Compilation } from './Compilation'; @@ -71,3 +75,52 @@ export class RuntimeModule { ); } } + +export function createRenderedRuntimeModule( + module: JsRuntimeModule, +): RuntimeModule { + const RuntimeModuleClass = { + [module.constructorName]: class extends RuntimeModule { + private _source: JsSource | undefined; + constructor() { + super(module.name, module.stage); + this._source = module.source; + } + + /** + * @deprecated use `module.constructor.name` instead + */ + get constructorName() { + return module.constructorName; + } + + /** + * @deprecated use `module.identifier()` instead + */ + get moduleIdentifier() { + return module.moduleIdentifier; + } + + get source(): JsSource | undefined { + return this._source; + } + + identifier(): string { + return module.moduleIdentifier; + } + + readableIdentifier(): string { + return module.moduleIdentifier; + } + + shouldIsolate(): boolean { + return module.isolate; + } + + generate(): string { + return this._source?.source.toString('utf-8') || ''; + } + }, + }[module.constructorName]; + return new RuntimeModuleClass(); +} diff --git a/packages/rspack/src/taps/compilation.ts b/packages/rspack/src/taps/compilation.ts index 00af3f009b8e..7fac14b015e0 100644 --- a/packages/rspack/src/taps/compilation.ts +++ b/packages/rspack/src/taps/compilation.ts @@ -6,6 +6,7 @@ import { __to_binding_runtime_globals, isReservedRuntimeGlobal, } from '../RuntimeGlobals'; +import { createRenderedRuntimeModule } from '../RuntimeModule'; import { createHash } from '../util/createHash'; import type { CreatePartialRegisters } from './types'; @@ -133,8 +134,11 @@ export const createCompilationHooksRegisters: CreatePartialRegisters< function (queried) { return function ({ module, chunk }: binding.JsRuntimeModuleArg) { + const runtimeModule = createRenderedRuntimeModule(module); + const compilation = getCompiler().__internal__get_compilation()!; + runtimeModule.attach(compilation, chunk, compilation.chunkGraph); const originSource = module.source?.source; - queried.call(module, chunk); + queried.call(runtimeModule, chunk); const newSource = module.source?.source; if (newSource && newSource !== originSource) { return module; diff --git a/tests/rspack-test/configCases/hooks/modify-extract-css-loading-runtime/rspack.config.js b/tests/rspack-test/configCases/hooks/modify-extract-css-loading-runtime/rspack.config.js index 5185739088a8..4f6fbf3427f3 100644 --- a/tests/rspack-test/configCases/hooks/modify-extract-css-loading-runtime/rspack.config.js +++ b/tests/rspack-test/configCases/hooks/modify-extract-css-loading-runtime/rspack.config.js @@ -4,7 +4,11 @@ class Plugin { apply(compiler) { compiler.hooks.compilation.tap("TestFakePlugin", compilation => { compilation.hooks.runtimeModule.tap("TestFakePlugin", (module, chunk) => { - if (module.constructorName === "CssLoadingRuntimeModule") { + if (module.constructor.name === "CssLoadingRuntimeModule") { + expect(module.constructorName).toBe("CssLoadingRuntimeModule"); + expect(module.moduleIdentifier).toBe("webpack/runtime/css loading"); + expect(module.identifier()).toBe("webpack/runtime/css loading"); + expect(module.readableIdentifier()).toBe("webpack/runtime/css loading"); const originSource = module.source.source.toString("utf-8"); module.source.source = Buffer.from( `${originSource}\n__webpack_require__.f.miniCss.test = true;\n`, diff --git a/website/docs/en/types/runtime-module.mdx b/website/docs/en/types/runtime-module.mdx index 2c18016ea79b..de5a6390d2fc 100644 --- a/website/docs/en/types/runtime-module.mdx +++ b/website/docs/en/types/runtime-module.mdx @@ -1,17 +1,18 @@ <> ```ts -type RuntimeModule = { +class RuntimeModule { source?: { isRaw: boolean; isBuffer: boolean; source: Buffer; map?: Buffer; }; - moduleIdentifier: string; - constructorName: string; + stage: number; name: string; -}; + identifier(): string; + readableIdentifier(): string; +} ``` diff --git a/website/docs/zh/types/runtime-module.mdx b/website/docs/zh/types/runtime-module.mdx index 2c18016ea79b..de5a6390d2fc 100644 --- a/website/docs/zh/types/runtime-module.mdx +++ b/website/docs/zh/types/runtime-module.mdx @@ -1,17 +1,18 @@ <> ```ts -type RuntimeModule = { +class RuntimeModule { source?: { isRaw: boolean; isBuffer: boolean; source: Buffer; map?: Buffer; }; - moduleIdentifier: string; - constructorName: string; + stage: number; name: string; -}; + identifier(): string; + readableIdentifier(): string; +} ```