CommonJsFullRequireDependency.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const Template = require("../Template");
  7. const { equals } = require("../util/ArrayHelpers");
  8. const { getTrimmedIdsAndRange } = require("../util/chainedImports");
  9. const makeSerializable = require("../util/makeSerializable");
  10. const propertyAccess = require("../util/propertyAccess");
  11. const ModuleDependency = require("./ModuleDependency");
  12. /** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
  13. /** @typedef {import("../Dependency")} Dependency */
  14. /** @typedef {import("../Dependency").ReferencedExports} ReferencedExports */
  15. /** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
  16. /** @typedef {import("../ModuleGraph")} ModuleGraph */
  17. /** @typedef {import("../javascript/JavascriptParser").Range} Range */
  18. /** @typedef {import("../ExportsInfo").ExportInfoName} ExportInfoName */
  19. /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
  20. /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
  21. /** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
  22. /** @typedef {import("../util/chainedImports").IdRanges} IdRanges */
  23. class CommonJsFullRequireDependency extends ModuleDependency {
  24. /**
  25. * @param {string} request the request string
  26. * @param {Range} range location in source code
  27. * @param {ExportInfoName[]} names accessed properties on module
  28. * @param {IdRanges=} idRanges ranges for members of ids; the two arrays are right-aligned
  29. */
  30. constructor(
  31. request,
  32. range,
  33. names,
  34. idRanges /* TODO webpack 6 make this non-optional. It must always be set to properly trim ids. */
  35. ) {
  36. super(request);
  37. this.range = range;
  38. this.names = names;
  39. this.idRanges = idRanges;
  40. /** @type {boolean} */
  41. this.call = false;
  42. /** @type {undefined | boolean} */
  43. this.asiSafe = undefined;
  44. }
  45. /**
  46. * Returns list of exports referenced by this dependency
  47. * @param {ModuleGraph} moduleGraph module graph
  48. * @param {RuntimeSpec} runtime the runtime for which the module is analysed
  49. * @returns {ReferencedExports} referenced exports
  50. */
  51. getReferencedExports(moduleGraph, runtime) {
  52. if (this.call) {
  53. const importedModule = moduleGraph.getModule(this);
  54. if (
  55. !importedModule ||
  56. importedModule.getExportsType(moduleGraph, false) !== "namespace"
  57. ) {
  58. return [this.names.slice(0, -1)];
  59. }
  60. }
  61. return [this.names];
  62. }
  63. /**
  64. * @param {ObjectSerializerContext} context context
  65. */
  66. serialize(context) {
  67. const { write } = context;
  68. write(this.names);
  69. write(this.idRanges);
  70. write(this.call);
  71. write(this.asiSafe);
  72. super.serialize(context);
  73. }
  74. /**
  75. * @param {ObjectDeserializerContext} context context
  76. */
  77. deserialize(context) {
  78. const { read } = context;
  79. this.names = read();
  80. this.idRanges = read();
  81. this.call = read();
  82. this.asiSafe = read();
  83. super.deserialize(context);
  84. }
  85. get type() {
  86. return "cjs full require";
  87. }
  88. get category() {
  89. return "commonjs";
  90. }
  91. }
  92. CommonJsFullRequireDependency.Template = class CommonJsFullRequireDependencyTemplate extends (
  93. ModuleDependency.Template
  94. ) {
  95. /**
  96. * @param {Dependency} dependency the dependency for which the template should be applied
  97. * @param {ReplaceSource} source the current replace source which can be modified
  98. * @param {DependencyTemplateContext} templateContext the context object
  99. * @returns {void}
  100. */
  101. apply(
  102. dependency,
  103. source,
  104. { runtimeTemplate, moduleGraph, chunkGraph, runtimeRequirements, runtime }
  105. ) {
  106. const dep = /** @type {CommonJsFullRequireDependency} */ (dependency);
  107. if (!dep.range) return;
  108. const importedModule = moduleGraph.getModule(dep);
  109. let requireExpr = runtimeTemplate.moduleExports({
  110. module: importedModule,
  111. chunkGraph,
  112. request: dep.request,
  113. weak: dep.weak,
  114. runtimeRequirements
  115. });
  116. const {
  117. trimmedRange: [trimmedRangeStart, trimmedRangeEnd],
  118. trimmedIds
  119. } = getTrimmedIdsAndRange(
  120. dep.names,
  121. dep.range,
  122. dep.idRanges,
  123. moduleGraph,
  124. dep
  125. );
  126. if (importedModule) {
  127. const usedImported = moduleGraph
  128. .getExportsInfo(importedModule)
  129. .getUsedName(trimmedIds, runtime);
  130. if (usedImported) {
  131. const comment = equals(usedImported, trimmedIds)
  132. ? ""
  133. : `${Template.toNormalComment(propertyAccess(trimmedIds))} `;
  134. const access = `${comment}${propertyAccess(usedImported)}`;
  135. requireExpr =
  136. dep.asiSafe === true
  137. ? `(${requireExpr}${access})`
  138. : `${requireExpr}${access}`;
  139. }
  140. }
  141. source.replace(trimmedRangeStart, trimmedRangeEnd - 1, requireExpr);
  142. }
  143. };
  144. makeSerializable(
  145. CommonJsFullRequireDependency,
  146. "webpack/lib/dependencies/CommonJsFullRequireDependency"
  147. );
  148. module.exports = CommonJsFullRequireDependency;