HarmonyExportDependencyParserPlugin.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const InnerGraph = require("../optimize/InnerGraph");
  7. const ConstDependency = require("./ConstDependency");
  8. const HarmonyExportExpressionDependency = require("./HarmonyExportExpressionDependency");
  9. const HarmonyExportHeaderDependency = require("./HarmonyExportHeaderDependency");
  10. const HarmonyExportImportedSpecifierDependency = require("./HarmonyExportImportedSpecifierDependency");
  11. const HarmonyExportSpecifierDependency = require("./HarmonyExportSpecifierDependency");
  12. const { ExportPresenceModes } = require("./HarmonyImportDependency");
  13. const {
  14. harmonySpecifierTag,
  15. getAssertions
  16. } = require("./HarmonyImportDependencyParserPlugin");
  17. const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency");
  18. const { HarmonyStarExportsList } = HarmonyExportImportedSpecifierDependency;
  19. module.exports = class HarmonyExportDependencyParserPlugin {
  20. constructor(options) {
  21. this.exportPresenceMode =
  22. options.reexportExportsPresence !== undefined
  23. ? ExportPresenceModes.fromUserOption(options.reexportExportsPresence)
  24. : options.exportsPresence !== undefined
  25. ? ExportPresenceModes.fromUserOption(options.exportsPresence)
  26. : options.strictExportPresence
  27. ? ExportPresenceModes.ERROR
  28. : ExportPresenceModes.AUTO;
  29. }
  30. apply(parser) {
  31. const { exportPresenceMode } = this;
  32. parser.hooks.export.tap(
  33. "HarmonyExportDependencyParserPlugin",
  34. statement => {
  35. const dep = new HarmonyExportHeaderDependency(
  36. statement.declaration && statement.declaration.range,
  37. statement.range
  38. );
  39. dep.loc = Object.create(statement.loc);
  40. dep.loc.index = -1;
  41. parser.state.module.addPresentationalDependency(dep);
  42. return true;
  43. }
  44. );
  45. parser.hooks.exportImport.tap(
  46. "HarmonyExportDependencyParserPlugin",
  47. (statement, source) => {
  48. parser.state.lastHarmonyImportOrder =
  49. (parser.state.lastHarmonyImportOrder || 0) + 1;
  50. const clearDep = new ConstDependency("", statement.range);
  51. clearDep.loc = Object.create(statement.loc);
  52. clearDep.loc.index = -1;
  53. parser.state.module.addPresentationalDependency(clearDep);
  54. const sideEffectDep = new HarmonyImportSideEffectDependency(
  55. source,
  56. parser.state.lastHarmonyImportOrder,
  57. getAssertions(statement)
  58. );
  59. sideEffectDep.loc = Object.create(statement.loc);
  60. sideEffectDep.loc.index = -1;
  61. parser.state.current.addDependency(sideEffectDep);
  62. return true;
  63. }
  64. );
  65. parser.hooks.exportExpression.tap(
  66. "HarmonyExportDependencyParserPlugin",
  67. (statement, expr) => {
  68. const isFunctionDeclaration = expr.type === "FunctionDeclaration";
  69. const comments = parser.getComments([
  70. statement.range[0],
  71. expr.range[0]
  72. ]);
  73. const dep = new HarmonyExportExpressionDependency(
  74. expr.range,
  75. statement.range,
  76. comments
  77. .map(c => {
  78. switch (c.type) {
  79. case "Block":
  80. return `/*${c.value}*/`;
  81. case "Line":
  82. return `//${c.value}\n`;
  83. }
  84. return "";
  85. })
  86. .join(""),
  87. expr.type.endsWith("Declaration") && expr.id
  88. ? expr.id.name
  89. : isFunctionDeclaration
  90. ? {
  91. id: expr.id ? expr.id.name : undefined,
  92. range: [
  93. expr.range[0],
  94. expr.params.length > 0
  95. ? expr.params[0].range[0]
  96. : expr.body.range[0]
  97. ],
  98. prefix: `${expr.async ? "async " : ""}function${
  99. expr.generator ? "*" : ""
  100. } `,
  101. suffix: `(${expr.params.length > 0 ? "" : ") "}`
  102. }
  103. : undefined
  104. );
  105. dep.loc = Object.create(statement.loc);
  106. dep.loc.index = -1;
  107. parser.state.current.addDependency(dep);
  108. InnerGraph.addVariableUsage(
  109. parser,
  110. expr.type.endsWith("Declaration") && expr.id
  111. ? expr.id.name
  112. : "*default*",
  113. "default"
  114. );
  115. return true;
  116. }
  117. );
  118. parser.hooks.exportSpecifier.tap(
  119. "HarmonyExportDependencyParserPlugin",
  120. (statement, id, name, idx) => {
  121. const settings = parser.getTagData(id, harmonySpecifierTag);
  122. let dep;
  123. const harmonyNamedExports = (parser.state.harmonyNamedExports =
  124. parser.state.harmonyNamedExports || new Set());
  125. harmonyNamedExports.add(name);
  126. InnerGraph.addVariableUsage(parser, id, name);
  127. if (settings) {
  128. dep = new HarmonyExportImportedSpecifierDependency(
  129. settings.source,
  130. settings.sourceOrder,
  131. settings.ids,
  132. name,
  133. harmonyNamedExports,
  134. null,
  135. exportPresenceMode,
  136. null,
  137. settings.assertions
  138. );
  139. } else {
  140. dep = new HarmonyExportSpecifierDependency(id, name);
  141. }
  142. dep.loc = Object.create(statement.loc);
  143. dep.loc.index = idx;
  144. parser.state.current.addDependency(dep);
  145. return true;
  146. }
  147. );
  148. parser.hooks.exportImportSpecifier.tap(
  149. "HarmonyExportDependencyParserPlugin",
  150. (statement, source, id, name, idx) => {
  151. const harmonyNamedExports = (parser.state.harmonyNamedExports =
  152. parser.state.harmonyNamedExports || new Set());
  153. let harmonyStarExports = null;
  154. if (name) {
  155. harmonyNamedExports.add(name);
  156. } else {
  157. harmonyStarExports = parser.state.harmonyStarExports =
  158. parser.state.harmonyStarExports || new HarmonyStarExportsList();
  159. }
  160. const dep = new HarmonyExportImportedSpecifierDependency(
  161. source,
  162. parser.state.lastHarmonyImportOrder,
  163. id ? [id] : [],
  164. name,
  165. harmonyNamedExports,
  166. harmonyStarExports && harmonyStarExports.slice(),
  167. exportPresenceMode,
  168. harmonyStarExports
  169. );
  170. if (harmonyStarExports) {
  171. harmonyStarExports.push(dep);
  172. }
  173. dep.loc = Object.create(statement.loc);
  174. dep.loc.index = idx;
  175. parser.state.current.addDependency(dep);
  176. return true;
  177. }
  178. );
  179. }
  180. };