Skip to content

Commit 25000a7

Browse files
authored
perf: napi communication (#11132)
1 parent ea8059e commit 25000a7

21 files changed

Lines changed: 574 additions & 419 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/node_binding/napi-binding.d.ts

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -615,17 +615,6 @@ export interface JsAfterEmitData {
615615
uid?: number
616616
}
617617

618-
export interface JsAfterResolveData {
619-
request: string
620-
context: string
621-
issuer: string
622-
issuerLayer?: string
623-
fileDependencies: Array<string>
624-
contextDependencies: Array<string>
625-
missingDependencies: Array<string>
626-
createData?: JsCreateData
627-
}
628-
629618
export interface JsAfterTemplateExecutionData {
630619
html: string
631620
headTags: Array<JsHtmlPluginTag>
@@ -2734,7 +2723,7 @@ export interface RegisterJsTaps {
27342723
registerNormalModuleFactoryFactorizeTaps: (stages: Array<number>) => Array<{ function: ((arg: JsFactorizeArgs) => Promise<JsFactorizeArgs>); stage: number; }>
27352724
registerNormalModuleFactoryResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: JsResolveArgs) => Promise<JsResolveArgs>); stage: number; }>
27362725
registerNormalModuleFactoryResolveForSchemeTaps: (stages: Array<number>) => Array<{ function: ((arg: JsResolveForSchemeArgs) => Promise<[boolean | undefined, JsResolveForSchemeArgs]>); stage: number; }>
2737-
registerNormalModuleFactoryAfterResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: JsAfterResolveData) => Promise<[boolean | undefined, JsCreateData | undefined]>); stage: number; }>
2726+
registerNormalModuleFactoryAfterResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: string) => Promise<[boolean | undefined, JsCreateData | undefined]>); stage: number; }>
27382727
registerNormalModuleFactoryCreateModuleTaps: (stages: Array<number>) => Array<{ function: ((arg: JsNormalModuleFactoryCreateModuleArgs) => Promise<void>); stage: number; }>
27392728
registerContextModuleFactoryBeforeResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: false | JsContextModuleFactoryBeforeResolveData) => Promise<false | JsContextModuleFactoryBeforeResolveData>); stage: number; }>
27402729
registerContextModuleFactoryAfterResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: false | JsContextModuleFactoryAfterResolveData) => Promise<false | JsContextModuleFactoryAfterResolveData>); stage: number; }>

crates/rspack_binding_api/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ futures = { workspace = true }
5757
glob = { workspace = true }
5858
heck = { workspace = true }
5959
once_cell = { workspace = true }
60+
rayon = { workspace = true }
6061
rspack_cacheable = { workspace = true }
6162
rspack_ids = { workspace = true }
6263
rspack_javascript_compiler = { workspace = true }

crates/rspack_binding_api/src/build_info.rs

Lines changed: 56 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::sync::LazyLock;
1+
use std::{cell::RefCell, sync::LazyLock};
22

