Skip to content

Commit

Permalink
feat: basic commonjs support (#38)
Browse files Browse the repository at this point in the history
  • Loading branch information
underfin committed Oct 11, 2023
1 parent a264b4a commit d40c919
Show file tree
Hide file tree
Showing 25 changed files with 919 additions and 185 deletions.
16 changes: 1 addition & 15 deletions crates/rolldown/src/bundler/bundle/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::bundler::{
ChunkId, ChunksVec,
},
graph::graph::Graph,
module::module::{Module, ModuleRenderContext},
module::module::Module,
options::{
normalized_input_options::NormalizedInputOptions,
normalized_output_options::NormalizedOutputOptions,
Expand Down Expand Up @@ -154,20 +154,6 @@ impl<'a> Bundle<'a> {
}
});

self
.graph
.modules
.iter_mut()
.par_bridge()
.for_each(|module| {
module.render(ModuleRenderContext {
canonical_names: &chunks[0].canonical_names,
symbols: &self.graph.symbols,
module_to_chunk: &module_to_chunk,
chunks: &chunks,
});
});

let assets = chunks
.iter()
.enumerate()
Expand Down
2 changes: 2 additions & 0 deletions crates/rolldown/src/bundler/chunk/chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ impl Chunk {
symbols: &graph.symbols,
module_to_chunk,
chunks,
modules: &graph.modules,
runtime: &graph.runtime,
})
})
.collect::<Vec<_>>()
Expand Down
104 changes: 88 additions & 16 deletions crates/rolldown/src/bundler/graph/linker.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use index_vec::IndexVec;
use oxc::{semantic::ReferenceId, span::Atom};
use rolldown_common::{LocalOrReExport, ModuleId, ResolvedExport, SymbolRef};
use rolldown_common::{LocalOrReExport, ModuleId, ModuleResolution, ResolvedExport, SymbolRef};
use rustc_hash::FxHashMap;

use super::graph::Graph;
Expand All @@ -18,6 +19,9 @@ impl<'graph> Linker<'graph> {
}

pub fn link(&mut self) {
// Create symbols for wrapped module
self.mark_modules_wrap();

// propagate star exports
for id in &self.graph.sorted_modules {
let importer = &self.graph.modules[*id];
Expand All @@ -33,8 +37,10 @@ impl<'graph> Linker<'graph> {
}
}
}

Self::mark_whether_namespace_referenced_and_mark_external_symbols(self.graph);
// Mark namespace symbol for namespace referenced
// Create symbols for external module
// Create symbols for import cjs module
Self::mark_extra_symbols(self.graph);

self
.graph
Expand All @@ -47,7 +53,55 @@ impl<'graph> Linker<'graph> {
})
}

