-
-
Notifications
You must be signed in to change notification settings - Fork 595
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: support module graph connection js api (#8812)
- Loading branch information
Showing
36 changed files
with
389 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
125 changes: 125 additions & 0 deletions
125
crates/rspack_binding_values/src/module_graph_connection.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
use std::{cell::RefCell, ptr::NonNull}; | ||
|
||
use napi::bindgen_prelude::ToNapiValue; | ||
use napi_derive::napi; | ||
use rspack_core::{Compilation, CompilationId, DependencyId, ModuleGraph}; | ||
use rspack_napi::OneShotRef; | ||
use rustc_hash::FxHashMap as HashMap; | ||
|
||
use crate::{JsDependencyWrapper, JsModuleWrapper}; | ||
|
||
#[napi] | ||
pub struct JsModuleGraphConnection { | ||
compilation: NonNull<Compilation>, | ||
dependency_id: DependencyId, | ||
} | ||
|
||
impl JsModuleGraphConnection { | ||
fn as_ref(&self) -> napi::Result<(&'static Compilation, ModuleGraph<'static>)> { | ||
let compilation = unsafe { self.compilation.as_ref() }; | ||
let module_graph = compilation.get_module_graph(); | ||
|
||
Ok((compilation, module_graph)) | ||
} | ||
} | ||
|
||
#[napi] | ||
impl JsModuleGraphConnection { | ||
#[napi(getter, ts_return_type = "JsDependency")] | ||
pub fn dependency(&self) -> napi::Result<JsDependencyWrapper> { | ||
let (compilation, module_graph) = self.as_ref()?; | ||
if let Some(dependency) = module_graph.dependency_by_id(&self.dependency_id) { | ||
Ok(JsDependencyWrapper::new( | ||
dependency.as_ref(), | ||
compilation.id(), | ||
Some(compilation), | ||
)) | ||
} else { | ||
Err(napi::Error::from_reason(format!( | ||
"Unable to access Dependency with id = {:#?} now. The Dependency have been removed on the Rust side.", | ||
self.dependency_id | ||
))) | ||
} | ||
} | ||
|
||
#[napi(getter, ts_return_type = "JsModule | null")] | ||
pub fn module(&self) -> napi::Result<Option<JsModuleWrapper>> { | ||
let (compilation, module_graph) = self.as_ref()?; | ||
if let Some(connection) = module_graph.connection_by_dependency_id(&self.dependency_id) { | ||
let module = module_graph.module_by_identifier(connection.module_identifier()); | ||
Ok(module.map(|m| JsModuleWrapper::new(m.as_ref(), compilation.id(), Some(compilation)))) | ||
} else { | ||
Err(napi::Error::from_reason(format!( | ||
"Unable to access ModuleGraphConnection with id = {:#?} now. The ModuleGraphConnection have been removed on the Rust side.", | ||
self.dependency_id | ||
))) | ||
} | ||
} | ||
} | ||
|
||
type ModuleGraphConnectionRefs = HashMap<DependencyId, OneShotRef<JsModuleGraphConnection>>; | ||
|
||
type ModuleGraphConnectionRefsByCompilationId = | ||
RefCell<HashMap<CompilationId, ModuleGraphConnectionRefs>>; | ||
|
||
thread_local! { | ||
static MODULE_GRAPH_CONNECTION_INSTANCE_REFS: ModuleGraphConnectionRefsByCompilationId = Default::default(); | ||
} | ||
|
||
pub struct JsModuleGraphConnectionWrapper { | ||
compilation_id: CompilationId, | ||
compilation: NonNull<Compilation>, | ||
dependency_id: DependencyId, | ||
} | ||
|
||
impl JsModuleGraphConnectionWrapper { | ||
pub fn new(dependency_id: DependencyId, compilation: &Compilation) -> Self { | ||
#[allow(clippy::unwrap_used)] | ||
Self { | ||
dependency_id, | ||
compilation_id: compilation.id(), | ||
compilation: NonNull::new(compilation as *const Compilation as *mut Compilation).unwrap(), | ||
} | ||
} | ||
|
||
pub fn cleanup_last_compilation(compilation_id: CompilationId) { | ||
MODULE_GRAPH_CONNECTION_INSTANCE_REFS.with(|refs| { | ||
let mut refs_by_compilation_id = refs.borrow_mut(); | ||
refs_by_compilation_id.remove(&compilation_id) | ||
}); | ||
} | ||
} | ||
|
||
impl ToNapiValue for JsModuleGraphConnectionWrapper { | ||
unsafe fn to_napi_value( | ||
env: napi::sys::napi_env, | ||
val: Self, | ||
) -> napi::Result<napi::sys::napi_value> { | ||
MODULE_GRAPH_CONNECTION_INSTANCE_REFS.with(|refs| { | ||
let mut refs_by_compilation_id = refs.borrow_mut(); | ||
let entry = refs_by_compilation_id.entry(val.compilation_id); | ||
let refs = match entry { | ||
std::collections::hash_map::Entry::Occupied(entry) => entry.into_mut(), | ||
std::collections::hash_map::Entry::Vacant(entry) => { | ||
let refs = HashMap::default(); | ||
entry.insert(refs) | ||
} | ||
}; | ||
|
||
match refs.entry(val.dependency_id) { | ||
std::collections::hash_map::Entry::Occupied(occupied_entry) => { | ||
let r = occupied_entry.get(); | ||
ToNapiValue::to_napi_value(env, r) | ||
} | ||
std::collections::hash_map::Entry::Vacant(vacant_entry) => { | ||
let js_dependency = JsModuleGraphConnection { | ||
compilation: val.compilation, | ||
dependency_id: val.dependency_id, | ||
}; | ||
let r = vacant_entry.insert(OneShotRef::new(env, js_dependency)?); | ||
ToNapiValue::to_napi_value(env, r) | ||
} | ||
} | ||
}) | ||
} | ||
} |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Empty file.
1 change: 1 addition & 0 deletions
1
packages/rspack-test-tools/tests/configCases/module-graph/get-outgoing-connections/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
import "./foo"; |
33 changes: 33 additions & 0 deletions
33
...spack-test-tools/tests/configCases/module-graph/get-outgoing-connections/rspack.config.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
const { normalize, join } = require('path'); | ||
|
||
const PLUGIN_NAME = "Test"; | ||
|
||
class Plugin { | ||
/** | ||
* @param {import("@rspack/core").Compiler} compiler | ||
*/ | ||
apply(compiler) { | ||
compiler.hooks.compilation.tap(PLUGIN_NAME, compilation => { | ||
compilation.hooks.finishModules.tap(PLUGIN_NAME, () => { | ||
const entry = Array.from(compilation.entries.values())[0]; | ||
const entryDependency = entry.dependencies[0]; | ||
const connection = compilation.moduleGraph.getConnection(entryDependency); | ||
const outgoingConnection = compilation.moduleGraph.getOutgoingConnections(connection.module)[0]; | ||
expect(normalize(outgoingConnection.module.request)).toBe(normalize(join(__dirname, 'foo.js'))); | ||
}); | ||
}); | ||
|
||
} | ||
} | ||
|
||
/** @type {import("@rspack/core").Configuration} */ | ||
module.exports = { | ||
target: "web", | ||
node: { | ||
__dirname: false, | ||
__filename: false, | ||
}, | ||
plugins: [ | ||
new Plugin() | ||
] | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.