1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use std::sync::Arc;
use crossbeam::{channel::Sender, queue::SegQueue};
use dashmap::DashSet;
use smol_str::SmolStr;
use swc::ecmascript::ast::ModuleItem;
use swc_ecma_ast::ModuleDecl;
use swc_ecma_visit::{VisitMutWith, VisitWith};
use crate::{
js_ext_module::JsExtModule, js_module::JsModule, plugin::ResolvedId, utils::parse_file,
visitors::DependencyScanner, PluginDriver, graph_container::{Msg, Relation},};
pub(crate) struct Worker {
pub job_queue: Arc<SegQueue<ResolvedId>>,
pub tx: Sender<Msg>,
pub processed_id: Arc<DashSet<SmolStr>>,
pub plugin_driver: Arc<PluginDriver>,
}
impl Worker {
fn fetch_job(&self) -> Option<ResolvedId> {
self.job_queue
.pop()
.filter(|resolved_id| !self.processed_id.contains(&resolved_id.id))
.map(|resolved_id| {
self.processed_id.insert(resolved_id.id.clone());
resolved_id
})
}
pub async fn run(&self) {
if let Some(resolved_id) = self.fetch_job() {
if resolved_id.external {
let mut js_ext_module = JsExtModule::new(resolved_id.id.clone());
} else {
let mut js_module = JsModule::new(resolved_id.id.clone());
let source = self.plugin_driver.load(&js_module.id).await;
js_module.source = source.clone();
let mut ast = parse_file(source, &resolved_id.id);
self.pre_analyze_imported_module(&js_module, &ast).await;
let mut dependenecy_scanner = DependencyScanner::new(&self.tx, &js_module);
ast.visit_children_with(&mut dependenecy_scanner);
for imported in dependenecy_scanner.dependencies.keys() {
let resolved_id = js_module.resolve_id(&self.plugin_driver, imported).await;
self.tx
.send(Msg::DependencyReference(
js_module.id.clone(),
resolved_id.id,
Relation::StaticImport,
))
.unwrap();
}
for dyn_imported in &dependenecy_scanner.dynamic_dependencies {
let resolved_id = js_module
.resolve_id(&self.plugin_driver, &dyn_imported.argument)
.await;
self.tx
.send(Msg::DependencyReference(
js_module.id.clone(),
resolved_id.id,
Relation::AsyncImport,
))
.unwrap();
}
println!("js_module {:#?}", js_module);
self.tx.send(Msg::NewMod(js_module)).unwrap();
}
}
}
pub async fn pre_analyze_imported_module(
&self,
js_module: &JsModule,
ast: &swc_ecma_ast::Module,
) {
for module_item in &ast.body {
if let ModuleItem::ModuleDecl(module_decl) = module_item {
let mut depended = None;
match module_decl {
ModuleDecl::Import(import_decl) => {
depended = Some(&import_decl.src.value);
}
ModuleDecl::ExportNamed(node) => {
if let Some(source_node) = &node.src {
depended = Some(&source_node.value);
}
}
ModuleDecl::ExportAll(node) => {
depended = Some(&node.src.value);
}
_ => {}
}
if let Some(depended) = depended {
let resolved_id = js_module
.resolve_id(&self.plugin_driver, &depended.to_string())
.await;
self.job_queue.push(resolved_id);
}
}
}
}
}