HarmonyExportExpressionDependency.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const ConcatenationScope = require("../ConcatenationScope");
  7. const RuntimeGlobals = require("../RuntimeGlobals");
  8. const makeSerializable = require("../util/makeSerializable");
  9. const HarmonyExportInitFragment = require("./HarmonyExportInitFragment");
  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("../ModuleGraphConnection").ConnectionState} ConnectionState */
  17. class HarmonyExportExpressionDependency extends NullDependency {
  18. constructor(range, rangeStatement, prefix, declarationId) {
  19. super();
  20. this.range = range;
  21. this.rangeStatement = rangeStatement;
  22. this.prefix = prefix;
  23. this.declarationId = declarationId;
  24. }
  25. get type() {
  26. return "harmony export expression";
  27. }
  28. /**
  29. * Returns the exported names
  30. * @param {ModuleGraph} moduleGraph module graph
  31. * @returns {ExportsSpec | undefined} export names
  32. */
  33. getExports(moduleGraph) {
  34. return {
  35. exports: ["default"],
  36. priority: 1,
  37. terminalBinding: true,
  38. dependencies: undefined
  39. };
  40. }
  41. /**
  42. * @param {ModuleGraph} moduleGraph the module graph
  43. * @returns {ConnectionState} how this dependency connects the module to referencing modules
  44. */
  45. getModuleEvaluationSideEffectsState(moduleGraph) {
  46. // The expression/declaration is already covered by SideEffectsFlagPlugin
  47. return false;
  48. }
  49. serialize(context) {
  50. const { write } = context;
  51. write(this.range);
  52. write(this.rangeStatement);
  53. write(this.prefix);
  54. write(this.declarationId);
  55. super.serialize(context);
  56. }
  57. deserialize(context) {
  58. const { read } = context;
  59. this.range = read();
  60. this.rangeStatement = read();
  61. this.prefix = read();
  62. this.declarationId = read();
  63. super.deserialize(context);
  64. }
  65. }
  66. makeSerializable(
  67. HarmonyExportExpressionDependency,
  68. "webpack/lib/dependencies/HarmonyExportExpressionDependency"
  69. );
  70. HarmonyExportExpressionDependency.Template = class HarmonyExportDependencyTemplate extends (
  71. NullDependency.Template
  72. ) {
  73. /**
  74. * @param {Dependency} dependency the dependency for which the template should be applied
  75. * @param {ReplaceSource} source the current replace source which can be modified
  76. * @param {DependencyTemplateContext} templateContext the context object
  77. * @returns {void}
  78. */
  79. apply(
  80. dependency,
  81. source,
  82. {
  83. module,
  84. moduleGraph,
  85. runtimeTemplate,
  86. runtimeRequirements,
  87. initFragments,
  88. runtime,
  89. concatenationScope
  90. }
  91. ) {
  92. const dep = /** @type {HarmonyExportExpressionDependency} */ (dependency);
  93. const { declarationId } = dep;
  94. const exportsName = module.exportsArgument;
  95. if (declarationId) {
  96. let name;
  97. if (typeof declarationId === "string") {
  98. name = declarationId;
  99. } else {
  100. name = ConcatenationScope.DEFAULT_EXPORT;
  101. source.replace(
  102. declarationId.range[0],
  103. declarationId.range[1] - 1,
  104. `${declarationId.prefix}${name}${declarationId.suffix}`
  105. );
  106. }
  107. if (concatenationScope) {
  108. concatenationScope.registerExport("default", name);
  109. } else {
  110. const used = moduleGraph
  111. .getExportsInfo(module)
  112. .getUsedName("default", runtime);
  113. if (used) {
  114. const map = new Map();
  115. map.set(used, `/* export default binding */ ${name}`);
  116. initFragments.push(new HarmonyExportInitFragment(exportsName, map));
  117. }
  118. }
  119. source.replace(
  120. dep.rangeStatement[0],
  121. dep.range[0] - 1,
  122. `/* harmony default export */ ${dep.prefix}`
  123. );
  124. } else {
  125. let content;
  126. const name = ConcatenationScope.DEFAULT_EXPORT;
  127. if (runtimeTemplate.supportsConst()) {
  128. content = `/* harmony default export */ const ${name} = `;
  129. if (concatenationScope) {
  130. concatenationScope.registerExport("default", name);
  131. } else {
  132. const used = moduleGraph
  133. .getExportsInfo(module)
  134. .getUsedName("default", runtime);
  135. if (used) {
  136. runtimeRequirements.add(RuntimeGlobals.exports);
  137. const map = new Map();
  138. map.set(used, name);
  139. initFragments.push(new HarmonyExportInitFragment(exportsName, map));
  140. } else {
  141. content = `/* unused harmony default export */ var ${name} = `;
  142. }
  143. }
  144. } else if (concatenationScope) {
  145. content = `/* harmony default export */ var ${name} = `;
  146. concatenationScope.registerExport("default", name);
  147. } else {
  148. const used = moduleGraph
  149. .getExportsInfo(module)
  150. .getUsedName("default", runtime);
  151. if (used) {
  152. runtimeRequirements.add(RuntimeGlobals.exports);
  153. // This is a little bit incorrect as TDZ is not correct, but we can't use const.
  154. content = `/* harmony default export */ ${exportsName}[${JSON.stringify(
  155. used
  156. )}] = `;
  157. } else {
  158. content = `/* unused harmony default export */ var ${name} = `;
  159. }
  160. }
  161. if (dep.range) {
  162. source.replace(
  163. dep.rangeStatement[0],
  164. dep.range[0] - 1,
  165. content + "(" + dep.prefix
  166. );
  167. source.replace(dep.range[1], dep.rangeStatement[1] - 0.5, ");");
  168. return;
  169. }
  170. source.replace(dep.rangeStatement[0], dep.rangeStatement[1] - 1, content);
  171. }
  172. }
  173. };
  174. module.exports = HarmonyExportExpressionDependency;