CommonJsExportsDependency.js 5.1 KB

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