Skip to content

Commit

Permalink
feat: support compilation.modules[i].blocks (#7460)
Browse files Browse the repository at this point in the history
* feat: module dto

* DependenciesBlockDTO

* feat: DependenciesBlockDTO

* feat: DependenciesBlock and Dependency in js side

* chore: update api md

* fix: js lint

* fix: cargo lint wrong

* fix: test case
  • Loading branch information
SyMind authored Aug 6, 2024
1 parent 34d5406 commit ccd6ee8
Show file tree
Hide file tree
Showing 12 changed files with 376 additions and 41 deletions.
25 changes: 24 additions & 1 deletion crates/node_binding/binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,16 @@ export class ExternalObject<T> {
[K: symbol]: T
}
}
export class DependenciesBlockDto {
get dependencies(): Array<DependencyDto>
get blocks(): Array<DependenciesBlockDto>
}
export type DependenciesBlockDTO = DependenciesBlockDto

export class DependencyDto {
get type(): string
get category(): string
get request(): string | undefined
}
export type DependencyDTO = DependencyDto

Expand Down Expand Up @@ -57,7 +64,7 @@ export class JsCompilation {
getAssets(): Readonly<JsAsset>[]
getAsset(name: string): JsAsset | null
getAssetSource(name: string): JsCompatSource | null
getModules(): Array<JsModule>
get modules(): Array<ModuleDTO>
getOptimizationBailout(): Array<JsStatsOptimizationBailout>
getChunks(): Array<JsChunk>
getNamedChunkKeys(): Array<string>
Expand Down Expand Up @@ -126,6 +133,22 @@ export class JsStats {
getLogging(acceptedTypes: number): Array<JsStatsLogging>
}

export class ModuleDto {
get context(): string | undefined
get originalSource(): JsCompatSource | undefined
get resource(): string | undefined
get moduleIdentifier(): string
get nameForCondition(): string | undefined
get request(): string | undefined
get userRequest(): string | undefined
get rawRequest(): string | undefined
get factoryMeta(): JsFactoryMeta | undefined
get type(): string
get layer(): string | undefined
get blocks(): Array<DependenciesBlockDto>
}
export type ModuleDTO = ModuleDto

export class Rspack {
constructor(options: RawOptions, builtinPlugins: Array<BuiltinPlugin>, registerJsTaps: RegisterJsTaps, outputFilesystem: ThreadsafeNodeFS, resolverFactoryReference: JsResolverFactory)
setNonSkippableRegisters(kinds: Array<RegisterJsTapKind>): void
Expand Down
33 changes: 26 additions & 7 deletions crates/rspack_binding_values/src/compilation/dependency.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use napi_derive::napi;
use rspack_core::{Compilation, DependencyId};
use rspack_core::{Compilation, Dependency, DependencyId, ModuleDependency, ModuleGraph};

#[napi]
pub struct DependencyDTO {
Expand All @@ -14,25 +14,44 @@ impl DependencyDTO {
compilation,
}
}

fn dependency<'a>(&self, module_graph: &'a ModuleGraph) -> &'a dyn Dependency {
module_graph
.dependency_by_id(&self.dependency_id)
.unwrap_or_else(|| panic!("Failed to get dependency by id = {:?}", &self.dependency_id))
.as_ref()
}

fn module_dependency<'a>(
&self,
module_graph: &'a ModuleGraph,
) -> Option<&'a dyn ModuleDependency> {
self.dependency(module_graph).as_module_dependency()
}
}

#[napi]
impl DependencyDTO {
#[napi(getter)]
pub fn get_type(&self) -> &str {
let module_graph = self.compilation.get_module_graph();
let dep = module_graph
.dependency_by_id(&self.dependency_id)
.unwrap_or_else(|| panic!("Failed to get dependency by id = {:?}", &self.dependency_id));
let dep = self.dependency(&module_graph);
dep.dependency_type().as_str()
}

#[napi(getter)]
pub fn category(&self) -> &str {
let module_graph = self.compilation.get_module_graph();
let dep = module_graph
.dependency_by_id(&self.dependency_id)
.unwrap_or_else(|| panic!("Failed to get dependency by id = {:?}", &self.dependency_id));
let dep = self.dependency(&module_graph);
dep.category().as_str()
}

#[napi(getter)]
pub fn request(&self) -> napi::Either<String, ()> {
let module_graph = self.compilation.get_module_graph();
match self.module_dependency(&module_graph) {
Some(dep) => napi::Either::A(dep.request().to_string()),
None => napi::Either::B(()),
}
}
}
14 changes: 8 additions & 6 deletions crates/rspack_binding_values/src/compilation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::ops::Deref;
use std::ops::DerefMut;
use std::path::PathBuf;

