rspack_plugin_javascript/visitors/dependency/parser/
mod.rs

1mod call_hooks_name;
2pub mod estree;
3mod walk;
4mod walk_block_pre;
5mod walk_module_pre;
6mod walk_pre;
7
8use std::{
9  borrow::Cow,
10  fmt::Display,
11  hash::{Hash, Hasher},
12  rc::Rc,
13  sync::Arc,
14};
15
16use bitflags::bitflags;
17pub use call_hooks_name::CallHooksName;
18use rspack_cacheable::{
19  cacheable,
20  with::{AsCacheable, AsOption, AsPreset, AsVec},
21};
22use rspack_core::{
23  AsyncDependenciesBlock, BoxDependency, BoxDependencyTemplate, BuildInfo, BuildMeta,
24  CompilerOptions, DependencyRange, FactoryMeta, JavascriptParserCommonjsExportsOption,
25  JavascriptParserOptions, ModuleIdentifier, ModuleLayer, ModuleType, ParseMeta, ResourceData,
26  TypeReexportPresenceMode,
27};
28use rspack_error::{Diagnostic, Result};
29use rspack_util::SpanExt;
30use rustc_hash::{FxHashMap, FxHashSet};
31use swc_core::{
32  atoms::Atom,
33  common::{
34    BytePos, Mark, SourceFile, SourceMap, Span, Spanned, comments::Comments, util::take::Take,
35  },
36  ecma::{
37    ast::{
38      ArrayPat, AssignPat, AssignTargetPat, CallExpr, Decl, Expr, Ident, Lit, MemberExpr,
39      MetaPropExpr, MetaPropKind, ObjectPat, ObjectPatProp, OptCall, OptChainBase, OptChainExpr,
40      Pat, Program, RestPat, Stmt, ThisExpr,
41    },
42    utils::ExprFactory,
43  },
44};
45
46use crate::{
47  BoxJavascriptParserPlugin,
48  dependency::local_module::LocalModule,
49  parser_plugin::{
50    self, ImportsReferencesState, InnerGraphState, JavaScriptParserPluginDrive,
51    JavascriptParserPlugin,
52  },
53  utils::eval::{self, BasicEvaluatedExpression},
54  visitors::{
55    ScanDependenciesResult,
56    scope_info::{
57      ScopeInfoDB, ScopeInfoId, TagInfo, TagInfoId, VariableInfo, VariableInfoFlags, VariableInfoId,
58    },
59  },
60};
61
62pub trait TagInfoData: Clone + Sized + 'static {
63  fn into_any(data: Self) -> Box<dyn anymap::CloneAny>;
64
65  fn downcast(any: Box<dyn anymap::CloneAny>) -> Self;
66}
67
68impl<T> TagInfoData for T
69where
70  T: Clone + Sized + 'static,
71{
72  fn into_any(data: Self) -> Box<dyn anymap::CloneAny> {
73    Box::new(data)
74  }
75
76  fn downcast(any: Box<dyn anymap::CloneAny>) -> Self {
77    *(any as Box<dyn std::any::Any>)
78      .downcast()
79      .expect("TagInfoData should be downcasted from correct tag info")
80  }
81}
82
83#[derive(Debug)]
84pub struct ExtractedMemberExpressionChainData {
85  pub object: Expr,
86  pub members: Vec<Atom>,
87  pub members_optionals: Vec<bool>,
88  pub member_ranges: Vec<Span>,
89}
90
91bitflags! {
92  #[derive(Clone, Copy)]
93  pub struct AllowedMemberTypes: u8 {
94    const CallExpression = 1 << 0;
95    const Expression = 1 << 1;
96  }
97}
98
99#[derive(Debug)]
100pub enum MemberExpressionInfo {
101  Call(CallExpressionInfo),
102  Expression(ExpressionExpressionInfo),
103}
104
105#[derive(Debug)]
106pub struct CallExpressionInfo {
107  pub call: CallExpr,
108  pub callee_name: String,
109  pub root_info: ExportedVariableInfo,
110  pub callee_members: Vec<Atom>,
111  pub members: Vec<Atom>,
112  pub members_optionals: Vec<bool>,
113  pub member_ranges: Vec<Span>,
114}
115
116#[derive(Debug)]
117pub struct ExpressionExpressionInfo {
118  pub name: String,
119  pub root_info: ExportedVariableInfo,
120  pub members: Vec<Atom>,
121  pub members_optionals: Vec<bool>,
122  pub member_ranges: Vec<Span>,
123}
124
125#[derive(Debug, Clone)]
126pub enum ExportedVariableInfo {
127  Name(Atom),
128  VariableInfo(VariableInfoId),
129}
130
131fn object_and_members_to_name(object: String, members_reversed: &[impl AsRef<str>]) -> String {
132  let mut name = object;
133  let iter = members_reversed.iter();
134  for member in iter.rev() {
135    name.push('.');
136    name.push_str(member.as_ref());
137  }
138  name
139}
140
141pub trait RootName {
142  fn get_root_name(&self) -> Option<Atom> {
143    None
144  }
145}
146
147impl RootName for Expr {
148  fn get_root_name(&self) -> Option<Atom> {
149    match self {
150      Expr::Ident(ident) => ident.get_root_name(),
151      Expr::This(this) => this.get_root_name(),
152      Expr::MetaProp(meta) => meta.get_root_name(),
153      _ => None,
154    }
155  }
156}
157
158impl RootName for ThisExpr {
159  fn get_root_name(&self) -> Option<Atom> {
160    Some("this".into())
161  }
162}
163
164impl RootName for Ident {
165  fn get_root_name(&self) -> Option<Atom> {
166    Some(self.sym.clone())
167  }
168}
169
170impl RootName for MetaPropExpr {
171  fn get_root_name(&self) -> Option<Atom> {
172    match self.kind {
173      MetaPropKind::NewTarget => Some("new.target".into()),
174      MetaPropKind::ImportMeta => Some("import.meta".into()),
175    }
176  }
177}
178
179pub struct NameInfo<'a> {
180  pub name: &'a Atom,
181  pub info: Option<&'a VariableInfo>,
182}
183
184#[derive(Clone, Copy, Debug)]
185pub enum TopLevelScope {
186  Top,
187  ArrowFunction,
188  False,
189}
190
191#[derive(Debug, Clone, Copy)]
192pub struct StatementPath {
193  span: Span,
194}
195
196impl Spanned for StatementPath {
197  fn span(&self) -> Span {
198    self.span
199  }
200}
201
202impl StatementPath {
203  fn from_span(span: Span) -> Self {
204    Self { span }
205  }
206}
207
208impl From<Span> for StatementPath {
209  fn from(value: Span) -> Self {
210    Self::from_span(value)
211  }
212}
213
214#[cacheable]
215#[derive(Debug, Clone, Hash, PartialEq, Eq)]
216pub struct DestructuringAssignmentProperty {
217  pub range: DependencyRange,
218  #[cacheable(with=AsPreset)]
219  pub id: Atom,
220  #[cacheable(omit_bounds, with=AsOption<AsCacheable>)]
221  pub pattern: Option<DestructuringAssignmentProperties>,
222  pub shorthand: bool,
223}
224
225#[cacheable]
226#[derive(Debug, Default, Clone, PartialEq, Eq)]
227pub struct DestructuringAssignmentProperties {
228  #[cacheable(with=AsVec<AsCacheable>)]
229  inner: FxHashSet<DestructuringAssignmentProperty>,
230}
231
232impl Hash for DestructuringAssignmentProperties {
233  fn hash<H: Hasher>(&self, state: &mut H) {
234    for prop in &self.inner {
235      prop.hash(state);
236    }
237  }
238}
239
240impl DestructuringAssignmentProperties {
241  pub fn new(properties: FxHashSet<DestructuringAssignmentProperty>) -> Self {
242    Self { inner: properties }
243  }
244
245  pub fn insert(&mut self, prop: DestructuringAssignmentProperty) -> bool {
246    self.inner.insert(prop)
247  }
248
249  pub fn extend(&mut self, other: Self) {
250    self.inner.extend(other.inner);
251  }
252
253  pub fn iter(&self) -> impl Iterator<Item = &DestructuringAssignmentProperty> {
254    self.inner.iter()
255  }
256
257  pub fn traverse_on_left<'a, F>(&'a self, on_left_node: &mut F)
258  where
259    F: FnMut(&mut Vec<&'a DestructuringAssignmentProperty>),
260  {
261    self.traverse_impl(on_left_node, &mut |_| {}, &mut Vec::new());
262  }
263
264  pub fn traverse_on_enter<'a, F>(&'a self, on_enter_node: &mut F)
265  where
266    F: FnMut(&mut Vec<&'a DestructuringAssignmentProperty>),
267  {
268    self.traverse_impl(&mut |_| {}, on_enter_node, &mut Vec::new());
269  }
270
271  fn traverse_impl<'a, L, E>(
272    &'a self,
273    on_left_node: &mut L,
274    on_enter_node: &mut E,
275    stack: &mut Vec<&'a DestructuringAssignmentProperty>,
276  ) where
277    L: FnMut(&mut Vec<&'a DestructuringAssignmentProperty>),
278    E: FnMut(&mut Vec<&'a DestructuringAssignmentProperty>),
279  {
280    for prop in &self.inner {
281      stack.push(prop);
282      on_enter_node(stack);
283      if let Some(pattern) = &prop.pattern {
284        pattern.traverse_impl(on_left_node, on_enter_node, stack);
285      } else {
286        on_left_node(stack);
287      }
288      stack.pop();
289    }
290  }
291}
292
293#[derive(Debug, Default)]
294pub struct DestructuringAssignmentPropertiesMap {
295  inner: FxHashMap<Span, DestructuringAssignmentProperties>,
296}
297
298impl DestructuringAssignmentPropertiesMap {
299  pub fn add(&mut self, span: Span, props: DestructuringAssignmentProperties) {
300    self.inner.entry(span).or_default().extend(props)
301  }
302
303  pub fn get(&self, span: &Span) -> Option<&DestructuringAssignmentProperties> {
304    self.inner.get(span)
305  }
306}
307
308pub struct JavascriptParser<'parser> {
309  // ===== results =======
310  errors: Vec<Diagnostic>,
311  warning_diagnostics: Vec<Diagnostic>,
312  dependencies: Vec<BoxDependency>,
313  presentational_dependencies: Vec<BoxDependencyTemplate>,
314  // Vec<Box<T: Sized>> makes sense if T is a large type (see #3530, 1st comment).
315  // #3530: https://github.com/rust-lang/rust-clippy/issues/3530
316  #[allow(clippy::vec_box)]
317  blocks: Vec<Box<AsyncDependenciesBlock>>,
318  // ===== inputs =======
319  pub source_map: Arc<SourceMap>,
320  pub(crate) source_file: &'parser SourceFile,
321  pub parse_meta: ParseMeta,
322  pub comments: Option<&'parser dyn Comments>,
323  pub factory_meta: Option<&'parser FactoryMeta>,
324  pub build_meta: &'parser mut BuildMeta,
325  pub build_info: &'parser mut BuildInfo,
326  pub resource_data: &'parser ResourceData,
327  pub(crate) compiler_options: &'parser CompilerOptions,
328  pub(crate) javascript_options: &'parser JavascriptParserOptions,
329  pub(crate) module_type: &'parser ModuleType,
330  pub(crate) module_layer: Option<&'parser ModuleLayer>,
331  pub module_identifier: &'parser ModuleIdentifier,
332  pub(crate) plugin_drive: Rc<JavaScriptParserPluginDrive>,
333  // ===== states =======
334  pub(crate) definitions_db: ScopeInfoDB,
335  pub(super) definitions: ScopeInfoId,
336  pub(crate) top_level_scope: TopLevelScope,
337  pub(crate) current_tag_info: Option<TagInfoId>,
338  pub in_try: bool,
339  pub(crate) in_short_hand: bool,
340  pub(crate) in_tagged_template_tag: bool,
341  pub(crate) member_expr_in_optional_chain: bool,
342  pub(crate) semicolons: &'parser mut FxHashSet<BytePos>,
343  pub(crate) statement_path: Vec<StatementPath>,
344  pub(crate) prev_statement: Option<StatementPath>,
345  pub is_esm: bool,
346  pub(crate) destructuring_assignment_properties: DestructuringAssignmentPropertiesMap,
347  pub(crate) dynamic_import_references: ImportsReferencesState,
348  pub(crate) worker_index: u32,
349  pub(crate) parser_exports_state: Option<bool>,
350  pub(crate) local_modules: Vec<LocalModule>,
351  pub(crate) last_esm_import_order: i32,
352  pub(crate) inner_graph: InnerGraphState,
353  pub(crate) has_inlinable_const_decls: bool,
354}
355
356impl<'parser> JavascriptParser<'parser> {
357  #[allow(clippy::too_many_arguments)]
358  pub fn new(
359    source_map: Arc<SourceMap>,
360    source_file: &'parser SourceFile,
361    compiler_options: &'parser CompilerOptions,
362    javascript_options: &'parser JavascriptParserOptions,
363    comments: Option<&'parser dyn Comments>,
364    module_identifier: &'parser ModuleIdentifier,
365    module_type: &'parser ModuleType,
366    module_layer: Option<&'parser ModuleLayer>,
367    resource_data: &'parser ResourceData,
368    factory_meta: Option<&'parser FactoryMeta>,
369    build_meta: &'parser mut BuildMeta,
370    build_info: &'parser mut BuildInfo,
371    semicolons: &'parser mut FxHashSet<BytePos>,
372    unresolved_mark: Mark,
373    parser_plugins: &'parser mut Vec<BoxJavascriptParserPlugin>,
374    parse_meta: ParseMeta,
375  ) -> Self {
376    let warning_diagnostics: Vec<Diagnostic> = Vec::with_capacity(4);
377    let mut errors = Vec::with_capacity(4);
378    let dependencies = Vec::with_capacity(64);
379    let blocks = Vec::with_capacity(64);
380    let presentational_dependencies = Vec::with_capacity(64);
381    let parser_exports_state: Option<bool> = None;
382
383    let mut plugins: Vec<BoxJavascriptParserPlugin> = Vec::with_capacity(32);
384
385    plugins.append(parser_plugins);
386
387    plugins.push(Box::new(parser_plugin::InitializeEvaluating));
388    plugins.push(Box::new(parser_plugin::JavascriptMetaInfoPlugin));
389    plugins.push(Box::new(parser_plugin::CheckVarDeclaratorIdent));
390    plugins.push(Box::new(parser_plugin::ConstPlugin));
391    plugins.push(Box::new(parser_plugin::UseStrictPlugin));
392    plugins.push(Box::new(
393      parser_plugin::RequireContextDependencyParserPlugin,
394    ));
395    plugins.push(Box::new(
396      parser_plugin::RequireEnsureDependenciesBlockParserPlugin,
397    ));
398    plugins.push(Box::new(parser_plugin::CompatibilityPlugin));
399
400    if module_type.is_js_auto() || module_type.is_js_esm() {
401      plugins.push(Box::new(parser_plugin::ESMTopLevelThisParserPlugin));
402      plugins.push(Box::new(parser_plugin::ESMDetectionParserPlugin::new(
403        compiler_options.experiments.top_level_await,
404      )));
405      plugins.push(Box::new(
406        parser_plugin::ImportMetaContextDependencyParserPlugin,
407      ));
408      if let Some(true) = javascript_options.import_meta {
409        plugins.push(Box::new(parser_plugin::ImportMetaPlugin));
410      } else {
411        plugins.push(Box::new(parser_plugin::ImportMetaDisabledPlugin));
412      }
413
414      plugins.push(Box::new(parser_plugin::ESMImportDependencyParserPlugin));
415      plugins.push(Box::new(parser_plugin::ESMExportDependencyParserPlugin));
416    }
417
418    if compiler_options.amd.is_some() && (module_type.is_js_auto() || module_type.is_js_dynamic()) {
419      plugins.push(Box::new(
420        parser_plugin::AMDRequireDependenciesBlockParserPlugin,
421      ));
422      plugins.push(Box::new(parser_plugin::AMDDefineDependencyParserPlugin));
423      plugins.push(Box::new(parser_plugin::AMDParserPlugin));
424    }
425
426    if module_type.is_js_auto() || module_type.is_js_dynamic() {
427      plugins.push(Box::new(parser_plugin::CommonJsImportsParserPlugin));
428      plugins.push(Box::new(parser_plugin::CommonJsPlugin));
429      let commonjs_exports = javascript_options
430        .commonjs
431        .as_ref()
432        .map_or(JavascriptParserCommonjsExportsOption::Enable, |commonjs| {
433          commonjs.exports
434        });
435      if commonjs_exports != JavascriptParserCommonjsExportsOption::Disable {
436        plugins.push(Box::new(parser_plugin::CommonJsExportsParserPlugin::new(
437          commonjs_exports == JavascriptParserCommonjsExportsOption::SkipInEsm,
438        )));
439      }
440      if compiler_options.node.is_some() {
441        plugins.push(Box::new(parser_plugin::NodeStuffPlugin));
442      }
443    }
444
445    if module_type.is_js_auto() || module_type.is_js_dynamic() || module_type.is_js_esm() {
446      plugins.push(Box::new(parser_plugin::WebpackIsIncludedPlugin));
447      plugins.push(Box::new(parser_plugin::ExportsInfoApiPlugin));
448      plugins.push(Box::new(parser_plugin::APIPlugin::new(
449        compiler_options.output.module,
450      )));
451      plugins.push(Box::new(parser_plugin::ImportParserPlugin));
452      plugins.push(Box::new(parser_plugin::WorkerPlugin::new(
453        javascript_options
454          .worker
455          .as_ref()
456          .expect("should have worker"),
457      )));
458      plugins.push(Box::new(parser_plugin::OverrideStrictPlugin));
459    }
460
461    // disabled by default for now, it's still experimental
462    if javascript_options.inline_const.unwrap_or_default() {
463      if !compiler_options.experiments.inline_const {
464        errors.push(rspack_error::error!("inlineConst is still an experimental feature. To continue using it, please enable 'experiments.inlineConst'.").into());
465      } else {
466        plugins.push(Box::new(parser_plugin::InlineConstPlugin));
467      }
468    }
469    if compiler_options.optimization.inner_graph {
470      plugins.push(Box::new(parser_plugin::InnerGraphPlugin::new(
471        unresolved_mark,
472      )));
473    }
474
475    if !matches!(
476      javascript_options
477        .type_reexports_presence
478        .unwrap_or_default(),
479      TypeReexportPresenceMode::NoTolerant
480    ) && !compiler_options.experiments.type_reexports_presence
481    {
482      errors.push(rspack_error::error!("typeReexportsPresence is still an experimental feature. To continue using it, please enable 'experiments.typeReexportsPresence'.").into());
483    }
484
485    let plugin_drive = Rc::new(JavaScriptParserPluginDrive::new(plugins));
486    let mut db = ScopeInfoDB::new();
487
488    Self {
489      last_esm_import_order: 0,
490      comments,
491      javascript_options,
492      source_map,
493      source_file,
494      errors,
495      warning_diagnostics,
496      dependencies,
497      presentational_dependencies,
498      blocks,
499      in_try: false,
500      in_short_hand: false,
501      top_level_scope: TopLevelScope::Top,
502      is_esm: matches!(module_type, ModuleType::JsEsm),
503      in_tagged_template_tag: false,
504      definitions: db.create(),
505      definitions_db: db,
506      plugin_drive,
507      resource_data,
508      factory_meta,
509      build_meta,
510      build_info,
511      compiler_options,
512      module_type,
513      module_layer,
514      parser_exports_state,
515      worker_index: 0,
516      module_identifier,
517      member_expr_in_optional_chain: false,
518      destructuring_assignment_properties: Default::default(),
519      dynamic_import_references: Default::default(),
520      semicolons,
521      statement_path: Default::default(),
522      current_tag_info: None,
523      prev_statement: None,
524      inner_graph: InnerGraphState::new(),
525      parse_meta,
526      local_modules: Default::default(),
527      has_inlinable_const_decls: true,
528    }
529  }
530
531  pub fn into_results(self) -> Result<ScanDependenciesResult, Vec<Diagnostic>> {
532    if self.errors.is_empty() {
533      Ok(ScanDependenciesResult {
534        dependencies: self.dependencies,
535        blocks: self.blocks,
536        presentational_dependencies: self.presentational_dependencies,
537        warning_diagnostics: self.warning_diagnostics,
538      })
539    } else {
540      Err(self.errors)
541    }
542  }
543
544  pub fn add_dependency(&mut self, dep: BoxDependency) {
545    self.dependencies.push(dep);
546  }
547
548  pub fn add_dependencies(&mut self, deps: impl IntoIterator<Item = BoxDependency>) {
549    self.dependencies.extend(deps);
550  }
551
552  pub fn pop_dependency(&mut self) -> Option<BoxDependency> {
553    self.dependencies.pop()
554  }
555
556  pub fn next_dependency_idx(&self) -> usize {
557    self.dependencies.len()
558  }
559
560  pub fn get_dependency_mut(&mut self, idx: usize) -> Option<&mut BoxDependency> {
561    self.dependencies.get_mut(idx)
562  }
563
564  pub fn collect_dependencies_for_block(
565    &mut self,
566    f: impl FnOnce(&mut JavascriptParser),
567  ) -> Vec<BoxDependency> {
568    let old_deps = std::mem::take(&mut self.dependencies);
569    f(self);
570    std::mem::replace(&mut self.dependencies, old_deps)
571  }
572
573  pub fn add_presentational_dependency(&mut self, dep: BoxDependencyTemplate) {
574    self.presentational_dependencies.push(dep);
575  }
576
577  pub fn add_presentational_dependencies(
578    &mut self,
579    deps: impl IntoIterator<Item = BoxDependencyTemplate>,
580  ) {
581    self.presentational_dependencies.extend(deps);
582  }
583
584  pub fn next_presentational_dependency_idx(&self) -> usize {
585    self.presentational_dependencies.len()
586  }
587
588  pub fn get_presentational_dependency_mut(
589    &mut self,
590    idx: usize,
591  ) -> Option<&mut BoxDependencyTemplate> {
592    self.presentational_dependencies.get_mut(idx)
593  }
594
595  pub fn add_block(&mut self, block: Box<AsyncDependenciesBlock>) {
596    self.blocks.push(block);
597  }
598
599  pub fn next_block_idx(&self) -> usize {
600    self.blocks.len()
601  }
602
603  pub fn get_block_mut(&mut self, idx: usize) -> Option<&mut Box<AsyncDependenciesBlock>> {
604    self.blocks.get_mut(idx)
605  }
606
607  pub fn add_error(&mut self, error: Diagnostic) {
608    self.errors.push(error);
609  }
610
611  pub fn add_errors(&mut self, errors: impl IntoIterator<Item = Diagnostic>) {
612    self.errors.extend(errors);
613  }
614
615  pub fn add_warning(&mut self, warning: Diagnostic) {
616    self.warning_diagnostics.push(warning);
617  }
618
619  pub fn add_warnings(&mut self, warnings: impl IntoIterator<Item = Diagnostic>) {
620    self.warning_diagnostics.extend(warnings);
621  }
622
623  pub fn is_top_level_scope(&self) -> bool {
624    matches!(self.top_level_scope, TopLevelScope::Top)
625  }
626
627  pub fn is_top_level_this(&self) -> bool {
628    !matches!(self.top_level_scope, TopLevelScope::False)
629  }
630
631  pub fn add_local_module(&mut self, name: &Atom, dep_idx: usize) {
632    self.local_modules.push(LocalModule::new(
633      name.clone(),
634      self.local_modules.len(),
635      dep_idx,
636    ));
637  }
638
639  pub fn get_local_module_mut(&mut self, name: &str) -> Option<&mut LocalModule> {
640    self.local_modules.iter_mut().find(|m| m.get_name() == name)
641  }
642
643  pub fn is_asi_position(&self, pos: BytePos) -> bool {
644    let curr_path = self.statement_path.last().expect("Should in statement");
645    if curr_path.span_hi() == pos && self.semicolons.contains(&pos) {
646      true
647    } else if curr_path.span_lo() == pos
648      && let Some(prev) = &self.prev_statement
649      && self.semicolons.contains(&prev.span_hi())
650    {
651      true
652    } else {
653      false
654    }
655  }
656
657  pub fn set_asi_position(&mut self, pos: BytePos) -> bool {
658    self.semicolons.insert(pos)
659  }
660
661  pub fn unset_asi_position(&mut self, pos: BytePos) -> bool {
662    self.semicolons.remove(&pos)
663  }
664
665  pub fn is_statement_level_expression(&self, expr_span: Span) -> bool {
666    let Some(curr_path) = self.statement_path.last() else {
667      return false;
668    };
669    curr_path.span() == expr_span
670  }
671
672  pub fn get_module_layer(&self) -> Option<&ModuleLayer> {
673    self.module_layer
674  }
675
676  pub fn get_variable_info(&mut self, name: &Atom) -> Option<&VariableInfo> {
677    let id = self.definitions_db.get(self.definitions, name)?;
678    Some(self.definitions_db.expect_get_variable(id))
679  }
680
681  pub fn get_tag_data(
682    &mut self,
683    name: &Atom,
684    tag: &'static str,
685  ) -> Option<Box<dyn anymap::CloneAny>> {
686    self
687      .get_variable_info(name)
688      .and_then(|variable_info| variable_info.tag_info)
689      .and_then(|tag_info_id| {
690        let mut tag_info = Some(self.definitions_db.expect_get_tag_info(tag_info_id));
691
692        while let Some(cur_tag_info) = tag_info {
693          if cur_tag_info.tag == tag {
694            return cur_tag_info.data.clone();
695          }
696          tag_info = cur_tag_info
697            .next
698            .map(|tag_info_id| self.definitions_db.expect_get_tag_info(tag_info_id))
699        }
700
701        None
702      })
703  }
704
705  pub fn get_free_info_from_variable<'a>(&'a mut self, name: &'a Atom) -> Option<NameInfo<'a>> {
706    let Some(info) = self.get_variable_info(name) else {
707      return Some(NameInfo { name, info: None });
708    };
709    let Some(name) = &info.name else {
710      return None;
711    };
712    if !info.is_free() {
713      return None;
714    }
715    Some(NameInfo {
716      name,
717      info: Some(info),
718    })
719  }
720
721  pub fn get_name_info_from_variable<'a>(&'a mut self, name: &'a Atom) -> Option<NameInfo<'a>> {
722    let Some(info) = self.get_variable_info(name) else {
723      return Some(NameInfo { name, info: None });
724    };
725    let Some(name) = &info.name else {
726      return None;
727    };
728    if !info.is_free() && !info.is_tagged() {
729      return None;
730    }
731    Some(NameInfo {
732      name,
733      info: Some(info),
734    })
735  }
736
737  pub fn get_all_variables_from_current_scope(
738    &self,
739  ) -> impl Iterator<Item = (&str, &VariableInfoId)> {
740    let scope = self.definitions_db.expect_get_scope(self.definitions);
741    scope.variables()
742  }
743
744  pub fn define_variable(&mut self, name: Atom) {
745    let definitions = self.definitions;
746    if let Some(variable_info) = self.get_variable_info(&name)
747      && variable_info.tag_info.is_some()
748      && definitions == variable_info.declared_scope
749    {
750      return;
751    }
752    let info = VariableInfo::create(
753      &mut self.definitions_db,
754      definitions,
755      None,
756      VariableInfoFlags::NORMAL,
757      None,
758    );
759    self.definitions_db.set(definitions, name, info);
760  }
761
762  pub fn set_variable(&mut self, name: Atom, variable: ExportedVariableInfo) {
763    let scope_id = self.definitions;
764    match variable {
765      ExportedVariableInfo::Name(variable) => {
766        if name == variable {
767          self.definitions_db.delete(scope_id, &name);
768        } else {
769          let variable = VariableInfo::create(
770            &mut self.definitions_db,
771            scope_id,
772            Some(variable),
773            VariableInfoFlags::FREE,
774            None,
775          );
776          self.definitions_db.set(scope_id, name, variable);
777        }
778      }
779      ExportedVariableInfo::VariableInfo(variable) => {
780        self.definitions_db.set(scope_id, name, variable);
781      }
782    }
783  }
784
785  fn undefined_variable(&mut self, name: &Atom) {
786    self.definitions_db.delete(self.definitions, name)
787  }
788
789  pub fn tag_variable<Data: TagInfoData>(
790    &mut self,
791    name: Atom,
792    tag: &'static str,
793    data: Option<Data>,
794  ) {
795    self.tag_variable_impl(name, tag, data, None);
796  }
797
798  pub fn tag_variable_with_flags<Data: TagInfoData>(
799    &mut self,
800    name: Atom,
801    tag: &'static str,
802    data: Option<Data>,
803    flags: VariableInfoFlags,
804  ) {
805    self.tag_variable_impl(name, tag, data, Some(flags));
806  }
807
808  fn tag_variable_impl<Data: TagInfoData>(
809    &mut self,
810    name: Atom,
811    tag: &'static str,
812    data: Option<Data>,
813    flags: Option<VariableInfoFlags>,
814  ) {
815    let flags = flags.unwrap_or(VariableInfoFlags::TAGGED);
816    let data = data.map(|data| TagInfoData::into_any(data));
817    let new_info = if let Some(old_info_id) = self.definitions_db.get(self.definitions, &name) {
818      let old_info = self.definitions_db.expect_get_variable(old_info_id);
819      if let Some(old_tag_info) = old_info.tag_info {
820        let declared_scope = old_info.declared_scope;
821        // FIXME: remove `.clone`
822        let name = old_info.name.clone();
823        let flags = old_info.flags | flags;
824        let tag_info = Some(TagInfo::create(
825          &mut self.definitions_db,
826          tag,
827          data,
828          Some(old_tag_info),
829        ));
830        VariableInfo::create(
831          &mut self.definitions_db,
832          declared_scope,
833          name,
834          flags,
835          tag_info,
836        )
837      } else {
838        let declared_scope = old_info.declared_scope;
839        let tag_info = Some(TagInfo::create(&mut self.definitions_db, tag, data, None));
840        VariableInfo::create(
841          &mut self.definitions_db,
842          declared_scope,
843          Some(name.clone()),
844          flags,
845          tag_info,
846        )
847      }
848    } else {
849      let tag_info = Some(TagInfo::create(&mut self.definitions_db, tag, data, None));
850      VariableInfo::create(
851        &mut self.definitions_db,
852        self.definitions,
853        Some(name.clone()),
854        flags,
855        tag_info,
856      )
857    };
858    self.definitions_db.set(self.definitions, name, new_info);
859  }
860
861  fn _get_member_expression_info(
862    &mut self,
863    object: Expr,
864    mut members: Vec<Atom>,
865    mut members_optionals: Vec<bool>,
866    mut member_ranges: Vec<Span>,
867    allowed_types: AllowedMemberTypes,
868  ) -> Option<MemberExpressionInfo> {
869    match object {
870      Expr::Call(expr) => {
871        if !allowed_types.contains(AllowedMemberTypes::CallExpression) {
872          return None;
873        }
874        let callee = expr.callee.as_expr()?;
875        let (root_name, mut root_members) = if let Some(member) = callee.as_member() {
876          let extracted = self.extract_member_expression_chain(member);
877          let root_name = extracted.object.get_root_name()?;
878          (root_name, extracted.members)
879        } else {
880          (callee.get_root_name()?, vec![])
881        };
882        let NameInfo {
883          name: resolved_root,
884          info: root_info,
885        } = self.get_name_info_from_variable(&root_name)?;
886
887        let callee_name = object_and_members_to_name(resolved_root.to_string(), &root_members);
888        root_members.reverse();
889        members.reverse();
890        members_optionals.reverse();
891        member_ranges.reverse();
892        Some(MemberExpressionInfo::Call(CallExpressionInfo {
893          call: expr,
894          callee_name,
895          root_info: root_info
896            .map(|i| ExportedVariableInfo::VariableInfo(i.id()))
897            .unwrap_or_else(|| ExportedVariableInfo::Name(root_name)),
898          callee_members: root_members,
899          members,
900          members_optionals,
901          member_ranges,
902        }))
903      }
904      Expr::MetaProp(_) | Expr::Ident(_) | Expr::This(_) => {
905        if !allowed_types.contains(AllowedMemberTypes::Expression) {
906          return None;
907        }
908        let root_name = object.get_root_name()?;
909
910        let NameInfo {
911          name: resolved_root,
912          info: root_info,
913        } = self.get_name_info_from_variable(&root_name)?;
914
915        let name = object_and_members_to_name(resolved_root.to_string(), &members);
916        members.reverse();
917        members_optionals.reverse();
918        member_ranges.reverse();
919        Some(MemberExpressionInfo::Expression(ExpressionExpressionInfo {
920          name,
921          root_info: root_info
922            .map(|i| ExportedVariableInfo::VariableInfo(i.id()))
923            .unwrap_or_else(|| ExportedVariableInfo::Name(root_name)),
924          members,
925          members_optionals,
926          member_ranges,
927        }))
928      }
929      _ => None,
930    }
931  }
932
933  pub fn get_member_expression_info_from_expr(
934    &mut self,
935    expr: &Expr,
936    allowed_types: AllowedMemberTypes,
937  ) -> Option<MemberExpressionInfo> {
938    expr
939      .as_member()
940      .and_then(|member| self.get_member_expression_info(member, allowed_types))
941      .or_else(|| {
942        self._get_member_expression_info(expr.clone(), vec![], vec![], vec![], allowed_types)
943      })
944  }
945
946  pub fn get_member_expression_info(
947    &mut self,
948    expr: &MemberExpr,
949    allowed_types: AllowedMemberTypes,
950  ) -> Option<MemberExpressionInfo> {
951    let ExtractedMemberExpressionChainData {
952      object,
953      members,
954      members_optionals,
955      member_ranges,
956    } = self.extract_member_expression_chain(expr);
957    self._get_member_expression_info(
958      object,
959      members,
960      members_optionals,
961      member_ranges,
962      allowed_types,
963    )
964  }
965
966  pub fn extract_member_expression_chain(
967    &self,
968    expr: &MemberExpr,
969  ) -> ExtractedMemberExpressionChainData {
970    let mut object = Expr::Member(expr.clone());
971    let mut members = Vec::new();
972    let mut members_optionals = Vec::new();
973    let mut member_ranges = Vec::new();
974    let mut in_optional_chain = self.member_expr_in_optional_chain;
975    loop {
976      match &mut object {
977        Expr::Member(expr) => {
978          if let Some(computed) = expr.prop.as_computed() {
979            let Expr::Lit(lit) = &*computed.expr else {
980              break;
981            };
982            let value = match lit {
983              Lit::Str(s) => s.value.clone(),
984              Lit::Bool(b) => if b.value { "true" } else { "false" }.into(),
985              Lit::Null(_) => "null".into(),
986              Lit::Num(n) => n.value.to_string().into(),
987              Lit::BigInt(i) => i.value.to_string().into(),
988              Lit::Regex(r) => r.exp.clone(),
989              Lit::JSXText(_) => unreachable!(),
990            };
991            members.push(value);
992            member_ranges.push(expr.obj.span());
993          } else if let Some(ident) = expr.prop.as_ident() {
994            members.push(ident.sym.clone());
995            member_ranges.push(expr.obj.span());
996          } else {
997            break;
998          }
999          members_optionals.push(in_optional_chain);
1000          object = *expr.obj.take();
1001          in_optional_chain = false;
1002        }
1003        Expr::OptChain(expr) => {
1004          in_optional_chain = expr.optional;
1005          if let OptChainBase::Member(member) = &mut *expr.base {
1006            object = Expr::Member(member.take());
1007          } else {
1008            break;
1009          }
1010        }
1011        _ => break,
1012      }
1013    }
1014    ExtractedMemberExpressionChainData {
1015      object,
1016      members,
1017      members_optionals,
1018      member_ranges,
1019    }
1020  }
1021
1022  fn enter_ident<F>(&mut self, ident: &Ident, on_ident: F)
1023  where
1024    F: FnOnce(&mut Self, &Ident),
1025  {
1026    if !ident
1027      .sym
1028      .call_hooks_name(self, |parser, for_name| {
1029        parser.plugin_drive.clone().pattern(parser, ident, for_name)
1030      })
1031      .unwrap_or_default()
1032    {
1033      on_ident(self, ident);
1034    }
1035  }
1036
1037  fn enter_array_pattern<F>(&mut self, array_pat: &ArrayPat, on_ident: F)
1038  where
1039    F: FnOnce(&mut Self, &Ident) + Copy,
1040  {
1041    array_pat
1042      .elems
1043      .iter()
1044      .flatten()
1045      .for_each(|ele| self.enter_pattern(Cow::Borrowed(ele), on_ident));
1046  }
1047
1048  fn enter_assignment_pattern<F>(&mut self, assign: &AssignPat, on_ident: F)
1049  where
1050    F: FnOnce(&mut Self, &Ident) + Copy,
1051  {
1052    self.enter_pattern(Cow::Borrowed(&assign.left), on_ident);
1053  }
1054
1055  fn enter_object_pattern<F>(&mut self, obj: &ObjectPat, on_ident: F)
1056  where
1057    F: FnOnce(&mut Self, &Ident) + Copy,
1058  {
1059    for prop in &obj.props {
1060      match prop {
1061        ObjectPatProp::KeyValue(kv) => self.enter_pattern(Cow::Borrowed(&kv.value), on_ident),
1062        ObjectPatProp::Assign(assign) => {
1063          let old = self.in_short_hand;
1064          if assign.value.is_none() {
1065            self.in_short_hand = true;
1066          }
1067          self.enter_ident(&assign.key, on_ident);
1068          self.in_short_hand = old;
1069        }
1070        ObjectPatProp::Rest(rest) => self.enter_rest_pattern(rest, on_ident),
1071      }
1072    }
1073  }
1074
1075  fn enter_rest_pattern<F>(&mut self, rest: &RestPat, on_ident: F)
1076  where
1077    F: FnOnce(&mut Self, &Ident) + Copy,
1078  {
1079    self.enter_pattern(Cow::Borrowed(&rest.arg), on_ident)
1080  }
1081
1082  fn enter_pattern<F>(&mut self, pattern: Cow<Pat>, on_ident: F)
1083  where
1084    F: FnOnce(&mut Self, &Ident) + Copy,
1085  {
1086    match &*pattern {
1087      Pat::Ident(ident) => self.enter_ident(&ident.id, on_ident),
1088      Pat::Array(array) => self.enter_array_pattern(array, on_ident),
1089      Pat::Assign(assign) => self.enter_assignment_pattern(assign, on_ident),
1090      Pat::Object(obj) => self.enter_object_pattern(obj, on_ident),
1091      Pat::Rest(rest) => self.enter_rest_pattern(rest, on_ident),
1092      Pat::Invalid(_) => (),
1093      Pat::Expr(_) => (),
1094    }
1095  }
1096
1097  fn enter_assign_target_pattern<F>(&mut self, pattern: Cow<AssignTargetPat>, on_ident: F)
1098  where
1099    F: FnOnce(&mut Self, &Ident) + Copy,
1100  {
1101    match &*pattern {
1102      AssignTargetPat::Array(array) => self.enter_array_pattern(array, on_ident),
1103      AssignTargetPat::Object(obj) => self.enter_object_pattern(obj, on_ident),
1104      AssignTargetPat::Invalid(_) => (),
1105    }
1106  }
1107
1108  fn enter_patterns<'a, I, F>(&mut self, patterns: I, on_ident: F)
1109  where
1110    F: FnOnce(&mut Self, &Ident) + Copy,
1111    I: Iterator<Item = Cow<'a, Pat>>,
1112  {
1113    for pattern in patterns {
1114      self.enter_pattern(pattern, on_ident);
1115    }
1116  }
1117
1118  fn enter_optional_chain<'a, C, M, R>(
1119    &mut self,
1120    expr: &'a OptChainExpr,
1121    on_call: C,
1122    on_member: M,
1123  ) -> R
1124  where
1125    C: FnOnce(&mut Self, &'a OptCall) -> R,
1126    M: FnOnce(&mut Self, &'a MemberExpr) -> R,
1127  {
1128    let member_expr_in_optional_chain = self.member_expr_in_optional_chain;
1129    let ret = match &*expr.base {
1130      OptChainBase::Call(call) => {
1131        if call.callee.is_member() {
1132          self.member_expr_in_optional_chain = expr.optional;
1133        }
1134        on_call(self, call)
1135      }
1136      OptChainBase::Member(member) => {
1137        self.member_expr_in_optional_chain = expr.optional;
1138        on_member(self, member)
1139      }
1140    };
1141    self.member_expr_in_optional_chain = member_expr_in_optional_chain;
1142    ret
1143  }
1144
1145  fn enter_declaration<F>(&mut self, decl: &Decl, on_ident: F)
1146  where
1147    F: FnOnce(&mut Self, &Ident) + Copy,
1148  {
1149    match decl {
1150      Decl::Class(c) => {
1151        self.enter_ident(&c.ident, on_ident);
1152      }
1153      Decl::Fn(f) => {
1154        self.enter_ident(&f.ident, on_ident);
1155      }
1156      Decl::Var(var) => {
1157        for decl in &var.decls {
1158          self.enter_pattern(Cow::Borrowed(&decl.name), on_ident);
1159        }
1160      }
1161      Decl::Using(_) => (),
1162      _ => unreachable!(),
1163    }
1164  }
1165
1166  fn enter_statement<S, H, F>(&mut self, statement: &S, call_hook: H, on_statement: F)
1167  where
1168    S: Spanned,
1169    H: FnOnce(&mut Self, &S) -> bool,
1170    F: FnOnce(&mut Self, &S),
1171  {
1172    self.statement_path.push(statement.span().into());
1173    if call_hook(self, statement) {
1174      self.prev_statement = self.statement_path.pop();
1175      return;
1176    }
1177    on_statement(self, statement);
1178    self.prev_statement = self.statement_path.pop();
1179  }
1180
1181  pub fn enter_destructuring_assignment<'a>(
1182    &mut self,
1183    pattern: &ObjectPat,
1184    expr: &'a Expr,
1185  ) -> Option<&'a Expr> {
1186    let expr = if let Some(await_expr) = expr.as_await_expr() {
1187      &await_expr.arg
1188    } else {
1189      expr
1190    };
1191    let destructuring = if let Some(assign) = expr.as_assign()
1192      && let Some(pat) = assign.left.as_pat()
1193      && let Some(obj_pat) = pat.as_object()
1194    {
1195      self.enter_destructuring_assignment(obj_pat, &assign.right)
1196    } else {
1197      let can_collect = self
1198        .plugin_drive
1199        .clone()
1200        .can_collect_destructuring_assignment_properties(self, expr)
1201        .unwrap_or_default();
1202      can_collect.then_some(expr)
1203    };
1204    if let Some(destructuring) = destructuring
1205      && let Some(keys) =
1206        self.collect_destructuring_assignment_properties_from_object_pattern(pattern)
1207    {
1208      self
1209        .destructuring_assignment_properties
1210        .add(destructuring.span(), keys);
1211    }
1212    destructuring
1213  }
1214
1215  pub fn walk_program(&mut self, ast: &Program) {
1216    if self.plugin_drive.clone().program(self, ast).is_none() {
1217      match ast {
1218        Program::Module(m) => {
1219          self.set_strict(true);
1220          self.prev_statement = None;
1221          self.module_pre_walk_module_items(&m.body);
1222          self.prev_statement = None;
1223          self.pre_walk_module_items(&m.body);
1224          self.prev_statement = None;
1225          self.block_pre_walk_module_items(&m.body);
1226          self.prev_statement = None;
1227          self.walk_module_items(&m.body);
1228        }
1229        Program::Script(s) => {
1230          self.detect_mode(&s.body);
1231          self.prev_statement = None;
1232          self.pre_walk_statements(&s.body);
1233          self.prev_statement = None;
1234          self.block_pre_walk_statements(&s.body);
1235          self.prev_statement = None;
1236          self.walk_statements(&s.body);
1237        }
1238      };
1239    }
1240    self.plugin_drive.clone().finish(self);
1241  }
1242
1243  fn set_strict(&mut self, value: bool) {
1244    let current_scope = self.definitions_db.expect_get_mut_scope(self.definitions);
1245    current_scope.is_strict = value;
1246  }
1247
1248  pub fn detect_mode(&mut self, stmts: &[Stmt]) {
1249    let Some(Lit::Str(str)) = stmts
1250      .first()
1251      .and_then(|stmt| stmt.as_expr())
1252      .and_then(|expr_stmt| expr_stmt.expr.as_lit())
1253    else {
1254      return;
1255    };
1256
1257    if str.value.as_str() == "use strict" {
1258      self.set_strict(true);
1259    }
1260  }
1261
1262  pub fn is_strict(&mut self) -> bool {
1263    let scope = self.definitions_db.expect_get_scope(self.definitions);
1264    scope.is_strict
1265  }
1266
1267  pub fn is_variable_defined(&mut self, name: &Atom) -> bool {
1268    let Some(info) = self.get_variable_info(name) else {
1269      return false;
1270    };
1271    !info.is_free()
1272  }
1273}
1274
1275impl JavascriptParser<'_> {
1276  pub fn evaluate_expression<'a>(&mut self, expr: &'a Expr) -> BasicEvaluatedExpression<'a> {
1277    match self.evaluating(expr) {
1278      Some(evaluated) => evaluated.with_expression(Some(expr)),
1279      None => BasicEvaluatedExpression::with_range(expr.span().real_lo(), expr.span().real_hi())
1280        .with_expression(Some(expr)),
1281    }
1282  }
1283
1284  pub fn evaluate<T: Display>(
1285    &mut self,
1286    source: String,
1287    error_title: T,
1288  ) -> Option<BasicEvaluatedExpression<'static>> {
1289    eval::eval_source(self, source, error_title)
1290  }
1291
1292  // same as `JavascriptParser._initializeEvaluating` in webpack
1293  // FIXME: should mv it to plugin(for example `parse.hooks.evaluate for`)
1294  fn evaluating<'a>(&mut self, expr: &'a Expr) -> Option<BasicEvaluatedExpression<'a>> {
1295    match expr {
1296      Expr::Tpl(tpl) => eval::eval_tpl_expression(self, tpl),
1297      Expr::TaggedTpl(tagged_tpl) => eval::eval_tagged_tpl_expression(self, tagged_tpl),
1298      Expr::Lit(lit) => eval::eval_lit_expr(lit),
1299      Expr::Cond(cond) => eval::eval_cond_expression(self, cond),
1300      Expr::Unary(unary) => eval::eval_unary_expression(self, unary),
1301      Expr::Bin(binary) => eval::eval_binary_expression(self, binary),
1302      Expr::Array(array) => eval::eval_array_expression(self, array),
1303      Expr::New(new) => eval::eval_new_expression(self, new),
1304      Expr::Call(call) => eval::eval_call_expression(self, call),
1305      Expr::OptChain(opt_chain) => self.enter_optional_chain(
1306        opt_chain,
1307        |parser, call| {
1308          let expr = Expr::Call(CallExpr {
1309            ctxt: call.ctxt,
1310            span: call.span,
1311            callee: call.callee.clone().as_callee(),
1312            args: call.args.clone(),
1313            type_args: None,
1314          });
1315          BasicEvaluatedExpression::with_owned_expression(expr, |expr| {
1316            #[allow(clippy::unwrap_used)]
1317            let call_expr = expr.as_call().unwrap();
1318            eval::eval_call_expression(parser, call_expr)
1319          })
1320        },
1321        |parser, member| eval::eval_member_expression(parser, member, expr),
1322      ),
1323      Expr::Member(member) => eval::eval_member_expression(self, member, expr),
1324      Expr::Ident(ident) => {
1325        let name = &ident.sym;
1326        if name.eq("undefined") {
1327          let mut eval =
1328            BasicEvaluatedExpression::with_range(ident.span.real_lo(), ident.span.real_hi());
1329          eval.set_undefined();
1330          return Some(eval);
1331        }
1332        let drive = self.plugin_drive.clone();
1333        name
1334          .call_hooks_name(self, |parser, name| {
1335            drive.evaluate_identifier(parser, name, ident.span.real_lo(), ident.span.real_hi())
1336          })
1337          .or_else(|| {
1338            let info = self.get_variable_info(name);
1339            if let Some(info) = info {
1340              if let Some(name) = &info.name
1341                && (info.is_free() || info.is_tagged())
1342              {
1343                let mut eval =
1344                  BasicEvaluatedExpression::with_range(ident.span.real_lo(), ident.span.real_hi());
1345                eval.set_identifier(
1346                  name.to_owned(),
1347                  ExportedVariableInfo::VariableInfo(info.id()),
1348                  None,
1349                  None,
1350                  None,
1351                );
1352                Some(eval)
1353              } else {
1354                None
1355              }
1356            } else {
1357              let mut eval =
1358                BasicEvaluatedExpression::with_range(ident.span.real_lo(), ident.span.real_hi());
1359              eval.set_identifier(
1360                ident.sym.clone(),
1361                ExportedVariableInfo::Name(name.clone()),
1362                None,
1363                None,
1364                None,
1365              );
1366              Some(eval)
1367            }
1368          })
1369      }
1370      Expr::This(this) => {
1371        let drive = self.plugin_drive.clone();
1372        let default_eval = || {
1373          let mut eval =
1374            BasicEvaluatedExpression::with_range(this.span.real_lo(), this.span.real_hi());
1375          eval.set_identifier(
1376            "this".into(),
1377            ExportedVariableInfo::Name("this".into()),
1378            None,
1379            None,
1380            None,
1381          );
1382          Some(eval)
1383        };
1384        let Some(info) = self.get_variable_info(&"this".into()) else {
1385          // use `ident.sym` as fallback for global variable(or maybe just a undefined variable)
1386          return drive
1387            .evaluate_identifier(self, "this", this.span.real_lo(), this.span.real_hi())
1388            .or_else(default_eval);
1389        };
1390        if let Some(name) = &info.name
1391          && (info.is_free() || info.is_tagged())
1392        {
1393          let name = name.clone();
1394          return drive
1395            .evaluate_identifier(self, &name, this.span.real_lo(), this.span.real_hi())
1396            .or_else(default_eval);
1397        }
1398        None
1399      }
1400      _ => None,
1401    }
1402  }
1403}