rspack_core 0.102.0-beta.0

rspack core
Documentation
use rspack_cacheable::{cacheable, with::AsPreset};
use swc_core::{
  atoms::Atom,
  ecma::{
    ast::{ClassExpr, Ident, ObjectPatProp, Prop},
    visit::{Visit, VisitWith, noop_visit_type},
  },
};

use crate::DependencyRange;

#[derive(Clone, Debug)]
pub struct ConcatenatedModuleIdent {
  pub id: Ident,
  pub shorthand: bool,
  pub is_class_expr_with_ident: bool,
}

#[cacheable]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ConcatenationScopeIdentKind {
  TopLevel,
  Global,
  UsedName,
}

#[cacheable]
#[derive(Clone, Debug)]
pub struct ConcatenationScopeIdent {
  pub range: DependencyRange,
  pub shorthand: bool,
  pub kind: ConcatenationScopeIdentKind,
}

#[cacheable]
#[derive(Clone, Debug)]
pub struct ConcatenationScopeCanonicalName {
  pub range: DependencyRange,
  #[cacheable(with=AsPreset)]
  pub name: Atom,
}

#[cacheable]
#[derive(Clone, Debug)]
pub struct AnalyzedConcatenationScopeInfo {
  pub module_ctxt: u32,
  pub global_ctxt: u32,
  pub idents: Vec<ConcatenationScopeIdent>,
  pub canonical_names: Vec<ConcatenationScopeCanonicalName>,
}

/// Make-time scope information required by faster module concatenation.
///
/// `Generated` is an explicit declaration that the module has no original
/// JavaScript scope. Any bindings introduced by its generator must be
/// registered through `ConcatenationScope` during code generation.
#[cacheable]
#[derive(Clone, Debug)]
pub enum PendingConcatenationScopeInfo {
  Analyzed(AnalyzedConcatenationScopeInfo),
  Generated,
}

#[derive(Default)]
pub struct IdentCollector {
  pub ids: Vec<ConcatenatedModuleIdent>,
}

impl IdentCollector {}

impl Visit for IdentCollector {
  noop_visit_type!();

  fn visit_ident(&mut self, node: &Ident) {
    self.ids.push(ConcatenatedModuleIdent {
      id: node.clone(),
      shorthand: false,
      is_class_expr_with_ident: false,
    });
  }

  fn visit_object_pat_prop(&mut self, n: &ObjectPatProp) {
    match n {
      ObjectPatProp::Assign(assign) => {
        self.ids.push(ConcatenatedModuleIdent {
          id: assign.key.clone().into(),
          shorthand: true,
          is_class_expr_with_ident: false,
        });
        assign.value.visit_with(self);
      }
      ObjectPatProp::KeyValue(_) | ObjectPatProp::Rest(_) => {
        n.visit_children_with(self);
      }
    }
  }

  fn visit_prop(&mut self, node: &Prop) {
    match node {
      Prop::Shorthand(node) => {
        self.ids.push(ConcatenatedModuleIdent {
          id: node.clone(),
          shorthand: true,
          is_class_expr_with_ident: false,
        });
      }
      _ => {
        node.visit_children_with(self);
      }
    }
  }

  /// https://github.com/webpack/webpack/blob/1f99ad6367f2b8a6ef17cce0e058f7a67fb7db18/lib/optimize/ConcatenatedModule.js#L1173-L1197
  fn visit_class_expr(&mut self, node: &ClassExpr) {
    if let Some(ref ident) = node.ident
      && node.class.super_class.is_some()
    {
      self.ids.push(ConcatenatedModuleIdent {
        id: ident.clone(),
        shorthand: false,
        is_class_expr_with_ident: true,
      });
    }
    node.class.visit_with(self);
  }
}