CommonJsExportsDependency.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const InitFragment = require("../InitFragment");
  7. const makeSerializable = require("../util/makeSerializable");
  8. const propertyAccess = require("../util/propertyAccess");
  9. const { handleDependencyBase } = require("./CommonJsDependencyHelpers");
  10. const NullDependency = require("./NullDependency");
  11. /** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
  12. /** @typedef {import("../Dependency")} Dependency */
  13. /** @typedef {import("../Dependency").ExportsSpec} ExportsSpec */
  14. /** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
  15. /** @typedef {import("../ModuleGraph")} ModuleGraph */
  16. /** @typedef {import("../javascript/JavascriptParser").Range} Range */
  17. /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
  18. /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
  19. /** @typedef {import("./CommonJsDependencyHelpers").CommonJSDependencyBaseKeywords} CommonJSDependencyBaseKeywords */
  20. const EMPTY_OBJECT = {};
  21. class CommonJsExportsDependency extends NullDependency {
  22. /**
  23. * @param {Range} range range
  24. * @param {Range | null} valueRange value range
  25. * @param {CommonJSDependencyBaseKeywords} base base
  26. * @param {string[]} names names
  27. */
  28. constructor(range, valueRange, base, names) {
  29. super();
  30. this.range = range;
  31. this.valueRange = valueRange;
  32. this.base = base;
  33. this.names = names;
  34. }
  35. get type() {
  36. return "cjs exports";
  37. }
  38. /**
  39. * Returns the exported names
  40. * @param {ModuleGraph} moduleGraph module graph
  41. * @returns {ExportsSpec | undefined} export names
  42. */
  43. getExports(moduleGraph) {
  44. const name = this.names[0];
  45. return {
  46. exports: [
  47. {
  48. name,
  49. // we can't mangle names that are in an empty object
  50. // because one could access the prototype property
  51. // when export isn't set yet
  52. canMangle: !(name in EMPTY_OBJECT)
  53. }
  54. ],
  55. dependencies: undefined
  56. };
  57. }
  58. /**
  59. * @param {ObjectSerializerContext} context context
  60. */
  61. serialize(context) {
  62. const { write } = context;
  63. write(this.range);
  64. write(this.valueRange);
  65. write(this.base);
  66. write(this.names);
  67. super.serialize(context);
  68. }
  69. /**
  70. * @param {ObjectDeserializerContext} context context
  71. */
  72. deserialize(context) {
  73. const { read } = context;
  74. this.range = read();
  75. this.valueRange = read();
  76. this.base = read();
  77. this.names = read();
  78. super.deserialize(context);
  79. }
  80. }
  81. makeSerializable(
  82. CommonJsExportsDependency,
  83. "webpack/lib/dependencies/CommonJsExportsDependency"
  84. );
  85. CommonJsExportsDependency.Template = class CommonJsExportsDependencyTemplate extends (
  86. NullDependency.Template
  87. ) {
  88. /**
  89. * @param {Dependency} dependency the dependency for which the template should be applied
  90. * @param {ReplaceSource} source the current replace source which can be modified
  91. * @param {DependencyTemplateContext} templateContext the context object
  92. * @returns {void}
  93. */
  94. apply(
  95. dependency,
  96. source,
  97. { module, moduleGraph, initFragments, runtimeRequirements, runtime }
  98. ) {
  99. const dep = /** @type {CommonJsExportsDependency} */ (dependency);
  100. const used = moduleGraph
  101. .getExportsInfo(module)
  102. .getUsedName(dep.names, runtime);
  103. const [type, base] = handleDependencyBase(
  104. dep.base,
  105. module,
  106. runtimeRequirements
  107. );
  108. switch (type) {
  109. case "expression":
  110. if (!used) {
  111. initFragments.push(
  112. new InitFragment(
  113. "var __webpack_unused_export__;\n",
  114. InitFragment.STAGE_CONSTANTS,
  115. 0,
  116. "__webpack_unused_export__"
  117. )
  118. );
  119. source.replace(
  120. dep.range[0],
  121. dep.range[1] - 1,
  122. "__webpack_unused_export__"
  123. );
  124. return;
  125. }
  126. source.replace(
  127. dep.range[0],
  128. dep.range[1] - 1,
  129. `${base}${propertyAccess(used)}`
  130. );
  131. return;
  132. case "Object.defineProperty":
  133. if (!used) {
  134. initFragments.push(
  135. new InitFragment(
  136. "var __webpack_unused_export__;\n",
  137. InitFragment.STAGE_CONSTANTS,
  138. 0,
  139. "__webpack_unused_export__"
  140. )
  141. );
  142. source.replace(
  143. dep.range[0],
  144. /** @type {Range} */ (dep.valueRange)[0] - 1,
  145. "__webpack_unused_export__ = ("
  146. );
  147. source.replace(
  148. /** @type {Range} */ (dep.valueRange)[1],
  149. dep.range[1] - 1,
  150. ")"
  151. );
  152. return;
  153. }
  154. source.replace(
  155. dep.range[0],
  156. /** @type {Range} */ (dep.valueRange)[0] - 1,
  157. `Object.defineProperty(${base}${propertyAccess(
  158. used.slice(0, -1)
  159. )}, ${JSON.stringify(used[used.length - 1])}, (`
  160. );
  161. source.replace(
  162. /** @type {Range} */ (dep.valueRange)[1],
  163. dep.range[1] - 1,
  164. "))"
  165. );
  166. return;
  167. }
  168. }
  169. };
  170. module.exports = CommonJsExportsDependency;