1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-21 04:52:26 -05:00
This commit is contained in:
Marvin Hagemeister 2024-11-27 09:07:39 +01:00
parent 0871741e98
commit ae831b111f
5 changed files with 454 additions and 363 deletions

View file

@ -1,6 +1,6 @@
use std::collections::HashMap; use std::collections::HashMap;
use deno_ast::MediaType; use deno_ast::{MediaType, ParsedSource};
use deno_core::url::Url; use deno_core::url::Url;
use deno_graph::{ExternalModule, JsonModule, WasmModule}; use deno_graph::{ExternalModule, JsonModule, WasmModule};
@ -16,11 +16,12 @@ pub struct BundleJsModule {
pub specifier: Url, pub specifier: Url,
pub media_type: MediaType, pub media_type: MediaType,
pub source: String, pub source: String,
pub ast: Option<ParsedSource>,
pub dependencies: Vec<BundleDep>, pub dependencies: Vec<BundleDep>,
} }
#[derive(Debug)] #[derive(Debug)]
pub enum BundleMod { pub enum BundleModule {
Js(BundleJsModule), Js(BundleJsModule),
Json(JsonModule), Json(JsonModule),
Wasm(WasmModule), Wasm(WasmModule),
@ -32,7 +33,7 @@ pub enum BundleMod {
pub struct BundleGraph { pub struct BundleGraph {
id: usize, id: usize,
url_to_id: HashMap<Url, usize>, url_to_id: HashMap<Url, usize>,
modules: HashMap<usize, BundleMod>, modules: HashMap<usize, BundleModule>,
} }
/// The bundle graph only contains fully resolved modules. /// The bundle graph only contains fully resolved modules.
@ -45,7 +46,29 @@ impl BundleGraph {
} }
} }
pub fn insert(&mut self, specifier: Url, module: BundleMod) -> usize { pub fn get_specifier(&self, id: usize) -> Option<Url> {
if let Some(module) = self.modules.get(&id) {
match module {
BundleModule::Js(m) => Some(m.specifier.clone()),
BundleModule::Json(m) => Some(m.specifier.clone()),
BundleModule::Wasm(m) => Some(m.specifier.clone()),
BundleModule::Node(_) => None, // FIXME
BundleModule::External(external_module) => todo!(),
}
} else {
None
}
}
pub fn get(&self, url: &Url) -> Option<&BundleModule> {
if let Some(id) = self.url_to_id.get(&url) {
return self.modules.get(&id);
}
None
}
pub fn insert(&mut self, specifier: Url, module: BundleModule) -> usize {
let id = self.register(specifier); let id = self.register(specifier);
self.modules.insert(id, module); self.modules.insert(id, module);
id id
@ -63,7 +86,7 @@ impl BundleGraph {
} }
pub fn add_dependency(&mut self, id: usize, dep: BundleDep) { pub fn add_dependency(&mut self, id: usize, dep: BundleDep) {
if let Some(BundleMod::Js(module)) = self.modules.get_mut(&id) { if let Some(BundleModule::Js(module)) = self.modules.get_mut(&id) {
module.dependencies.push(dep) module.dependencies.push(dep)
} }
} }

View file

@ -0,0 +1,173 @@
use std::{
collections::{HashMap, HashSet},
sync::Arc,
};
use deno_core::{anyhow::Context, error::AnyError, url::Url};
use deno_graph::{GraphKind, Module, ModuleGraph, NpmModule};
use deno_runtime::deno_node::NodeResolver;
use indexmap::IndexSet;
use node_resolver::{NodeModuleKind, NodeResolutionMode};
use crate::{
graph_util::{CreateGraphOptions, ModuleGraphCreator},
npm::CliNpmResolver,
tools::bundle::bundle_graph::BundleDep,
};
use super::bundle_graph::{BundleGraph, BundleJsModule, BundleModule};
pub async fn build_resolved_graph(
module_graph_creator: &Arc<ModuleGraphCreator>,
npm_resolver: &Arc<dyn CliNpmResolver>,
node_resolver: &Arc<NodeResolver>,
files: Vec<Url>,
) -> Result<BundleGraph, AnyError> {
let graph = module_graph_creator
.create_graph_with_options(CreateGraphOptions {
graph_kind: GraphKind::CodeOnly,
roots: files.clone(),
is_dynamic: false,
loader: None,
})
.await?;
graph.valid()?;
let mut bundle_graph = BundleGraph::new();
let mut npm_modules: IndexSet<Url> = IndexSet::new();
let mut seen: HashSet<Url> = HashSet::new();
let mut pending_npm_dep_links: HashMap<usize, Url> = HashMap::new();
walk_graph(
&graph,
&mut seen,
npm_resolver,
node_resolver,
&mut bundle_graph,
&mut npm_modules,
&mut pending_npm_dep_links,
);
// Resolve npm modules
// Hack: Create sub graphs for every npm module we encounter and
// expand npm specifiers to the actual file
while let Some(url) = npm_modules.pop() {
let npm_graph = module_graph_creator
.create_graph_with_options(CreateGraphOptions {
graph_kind: GraphKind::CodeOnly,
roots: vec![url.clone()],
is_dynamic: false,
loader: None,
})
.await?;
walk_graph(
&npm_graph,
&mut seen,
npm_resolver,
node_resolver,
&mut bundle_graph,
&mut npm_modules,
&mut pending_npm_dep_links,
);
}
Ok(bundle_graph)
}
fn walk_graph(
graph: &ModuleGraph,
seen: &mut HashSet<Url>,
npm_resolver: &Arc<dyn CliNpmResolver>,
node_resolver: &Arc<NodeResolver>,
bundle_graph: &mut BundleGraph,
npm_modules: &mut IndexSet<Url>,
pending_npm_dep_links: &mut HashMap<usize, Url>,
) {
for module in graph.modules() {
let url = module.specifier();
if seen.contains(&url) {
continue;
}
seen.insert(url.clone());
match module {
Module::Npm(module) => {
let resolved = resolve_npm_module(&module, npm_resolver, node_resolver);
npm_modules.insert(resolved.clone());
}
Module::Js(js_module) => {
let id = bundle_graph.insert(
url.clone(),
BundleModule::Js(BundleJsModule {
specifier: url.clone(),
media_type: js_module.media_type,
source: js_module.source.to_string(),
ast: None,
dependencies: vec![],
}),
);
for (raw, dep) in &js_module.dependencies {
if let Some(code) = dep.get_code() {
if code.scheme() == "npm" {
pending_npm_dep_links.insert(id, code.clone());
} else {
let dep_id = bundle_graph.register(code.clone());
bundle_graph.add_dependency(
id,
BundleDep {
id: dep_id,
raw: raw.to_string(),
is_dyanmic: dep.is_dynamic,
},
);
}
}
}
}
Module::Json(json_module) => {
bundle_graph
.insert(url.clone(), BundleModule::Json(json_module.clone()));
}
Module::Wasm(wasm_module) => {
bundle_graph
.insert(url.clone(), BundleModule::Wasm(wasm_module.clone()));
}
Module::Node(built_in_node_module) => {
bundle_graph.insert(
url.clone(),
BundleModule::Node(built_in_node_module.module_name.to_string()),
);
}
Module::External(external_module) => todo!(),
}
}
}
fn resolve_npm_module(
module: &NpmModule,
npm_resolver: &Arc<dyn CliNpmResolver>,
node_resolver: &Arc<NodeResolver>,
) -> Url {
let nv = module.nv_reference.nv();
let managed = npm_resolver.as_managed().unwrap();
let package_folder = managed.resolve_pkg_folder_from_deno_module(nv).unwrap();
let resolved = node_resolver
.resolve_package_subpath_from_deno_module(
&package_folder,
module.nv_reference.sub_path(),
None, // FIXME
NodeModuleKind::Esm, // FIXME
NodeResolutionMode::Execution,
)
.with_context(|| format!("Could not resolve '{}'.", module.nv_reference))
.unwrap();
resolved
}

View file

@ -0,0 +1,191 @@
use std::collections::{HashMap, HashSet};
use deno_core::url::Url;
use indexmap::IndexSet;
use crate::args::{BundleFlags, BundlePlatform};
use super::bundle_graph::{BundleGraph, BundleModule};
pub fn assign_chunks(
bundle_flags: &BundleFlags,
chunk_graph: &mut ChunkGraph,
graph: &BundleGraph,
url: &Url,
parent_chunk_id: Option<usize>,
is_dynamic: bool,
) {
let module = graph.get(url).unwrap();
match &module {
&BundleModule::Js(js_module) => {
let chunk_id = chunk_graph.assign_specifier_to_chunk(
url,
parent_chunk_id,
ChunkKind::Js,
is_dynamic,
);
for dep in &js_module.dependencies {
if let Some(specifier) = graph.get_specifier(dep.id) {
assign_chunks(
bundle_flags,
chunk_graph,
graph,
&specifier,
Some(chunk_id),
dep.is_dyanmic,
);
}
}
}
BundleModule::Json(json_module) => {
chunk_graph.assign_specifier_to_chunk(
url,
parent_chunk_id,
ChunkKind::Js,
is_dynamic,
);
}
BundleModule::Wasm(wasm_module) => {
chunk_graph.assign_specifier_to_chunk(
url,
parent_chunk_id,
ChunkKind::Asset("wasm".to_string()),
true,
);
}
BundleModule::Node(built_in_node_module) => {
if let BundlePlatform::Browser = bundle_flags.platform {
// TODO: Show where it was imported from
log::log!(
log::Level::Error,
"Imported Node internal module '{}' which will fail in browsers.",
built_in_node_module
);
}
}
BundleModule::External(external_module) => todo!(),
}
}
#[derive(Debug, Eq, PartialEq)]
pub enum ChunkKind {
Asset(String),
Js,
}
#[derive(Debug)]
pub struct Chunk {
pub id: usize,
pub name: String,
pub kind: ChunkKind,
pub parent_ids: HashSet<usize>,
pub children: Vec<usize>, // TODO: IndexSet?
pub specifiers: IndexSet<Url>,
}
#[derive(Debug)]
pub struct ChunkGraph {
pub id: usize,
pub chunks: HashMap<usize, Chunk>,
pub root_chunks: HashSet<usize>,
pub specifier_to_chunks: HashMap<Url, Vec<usize>>,
}
impl ChunkGraph {
pub fn new() -> Self {
Self {
id: 0,
chunks: HashMap::new(),
root_chunks: HashSet::new(),
specifier_to_chunks: HashMap::new(),
}
}
fn get_or_create_chunk(
&mut self,
url: &Url,
parent_chunk_id: Option<usize>,
kind: ChunkKind,
is_dynamic: bool,
) -> usize {
if let Some(parent_chunk_id) = parent_chunk_id {
if !is_dynamic {
return parent_chunk_id;
}
}
let name = if let Ok(f) = url.to_file_path() {
if let Some(name) = f.file_stem() {
name.to_string_lossy().to_string()
} else {
format!("chunk_{}", self.id)
}
} else {
format!("chunk_{}", self.id)
};
let ext = match &kind {
ChunkKind::Asset(ext) => ext,
ChunkKind::Js => "js",
};
let full_name = format!("{}.{}", name, ext);
self.new_chunk(full_name, parent_chunk_id, kind)
}
pub fn assign_specifier_to_chunk(
&mut self,
url: &Url,
parent_chunk_id: Option<usize>,
kind: ChunkKind,
is_dynamic: bool,
) -> usize {
let chunk_id =
self.get_or_create_chunk(&url, parent_chunk_id, kind, is_dynamic);
if let Some(value) = self.specifier_to_chunks.get_mut(&url) {
value.push(chunk_id)
} else {
let value = vec![chunk_id];
self.specifier_to_chunks.insert(url.clone(), value);
}
if let Some(chunk) = self.chunks.get_mut(&chunk_id) {
chunk.specifiers.insert(url.clone());
}
chunk_id
}
fn new_chunk(
&mut self,
name: String,
parent_id: Option<usize>,
kind: ChunkKind,
) -> usize {
let id = self.id;
self.id += 1;
let mut parent_ids = HashSet::new();
if let Some(parent_id) = parent_id {
parent_ids.insert(parent_id);
} else {
self.root_chunks.insert(id);
}
let chunk = Chunk {
id,
name,
kind,
parent_ids,
children: vec![],
specifiers: IndexSet::new(),
};
self.chunks.insert(id, chunk);
id
}
}

View file

@ -1,31 +1,28 @@
use std::{ use std::{
cmp::Ordering, cmp::Ordering,
collections::{HashMap, HashSet},
fs, fs,
io::Write, io::Write,
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::Arc, sync::Arc,
}; };
use bundle_graph::{BundleDep, BundleGraph, BundleJsModule, BundleMod}; use bundle_graph::BundleModule;
use deno_core::{anyhow::Context, error::AnyError, url::Url}; use bundle_resolver::build_resolved_graph;
use deno_graph::{GraphKind, Module, ModuleGraph, NpmModule, Resolution}; use chunk_graph::{assign_chunks, ChunkGraph};
use deno_runtime::{colors, deno_node::NodeResolver}; use deno_core::error::AnyError;
use deno_semver::package; use deno_runtime::colors;
use flate2::{write::ZlibEncoder, Compression}; use flate2::{write::ZlibEncoder, Compression};
use indexmap::IndexSet;
use node_resolver::{NodeModuleKind, NodeResolutionMode};
use crate::{ use crate::{
args::{BundleFlags, BundlePlatform, Flags}, args::{BundleFlags, Flags},
factory::CliFactory, factory::CliFactory,
graph_util::CreateGraphOptions,
npm::CliNpmResolver,
resolver::CjsTracker,
util::{fs::collect_specifiers, path::matches_pattern_or_exact_path}, util::{fs::collect_specifiers, path::matches_pattern_or_exact_path},
}; };
mod bundle_graph; mod bundle_graph;
mod bundle_resolver;
mod chunk_graph;
mod transform;
#[derive(Debug)] #[derive(Debug)]
struct BundleChunkStat { struct BundleChunkStat {
@ -62,159 +59,20 @@ pub async fn bundle(
let module_graph_creator = factory.module_graph_creator().await?; let module_graph_creator = factory.module_graph_creator().await?;
let graph = module_graph_creator let bundle_graph = build_resolved_graph(
.create_graph_with_options(CreateGraphOptions { module_graph_creator,
graph_kind: GraphKind::CodeOnly, npm_resolver,
roots: files.clone(), node_resolver,
is_dynamic: false, files.clone(),
loader: None, )
}) .await?;
.await?;
graph.valid()?;
let mut bundle_graph = BundleGraph::new();
let mut id = 0;
let mut all_modules: HashMap<Url, Module> = HashMap::new();
let mut module_to_id: HashMap<Url, usize> = HashMap::new();
let mut id_to_module: HashMap<usize, Url> = HashMap::new();
let mut npm_modules: IndexSet<Url> = IndexSet::new();
let mut seen: IndexSet<Url> = IndexSet::new();
fn resolve_npm_module(
module: &NpmModule,
npm_resolver: &Arc<dyn CliNpmResolver>,
node_resolver: &Arc<NodeResolver>,
) -> Url {
let nv = module.nv_reference.nv();
let managed = npm_resolver.as_managed().unwrap();
let package_folder =
managed.resolve_pkg_folder_from_deno_module(nv).unwrap();
let resolved = node_resolver
.resolve_package_subpath_from_deno_module(
&package_folder,
module.nv_reference.sub_path(),
None, // FIXME
NodeModuleKind::Esm, // FIXME
NodeResolutionMode::Execution,
)
.with_context(|| format!("Could not resolve '{}'.", module.nv_reference))
.unwrap();
resolved
}
let mut pending_npm_dep_links: HashMap<usize, Url> = HashMap::new();
// Hack: Create sub graphs for every npm module we encounter and
// expand npm specifiers to the actual file
for module in graph.modules() {
let url = module.specifier();
seen.insert(url.clone());
let current_id = id;
module_to_id.insert(url.clone(), current_id);
id_to_module.insert(current_id, url.clone());
id += 1;
match module {
Module::Npm(module) => {
let resolved = resolve_npm_module(&module, npm_resolver, node_resolver);
npm_modules.insert(resolved.clone());
}
Module::Js(js_module) => {
let id = bundle_graph.insert(
url.clone(),
BundleMod::Js(BundleJsModule {
specifier: url.clone(),
media_type: js_module.media_type,
source: js_module.source.to_string(),
dependencies: vec![],
}),
);
for (raw, dep) in &js_module.dependencies {
if let Some(code) = dep.get_code() {
if code.scheme() == "npm" {
pending_npm_dep_links.insert(id, code.clone());
} else {
let dep_id = bundle_graph.register(code.clone());
bundle_graph.add_dependency(
id,
BundleDep {
id: dep_id,
raw: raw.to_string(),
is_dyanmic: dep.is_dynamic,
},
);
}
}
eprintln!("JS dep {} {:#?}", raw, dep);
}
}
Module::Json(json_module) => {
bundle_graph.insert(url.clone(), BundleMod::Json(json_module.clone()));
}
Module::Wasm(wasm_module) => {
bundle_graph.insert(url.clone(), BundleMod::Wasm(wasm_module.clone()));
}
Module::Node(built_in_node_module) => {
bundle_graph.insert(
url.clone(),
BundleMod::Node(built_in_node_module.module_name.to_string()),
);
}
Module::External(external_module) => todo!(),
}
}
let npm_modules_vec =
npm_modules.iter().map(|u| u.clone()).collect::<Vec<_>>();
eprintln!("npm vec: {:#?}", npm_modules_vec);
while let Some(url) = npm_modules.pop() {
let npm_graph = module_graph_creator
.create_graph_with_options(CreateGraphOptions {
graph_kind: GraphKind::CodeOnly,
roots: vec![url.clone()],
is_dynamic: false,
loader: None,
})
.await?;
for module in npm_graph.modules() {
if seen.contains(module.specifier()) {
continue;
}
match module {
Module::Npm(module) => {
let resolved =
resolve_npm_module(&module, npm_resolver, node_resolver);
npm_modules.insert(resolved.clone());
}
_ => {
all_modules.insert(url.clone(), module.clone());
}
}
}
eprintln!("RES {:#?}", all_modules);
}
let mut chunk_graph = ChunkGraph::new(); let mut chunk_graph = ChunkGraph::new();
for file in files { for file in files {
assign_chunks( assign_chunks(
&bundle_flags, &bundle_flags,
&mut chunk_graph, &mut chunk_graph,
&all_modules, &bundle_graph,
npm_resolver,
node_resolver,
cjs_tracker,
&file, &file,
None, None,
true, true,
@ -238,11 +96,17 @@ pub async fn bundle(
let mut source = String::new(); let mut source = String::new();
for spec in chunk.specifiers.iter().rev() { for spec in chunk.specifiers.iter().rev() {
if let Some(module) = graph.get(&spec) { if let Some(module) = bundle_graph.get(&spec) {
// FIXME: don't print module urls by default // FIXME: don't print module urls by default
source.push_str(&format!("// {}\n", spec.to_string())); source.push_str(&format!("// {}\n", spec.to_string()));
if let Some(contents) = &module.source() { match module {
source.push_str(contents); BundleModule::Js(bundle_js_module) => {
source.push_str(&bundle_js_module.source);
}
BundleModule::Json(json_module) => todo!(),
BundleModule::Wasm(wasm_module) => todo!(),
BundleModule::Node(_) => todo!(),
BundleModule::External(external_module) => todo!(),
} }
} }
} }
@ -302,199 +166,3 @@ pub async fn bundle(
Ok(()) Ok(())
} }
fn assign_chunks(
bundle_flags: &BundleFlags,
chunk_graph: &mut ChunkGraph,
graph: &HashMap<Url, Module>,
npm_resolver: &Arc<dyn CliNpmResolver>,
node_resolver: &Arc<NodeResolver>,
cjs_tracker: &Arc<CjsTracker>,
url: &Url,
parent_chunk_id: Option<usize>,
is_dynamic: bool,
) {
let module = graph.get(url).unwrap();
match module {
Module::Js(js_module) => {
let chunk_id = chunk_graph.assign_specifier_to_chunk(
url,
parent_chunk_id,
ChunkKind::Js,
is_dynamic,
);
for (_, dep) in &js_module.dependencies {
match &dep.maybe_code {
Resolution::None => todo!(),
Resolution::Ok(resolution_resolved) => {
assign_chunks(
bundle_flags,
chunk_graph,
graph,
npm_resolver,
node_resolver,
cjs_tracker,
&resolution_resolved.specifier,
Some(chunk_id),
dep.is_dynamic,
);
}
Resolution::Err(resolution_error) => todo!(),
}
}
}
Module::Json(json_module) => {
chunk_graph.assign_specifier_to_chunk(
url,
parent_chunk_id,
ChunkKind::Js,
is_dynamic,
);
}
Module::Wasm(wasm_module) => {
chunk_graph.assign_specifier_to_chunk(
url,
parent_chunk_id,
ChunkKind::Asset("wasm".to_string()),
true,
);
}
Module::Npm(_) => {
unreachable!()
}
Module::Node(built_in_node_module) => {
if let BundlePlatform::Browser = bundle_flags.platform {
// TODO: Show where it was imported from
log::log!(
log::Level::Error,
"Imported Node internal module '{}' which will fail in browsers.",
built_in_node_module.specifier.to_string()
);
}
}
Module::External(external_module) => todo!(),
}
}
#[derive(Debug, Eq, PartialEq)]
enum ChunkKind {
Asset(String),
Js,
}
#[derive(Debug)]
struct Chunk {
id: usize,
name: String,
pub kind: ChunkKind,
parent_ids: HashSet<usize>,
children: Vec<usize>, // TODO: IndexSet?
specifiers: IndexSet<Url>,
}
#[derive(Debug)]
struct ChunkGraph {
pub id: usize,
pub chunks: HashMap<usize, Chunk>,
pub root_chunks: HashSet<usize>,
pub specifier_to_chunks: HashMap<Url, Vec<usize>>,
}
impl ChunkGraph {
fn new() -> Self {
Self {
id: 0,
chunks: HashMap::new(),
root_chunks: HashSet::new(),
specifier_to_chunks: HashMap::new(),
}
}
fn get_or_create_chunk(
&mut self,
url: &Url,
parent_chunk_id: Option<usize>,
kind: ChunkKind,
is_dynamic: bool,
) -> usize {
if let Some(parent_chunk_id) = parent_chunk_id {
if !is_dynamic {
return parent_chunk_id;
}
}
let name = if let Ok(f) = url.to_file_path() {
if let Some(name) = f.file_stem() {
name.to_string_lossy().to_string()
} else {
format!("chunk_{}", self.id)
}
} else {
format!("chunk_{}", self.id)
};
let ext = match &kind {
ChunkKind::Asset(ext) => ext,
ChunkKind::Js => "js",
};
let full_name = format!("{}.{}", name, ext);
self.new_chunk(full_name, parent_chunk_id, kind)
}
fn assign_specifier_to_chunk(
&mut self,
url: &Url,
parent_chunk_id: Option<usize>,
kind: ChunkKind,
is_dynamic: bool,
) -> usize {
let chunk_id =
self.get_or_create_chunk(&url, parent_chunk_id, kind, is_dynamic);
if let Some(value) = self.specifier_to_chunks.get_mut(&url) {
value.push(chunk_id)
} else {
let value = vec![chunk_id];
self.specifier_to_chunks.insert(url.clone(), value);
}
if let Some(chunk) = self.chunks.get_mut(&chunk_id) {
chunk.specifiers.insert(url.clone());
}
chunk_id
}
fn new_chunk(
&mut self,
name: String,
parent_id: Option<usize>,
kind: ChunkKind,
) -> usize {
let id = self.id;
self.id += 1;
let mut parent_ids = HashSet::new();
if let Some(parent_id) = parent_id {
parent_ids.insert(parent_id);
} else {
self.root_chunks.insert(id);
}
let chunk = Chunk {
id,
name,
kind,
parent_ids,
children: vec![],
specifiers: IndexSet::new(),
};
self.chunks.insert(id, chunk);
id
}
}

View file

@ -0,0 +1,36 @@
use deno_ast::{
parse_module, swc::visit::FoldWith, ParseParams, ParsedSource, SourceMap,
};
use super::bundle_graph::{BundleJsModule, BundleModule};
pub fn transform_bundle(module: &BundleModule) {
//
match module {
BundleModule::Js(module) => {
let parsed_source = parse_module(ParseParams {
specifier: module.specifier.clone(),
media_type: module.media_type,
capture_tokens: false,
maybe_syntax: None,
scope_analysis: false,
text: module.source.clone().into(),
})
.unwrap();
// TODO: optional
let source_map =
SourceMap::single(module.specifier.clone(), module.source.clone());
let program = parsed_source.program();
// Transpile
}
// FIXME
BundleModule::Json(_json_module) => todo!(),
BundleModule::Wasm(_wasm_module) => {}
BundleModule::Node(_) | BundleModule::External(_) => {}
}
}