Skip to content

Commit

Permalink
V3: Using JsBuffer to transfer AssetGraph to Nodejs (#313)
Browse files Browse the repository at this point in the history
  • Loading branch information
alshdavid authored Jan 23, 2025
1 parent f3ea398 commit 4cc2520
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 185 deletions.
2 changes: 0 additions & 2 deletions crates/atlaspack_core/src/asset_graph/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#[allow(clippy::module_inception)]
mod asset_graph;
mod propagate_requested_symbols;
mod serialize_asset_graph;

pub use self::asset_graph::*;
pub use self::propagate_requested_symbols::*;
pub use self::serialize_asset_graph::*;
172 changes: 0 additions & 172 deletions crates/atlaspack_core/src/asset_graph/serialize_asset_graph.rs

This file was deleted.

12 changes: 2 additions & 10 deletions crates/node-bindings/src/atlaspack/atlaspack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ use atlaspack::rpc::nodejs::NodejsRpcFactory;
use atlaspack::rpc::nodejs::NodejsWorker;
use atlaspack::rpc::RpcFactoryRef;
use atlaspack::Atlaspack;
use atlaspack_core::asset_graph::serialize_asset_graph;
use atlaspack_core::types::AtlaspackOptions;
use atlaspack_napi_helpers::JsTransferable;
use atlaspack_package_manager::PackageManagerRef;

use super::file_system_napi::FileSystemNapi;
use super::napi_result::NapiAtlaspackResult;
use super::package_manager_napi::PackageManagerNapi;
use super::serialize_asset_graph::serialize_asset_graph;

#[napi(object)]
pub struct AtlaspackNapiBuildOptions {
Expand Down Expand Up @@ -148,15 +148,7 @@ impl AtlaspackNapi {
// not supplied as JavaScript Error types. The JavaScript layer needs to handle conversions
deferred.resolve(move |env| match result {
Ok(asset_graph) => {
let mut js_object = env.create_object()?;

js_object.set_named_property("edges", env.to_js_value(&asset_graph.edges())?)?;
js_object.set_named_property(
"nodes",
serialize_asset_graph(&asset_graph, MAX_STRING_LENGTH)?,
)?;

NapiAtlaspackResult::ok(&env, js_object)
NapiAtlaspackResult::ok(&env, serialize_asset_graph(&env, &asset_graph)?)
}
Err(error) => {
let js_object = env.to_js_value(&AtlaspackError::from(&error))?;
Expand Down
1 change: 1 addition & 0 deletions crates/node-bindings/src/atlaspack/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ pub mod file_system_napi;
pub mod monitoring;
pub mod napi_result;
pub mod package_manager_napi;
pub mod serialize_asset_graph;
pub mod worker;
77 changes: 77 additions & 0 deletions crates/node-bindings/src/atlaspack/serialize_asset_graph.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use napi::{Env, JsObject};
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use serde::Serialize;

use atlaspack_core::asset_graph::{AssetGraph, AssetGraphNode, DependencyState};
use atlaspack_core::types::{Asset, Dependency};

/// Returns
/// ```typescript
/// type SerializedAssetGraph = {
/// edges: Array<number>,
/// nodes: Array<JsBuffer>,
/// }
/// ```
pub fn serialize_asset_graph(env: &Env, asset_graph: &AssetGraph) -> anyhow::Result<JsObject> {
// Serialize graph nodes in parallel
let nodes = asset_graph
.nodes()
.collect::<Vec<_>>()
.par_iter()
.map(|item| {
serde_json::to_vec(&match item {
AssetGraphNode::Root => SerializedAssetGraphNode::Root,
AssetGraphNode::Entry => SerializedAssetGraphNode::Entry,
AssetGraphNode::Asset(asset_node) => SerializedAssetGraphNode::Asset {
value: asset_node.asset.clone(),
},
AssetGraphNode::Dependency(dependency_node) => SerializedAssetGraphNode::Dependency {
value: SerializedDependency {
id: dependency_node.dependency.id(),
dependency: dependency_node.dependency.as_ref().clone(),
},
has_deferred: dependency_node.state == DependencyState::Deferred,
},
})
})
.collect::<Vec<_>>();

// Collect the results into a JavaScript Array
// TODO NAPI3 allows removing this
let mut js_nodes = env.create_array_with_length(nodes.len())?;

for (i, node_bytes) in nodes.into_iter().enumerate() {
let js_buffer = env.create_buffer_with_data(node_bytes?)?;
let js_buffer = js_buffer.into_unknown();

js_nodes.set_element(i as u32, js_buffer)?;
}

// TODO use a napi_derive::napi(object) with NAPI3
let mut napi_asset_graph = env.create_object()?;
napi_asset_graph.set_named_property("edges", asset_graph.edges())?;
napi_asset_graph.set_named_property("nodes", js_nodes)?;

Ok(napi_asset_graph)
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SerializedDependency {
id: String,
dependency: Dependency,
}

#[derive(Debug, Serialize)]
#[serde(tag = "type", rename_all = "camelCase")]
enum SerializedAssetGraphNode {
Root,
Entry,
Asset {
value: Asset,
},
Dependency {
value: SerializedDependency,
has_deferred: bool,
},
}
2 changes: 1 addition & 1 deletion packages/core/core/src/requests/AssetGraphRequestRust.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function createAssetGraphRequestRust(
let options = input.options;
let serializedAssetGraph = await rustAtlaspack.buildAssetGraph();

serializedAssetGraph.nodes = serializedAssetGraph.nodes.flatMap((node) =>
serializedAssetGraph.nodes = serializedAssetGraph.nodes.map((node) =>
JSON.parse(node),
);

Expand Down

0 comments on commit 4cc2520

Please sign in to comment.