Skip to main content

rspack_plugin_javascript/dependency/esm/
esm_compatibility_dependency.rs

1use rspack_cacheable::{cacheable, cacheable_dyn};
2use rspack_core::{
3  DependencyCodeGeneration, DependencyTemplate, DependencyTemplateType, InitFragmentKey,
4  InitFragmentStage, ModuleGraph, NormalInitFragment, PrefetchExportsInfoMode, RuntimeGlobals,
5  TemplateContext, TemplateReplaceSource, UsageState,
6};
7use swc_core::atoms::Atom;
8
9// Mark module `__esModule`.
10// Add `__webpack_require__.r(__webpack_exports__);`.
11#[cacheable]
12#[derive(Debug, Clone)]
13pub struct ESMCompatibilityDependency;
14
15#[cacheable_dyn]
16impl DependencyCodeGeneration for ESMCompatibilityDependency {
17  fn dependency_template(&self) -> Option<DependencyTemplateType> {
18    Some(ESMCompatibilityDependencyTemplate::template_type())
19  }
20}
21
22#[cacheable]
23#[derive(Debug, Default)]
24pub struct ESMCompatibilityDependencyTemplate;
25
26impl ESMCompatibilityDependencyTemplate {
27  pub fn template_type() -> DependencyTemplateType {
28    DependencyTemplateType::Custom("ESMCompatibilityDependency")
29  }
30}
31
32impl DependencyTemplate for ESMCompatibilityDependencyTemplate {
33  fn render(
34    &self,
35    _dep: &dyn DependencyCodeGeneration,
36    _source: &mut TemplateReplaceSource,
37    code_generatable_context: &mut TemplateContext,
38  ) {
39    let TemplateContext {
40      runtime_requirements,
41      init_fragments,
42      compilation,
43      module,
44      runtime,
45      concatenation_scope,
46      ..
47    } = code_generatable_context;
48    if concatenation_scope.is_some() {
49      return;
50    }
51    let module_graph = compilation.get_module_graph();
52    let module = module_graph
53      .module_by_identifier(&module.identifier())
54      .expect("should have mgm");
55    let name = Atom::from("__esModule");
56    let exports_info = module_graph
57      .get_prefetched_exports_info(&module.identifier(), PrefetchExportsInfoMode::Default);
58    let used = exports_info
59      .get_read_only_export_info(&name)
60      .get_used(*runtime);
61    if !matches!(used, UsageState::Unused) {
62      runtime_requirements.insert(RuntimeGlobals::MAKE_NAMESPACE_OBJECT);
63      runtime_requirements.insert(RuntimeGlobals::EXPORTS);
64      init_fragments.push(Box::new(NormalInitFragment::new(
65        format!(
66          "{}({});\n",
67          compilation
68            .runtime_template
69            .render_runtime_globals(&RuntimeGlobals::MAKE_NAMESPACE_OBJECT),
70          compilation
71            .runtime_template
72            .render_exports_argument(module.get_exports_argument()),
73        ),
74        InitFragmentStage::StageESMExports,
75        0,
76        InitFragmentKey::ESMCompatibility,
77        None,
78      )));
79    }
80
81    if ModuleGraph::is_async(
82      &compilation.async_modules_artifact.borrow(),
83      &module.identifier(),
84    ) {
85      runtime_requirements.insert(RuntimeGlobals::MODULE);
86      runtime_requirements.insert(RuntimeGlobals::ASYNC_MODULE);
87      init_fragments.push(Box::new(NormalInitFragment::new(
88        format!(
89          "{}({}, async function (__rspack_load_async_deps, __rspack_async_done) {{ try {{\n",
90          compilation
91            .runtime_template
92            .render_runtime_globals(&RuntimeGlobals::ASYNC_MODULE),
93          compilation.runtime_template.render_module_argument(
94            module_graph
95              .module_by_identifier(&module.identifier())
96              .expect("should have mgm")
97              .get_module_argument()
98          ),
99        ),
100        InitFragmentStage::StageAsyncBoundary,
101        0,
102        InitFragmentKey::unique(),
103        Some(format!(
104          "\n__rspack_async_done();\n}} catch(e) {{ __rspack_async_done(e); }} }}{});",
105          if module.build_meta().has_top_level_await {
106            ", 1"
107          } else {
108            ""
109          }
110        )),
111      )));
112    }
113  }
114}