33
use napi::{
44
bindgen_prelude::{
@@ -150,9 +150,7 @@ impl BuildInfo {
150150
}
151151
}
152152

153-
fn create_known_private_properties(env: &Env) -> napi::Result<Vec<Property>> {
154-
let mut properties = vec![];
155-
153+
fn create_known_private_properties(env: &Env, properties: &mut Vec<Property>) -> napi::Result<()> {
156154
BUILD_INFO_ASSETS_SYMBOL.with(|once_cell| {
157155
#[allow(clippy::unwrap_used)]
158156
let symbol = once_cell.get().unwrap();
@@ -264,7 +262,11 @@ fn create_known_private_properties(env: &Env) -> napi::Result<Vec<Property>> {
264262
Ok::<(), napi::Error>(())
265263
})?;
266264

267-
Ok(properties)
265+
Ok(())
266+
}
267+
268+
thread_local! {
269+
static BUILD_INFO_PROPERTIES_BUFFER: RefCell<Vec<Property>> = const { RefCell::new(Vec::new()) };
268270
}
269271

270272
impl ToNapiValue for BuildInfo {
@@ -278,59 +280,64 @@ impl ToNapiValue for BuildInfo {
278280
let napi_val = ToNapiValue::to_napi_value(env, known)?;
279281
let mut object = Object::from_raw(env, napi_val);
280282

281-
let mut properties = create_known_private_properties(&env_wrapper)?;
282-
283-
let commit_custom_fields_fn: napi::bindgen_prelude::Function<'_, (), ()> = env_wrapper
284-
.create_function_from_closure("commitCustomFieldsToRust", |ctx| {
285-
let object = ctx.this::<Object>()?;
286-
let env = ctx.env;
287-
let this: &mut KnownBuildInfo = FromNapiMutRef::from_napi_mut_ref(env.raw(), object.raw())?;
288-
289-
this.with_mut(|module| {
290-
let mut extras = serde_json::Map::new();
291-
let names = Array::from_unknown(object.get_property_names()?.to_unknown())?;
292-
for index in 0..names.len() {
293-
if let Some(name) = names.get::<String>(index)? {
294-
if !KNOWN_BUILD_INFO_FIELD_NAMES.contains(name.as_str()) {
295-
let value = object.get_named_property::<Unknown>(&name)?;
296-
if let Some(json_value) = unknown_to_json_value(value)? {
297-
extras.insert(name, json_value);
283+
BUILD_INFO_PROPERTIES_BUFFER.with(|ref_cell| {
284+
let mut properties = ref_cell.borrow_mut();
285+
properties.clear();
286+
create_known_private_properties(&env_wrapper, &mut properties)?;
287+
288+
let commit_custom_fields_fn: napi::bindgen_prelude::Function<'_, (), ()> = env_wrapper
289+
.create_function_from_closure("commitCustomFieldsToRust", |ctx| {
290+
let object = ctx.this::<Object>()?;
291+
let env = ctx.env;
292+
let this: &mut KnownBuildInfo =
293+
FromNapiMutRef::from_napi_mut_ref(env.raw(), object.raw())?;
294+
295+
this.with_mut(|module| {
296+
let mut extras = serde_json::Map::new();
297+
let names = Array::from_unknown(object.get_property_names()?.to_unknown())?;
298+
for index in 0..names.len() {
299+
if let Some(name) = names.get::<String>(index)? {
300+
if !KNOWN_BUILD_INFO_FIELD_NAMES.contains(name.as_str()) {
301+
let value = object.get_named_property::<Unknown>(&name)?;
302+
if let Some(json_value) = unknown_to_json_value(value)? {
303+
extras.insert(name, json_value);
304+
}
298305
}
299306
}
300307
}
301-
}
302308

303-
module.build_info_mut().extras = extras;
304-
305-
Ok(())
306-
})
309+
module.build_info_mut().extras = extras;
310+
311+
Ok(())
312+
})
313+
})?;
314+
315+
val.with_ref(|module| {
316+
let extras = &module.build_info().extras;
317+
properties.reserve(extras.len() + 1);
318+
for (key, value) in extras {
319+
let napi_val = ToNapiValue::to_napi_value(env, value)?;
320+
properties.push(
321+
Property::new()
322+
.with_utf8_name(key)?
323+
.with_value(&Object::from_raw(env, napi_val)),
324+
);
325+
}
326+
Ok(())
307327
})?;
308-
309-
val.with_ref(|module| {
310-
let extras = &module.build_info().extras;
311-
properties.reserve(extras.len() + 1);
312-
for (key, value) in extras {
313-
let napi_val = ToNapiValue::to_napi_value(env, value)?;
328+
COMMIT_CUSTOM_FIELDS_SYMBOL.with(|once_cell| {
329+
#[allow(clippy::unwrap_used)]
330+
let symbol = once_cell.get().unwrap();
314331
properties.push(
315332
Property::new()
316-
.with_utf8_name(key)?
317-
.with_value(&Object::from_raw(env, napi_val)),
333+
.with_name(&env_wrapper, symbol)?
334+
.with_value(&commit_custom_fields_fn)
335+
.with_property_attributes(PropertyAttributes::Configurable),
318336
);
319-
}
320-
Ok(())
321-
})?;
322-
COMMIT_CUSTOM_FIELDS_SYMBOL.with(|once_cell| {
323-
#[allow(clippy::unwrap_used)]
324-
let symbol = once_cell.get().unwrap();
325-
properties.push(
326-
Property::new()
327-
.with_name(&env_wrapper, symbol)?
328-
.with_value(&commit_custom_fields_fn)
329-
.with_property_attributes(PropertyAttributes::Configurable),
330-
);
331-
Ok::<(), napi::Error>(())
337+
Ok::<(), napi::Error>(())
338+
})?;
339+
object.define_properties(&properties)
332340
})?;
333-
object.define_properties(&properties)?;
334341

335342
Ok(napi_val)
336343
}

crates/rspack_binding_api/src/compilation/mod.rs

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -163,21 +163,20 @@ impl JsCompilation {
163163
}
164164

165165
#[napi(getter, ts_return_type = "Array<Module>")]
166-
pub fn modules(&self) -> Result<Vec<ModuleObject>> {
166+
pub fn modules<'a>(&self, env: &'a Env) -> Result<Array<'a>> {
167167
let compilation = self.as_ref()?;
168-
169-
Ok(
170-
compilation
171-
.get_module_graph()
172-
.modules()
173-
.keys()
174-
.filter_map(|module_id| {
175-
compilation
176-
.module_by_identifier(module_id)
177-
.map(|module| ModuleObject::with_ref(module.as_ref(), compilation.compiler_id()))
178-
})
179-
.collect::<Vec<_>>(),
180-
)
168+
let module_graph = compilation.get_module_graph();
169+
let modules = module_graph.modules();
170+
let mut arr = env.create_array(modules.len() as u32)?;
171+
for (i, identifier) in modules.keys().enumerate() {
172+
arr.set(
173+
i as u32,
174+
compilation
175+
.module_by_identifier(identifier)
176+
.map(|module| ModuleObject::with_ref(module.as_ref(), compilation.compiler_id())),
177+
)?;
178+
}
179+
Ok(arr)
181180
}
182181

183182
#[napi(getter, ts_return_type = "Array<Module>")]

crates/rspack_binding_api/src/dependency.rs

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use std::{cell::RefCell, ptr::NonNull};
22

3-
use napi::{bindgen_prelude::ToNapiValue, Either, Env, JsString};
3+
use napi::{
4+
bindgen_prelude::{Array, ToNapiValue},
5+
Either, Env,
6+
};
47
use napi_derive::napi;
58
use rspack_core::{Compilation, CompilationId, DependencyId};
69
use rspack_napi::OneShotInstanceRef;
@@ -123,36 +126,36 @@ impl Dependency {
123126
Ok(())
124127
}
125128

126-
#[napi(getter)]
127-
pub fn ids<'a>(&mut self, env: &'a Env) -> napi::Result<Either<Vec<JsString<'a>>, ()>> {
129+
#[napi(getter, ts_return_type = "Array<string> | undefined")]
130+
pub fn ids<'a>(&mut self, env: &'a Env) -> napi::Result<Either<Array<'a>, ()>> {
128131
let (dependency, compilation) = self.as_ref()?;
129132

130133
Ok(match compilation {
131134
Some(compilation) => {
132135
let module_graph = compilation.get_module_graph();
133136
if let Some(dependency) = dependency.downcast_ref::<CommonJsExportRequireDependency>() {
134-
let ids = dependency
135-
.get_ids(&module_graph)
136-
.iter()
137-
.map(|atom| env.create_string(atom.as_str()))
138-
.collect::<napi::Result<Vec<_>>>()?;
139-
Either::A(ids)
137+
let ids = dependency.get_ids(&module_graph);
138+
let mut arr = env.create_array(ids.len() as u32)?;
139+
for (i, v) in ids.iter().enumerate() {
140+
arr.set(i as u32, v.as_str())?;
141+
}
142+
Either::A(arr)
140143
} else if let Some(dependency) =
141144
dependency.downcast_ref::<ESMExportImportedSpecifierDependency>()
142145
{
143-
let ids = dependency
144-
.get_ids(&module_graph)
145-
.iter()
146-
.map(|atom| env.create_string(atom.as_str()))
147-
.collect::<napi::Result<Vec<_>>>()?;
148-
Either::A(ids)
146+
let ids = dependency.get_ids(&module_graph);
147+
let mut arr = env.create_array(ids.len() as u32)?;
148+
for (i, v) in ids.iter().enumerate() {
149+
arr.set(i as u32, v.as_str())?;
150+
}
151+
Either::A(arr)
149152
} else if let Some(dependency) = dependency.downcast_ref::<ESMImportSpecifierDependency>() {
150-
let ids = dependency
151-
.get_ids(&module_graph)
152-
.iter()
153-
.map(|atom| env.create_string(atom.as_str()))
154-
.collect::<napi::Result<Vec<_>>>()?;
155-
Either::A(ids)
153+
let ids = dependency.get_ids(&module_graph);
154+
let mut arr = env.create_array(ids.len() as u32)?;
155+
for (i, v) in ids.iter().enumerate() {
156+
arr.set(i as u32, v.as_str())?;
157+
}
158+
Either::A(arr)
156159
} else {
157160
Either::B(())
158161
}

0 commit comments

Comments
 (0)