pub use dependency::*;
use entries::JsEntries;
use napi_derive::napi;
use rspack_collections::IdentifierSet;
Expand All @@ -25,8 +26,8 @@ use crate::utils::callbackify;
use crate::JsStatsOptimizationBailout;
use crate::LocalJsFilename;
use crate::{
chunk::JsChunk, module::JsModule, CompatSource, JsAsset, JsAssetInfo, JsChunkGroup,
JsCompatSource, JsPathData, JsStats, ToJsCompatSource,
chunk::JsChunk, CompatSource, JsAsset, JsAssetInfo, JsChunkGroup, JsCompatSource, JsPathData,
JsStats, ModuleDTO, ToJsCompatSource,
};
use crate::{JsDiagnostic, JsRspackError};

Expand Down Expand Up @@ -148,14 +149,15 @@ impl JsCompilation {
.transpose()
}

#[napi]
pub fn get_modules(&self) -> Vec<JsModule> {
#[napi(getter)]
pub fn modules(&'static self) -> Vec<ModuleDTO> {
self
.0
.get_module_graph()
.modules()
.values()
.filter_map(|module| module.to_js_module().ok())
.keys()
.cloned()
.map(|module_id| ModuleDTO::new(module_id, self.0))
.collect::<Vec<_>>()
}

Expand Down
204 changes: 202 additions & 2 deletions crates/rspack_binding_values/src/module.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,216 @@
use napi_derive::napi;
use rspack_core::{CompilerModuleContext, Module};
use rspack_core::{
AsyncDependenciesBlock, AsyncDependenciesBlockIdentifier, Compilation, CompilerModuleContext,
DependenciesBlock, Module, ModuleGraph, ModuleIdentifier,
};
use rspack_napi::napi::bindgen_prelude::*;

use super::{JsCompatSource, ToJsCompatSource};
use crate::{JsChunk, JsCodegenerationResults};
use crate::{DependencyDTO, JsChunk, JsCodegenerationResults};

#[derive(Default)]
#[napi(object)]
pub struct JsFactoryMeta {
pub side_effect_free: Option<bool>,
}

#[napi]
pub struct DependenciesBlockDTO {
block_id: AsyncDependenciesBlockIdentifier,
compilation: &'static Compilation,
}

impl DependenciesBlockDTO {
pub fn new(
block_id: AsyncDependenciesBlockIdentifier,
compilation: &'static Compilation,
) -> Self {
Self {
block_id,
compilation,
}
}

fn block<'a>(&self, module_graph: &'a ModuleGraph) -> &'a AsyncDependenciesBlock {
module_graph.block_by_id(&self.block_id).unwrap_or_else(|| {
panic!(
"Cannot find block with id = {:?}. It might have been removed on the Rust side.",
self.block_id
)
})
}
}

#[napi]
impl DependenciesBlockDTO {
#[napi(getter)]
pub fn dependencies(&self) -> Vec<DependencyDTO> {
let module_graph = self.compilation.get_module_graph();
let block = self.block(&module_graph);
block
.get_dependencies()
.iter()
.cloned()
.map(|dep_id| DependencyDTO::new(dep_id, self.compilation))
.collect::<Vec<_>>()
}

#[napi(getter)]
pub fn blocks(&self) -> Vec<DependenciesBlockDTO> {
let module_graph = self.compilation.get_module_graph();
let block = self.block(&module_graph);
let blocks = block.get_blocks();
blocks
.iter()
.cloned()
.map(|block_id| DependenciesBlockDTO::new(block_id, self.compilation))
.collect::<Vec<_>>()
}
}

#[napi]
pub struct ModuleDTO {
pub(crate) module_id: ModuleIdentifier,
pub(crate) compilation: &'static Compilation,
}

impl ModuleDTO {
pub fn new(module_id: ModuleIdentifier, compilation: &'static Compilation) -> Self {
Self {
module_id,
compilation,
}
}

fn module(&self) -> &dyn Module {
self
.compilation
.module_by_identifier(&self.module_id)
.unwrap_or_else(|| {
panic!(
"Cannot find module with id = {}. It might have been removed on the Rust side.",
self.module_id
)
})
.as_ref()
}
}

