HarmonyImportSideEffectDependency.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const Dependency = require("../Dependency");
  7. const InitFragment = require("../InitFragment");
  8. const Module = require("../Module");
  9. const { JAVASCRIPT_TYPE } = require("../ModuleSourceTypeConstants");
  10. const makeSerializable = require("../util/makeSerializable");
  11. const HarmonyImportDependency = require("./HarmonyImportDependency");
  12. const { ImportPhaseUtils } = require("./ImportPhase");
  13. /** @import { ReplaceSource } from "webpack-sources" */
  14. /** @import { GetConditionFn, LazyUntil } from "../Dependency" */
  15. /** @import { DependencyTemplateContext } from "../DependencyTemplate" */
  16. /** @import ModuleGraph from "../ModuleGraph" */
  17. /** @import { ConnectionState } from "../ModuleGraphConnection" */
  18. /** @import { ImportAttributes } from "../javascript/JavascriptParser" */
  19. /** @import { ImportPhaseType } from "./ImportPhase" */
  20. class HarmonyImportSideEffectDependency extends HarmonyImportDependency {
  21. /**
  22. * Creates an instance of HarmonyImportSideEffectDependency.
  23. * @param {string} request the request string
  24. * @param {number} sourceOrder source order
  25. * @param {ImportPhaseType} phase import phase
  26. * @param {ImportAttributes=} attributes import attributes
  27. */
  28. constructor(request, sourceOrder, phase, attributes) {
  29. super(request, sourceOrder, phase, attributes);
  30. }
  31. get type() {
  32. return "harmony side effect evaluation";
  33. }
  34. /**
  35. * Returns the export name this dependency requests from its target module (lazy barrel optimization).
  36. * @returns {string | true | null} export name, true for all exports, null for none
  37. */
  38. getForwardId() {
  39. return null;
  40. }
  41. /**
  42. * Returns how this dependency may be deferred when its parent module is side-effect-free (lazy barrel optimization).
  43. * @returns {LazyUntil | null} lazy classification, null when it must be processed eagerly
  44. */
  45. getLazyUntil() {
  46. return Dependency.LAZY_UNTIL_REQUEST;
  47. }
  48. /**
  49. * Returns function to determine if the connection is active.
  50. * @param {ModuleGraph} moduleGraph module graph
  51. * @returns {null | false | GetConditionFn} function to determine if the connection is active
  52. */
  53. getCondition(moduleGraph) {
  54. return (connection) => {
  55. const refModule = connection.resolvedModule;
  56. if (!refModule) return true;
  57. return refModule.getSideEffectsConnectionState(moduleGraph);
  58. };
  59. }
  60. /**
  61. * Gets module evaluation side effects state.
  62. * @param {ModuleGraph} moduleGraph the module graph
  63. * @returns {ConnectionState} how this dependency connects the module to referencing modules
  64. */
  65. getModuleEvaluationSideEffectsState(moduleGraph) {
  66. const refModule = moduleGraph.getModule(this);
  67. if (!refModule) return true;
  68. return refModule.getSideEffectsConnectionState(moduleGraph);
  69. }
  70. }
  71. makeSerializable(
  72. HarmonyImportSideEffectDependency,
  73. "webpack/lib/dependencies/HarmonyImportSideEffectDependency"
  74. );
  75. HarmonyImportSideEffectDependency.Template = class HarmonyImportSideEffectDependencyTemplate extends (
  76. HarmonyImportDependency.Template
  77. ) {
  78. /**
  79. * Applies the plugin by registering its hooks on the compiler.
  80. * @param {Dependency} dependency the dependency for which the template should be applied
  81. * @param {ReplaceSource} source the current replace source which can be modified
  82. * @param {DependencyTemplateContext} templateContext the context object
  83. * @returns {void}
  84. */
  85. apply(dependency, source, templateContext) {
  86. const { moduleGraph, concatenationScope, runtime, initFragments } =
  87. templateContext;
  88. const module = /** @type {Module} */ (moduleGraph.getModule(dependency));
  89. if (module && !Module.getSourceBasicTypes(module).has(JAVASCRIPT_TYPE)) {
  90. // no need to render import
  91. return;
  92. }
  93. if (concatenationScope && concatenationScope.isModuleInScope(module)) {
  94. if (concatenationScope.isModuleWrapped(module)) {
  95. const dep = /** @type {HarmonyImportSideEffectDependency} */ (
  96. dependency
  97. );
  98. if (ImportPhaseUtils.isDefer(dep.phase)) return;
  99. const connection = moduleGraph.getConnection(dep);
  100. if (!connection || !connection.isTargetActive(runtime)) return;
  101. // A hoisted body cannot be deferred, so its imports evaluate at their
  102. // own slots; calling from here would run them after everything hoisted
  103. // in between. Eagerness stops at one level: a module is generated
  104. // before its importers, so it never learns whether it is itself eager.
  105. if (concatenationScope.isWrapped()) {
  106. initFragments.push(
  107. new InitFragment(
  108. `${concatenationScope.createModuleReference(module, {
  109. moduleExportsAccess: true,
  110. asiSafe: true
  111. })};\n`,
  112. InitFragment.STAGE_HARMONY_IMPORTS,
  113. /** @type {number} */ (dep.sourceOrder),
  114. `cjs eager init ${module.identifier()}`
  115. )
  116. );
  117. } else {
  118. concatenationScope.registerEagerModule(module);
  119. }
  120. }
  121. return;
  122. }
  123. super.apply(dependency, source, templateContext);
  124. }
  125. };
  126. module.exports = HarmonyImportSideEffectDependency;