Skip to content

Commit

Permalink
feat: add RuntimeNormalModuleTask (#40)
Browse files Browse the repository at this point in the history
* feat: should have different kind of module task

* Add RuntimeNormalModuleTask
  • Loading branch information
hyf0 authored Oct 12, 2023
1 parent d40c919 commit 2401386
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 43 deletions.
4 changes: 2 additions & 2 deletions crates/rolldown/src/bundler/module/module_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::bundler::graph::symbols::SymbolMap;
use super::NormalModule;

#[derive(Debug, Default)]
pub struct ModuleBuilder {
pub struct NormalModuleBuilder {
pub id: Option<ModuleId>,
pub path: Option<ResourceId>,
pub ast: Option<OxcProgram>,
Expand All @@ -31,7 +31,7 @@ pub struct ModuleBuilder {
pub module_resolution: Option<ModuleResolution>,
}

impl ModuleBuilder {
impl NormalModuleBuilder {
pub fn initialize_namespace_binding(&mut self, symbol_table: &mut SymbolMap) {
let name = format!("{}_ns", self.path.as_ref().unwrap().generate_unique_name());
let symbol_ref: SymbolRef = (self.id.unwrap(), symbol_table.create_symbol(name.into())).into();
Expand Down
8 changes: 5 additions & 3 deletions crates/rolldown/src/bundler/module_loader/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#[allow(clippy::module_inception)]
mod module_loader;
mod module_task;
mod normal_module_task;
mod runtime_normal_module_task;
mod task_result;

pub use module_loader::ModuleLoader;

use self::task_result::TaskResult;
use self::task_result::NormalModuleTaskResult;
pub enum Msg {
Done(TaskResult),
NormalModuleDone(NormalModuleTaskResult),
RuntimeNormalModuleDone(NormalModuleTaskResult),
}
57 changes: 40 additions & 17 deletions crates/rolldown/src/bundler/module_loader/module_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ use rolldown_resolver::Resolver;
use rolldown_utils::block_on_spawn_all;
use rustc_hash::{FxHashMap, FxHashSet};

use super::module_task::ModuleTask;
use super::task_result::TaskResult;
use super::normal_module_task::NormalModuleTask;
use super::runtime_normal_module_task::RuntimeNormalModuleTask;
use super::task_result::NormalModuleTaskResult;
use super::Msg;
use crate::bundler::graph::graph::Graph;
use crate::bundler::graph::symbols::{SymbolMap, Symbols};
Expand Down Expand Up @@ -52,13 +53,7 @@ impl<'a> ModuleLoader<'a> {

let mut intermediate_modules: IndexVec<ModuleId, Option<Module>> =
IndexVec::with_capacity(resolved_entries.len() + 1 /* runtime */);
self.graph.runtime.id = self.try_spawn_new_task(
&ResolvedRequestInfo {
path: RUNTIME_PATH.to_string().into(),
is_external: false,
},
&mut intermediate_modules,
);
self.graph.runtime.id = self.try_spawn_runtime_normal_module_task(&mut intermediate_modules);

let mut entries = resolved_entries
.into_iter()
Expand All @@ -76,8 +71,8 @@ impl<'a> ModuleLoader<'a> {
while self.remaining > 0 {
let Some(msg) = self.rx.recv().await else { break };
match msg {
Msg::Done(task_result) => {
let TaskResult {
Msg::NormalModuleDone(task_result) => {
let NormalModuleTaskResult {
module_id,
symbol_map: symbol_table,
resolved_deps,
Expand Down Expand Up @@ -107,18 +102,29 @@ impl<'a> ModuleLoader<'a> {
}
intermediate_modules[module_id] = Some(Module::Normal(builder.build()));

tables[task_result.module_id] = symbol_table
}
Msg::RuntimeNormalModuleDone(task_result) => {
let NormalModuleTaskResult {
module_id,
symbol_map: symbol_table,
builder,
..
} = task_result;
while tables.len() <= task_result.module_id.raw() as usize {
tables.push(Default::default());
}
let runtime_normal_module = builder.build();
self.graph.runtime.init_symbols(&runtime_normal_module);
intermediate_modules[module_id] = Some(Module::Normal(runtime_normal_module));

tables[task_result.module_id] = symbol_table
}
}
self.remaining -= 1;
}
self.graph.symbols = Symbols::new(tables);

self
.graph
.runtime
.init_symbols(&self.graph.symbols.tables[self.graph.runtime.id]);

self.graph.modules = intermediate_modules
.into_iter()
.map(|m| m.unwrap())
Expand Down Expand Up @@ -191,11 +197,28 @@ impl<'a> ModuleLoader<'a> {

let module_path = ResourceId::new(info.path.clone(), &self.input_options.cwd);

let task = ModuleTask::new(id, self.resolver.clone(), module_path, self.tx.clone());
let task = NormalModuleTask::new(id, self.resolver.clone(), module_path, self.tx.clone());
tokio::spawn(async move { task.run().await });
}
id
}
}
}

fn try_spawn_runtime_normal_module_task(
&mut self,
intermediate_modules: &mut IndexVec<ModuleId, Option<Module>>,
) -> ModuleId {
match self.visited.entry(RUNTIME_PATH.to_string().into()) {
std::collections::hash_map::Entry::Occupied(visited) => *visited.get(),
std::collections::hash_map::Entry::Vacant(not_visited) => {
let id = intermediate_modules.push(None);
not_visited.insert(id);
self.remaining += 1;
let task = RuntimeNormalModuleTask::new(id, self.resolver.clone(), self.tx.clone());
tokio::spawn(async move { task.run().await });
id
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ use super::Msg;
use crate::{
bundler::{
graph::symbols::SymbolMap,
module::module_builder::ModuleBuilder,
module_loader::TaskResult,
module::module_builder::NormalModuleBuilder,
module_loader::NormalModuleTaskResult,
resolve_id::{resolve_id, ResolvedRequestInfo},
runtime::RUNTIME_PATH,
visitors::scanner::{self, ScanResult},
},
BuildError, BuildResult, SharedResolver,
};
pub struct ModuleTask {
pub struct NormalModuleTask {
module_id: ModuleId,
path: ResourceId,
tx: tokio::sync::mpsc::UnboundedSender<Msg>,
Expand All @@ -30,7 +30,7 @@ pub struct ModuleTask {
resolver: SharedResolver,
}

impl ModuleTask {
impl NormalModuleTask {
pub fn new(
id: ModuleId,
resolver: SharedResolver,
Expand All @@ -48,7 +48,7 @@ impl ModuleTask {
}

pub async fn run(mut self) -> anyhow::Result<()> {
let mut builder = ModuleBuilder::default();
let mut builder = NormalModuleBuilder::default();
tracing::trace!("process {:?}", self.path);
// load
let source = if RUNTIME_PATH == self.path.as_ref() {
Expand Down Expand Up @@ -93,7 +93,7 @@ impl ModuleTask {

self
.tx
.send(Msg::Done(TaskResult {
.send(Msg::NormalModuleDone(NormalModuleTaskResult {
resolved_deps: res,
module_id: self.module_id,
errors: self.errors,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
use oxc::{
ast::VisitMut,
semantic::{ScopeTree, SymbolTable},
span::SourceType,
};
use rolldown_common::{ModuleId, ResourceId};
use rolldown_oxc::{OxcCompiler, OxcProgram};

use super::Msg;
use crate::{
bundler::{
graph::symbols::SymbolMap,
module::module_builder::NormalModuleBuilder,
module_loader::NormalModuleTaskResult,
runtime::RUNTIME_PATH,
visitors::scanner::{self, ScanResult},
},
BuildError, SharedResolver,
};
pub struct RuntimeNormalModuleTask {
module_id: ModuleId,
tx: tokio::sync::mpsc::UnboundedSender<Msg>,
errors: Vec<BuildError>,
warnings: Vec<BuildError>,
resolver: SharedResolver,
}

impl RuntimeNormalModuleTask {
pub fn new(
id: ModuleId,
resolver: SharedResolver,
tx: tokio::sync::mpsc::UnboundedSender<Msg>,
) -> Self {
Self {
module_id: id,
resolver,
tx,
errors: Default::default(),
warnings: Default::default(),
}
}

pub async fn run(self) -> anyhow::Result<()> {
let mut builder = NormalModuleBuilder::default();
// load
let source = include_str!("../runtime/index.js").to_string();

let (ast, scope, scan_result, symbol) = self.make_ast(source);

let mut symbol_map = SymbolMap::from_symbol_table(symbol);

let ScanResult {
named_imports,
named_exports,
stmt_infos,
import_records,
star_exports,
export_default_symbol_id,
imports,
module_resolution,
} = scan_result;

builder.id = Some(self.module_id);
builder.ast = Some(ast);
builder.path = Some(ResourceId::new(
RUNTIME_PATH.to_string().into(),
self.resolver.cwd(),
));
builder.named_imports = Some(named_imports);
builder.named_exports = Some(named_exports);
builder.stmt_infos = Some(stmt_infos);
builder.import_records = Some(import_records);
builder.imports = Some(imports);
builder.star_exports = Some(star_exports);
builder.default_export_symbol = export_default_symbol_id;
builder.scope = Some(scope);
builder.module_resolution = module_resolution;
builder.initialize_namespace_binding(&mut symbol_map);

self
.tx
.send(Msg::RuntimeNormalModuleDone(NormalModuleTaskResult {
resolved_deps: Default::default(),
module_id: self.module_id,
errors: self.errors,
warnings: self.warnings,
symbol_map,
builder,
}))
.unwrap();
Ok(())
}

fn make_ast(&self, source: String) -> (OxcProgram, ScopeTree, ScanResult, SymbolTable) {
let source_type = SourceType::default();
let mut program = OxcCompiler::parse(source, source_type);

let semantic = program.make_semantic(source_type);
let (mut symbol_table, mut scope) = semantic.into_symbol_table_and_scope_tree();
let mut scanner = scanner::Scanner::new(
self.module_id,
&mut scope,
&mut symbol_table,
"should be unreachable for runtime module",
);
scanner.visit_program(program.program_mut());
let scan_result = scanner.result;

(program, scope, scan_result, symbol_table)
}
}
6 changes: 3 additions & 3 deletions crates/rolldown/src/bundler/module_loader/task_result.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use rolldown_common::{ImportRecordId, ModuleId};

use crate::bundler::graph::symbols::SymbolMap;
use crate::bundler::module::module_builder::ModuleBuilder;
use crate::bundler::module::module_builder::NormalModuleBuilder;
use crate::bundler::resolve_id::ResolvedRequestInfo;
use crate::BuildError;

pub struct TaskResult {
pub struct NormalModuleTaskResult {
pub module_id: ModuleId,
pub symbol_map: SymbolMap,
pub resolved_deps: Vec<(ImportRecordId, ResolvedRequestInfo)>,
pub errors: Vec<BuildError>,
pub warnings: Vec<BuildError>,
pub builder: ModuleBuilder,
pub builder: NormalModuleBuilder,
}
25 changes: 13 additions & 12 deletions crates/rolldown/src/bundler/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use oxc::{semantic::SymbolId, span::Atom};
use rolldown_common::{ModuleId, SymbolRef};
use rustc_hash::FxHashMap;

use super::graph::symbols::SymbolMap;
use super::module::NormalModule;

pub static RUNTIME_PATH: &str = "\0rolldown-runtime.js";

Expand All @@ -13,19 +13,20 @@ pub struct Runtime {
}

impl Runtime {
pub fn init_symbols(&mut self, runtime_symbol_map: &SymbolMap) {
// TODO: we should only storing top level symbols here.
// But currently, I'm not sure how to get the scope info for the runtime module
self.name_to_symbol = runtime_symbol_map
.names
.iter()
.enumerate()
.map(|(id, name)| (name.clone(), id.into()))
.collect()
pub fn init_symbols(&mut self, runtime_module: &NormalModule) {
self.name_to_symbol = runtime_module
.scope
.get_bindings(runtime_module.scope.root_scope_id())
.clone()
.into_iter()
.collect();
}

pub fn resolve_symbol(&self, name: &Atom) -> SymbolRef {
let symbol_id = self.name_to_symbol[name];
(self.id, symbol_id).into()
let symbol_id = self
.name_to_symbol
.get(name)
.unwrap_or_else(|| panic!("Failed to resolve symbol: {}", name));
(self.id, *symbol_id).into()
}
}

0 comments on commit 2401386

Please sign in to comment.