rspack_plugin_javascript 0.100.0-rc.3

rspack javascript plugin
Documentation
use rspack_core::{
  Compilation, ExportsInfoArtifact, GetTargetResult, ModuleGraph, ModuleGraphConnection,
  ModuleIdentifier, PrefetchExportsInfoMode, ResolvedExportInfoTarget, RuntimeCondition,
  RuntimeSpec, UsageState, UsedByExports, UsedByExportsCondition, filter_runtime, get_target,
};

pub mod plugin;
pub mod state;

pub(crate) fn has_impure_deferred_pure_checks(
  module_graph: &ModuleGraph,
  exports_info_artifact: &ExportsInfoArtifact,
  used_by_exports: &UsedByExports,
) -> bool {
  used_by_exports
    .deferred_pure_checks
    .iter()
    .any(|deferred_check| {
      let Some(ref_module) =
        module_graph.module_identifier_by_dependency_id(&deferred_check.dep_id)
      else {
        return true;
      };

      let target_exports_info = exports_info_artifact
        .get_prefetched_exports_info(ref_module, PrefetchExportsInfoMode::Default);
      let target_export_info =
        target_exports_info.get_export_info_without_mut_module_graph(&deferred_check.atom);
      let resolve_filter = |_: &ResolvedExportInfoTarget| true;

      let (ref_module_id, atom) = if let Some(GetTargetResult::Target(target)) = get_target(
        &target_export_info,
        module_graph,
        exports_info_artifact,
        &resolve_filter,
        &mut Default::default(),
      ) {
        let atom = if target.module == *ref_module {
          deferred_check.atom.clone()
        } else {
          target
            .export
            .as_ref()
            .and_then(|export| export.first().cloned())
            .unwrap_or_else(|| deferred_check.atom.clone())
        };
        (target.module, atom)
      } else {
        (*ref_module, deferred_check.atom.clone())
      };

      let Some(ref_module) = module_graph.module_by_identifier(&ref_module_id) else {
        return true;
      };
      let Some(side_effects_free) = &ref_module.build_info().side_effects_free else {
        return true;
      };

      !side_effects_free.contains(&atom)
    })
}

pub(crate) fn runtime_condition_used_by_exports(
  compilation: &Compilation,
  module_identifier: &ModuleIdentifier,
  runtime: Option<&RuntimeSpec>,
  used_by_exports: Option<&UsedByExports>,
) -> RuntimeCondition {
  let Some(used_by_exports) = used_by_exports else {
    return RuntimeCondition::Boolean(true);
  };

  if has_impure_deferred_pure_checks(
    compilation.get_module_graph(),
    &compilation.exports_info_artifact,
    used_by_exports,
  ) {
    return RuntimeCondition::Boolean(true);
  }

  match &used_by_exports.condition {
    UsedByExportsCondition::Bool(used) => RuntimeCondition::Boolean(*used),
    UsedByExportsCondition::Set(used_by_exports) => {
      let exports_info = compilation
        .exports_info_artifact
        .get_prefetched_exports_info(module_identifier, PrefetchExportsInfoMode::Default);
      filter_runtime(runtime, |cur_runtime| {
        used_by_exports.iter().any(|name| {
          exports_info.get_used(std::slice::from_ref(name), cur_runtime) != UsageState::Unused
        })
      })
    }
  }
}

pub fn connection_active_used_by_exports(
  connection: &ModuleGraphConnection,
  runtime: Option<&RuntimeSpec>,
  mg: &ModuleGraph,
  exports_info_artifact: &ExportsInfoArtifact,
  used_by_exports: Option<&UsedByExports>,
) -> bool {
  let Some(used_by_exports) = used_by_exports.as_ref() else {
    return true;
  };
  if has_impure_deferred_pure_checks(mg, exports_info_artifact, used_by_exports) {
    return true;
  }
  let used_by_exports = match &used_by_exports.condition {
    UsedByExportsCondition::Set(used_by_exports) => used_by_exports,
    UsedByExportsCondition::Bool(used) => return *used,
  };
  let module_identifier = mg
    .get_parent_module(&connection.dependency_id)
    .expect("should have parent module");
  let exports_info = exports_info_artifact.get_exports_info_data(module_identifier);
  used_by_exports.iter().any(|name| {
    exports_info
      .named_exports(name)
      .unwrap_or_else(|| exports_info.other_exports_info())
      .get_used(runtime)
      != UsageState::Unused
  })
}