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 ast_path_trie::AstPathTrieBuilder,
19 chunk::CjsStaticExports,
20 code_gen::CodeGen,
21};
22
23mod effects;
24mod eval_context;
25pub(crate) mod visitor;
26
27#[derive(Debug)]
28pub struct VarGraph<'a> {
29 pub values: FxHashMap<Id, JsValue<'a>>,
30
31 pub free_var_ids: FxHashMap<Atom, Id>,
36
37 pub effects: Vec<Effect<'a>>,
38 pub code_gens: Vec<CodeGen>,
40 pub ast_paths: AstPathTrieBuilder,
43
44 pub require_usage: FxHashMap<BytePos, ExportUsage>,
47
48 pub cjs_static_exports: Option<CjsStaticExports>,
51
52 pub has_direct_eval: bool,
56}
57
58impl<'a> VarGraph<'a> {
59 pub fn normalize(&mut self, arena: &'a Bump) {
60 for value in self.values.values_mut() {
61 value.normalize(arena);
62 }
63 for effect in self.effects.iter_mut() {
64 effect.normalize(arena);
65 }
66 }
67}
68
69pub fn create_graph<'a>(
70 arena: &'a Bump,
71 m: &Program,
72 eval_context: &EvalContext,
73 analyze_mode: AnalyzeMode,
74 supports_block_scoping: bool,
75 specified_module_type: SpecifiedModuleType,
76 cjs_tree_shaking: bool,
77 cjs_scope_hoisting: bool,
78) -> VarGraph<'a> {
79 let mut analyzer = Analyzer {
80 arena,
81 analyze_mode,
82 data: VarGraph {
83 values: Default::default(),
84 free_var_ids: Default::default(),
85 effects: Default::default(),
86 code_gens: Default::default(),
87 ast_paths: Default::default(),
88 require_usage: Default::default(),
89 cjs_static_exports: Default::default(),
90 has_direct_eval: false,
91 },
92 eval_context,
93 state: Default::default(),
94 effects: Default::default(),
95 hoisted_effects: Default::default(),
96 code_gens: Default::default(),
97 ast_paths: Default::default(),
98 supports_block_scoping,
99 };
100
101 if (cjs_tree_shaking || cjs_scope_hoisting)
104 && analyze_mode.is_codegen
105 && eval_context.is_cjs(specified_module_type)
106 {
107 analyzer.enable_cjs_exports();
108 }
109
110 if cjs_tree_shaking && analyze_mode.is_codegen {
111 analyzer.enable_require_usage(&eval_context.imports);
112 }
113
114 m.visit_with_ast_path(&mut analyzer, &mut Default::default());
115
116 let mut graph = analyzer.data;
117 graph.normalize(arena);
118
119 graph
120}