#[napi]
impl ModuleDTO {
#[napi(getter)]
pub fn context(&self) -> Either<String, ()> {
let module = self.module();
match module.get_context() {
Some(ctx) => Either::A(ctx.to_string()),
None => Either::B(()),
}
}

#[napi(getter)]
pub fn original_source(&self) -> Either<JsCompatSource, ()> {
let module = self.module();
match module.original_source() {
Some(source) => match source.to_js_compat_source().ok() {
Some(s) => Either::A(s),
None => Either::B(()),
},
None => Either::B(()),
}
}

#[napi(getter)]
pub fn resource(&self) -> Either<String, ()> {
let module = self.module();
match module.try_as_normal_module() {
Ok(normal_module) => Either::A(normal_module.resource_resolved_data().resource.to_string()),
Err(_) => Either::B(()),
}
}

#[napi(getter)]
pub fn module_identifier(&self) -> &str {
let module = self.module();
module.identifier().as_str()
}

#[napi(getter)]
pub fn name_for_condition(&self) -> Either<String, ()> {
let module = self.module();
match module.name_for_condition() {
Some(s) => Either::A(s.to_string()),
None => Either::B(()),
}
}

#[napi(getter)]
pub fn request(&self) -> Either<&str, ()> {
let module = self.module();
match module.try_as_normal_module() {
Ok(normal_module) => Either::A(normal_module.request()),
Err(_) => Either::B(()),
}
}

#[napi(getter)]
pub fn user_request(&self) -> Either<&str, ()> {
let module = self.module();
match module.try_as_normal_module() {
Ok(normal_module) => Either::A(normal_module.user_request()),
Err(_) => Either::B(()),
}
}

#[napi(getter)]
pub fn raw_request(&self) -> Either<&str, ()> {
let module = self.module();
match module.try_as_normal_module() {
Ok(normal_module) => Either::A(normal_module.raw_request()),
Err(_) => Either::B(()),
}
}

#[napi(getter)]
pub fn factory_meta(&self) -> Either<JsFactoryMeta, ()> {
let module = self.module();
match module.try_as_normal_module() {
Ok(normal_module) => match normal_module.factory_meta() {
Some(meta) => Either::A(JsFactoryMeta {
side_effect_free: meta.side_effect_free,
}),
None => Either::B(()),
},
Err(_) => Either::B(()),
}
}

#[napi(getter)]
pub fn get_type(&self) -> &str {
let module = self.module();
module.module_type().as_str()
}

#[napi(getter)]
pub fn layer(&self) -> Either<&String, ()> {
let module = self.module();
match module.get_layer() {
Some(layer) => Either::A(layer),
None => Either::B(()),
}
}

#[napi(getter)]
pub fn blocks(&self) -> Vec<DependenciesBlockDTO> {
let module = self.module();
let blocks = module.get_blocks();
blocks
.iter()
.cloned()
.map(|block_id| DependenciesBlockDTO::new(block_id, self.compilation))
.collect::<Vec<_>>()
}
}

#[derive(Default)]
#[napi(object)]
pub struct JsModule {
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import("./a");
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const rspack = require("@rspack/core");

const PLUGIN_NAME = "plugin";

class Plugin {
/**
* @param {import("@rspack/core").Compiler} compiler
*/
apply(compiler) {
compiler.hooks.make.tap(PLUGIN_NAME, (compilation) => {
compilation.hooks.processAssets.tap(
{
name: PLUGIN_NAME,
stage: rspack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS,
},
() => {
const module = Array.from(compilation.modules).find(module => module.rawRequest === "./index.js");
const block = module.blocks[0];
expect(block.dependencies[0].request).toBe("./a");
}
)
});
}
}

/**@type {import("@rspack/core").Configuration}*/
module.exports = {
entry: "./index.js",
plugins: [new Plugin()]
};
Loading

2 comments on commit ccd6ee8

@rspack-bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Ran ecosystem CI: Open

suite result
modernjs ❌ failure
_selftest ✅ success
nx ❌ failure
rspress ✅ success
rsbuild ❌ failure
examples ✅ success

@rspack-bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Benchmark detail: Open

Name Base (2024-08-06 b30f0a8) Current Change
10000_development-mode + exec 2.33 s ± 47 ms 2.33 s ± 37 ms -0.03 %
10000_development-mode_hmr + exec 711 ms ± 8 ms 712 ms ± 8.8 ms +0.12 %
10000_production-mode + exec 2.89 s ± 41 ms 2.86 s ± 39 ms -1.04 %
arco-pro_development-mode + exec 1.87 s ± 68 ms 1.9 s ± 83 ms +1.78 %
arco-pro_development-mode_hmr + exec 435 ms ± 1.7 ms 434 ms ± 2.4 ms -0.16 %
arco-pro_production-mode + exec 3.41 s ± 68 ms 3.5 s ± 219 ms +2.71 %
threejs_development-mode_10x + exec 1.71 s ± 16 ms 1.71 s ± 11 ms -0.15 %
threejs_development-mode_10x_hmr + exec 828 ms ± 7.8 ms 823 ms ± 7.3 ms -0.55 %
threejs_production-mode_10x + exec 5.51 s ± 48 ms 5.51 s ± 20 ms -0.05 %
arco-pro_production-mode_generate-package-json-webpack-plugin + exec 3.53 s ± 98 ms 3.52 s ± 93 ms -0.36 %

Please sign in to comment.