CommonJsFullRequireDependency.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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 makeSerializable = require("../util/makeSerializable");
  9. const propertyAccess = require("../util/propertyAccess");
  10. const ModuleDependency = require("./ModuleDependency");
  11. /** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
  12. /** @typedef {import("../Dependency")} Dependency */
  13. /** @typedef {import("../Dependency").ReferencedExport} ReferencedExport */
  14. /** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
  15. /** @typedef {import("../ModuleGraph")} ModuleGraph */
  16. /** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
  17. class CommonJsFullRequireDependency extends ModuleDependency {
  18. /**
  19. * @param {string} request the request string
  20. * @param {[number, number]} range location in source code
  21. * @param {string[]} names accessed properties on module
  22. */
  23. constructor(request, range, names) {
  24. super(request);
  25. this.range = range;
  26. this.names = names;
  27. this.call = false;
  28. this.asiSafe = undefined;
  29. }
  30. /**
  31. * Returns list of exports referenced by this dependency
  32. * @param {ModuleGraph} moduleGraph module graph
  33. * @param {RuntimeSpec} runtime the runtime for which the module is analysed
  34. * @returns {(string[] | ReferencedExport)[]} referenced exports
  35. */
  36. getReferencedExports(moduleGraph, runtime) {
  37. if (this.call) {
  38. const importedModule = moduleGraph.getModule(this);
  39. if (
  40. !importedModule ||
  41. importedModule.getExportsType(moduleGraph, false) !== "namespace"
  42. ) {
  43. return [this.names.slice(0, -1)];
  44. }
  45. }
  46. return [this.names];
  47. }
  48. serialize(context) {
  49. const { write } = context;
  50. write(this.names);
  51. write(this.call);
  52. write(this.asiSafe);
  53. super.serialize(context);
  54. }
  55. deserialize(context) {
  56. const { read } = context;
  57. this.names = read();
  58. this.call = read();
  59. this.asiSafe = read();
  60. super.deserialize(context);
  61. }
  62. get type() {
  63. return "cjs full require";
  64. }
  65. get category() {
  66. return "commonjs";
  67. }
  68. }
  69. CommonJsFullRequireDependency.Template = class CommonJsFullRequireDependencyTemplate extends (
  70. ModuleDependency.Template
  71. ) {
  72. /**
  73. * @param {Dependency} dependency the dependency for which the template should be applied
  74. * @param {ReplaceSource} source the current replace source which can be modified
  75. * @param {DependencyTemplateContext} templateContext the context object
  76. * @returns {void}
  77. */
  78. apply(
  79. dependency,
  80. source,
  81. {
  82. module,
  83. runtimeTemplate,
  84. moduleGraph,
  85. chunkGraph,
  86. runtimeRequirements,
  87. runtime,
  88. initFragments
  89. }
  90. ) {
  91. const dep = /** @type {CommonJsFullRequireDependency} */ (dependency);
  92. if (!dep.range) return;
  93. const importedModule = moduleGraph.getModule(dep);
  94. let requireExpr = runtimeTemplate.moduleExports({
  95. module: importedModule,
  96. chunkGraph,
  97. request: dep.request,
  98. weak: dep.weak,
  99. runtimeRequirements
  100. });
  101. if (importedModule) {
  102. const ids = dep.names;
  103. const usedImported = moduleGraph
  104. .getExportsInfo(importedModule)
  105. .getUsedName(ids, runtime);
  106. if (usedImported) {
  107. const comment = equals(usedImported, ids)
  108. ? ""
  109. : Template.toNormalComment(propertyAccess(ids)) + " ";
  110. const access = `${comment}${propertyAccess(usedImported)}`;
  111. requireExpr =
  112. dep.asiSafe === true
  113. ? `(${requireExpr}${access})`
  114. : `${requireExpr}${access}`;
  115. }
  116. }
  117. source.replace(dep.range[0], dep.range[1] - 1, requireExpr);
  118. }
  119. };
  120. makeSerializable(
  121. CommonJsFullRequireDependency,
  122. "webpack/lib/dependencies/CommonJsFullRequireDependency"
  123. );
  124. module.exports = CommonJsFullRequireDependency;