fn mark_whether_namespace_referenced_and_mark_external_symbols(graph: &mut Graph) {
fn mark_modules_wrap(&mut self) {
let mut modules_wrap = index_vec::index_vec![
false;
self.graph.modules.len()
];

for module_id in &self.graph.sorted_modules {
match &self.graph.modules[*module_id] {
Module::Normal(m) => {
if m.module_resolution == ModuleResolution::CommonJs {
mark_module_wrap(self.graph, *module_id, &mut modules_wrap);
}
}
Module::External(_) => {}
}
}

for (module_id, wrap) in modules_wrap.into_iter_enumerated() {
if wrap {
match &mut self.graph.modules[module_id] {
Module::Normal(m) => {
m.add_wrap_symbol(&mut self.graph.symbols);
}
Module::External(_) => {}
}
}
}

fn mark_module_wrap(
graph: &Graph,
module_id: ModuleId,
modules_wrap: &mut IndexVec<ModuleId, bool>,
) {
match &graph.modules[module_id] {
Module::Normal(module) => {
if modules_wrap[module_id] {
return;
}
modules_wrap[module_id] = true;
module.import_records.iter().for_each(|record| {
mark_module_wrap(graph, record.resolved_module, modules_wrap);
});
}
Module::External(_) => {}
}
}
}

fn mark_extra_symbols(graph: &mut Graph) {
for id in &graph.sorted_modules {
let importer = &graph.modules[*id];
let importee_list = importer
Expand All @@ -58,19 +112,31 @@ impl<'graph> Linker<'graph> {
})
.collect::<Vec<_>>();

// add external symbol
let mut external_symbols = vec![];
// Create symbols for external module
// Create symbols for import cjs module
let mut extra_symbols = vec![];
match importer {
Module::Normal(importer) => {
importer.named_imports.iter().for_each(|(_id, info)| {
let import_record = &importer.import_records[info.record_id];
let importee = &graph.modules[import_record.resolved_module];
if let Module::External(_) = importee {
external_symbols.push((
import_record.resolved_module,
info.imported.clone(),
info.is_imported_star,
));
match importee {
Module::Normal(importee) => {
if importee.module_resolution == ModuleResolution::CommonJs {
extra_symbols.push((
import_record.resolved_module,
info.imported.clone(),
info.is_imported_star,
));
}
}
Module::External(_) => {
extra_symbols.push((
import_record.resolved_module,
info.imported.clone(),
info.is_imported_star,
));
}
}
});
importer
Expand All @@ -82,7 +148,7 @@ impl<'graph> Linker<'graph> {
let import_record = &importer.import_records[re.record_id];
let importee = &graph.modules[import_record.resolved_module];
if let Module::External(_) = importee {
external_symbols.push((
extra_symbols.push((
import_record.resolved_module,
re.imported.clone(),
re.is_imported_star,
Expand All @@ -93,12 +159,16 @@ impl<'graph> Linker<'graph> {
}
Module::External(_) => {}
}
external_symbols
extra_symbols
.into_iter()
.for_each(|(importee, imported, is_imported_star)| {
let importee = &mut graph.modules[importee];
match importee {
Module::Normal(_) => {}
Module::Normal(importee) => {
if importee.module_resolution == ModuleResolution::CommonJs {
importee.add_cjs_symbol(&mut graph.symbols, imported, is_imported_star)
}
}
Module::External(importee) => {
importee.add_export_symbol(&mut graph.symbols, imported, is_imported_star);
}
Expand Down Expand Up @@ -213,7 +283,9 @@ impl<'graph> Linker<'graph> {
let importee = &self.graph.modules[import_record.resolved_module];
match importee {
Module::Normal(importee) => {
let resolved_ref = if info.is_imported_star {
let resolved_ref = if importee.module_resolution == ModuleResolution::CommonJs {
importee.resolve_cjs_symbol(&info.imported, info.is_imported_star)
} else if info.is_imported_star {
importee.namespace_symbol.0
} else {
match importee.resolve_export(
Expand Down
15 changes: 9 additions & 6 deletions crates/rolldown/src/bundler/graph/symbols.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use oxc::{
span::Atom,
};
use rolldown_common::{ModuleId, SymbolRef};
use rolldown_utils::reserved_word::is_reserved_word;
use rustc_hash::FxHashMap;

#[derive(Debug, Default)]
Expand All @@ -25,7 +26,11 @@ impl SymbolMap {
}

pub fn create_symbol(&mut self, name: Atom) -> SymbolId {
self.names.push(name)
if is_reserved_word(&name) {
self.names.push(format!("_{name}").into())
} else {
self.names.push(name)
}
}

pub fn create_reference(&mut self, id: Option<SymbolId>) -> ReferenceId {
Expand Down Expand Up @@ -96,13 +101,11 @@ impl Symbols {
}

pub fn get_symbol_final_name<'a>(
module_id: ModuleId,
symbol_id: SymbolId,
symbol: SymbolRef,
symbols: &'a Symbols,
final_names: &'a FxHashMap<SymbolRef, Atom>,
) -> Option<&'a Atom> {
let symbol_ref = (module_id, symbol_id).into();
let final_ref = symbols.par_get_canonical_ref(symbol_ref);
let final_ref = symbols.par_get_canonical_ref(symbol);
final_names.get(&final_ref)
}

Expand All @@ -113,5 +116,5 @@ pub fn get_reference_final_name<'a>(
final_names: &'a FxHashMap<SymbolRef, Atom>,
) -> Option<&'a Atom> {
symbols.tables[module_id].references[reference_id]
.and_then(|symbol| get_symbol_final_name(module_id, symbol, symbols, final_names))
.and_then(|symbol| get_symbol_final_name((module_id, symbol).into(), symbols, final_names))
}
12 changes: 5 additions & 7 deletions crates/rolldown/src/bundler/module/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ use string_wizard::MagicString;
use crate::bundler::{
chunk::{ChunkId, ChunksVec},
graph::symbols::Symbols,
runtime::Runtime,
};

use super::{external_module::ExternalModule, NormalModule};
use super::{external_module::ExternalModule, module_id::ModuleVec, NormalModule};

#[derive(Debug)]
pub enum Module {
Expand Down Expand Up @@ -62,12 +63,7 @@ impl Module {

pub fn mark_symbol_for_namespace_referenced(&mut self) {
match self {
Module::Normal(m) => {
if !m.is_symbol_for_namespace_referenced {
m.is_symbol_for_namespace_referenced = true;
m.initialize_namespace()
}
}
Module::Normal(m) => m.initialize_namespace(),
Module::External(m) => m.is_symbol_for_namespace_referenced = true,
}
}
Expand All @@ -85,4 +81,6 @@ pub struct ModuleRenderContext<'a> {
pub symbols: &'a Symbols,
pub module_to_chunk: &'a IndexVec<ModuleId, Option<ChunkId>>,
pub chunks: &'a ChunksVec,
pub modules: &'a ModuleVec,
pub runtime: &'a Runtime,
}
12 changes: 8 additions & 4 deletions crates/rolldown/src/bundler/module/module_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use oxc::{
span::{Atom, Span},
};
use rolldown_common::{
ImportRecord, ImportRecordId, LocalOrReExport, ModuleId, NamedImport, ResourceId, StmtInfo,
StmtInfoId, SymbolRef,
ImportRecord, ImportRecordId, LocalOrReExport, ModuleId, ModuleResolution, NamedImport,
ResourceId, StmtInfo, StmtInfoId, SymbolRef,
};
use rolldown_oxc::OxcProgram;
use rustc_hash::FxHashMap;
Expand All @@ -23,11 +23,12 @@ pub struct ModuleBuilder {
pub named_exports: Option<FxHashMap<Atom, LocalOrReExport>>,
pub stmt_infos: Option<IndexVec<StmtInfoId, StmtInfo>>,
pub import_records: Option<IndexVec<ImportRecordId, ImportRecord>>,
pub dynamic_imports: Option<FxHashMap<Span, ImportRecordId>>,
pub imports: Option<FxHashMap<Span, ImportRecordId>>,
pub star_exports: Option<Vec<ImportRecordId>>,
pub scope: Option<ScopeTree>,
pub default_export_symbol: Option<SymbolId>,
pub namespace_symbol: Option<(SymbolRef, ReferenceId)>,
pub module_resolution: Option<ModuleResolution>,
}

impl ModuleBuilder {
Expand All @@ -48,7 +49,7 @@ impl ModuleBuilder {
named_exports: self.named_exports.unwrap(),
stmt_infos: self.stmt_infos.unwrap(),
import_records: self.import_records.unwrap(),
dynamic_imports: self.dynamic_imports.unwrap(),
imports: self.imports.unwrap(),
star_exports: self.star_exports.unwrap(),
resolved_exports: Default::default(),
resolved_star_exports: Default::default(),
Expand All @@ -57,6 +58,9 @@ impl ModuleBuilder {
namespace_symbol: self.namespace_symbol.unwrap(),
is_symbol_for_namespace_referenced: false,
source_mutations: Default::default(),
module_resolution: self.module_resolution.unwrap_or(ModuleResolution::Esm),
cjs_symbols: Default::default(),
wrap_symbol: None,
}
}
}

0 comments on commit d40c919

Please sign in to comment.