turbopack_ecmascript/analyzer/graph/
mod.rs1use rustc_hash::FxHashMap;
2use swc_core::{
3 atoms::Atom,
4 common::BytePos,
5 ecma::{ast::*, visit::VisitWithAstPath},
6};
7use turbopack_core::resolve::ExportUsage;
8
9pub use crate::analyzer::graph::{
10 effects::{
11 AssignmentScope, AssignmentScopes, ConditionalKind, Effect, EffectArg, EffectsBlock,
12 },
13 eval_context::EvalContext,
14};
15use crate::{
16 AnalyzeMode, SpecifiedModuleType,
17 analyzer::{Bump, JsValue, graph::visitor::Analyzer},
18 chunk::CjsStaticExports,
19 code_gen::CodeGen,
20};
21
22mod effects;
23mod eval_context;
24pub(crate) mod visitor;
25
26#[derive(Debug)]
27pub struct VarGraph<'a> {
28 pub values: FxHashMap<Id, JsValue<'a>>,
29
30 pub free_var_ids: FxHashMap<Atom, Id>,
35
36 pub effects: Vec<Effect<'a>>,
37 pub code_gens: Vec<CodeGen>,
39
40 pub require_usage: FxHashMap<BytePos, ExportUsage>,
43
44 pub cjs_static_exports: Option<CjsStaticExports>,
47}
48
49impl<'a> VarGraph<'a> {
50 pub fn normalize(&mut self, arena: &'a Bump) {
51 for value in self.values.values_mut() {
52 value.normalize(arena);
53 }
54 for effect in self.effects.iter_mut() {
55 effect.normalize(arena);
56 }
57 }
58}
59
60pub fn create_graph<'a>(
61 arena: &'a Bump,
62 m: &Program,
63 eval_context: &EvalContext,
64 analyze_mode: AnalyzeMode,
65 supports_block_scoping: bool,
66 specified_module_type: SpecifiedModuleType,
67 cjs_tree_shaking: bool,
68 cjs_scope_hoisting: bool,
69) -> VarGraph<'a> {
70 let mut analyzer = Analyzer {
71 arena,
72 analyze_mode,
73 data: VarGraph {
74 values: Default::default(),
75 free_var_ids: Default::default(),
76 effects: Default::default(),
77 code_gens: Default::default(),
78 require_usage: Default::default(),
79 cjs_static_exports: Default::default(),
80 },
81 eval_context,
82 state: Default::default(),
83 effects: Default::default(),
84 hoisted_effects: Default::default(),
85 code_gens: Default::default(),
86 supports_block_scoping,
87 };
88
89 if (cjs_tree_shaking || cjs_scope_hoisting)
92 && analyze_mode.is_code_gen()
93 && eval_context.is_cjs(specified_module_type)
94 {
95 analyzer.enable_cjs_exports();
96 }
97
98 if cjs_tree_shaking && analyze_mode.is_code_gen() {
99 analyzer.enable_require_usage(&eval_context.imports);
100 }
101
102 m.visit_with_ast_path(&mut analyzer, &mut Default::default());
103
104 let mut graph = analyzer.data;
105 graph.normalize(arena);
106
107 graph
108}