HarmonyExportImportedSpecifierDependency.js 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const ConditionalInitFragment = require("../ConditionalInitFragment");
  7. const Dependency = require("../Dependency");
  8. const { UsageState } = require("../ExportsInfo");
  9. const HarmonyLinkingError = require("../HarmonyLinkingError");
  10. const InitFragment = require("../InitFragment");
  11. const RuntimeGlobals = require("../RuntimeGlobals");
  12. const Template = require("../Template");
  13. const {
  14. getMakeDeferredNamespaceModeFromExportsType
  15. } = require("../runtime/MakeDeferredNamespaceObjectRuntime");
  16. const { countIterable } = require("../util/IterableHelpers");
  17. const { combine, first } = require("../util/SetHelpers");
  18. const makeSerializable = require("../util/makeSerializable");
  19. const propertyAccess = require("../util/propertyAccess");
  20. const { propertyName } = require("../util/propertyName");
  21. const {
  22. filterRuntime,
  23. getRuntimeKey,
  24. keyToRuntime
  25. } = require("../util/runtime");
  26. const HarmonyExportInitFragment = require("./HarmonyExportInitFragment");
  27. const HarmonyImportDependency = require("./HarmonyImportDependency");
  28. const { ImportPhaseUtils } = require("./ImportPhase");
  29. const processExportInfo = require("./processExportInfo");
  30. /** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
  31. /** @typedef {import("../ChunkGraph")} ChunkGraph */
  32. /** @typedef {import("../Dependency").ExportsSpec} ExportsSpec */
  33. /** @typedef {import("../Dependency").GetConditionFn} GetConditionFn */
  34. /** @typedef {import("../Dependency").RawReferencedExports} RawReferencedExports */
  35. /** @typedef {import("../Dependency").ReferencedExports} ReferencedExports */
  36. /** @typedef {import("../Dependency").TRANSITIVE} TRANSITIVE */
  37. /** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
  38. /** @typedef {import("../ExportsInfo")} ExportsInfo */
  39. /** @typedef {import("../ExportsInfo").ExportInfo} ExportInfo */
  40. /** @typedef {import("../ExportsInfo").ExportInfoName} ExportInfoName */
  41. /** @typedef {import("../ExportsInfo").UsedName} UsedName */
  42. /** @typedef {import("../Generator").GenerateContext} GenerateContext */
  43. /** @typedef {import("../Module")} Module */
  44. /** @typedef {import("../Module").BuildMeta} BuildMeta */
  45. /** @typedef {import("../Module").RuntimeRequirements} RuntimeRequirements */
  46. /** @typedef {import("../Module").ExportsType} ExportsType */
  47. /** @typedef {import("../ModuleGraph")} ModuleGraph */
  48. /** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection */
  49. /** @typedef {import("../ModuleGraphConnection").ConnectionState} ConnectionState */
  50. /** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
  51. /** @typedef {import("../WebpackError")} WebpackError */
  52. /** @typedef {import("../javascript/JavascriptParser").ImportAttributes} ImportAttributes */
  53. /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
  54. /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
  55. /** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
  56. /** @typedef {import("./HarmonyImportDependency").Ids} Ids */
  57. /** @typedef {import("./HarmonyImportDependency").ExportPresenceMode} ExportPresenceMode */
  58. /** @typedef {import("./HarmonyExportInitFragment").ExportMap} ExportMap */
  59. /** @typedef {import("../dependencies/ImportPhase").ImportPhaseType} ImportPhaseType */
  60. /** @typedef {"missing" | "unused" | "empty-star" | "reexport-dynamic-default" | "reexport-named-default" | "reexport-namespace-object" | "reexport-fake-namespace-object" | "reexport-undefined" | "normal-reexport" | "dynamic-reexport"} ExportModeType */
  61. const { ExportPresenceModes } = HarmonyImportDependency;
  62. const idsSymbol = Symbol("HarmonyExportImportedSpecifierDependency.ids");
  63. class NormalReexportItem {
  64. /**
  65. * @param {string} name export name
  66. * @param {Ids} ids reexported ids from other module
  67. * @param {ExportInfo} exportInfo export info from other module
  68. * @param {boolean} checked true, if it should be checked at runtime if this export exists
  69. * @param {boolean} hidden true, if it is hidden behind another active export in the same module
  70. */
  71. constructor(name, ids, exportInfo, checked, hidden) {
  72. this.name = name;
  73. this.ids = ids;
  74. this.exportInfo = exportInfo;
  75. this.checked = checked;
  76. this.hidden = hidden;
  77. }
  78. }
  79. /** @typedef {Set<string>} ExportModeIgnored */
  80. /** @typedef {Set<string>} ExportModeHidden */
  81. class ExportMode {
  82. /**
  83. * @param {ExportModeType} type type of the mode
  84. */
  85. constructor(type) {
  86. /** @type {ExportModeType} */
  87. this.type = type;
  88. // for "normal-reexport":
  89. /** @type {NormalReexportItem[] | null} */
  90. this.items = null;
  91. // for "reexport-named-default" | "reexport-fake-namespace-object" | "reexport-namespace-object"
  92. /** @type {string | null} */
  93. this.name = null;
  94. /** @type {ExportInfo | null} */
  95. this.partialNamespaceExportInfo = null;
  96. // for "dynamic-reexport":
  97. /** @type {ExportModeIgnored | null} */
  98. this.ignored = null;
  99. // for "dynamic-reexport" | "empty-star":
  100. /** @type {ExportModeHidden | undefined | null} */
  101. this.hidden = null;
  102. // for "missing":
  103. /** @type {string | null} */
  104. this.userRequest = null;
  105. // for "reexport-fake-namespace-object":
  106. /** @type {number} */
  107. this.fakeType = 0;
  108. }
  109. }
  110. /** @typedef {number[]} DependencyIndices */
  111. /**
  112. * @param {ModuleGraph} moduleGraph module graph
  113. * @param {HarmonyExportImportedSpecifierDependency[]} dependencies dependencies
  114. * @param {HarmonyExportImportedSpecifierDependency=} additionalDependency additional dependency
  115. * @returns {{ names: ExportInfoName[], dependencyIndices: DependencyIndices }} result
  116. */
  117. const determineExportAssignments = (
  118. moduleGraph,
  119. dependencies,
  120. additionalDependency
  121. ) => {
  122. /** @type {Set<ExportInfoName>} */
  123. const names = new Set();
  124. /** @type {DependencyIndices} */
  125. const dependencyIndices = [];
  126. if (additionalDependency) {
  127. dependencies = [...dependencies, additionalDependency];
  128. }
  129. for (const dep of dependencies) {
  130. const i = dependencyIndices.length;
  131. dependencyIndices[i] = names.size;
  132. const otherImportedModule = moduleGraph.getModule(dep);
  133. if (otherImportedModule) {
  134. const exportsInfo = moduleGraph.getExportsInfo(otherImportedModule);
  135. for (const exportInfo of exportsInfo.exports) {
  136. if (
  137. exportInfo.provided === true &&
  138. exportInfo.name !== "default" &&
  139. !names.has(exportInfo.name)
  140. ) {
  141. names.add(exportInfo.name);
  142. dependencyIndices[i] = names.size;
  143. }
  144. }
  145. }
  146. }
  147. dependencyIndices.push(names.size);
  148. return { names: [...names], dependencyIndices };
  149. };
  150. /**
  151. * @param {object} options options
  152. * @param {ExportInfoName[]} options.names names
  153. * @param {DependencyIndices} options.dependencyIndices dependency indices
  154. * @param {string} name name
  155. * @param {ReadonlyArray<HarmonyExportImportedSpecifierDependency>} dependencies dependencies
  156. * @returns {HarmonyExportImportedSpecifierDependency | undefined} found dependency or nothing
  157. */
  158. const findDependencyForName = (
  159. { names, dependencyIndices },
  160. name,
  161. dependencies
  162. ) => {
  163. const dependenciesIt = dependencies[Symbol.iterator]();
  164. const dependencyIndicesIt = dependencyIndices[Symbol.iterator]();
  165. let dependenciesItResult = dependenciesIt.next();
  166. let dependencyIndicesItResult = dependencyIndicesIt.next();
  167. if (dependencyIndicesItResult.done) return;
  168. for (let i = 0; i < names.length; i++) {
  169. while (i >= dependencyIndicesItResult.value) {
  170. dependenciesItResult = dependenciesIt.next();
  171. dependencyIndicesItResult = dependencyIndicesIt.next();
  172. if (dependencyIndicesItResult.done) return;
  173. }
  174. if (names[i] === name) return dependenciesItResult.value;
  175. }
  176. return undefined;
  177. };
  178. /**
  179. * @param {ModuleGraph} moduleGraph the module graph
  180. * @param {HarmonyExportImportedSpecifierDependency} dep the dependency
  181. * @param {string} runtimeKey the runtime key
  182. * @returns {ExportMode} the export mode
  183. */
  184. const getMode = (moduleGraph, dep, runtimeKey) => {
  185. const importedModule = moduleGraph.getModule(dep);
  186. if (!importedModule) {
  187. const mode = new ExportMode("missing");
  188. mode.userRequest = dep.userRequest;
  189. return mode;
  190. }
  191. const name = dep.name;
  192. const runtime = keyToRuntime(runtimeKey);
  193. const parentModule = /** @type {Module} */ (moduleGraph.getParentModule(dep));
  194. const exportsInfo = moduleGraph.getExportsInfo(parentModule);
  195. if (
  196. name
  197. ? exportsInfo.getUsed(name, runtime) === UsageState.Unused
  198. : exportsInfo.isUsed(runtime) === false
  199. ) {
  200. const mode = new ExportMode("unused");
  201. mode.name = name || "*";
  202. return mode;
  203. }
  204. const importedExportsType = importedModule.getExportsType(
  205. moduleGraph,
  206. /** @type {BuildMeta} */
  207. (parentModule.buildMeta).strictHarmonyModule
  208. );
  209. const ids = dep.getIds(moduleGraph);
  210. // Special handling for reexporting the default export
  211. // from non-namespace modules
  212. if (name && ids.length > 0 && ids[0] === "default") {
  213. switch (importedExportsType) {
  214. case "dynamic": {
  215. const mode = new ExportMode("reexport-dynamic-default");
  216. mode.name = name;
  217. return mode;
  218. }
  219. case "default-only":
  220. case "default-with-named": {
  221. const exportInfo = exportsInfo.getReadOnlyExportInfo(name);
  222. const mode = new ExportMode("reexport-named-default");
  223. mode.name = name;
  224. mode.partialNamespaceExportInfo = exportInfo;
  225. return mode;
  226. }
  227. }
  228. }
  229. // reexporting with a fixed name
  230. if (name) {
  231. /** @type {ExportMode} */
  232. let mode;
  233. const exportInfo = exportsInfo.getReadOnlyExportInfo(name);
  234. if (ids.length > 0) {
  235. // export { name as name }
  236. switch (importedExportsType) {
  237. case "default-only":
  238. mode = new ExportMode("reexport-undefined");
  239. mode.name = name;
  240. break;
  241. default:
  242. mode = new ExportMode("normal-reexport");
  243. mode.items = [
  244. new NormalReexportItem(name, ids, exportInfo, false, false)
  245. ];
  246. break;
  247. }
  248. } else {
  249. // export * as name
  250. switch (importedExportsType) {
  251. case "default-only":
  252. mode = new ExportMode("reexport-fake-namespace-object");
  253. mode.name = name;
  254. mode.partialNamespaceExportInfo = exportInfo;
  255. mode.fakeType = 0;
  256. break;
  257. case "default-with-named":
  258. mode = new ExportMode("reexport-fake-namespace-object");
  259. mode.name = name;
  260. mode.partialNamespaceExportInfo = exportInfo;
  261. mode.fakeType = 2;
  262. break;
  263. case "dynamic":
  264. default:
  265. mode = new ExportMode("reexport-namespace-object");
  266. mode.name = name;
  267. mode.partialNamespaceExportInfo = exportInfo;
  268. }
  269. }
  270. return mode;
  271. }
  272. // Star reexporting
  273. const { ignoredExports, exports, checked, hidden } = dep.getStarReexports(
  274. moduleGraph,
  275. runtime,
  276. exportsInfo,
  277. importedModule
  278. );
  279. if (!exports) {
  280. // We have too few info about the modules
  281. // Delegate the logic to the runtime code
  282. const mode = new ExportMode("dynamic-reexport");
  283. mode.ignored = ignoredExports;
  284. mode.hidden = hidden;
  285. return mode;
  286. }
  287. if (exports.size === 0) {
  288. const mode = new ExportMode("empty-star");
  289. mode.hidden = hidden;
  290. return mode;
  291. }
  292. const mode = new ExportMode("normal-reexport");
  293. mode.items = Array.from(
  294. exports,
  295. (exportName) =>
  296. new NormalReexportItem(
  297. exportName,
  298. [exportName],
  299. exportsInfo.getReadOnlyExportInfo(exportName),
  300. /** @type {Checked} */
  301. (checked).has(exportName),
  302. false
  303. )
  304. );
  305. if (hidden !== undefined) {
  306. for (const exportName of hidden) {
  307. mode.items.push(
  308. new NormalReexportItem(
  309. exportName,
  310. [exportName],
  311. exportsInfo.getReadOnlyExportInfo(exportName),
  312. false,
  313. true
  314. )
  315. );
  316. }
  317. }
  318. return mode;
  319. };
  320. /** @typedef {Set<string>} Exports */
  321. /** @typedef {Set<string>} Checked */
  322. /** @typedef {Set<string>} Hidden */
  323. /** @typedef {Set<string>} IgnoredExports */
  324. class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
  325. /**
  326. * @param {string} request the request string
  327. * @param {number} sourceOrder the order in the original source file
  328. * @param {Ids} ids the requested export name of the imported module
  329. * @param {string | null} name the export name of for this module
  330. * @param {Set<string>} activeExports other named exports in the module
  331. * @param {ReadonlyArray<HarmonyExportImportedSpecifierDependency> | null} otherStarExports other star exports in the module before this import
  332. * @param {ExportPresenceMode} exportPresenceMode mode of checking export names
  333. * @param {HarmonyStarExportsList | null} allStarExports all star exports in the module
  334. * @param {ImportPhaseType} phase import phase
  335. * @param {ImportAttributes=} attributes import attributes
  336. */
  337. constructor(
  338. request,
  339. sourceOrder,
  340. ids,
  341. name,
  342. activeExports,
  343. otherStarExports,
  344. exportPresenceMode,
  345. allStarExports,
  346. phase,
  347. attributes
  348. ) {
  349. super(request, sourceOrder, phase, attributes);
  350. this.ids = ids;
  351. this.name = name;
  352. this.activeExports = activeExports;
  353. this.otherStarExports = otherStarExports;
  354. this.exportPresenceMode = exportPresenceMode;
  355. this.allStarExports = allStarExports;
  356. }
  357. /**
  358. * @returns {boolean | TRANSITIVE} true, when changes to the referenced module could affect the referencing module; TRANSITIVE, when changes to the referenced module could affect referencing modules of the referencing module
  359. */
  360. couldAffectReferencingModule() {
  361. return Dependency.TRANSITIVE;
  362. }
  363. // TODO webpack 6 remove
  364. get id() {
  365. throw new Error("id was renamed to ids and type changed to string[]");
  366. }
  367. // TODO webpack 6 remove
  368. getId() {
  369. throw new Error("id was renamed to ids and type changed to string[]");
  370. }
  371. // TODO webpack 6 remove
  372. setId() {
  373. throw new Error("id was renamed to ids and type changed to string[]");
  374. }
  375. get type() {
  376. return "harmony export imported specifier";
  377. }
  378. /**
  379. * @param {ModuleGraph} moduleGraph the module graph
  380. * @returns {Ids} the imported id
  381. */
  382. getIds(moduleGraph) {
  383. return moduleGraph.getMeta(this)[idsSymbol] || this.ids;
  384. }
  385. /**
  386. * @param {ModuleGraph} moduleGraph the module graph
  387. * @param {Ids} ids the imported ids
  388. * @returns {void}
  389. */
  390. setIds(moduleGraph, ids) {
  391. moduleGraph.getMeta(this)[idsSymbol] = ids;
  392. }
  393. /**
  394. * @param {ModuleGraph} moduleGraph the module graph
  395. * @param {RuntimeSpec} runtime the runtime
  396. * @returns {ExportMode} the export mode
  397. */
  398. getMode(moduleGraph, runtime) {
  399. return moduleGraph.dependencyCacheProvide(
  400. this,
  401. getRuntimeKey(runtime),
  402. getMode
  403. );
  404. }
  405. /**
  406. * @param {ModuleGraph} moduleGraph the module graph
  407. * @param {RuntimeSpec} runtime the runtime
  408. * @param {ExportsInfo} exportsInfo exports info about the current module (optional)
  409. * @param {Module} importedModule the imported module (optional)
  410. * @returns {{ exports?: Exports, checked?: Checked, ignoredExports: IgnoredExports, hidden?: Hidden }} information
  411. */
  412. getStarReexports(
  413. moduleGraph,
  414. runtime,
  415. exportsInfo = moduleGraph.getExportsInfo(
  416. /** @type {Module} */ (moduleGraph.getParentModule(this))
  417. ),
  418. importedModule = /** @type {Module} */ (moduleGraph.getModule(this))
  419. ) {
  420. const importedExportsInfo = moduleGraph.getExportsInfo(importedModule);
  421. const noExtraExports =
  422. importedExportsInfo.otherExportsInfo.provided === false;
  423. const noExtraImports =
  424. exportsInfo.otherExportsInfo.getUsed(runtime) === UsageState.Unused;
  425. /** @type {IgnoredExports} */
  426. const ignoredExports = new Set(["default", ...this.activeExports]);
  427. /** @type {Hidden | undefined} */
  428. let hiddenExports;
  429. const otherStarExports =
  430. this._discoverActiveExportsFromOtherStarExports(moduleGraph);
  431. if (otherStarExports !== undefined) {
  432. hiddenExports = new Set();
  433. for (let i = 0; i < otherStarExports.namesSlice; i++) {
  434. hiddenExports.add(otherStarExports.names[i]);
  435. }
  436. for (const e of ignoredExports) hiddenExports.delete(e);
  437. }
  438. if (!noExtraExports && !noExtraImports) {
  439. return {
  440. ignoredExports,
  441. hidden: hiddenExports
  442. };
  443. }
  444. /** @type {Exports} */
  445. const exports = new Set();
  446. /** @type {Checked} */
  447. const checked = new Set();
  448. /** @type {Hidden | undefined} */
  449. const hidden = hiddenExports !== undefined ? new Set() : undefined;
  450. if (noExtraImports) {
  451. for (const exportInfo of exportsInfo.orderedExports) {
  452. const name = exportInfo.name;
  453. if (ignoredExports.has(name)) continue;
  454. if (exportInfo.getUsed(runtime) === UsageState.Unused) continue;
  455. const importedExportInfo =
  456. importedExportsInfo.getReadOnlyExportInfo(name);
  457. if (importedExportInfo.provided === false) continue;
  458. if (hiddenExports !== undefined && hiddenExports.has(name)) {
  459. /** @type {Hidden} */
  460. (hidden).add(name);
  461. continue;
  462. }
  463. exports.add(name);
  464. if (importedExportInfo.provided === true) continue;
  465. checked.add(name);
  466. }
  467. } else if (noExtraExports) {
  468. for (const importedExportInfo of importedExportsInfo.orderedExports) {
  469. const name = importedExportInfo.name;
  470. if (ignoredExports.has(name)) continue;
  471. if (importedExportInfo.provided === false) continue;
  472. const exportInfo = exportsInfo.getReadOnlyExportInfo(name);
  473. if (exportInfo.getUsed(runtime) === UsageState.Unused) continue;
  474. if (hiddenExports !== undefined && hiddenExports.has(name)) {
  475. /** @type {ExportModeHidden} */
  476. (hidden).add(name);
  477. continue;
  478. }
  479. exports.add(name);
  480. if (importedExportInfo.provided === true) continue;
  481. checked.add(name);
  482. }
  483. }
  484. return { ignoredExports, exports, checked, hidden };
  485. }
  486. /**
  487. * @param {ModuleGraph} moduleGraph module graph
  488. * @returns {null | false | GetConditionFn} function to determine if the connection is active
  489. */
  490. getCondition(moduleGraph) {
  491. return (connection, runtime) => {
  492. const mode = this.getMode(moduleGraph, runtime);
  493. return mode.type !== "unused" && mode.type !== "empty-star";
  494. };
  495. }
  496. /**
  497. * @param {ModuleGraph} moduleGraph the module graph
  498. * @returns {ConnectionState} how this dependency connects the module to referencing modules
  499. */
  500. getModuleEvaluationSideEffectsState(moduleGraph) {
  501. return false;
  502. }
  503. /**
  504. * Returns list of exports referenced by this dependency
  505. * @param {ModuleGraph} moduleGraph module graph
  506. * @param {RuntimeSpec} runtime the runtime for which the module is analysed
  507. * @returns {ReferencedExports} referenced exports
  508. */
  509. getReferencedExports(moduleGraph, runtime) {
  510. const mode = this.getMode(moduleGraph, runtime);
  511. switch (mode.type) {
  512. case "missing":
  513. case "unused":
  514. case "empty-star":
  515. case "reexport-undefined":
  516. return Dependency.NO_EXPORTS_REFERENCED;
  517. case "reexport-dynamic-default":
  518. return Dependency.EXPORTS_OBJECT_REFERENCED;
  519. case "reexport-named-default": {
  520. if (!mode.partialNamespaceExportInfo) {
  521. return Dependency.EXPORTS_OBJECT_REFERENCED;
  522. }
  523. /** @type {RawReferencedExports} */
  524. const referencedExports = [];
  525. processExportInfo(
  526. runtime,
  527. referencedExports,
  528. [],
  529. /** @type {ExportInfo} */ (mode.partialNamespaceExportInfo)
  530. );
  531. return referencedExports;
  532. }
  533. case "reexport-namespace-object":
  534. case "reexport-fake-namespace-object": {
  535. if (!mode.partialNamespaceExportInfo) {
  536. return Dependency.EXPORTS_OBJECT_REFERENCED;
  537. }
  538. /** @type {RawReferencedExports} */
  539. const referencedExports = [];
  540. processExportInfo(
  541. runtime,
  542. referencedExports,
  543. [],
  544. /** @type {ExportInfo} */ (mode.partialNamespaceExportInfo),
  545. mode.type === "reexport-fake-namespace-object"
  546. );
  547. return referencedExports;
  548. }
  549. case "dynamic-reexport":
  550. return Dependency.EXPORTS_OBJECT_REFERENCED;
  551. case "normal-reexport": {
  552. /** @type {RawReferencedExports} */
  553. const referencedExports = [];
  554. for (const {
  555. ids,
  556. exportInfo,
  557. hidden
  558. } of /** @type {NormalReexportItem[]} */ (mode.items)) {
  559. if (hidden) continue;
  560. processExportInfo(runtime, referencedExports, ids, exportInfo, false);
  561. }
  562. return referencedExports;
  563. }
  564. default:
  565. throw new Error(`Unknown mode ${mode.type}`);
  566. }
  567. }
  568. /**
  569. * @param {ModuleGraph} moduleGraph the module graph
  570. * @returns {{ names: ExportInfoName[], namesSlice: number, dependencyIndices: DependencyIndices, dependencyIndex: number } | undefined} exported names and their origin dependency
  571. */
  572. _discoverActiveExportsFromOtherStarExports(moduleGraph) {
  573. if (!this.otherStarExports) return;
  574. const i =
  575. "length" in this.otherStarExports
  576. ? this.otherStarExports.length
  577. : countIterable(this.otherStarExports);
  578. if (i === 0) return;
  579. if (this.allStarExports) {
  580. const { names, dependencyIndices } = moduleGraph.cached(
  581. determineExportAssignments,
  582. this.allStarExports.dependencies
  583. );
  584. return {
  585. names,
  586. namesSlice: dependencyIndices[i - 1],
  587. dependencyIndices,
  588. dependencyIndex: i
  589. };
  590. }
  591. const { names, dependencyIndices } = moduleGraph.cached(
  592. determineExportAssignments,
  593. /** @type {HarmonyExportImportedSpecifierDependency[]} */
  594. (this.otherStarExports),
  595. this
  596. );
  597. return {
  598. names,
  599. namesSlice: dependencyIndices[i - 1],
  600. dependencyIndices,
  601. dependencyIndex: i
  602. };
  603. }
  604. /**
  605. * Returns the exported names
  606. * @param {ModuleGraph} moduleGraph module graph
  607. * @returns {ExportsSpec | undefined} export names
  608. */
  609. getExports(moduleGraph) {
  610. const mode = this.getMode(moduleGraph, undefined);
  611. switch (mode.type) {
  612. case "missing":
  613. return;
  614. case "dynamic-reexport": {
  615. const from =
  616. /** @type {ModuleGraphConnection} */
  617. (moduleGraph.getConnection(this));
  618. return {
  619. exports: true,
  620. from,
  621. canMangle: false,
  622. excludeExports: mode.hidden
  623. ? combine(
  624. /** @type {ExportModeIgnored} */ (mode.ignored),
  625. mode.hidden
  626. )
  627. : /** @type {ExportModeIgnored} */ (mode.ignored),
  628. hideExports: mode.hidden,
  629. dependencies: [from.module]
  630. };
  631. }
  632. case "empty-star":
  633. return {
  634. exports: [],
  635. hideExports: mode.hidden,
  636. dependencies: [/** @type {Module} */ (moduleGraph.getModule(this))]
  637. };
  638. // falls through
  639. case "normal-reexport": {
  640. const from =
  641. /** @type {ModuleGraphConnection} */
  642. (moduleGraph.getConnection(this));
  643. return {
  644. exports: Array.from(
  645. /** @type {NormalReexportItem[]} */ (mode.items),
  646. (item) => ({
  647. name: item.name,
  648. from,
  649. export: item.ids,
  650. hidden: item.hidden
  651. })
  652. ),
  653. priority: 1,
  654. dependencies: [from.module]
  655. };
  656. }
  657. case "reexport-dynamic-default": {
  658. const from =
  659. /** @type {ModuleGraphConnection} */
  660. (moduleGraph.getConnection(this));
  661. return {
  662. exports: [
  663. {
  664. name: /** @type {string} */ (mode.name),
  665. from,
  666. export: ["default"]
  667. }
  668. ],
  669. priority: 1,
  670. dependencies: [from.module]
  671. };
  672. }
  673. case "reexport-undefined":
  674. return {
  675. exports: [/** @type {string} */ (mode.name)],
  676. dependencies: [/** @type {Module} */ (moduleGraph.getModule(this))]
  677. };
  678. case "reexport-fake-namespace-object": {
  679. const from =
  680. /** @type {ModuleGraphConnection} */
  681. (moduleGraph.getConnection(this));
  682. return {
  683. exports: [
  684. {
  685. name: /** @type {string} */ (mode.name),
  686. from,
  687. export: null,
  688. exports: [
  689. {
  690. name: "default",
  691. canMangle: false,
  692. from,
  693. export: null
  694. }
  695. ]
  696. }
  697. ],
  698. priority: 1,
  699. dependencies: [from.module]
  700. };
  701. }
  702. case "reexport-namespace-object": {
  703. const from =
  704. /** @type {ModuleGraphConnection} */
  705. (moduleGraph.getConnection(this));
  706. return {
  707. exports: [
  708. {
  709. name: /** @type {string} */ (mode.name),
  710. from,
  711. export: null
  712. }
  713. ],
  714. priority: 1,
  715. dependencies: [from.module]
  716. };
  717. }
  718. case "reexport-named-default": {
  719. const from =
  720. /** @type {ModuleGraphConnection} */
  721. (moduleGraph.getConnection(this));
  722. return {
  723. exports: [
  724. {
  725. name: /** @type {string} */ (mode.name),
  726. from,
  727. export: ["default"]
  728. }
  729. ],
  730. priority: 1,
  731. dependencies: [from.module]
  732. };
  733. }
  734. default:
  735. throw new Error(`Unknown mode ${mode.type}`);
  736. }
  737. }
  738. /**
  739. * @param {ModuleGraph} moduleGraph module graph
  740. * @returns {ExportPresenceMode} effective mode
  741. */
  742. _getEffectiveExportPresenceLevel(moduleGraph) {
  743. if (this.exportPresenceMode !== ExportPresenceModes.AUTO) {
  744. return this.exportPresenceMode;
  745. }
  746. const module = /** @type {Module} */ (moduleGraph.getParentModule(this));
  747. return /** @type {BuildMeta} */ (module.buildMeta).strictHarmonyModule
  748. ? ExportPresenceModes.ERROR
  749. : ExportPresenceModes.WARN;
  750. }
  751. /**
  752. * Returns warnings
  753. * @param {ModuleGraph} moduleGraph module graph
  754. * @returns {WebpackError[] | null | undefined} warnings
  755. */
  756. getWarnings(moduleGraph) {
  757. const exportsPresence = this._getEffectiveExportPresenceLevel(moduleGraph);
  758. if (exportsPresence === ExportPresenceModes.WARN) {
  759. return this._getErrors(moduleGraph);
  760. }
  761. return null;
  762. }
  763. /**
  764. * Returns errors
  765. * @param {ModuleGraph} moduleGraph module graph
  766. * @returns {WebpackError[] | null | undefined} errors
  767. */
  768. getErrors(moduleGraph) {
  769. const exportsPresence = this._getEffectiveExportPresenceLevel(moduleGraph);
  770. if (exportsPresence === ExportPresenceModes.ERROR) {
  771. return this._getErrors(moduleGraph);
  772. }
  773. return null;
  774. }
  775. /**
  776. * @param {ModuleGraph} moduleGraph module graph
  777. * @returns {WebpackError[] | undefined} errors
  778. */
  779. _getErrors(moduleGraph) {
  780. const ids = this.getIds(moduleGraph);
  781. let errors = this.getLinkingErrors(
  782. moduleGraph,
  783. ids,
  784. `(reexported as '${this.name}')`
  785. );
  786. if (ids.length === 0 && this.name === null) {
  787. const potentialConflicts =
  788. this._discoverActiveExportsFromOtherStarExports(moduleGraph);
  789. if (potentialConflicts && potentialConflicts.namesSlice > 0) {
  790. const ownNames = new Set(
  791. potentialConflicts.names.slice(
  792. potentialConflicts.namesSlice,
  793. potentialConflicts.dependencyIndices[
  794. potentialConflicts.dependencyIndex
  795. ]
  796. )
  797. );
  798. const importedModule = moduleGraph.getModule(this);
  799. if (importedModule) {
  800. const exportsInfo = moduleGraph.getExportsInfo(importedModule);
  801. /** @type {Map<string, ExportInfoName[]>} */
  802. const conflicts = new Map();
  803. for (const exportInfo of exportsInfo.orderedExports) {
  804. if (exportInfo.provided !== true) continue;
  805. if (exportInfo.name === "default") continue;
  806. if (this.activeExports.has(exportInfo.name)) continue;
  807. if (ownNames.has(exportInfo.name)) continue;
  808. const conflictingDependency = findDependencyForName(
  809. potentialConflicts,
  810. exportInfo.name,
  811. this.allStarExports
  812. ? this.allStarExports.dependencies
  813. : [
  814. .../** @type {ReadonlyArray<HarmonyExportImportedSpecifierDependency>} */
  815. (this.otherStarExports),
  816. this
  817. ]
  818. );
  819. if (!conflictingDependency) continue;
  820. const target = exportInfo.getTerminalBinding(moduleGraph);
  821. if (!target) continue;
  822. const conflictingModule =
  823. /** @type {Module} */
  824. (moduleGraph.getModule(conflictingDependency));
  825. if (conflictingModule === importedModule) continue;
  826. const conflictingExportInfo = moduleGraph.getExportInfo(
  827. conflictingModule,
  828. exportInfo.name
  829. );
  830. const conflictingTarget =
  831. conflictingExportInfo.getTerminalBinding(moduleGraph);
  832. if (!conflictingTarget) continue;
  833. if (target === conflictingTarget) continue;
  834. const list = conflicts.get(conflictingDependency.request);
  835. if (list === undefined) {
  836. conflicts.set(conflictingDependency.request, [exportInfo.name]);
  837. } else {
  838. list.push(exportInfo.name);
  839. }
  840. }
  841. for (const [request, exports] of conflicts) {
  842. if (!errors) errors = [];
  843. errors.push(
  844. new HarmonyLinkingError(
  845. `The requested module '${
  846. this.request
  847. }' contains conflicting star exports for the ${
  848. exports.length > 1 ? "names" : "name"
  849. } ${exports
  850. .map((e) => `'${e}'`)
  851. .join(", ")} with the previous requested module '${request}'`
  852. )
  853. );
  854. }
  855. }
  856. }
  857. }
  858. return errors;
  859. }
  860. /**
  861. * @param {ObjectSerializerContext} context context
  862. */
  863. serialize(context) {
  864. const { write, setCircularReference } = context;
  865. setCircularReference(this);
  866. write(this.ids);
  867. write(this.name);
  868. write(this.activeExports);
  869. write(this.otherStarExports);
  870. write(this.exportPresenceMode);
  871. write(this.allStarExports);
  872. super.serialize(context);
  873. }
  874. /**
  875. * @param {ObjectDeserializerContext} context context
  876. */
  877. deserialize(context) {
  878. const { read, setCircularReference } = context;
  879. setCircularReference(this);
  880. this.ids = read();
  881. this.name = read();
  882. this.activeExports = read();
  883. this.otherStarExports = read();
  884. this.exportPresenceMode = read();
  885. this.allStarExports = read();
  886. super.deserialize(context);
  887. }
  888. }
  889. makeSerializable(
  890. HarmonyExportImportedSpecifierDependency,
  891. "webpack/lib/dependencies/HarmonyExportImportedSpecifierDependency"
  892. );
  893. HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedSpecifierDependencyTemplate extends (
  894. HarmonyImportDependency.Template
  895. ) {
  896. /**
  897. * @param {Dependency} dependency the dependency for which the template should be applied
  898. * @param {ReplaceSource} source the current replace source which can be modified
  899. * @param {DependencyTemplateContext} templateContext the context object
  900. * @returns {void}
  901. */
  902. apply(dependency, source, templateContext) {
  903. const { moduleGraph, runtime, concatenationScope } = templateContext;
  904. const dep = /** @type {HarmonyExportImportedSpecifierDependency} */ (
  905. dependency
  906. );
  907. const mode = dep.getMode(moduleGraph, runtime);
  908. if (concatenationScope) {
  909. switch (mode.type) {
  910. case "reexport-undefined":
  911. concatenationScope.registerRawExport(
  912. /** @type {NonNullable<ExportMode["name"]>} */ (mode.name),
  913. "/* reexport non-default export from non-harmony */ undefined"
  914. );
  915. }
  916. return;
  917. }
  918. if (mode.type !== "unused" && mode.type !== "empty-star") {
  919. super.apply(dependency, source, templateContext);
  920. this._addExportFragments(
  921. templateContext.initFragments,
  922. dep,
  923. mode,
  924. templateContext.module,
  925. moduleGraph,
  926. templateContext.chunkGraph,
  927. runtime,
  928. templateContext.runtimeTemplate,
  929. templateContext.runtimeRequirements
  930. );
  931. }
  932. }
  933. /**
  934. * @param {InitFragment<GenerateContext>[]} initFragments target array for init fragments
  935. * @param {HarmonyExportImportedSpecifierDependency} dep dependency
  936. * @param {ExportMode} mode the export mode
  937. * @param {Module} module the current module
  938. * @param {ModuleGraph} moduleGraph the module graph
  939. * @param {ChunkGraph} chunkGraph the chunk graph
  940. * @param {RuntimeSpec} runtime the runtime
  941. * @param {RuntimeTemplate} runtimeTemplate the runtime template
  942. * @param {RuntimeRequirements} runtimeRequirements runtime requirements
  943. * @returns {void}
  944. */
  945. _addExportFragments(
  946. initFragments,
  947. dep,
  948. mode,
  949. module,
  950. moduleGraph,
  951. chunkGraph,
  952. runtime,
  953. runtimeTemplate,
  954. runtimeRequirements
  955. ) {
  956. const importedModule = /** @type {Module} */ (moduleGraph.getModule(dep));
  957. const importVar = dep.getImportVar(moduleGraph);
  958. const isDeferred =
  959. ImportPhaseUtils.isDefer(dep.phase) &&
  960. !(/** @type {BuildMeta} */ (importedModule.buildMeta).async);
  961. if (
  962. (mode.type === "reexport-namespace-object" ||
  963. mode.type === "reexport-fake-namespace-object") &&
  964. isDeferred
  965. ) {
  966. initFragments.push(
  967. ...this.getReexportDeferredNamespaceObjectFragments(
  968. importedModule,
  969. chunkGraph,
  970. moduleGraph
  971. .getExportsInfo(module)
  972. .getUsedName(mode.name ? mode.name : [], runtime),
  973. importVar,
  974. importedModule.getExportsType(
  975. moduleGraph,
  976. module.buildMeta && module.buildMeta.strictHarmonyModule
  977. ),
  978. runtimeRequirements
  979. )
  980. );
  981. return;
  982. }
  983. switch (mode.type) {
  984. case "missing":
  985. case "empty-star":
  986. initFragments.push(
  987. new InitFragment(
  988. "/* empty/unused harmony star reexport */\n",
  989. InitFragment.STAGE_HARMONY_EXPORTS,
  990. 1
  991. )
  992. );
  993. break;
  994. case "unused":
  995. initFragments.push(
  996. new InitFragment(
  997. `${Template.toNormalComment(
  998. `unused harmony reexport ${mode.name}`
  999. )}\n`,
  1000. InitFragment.STAGE_HARMONY_EXPORTS,
  1001. 1
  1002. )
  1003. );
  1004. break;
  1005. case "reexport-dynamic-default":
  1006. initFragments.push(
  1007. this.getReexportFragment(
  1008. module,
  1009. "reexport default from dynamic",
  1010. moduleGraph
  1011. .getExportsInfo(module)
  1012. .getUsedName(/** @type {string} */ (mode.name), runtime),
  1013. importVar,
  1014. null,
  1015. runtimeRequirements
  1016. )
  1017. );
  1018. break;
  1019. case "reexport-fake-namespace-object":
  1020. initFragments.push(
  1021. ...this.getReexportFakeNamespaceObjectFragments(
  1022. module,
  1023. moduleGraph
  1024. .getExportsInfo(module)
  1025. .getUsedName(/** @type {string} */ (mode.name), runtime),
  1026. importVar,
  1027. mode.fakeType,
  1028. runtimeRequirements
  1029. )
  1030. );
  1031. break;
  1032. case "reexport-undefined":
  1033. initFragments.push(
  1034. this.getReexportFragment(
  1035. module,
  1036. "reexport non-default export from non-harmony",
  1037. moduleGraph
  1038. .getExportsInfo(module)
  1039. .getUsedName(/** @type {string} */ (mode.name), runtime),
  1040. "undefined",
  1041. "",
  1042. runtimeRequirements
  1043. )
  1044. );
  1045. break;
  1046. case "reexport-named-default":
  1047. initFragments.push(
  1048. this.getReexportFragment(
  1049. module,
  1050. "reexport default export from named module",
  1051. moduleGraph
  1052. .getExportsInfo(module)
  1053. .getUsedName(/** @type {string} */ (mode.name), runtime),
  1054. importVar,
  1055. "",
  1056. runtimeRequirements
  1057. )
  1058. );
  1059. break;
  1060. case "reexport-namespace-object":
  1061. initFragments.push(
  1062. this.getReexportFragment(
  1063. module,
  1064. "reexport module object",
  1065. moduleGraph
  1066. .getExportsInfo(module)
  1067. .getUsedName(/** @type {string} */ (mode.name), runtime),
  1068. importVar,
  1069. "",
  1070. runtimeRequirements
  1071. )
  1072. );
  1073. break;
  1074. case "normal-reexport":
  1075. for (const {
  1076. name,
  1077. ids,
  1078. checked,
  1079. hidden
  1080. } of /** @type {NormalReexportItem[]} */ (mode.items)) {
  1081. if (hidden) continue;
  1082. if (checked) {
  1083. const connection = moduleGraph.getConnection(dep);
  1084. const key = `harmony reexport (checked) ${importVar} ${name}`;
  1085. const runtimeCondition = dep.weak
  1086. ? false
  1087. : connection
  1088. ? filterRuntime(runtime, (r) => connection.isTargetActive(r))
  1089. : true;
  1090. initFragments.push(
  1091. new ConditionalInitFragment(
  1092. `/* harmony reexport (checked) */ ${this.getConditionalReexportStatement(
  1093. module,
  1094. name,
  1095. importVar,
  1096. ids,
  1097. runtimeRequirements
  1098. )}`,
  1099. moduleGraph.isAsync(importedModule)
  1100. ? InitFragment.STAGE_ASYNC_HARMONY_IMPORTS
  1101. : InitFragment.STAGE_HARMONY_IMPORTS,
  1102. /** @type {number} */ (dep.sourceOrder),
  1103. key,
  1104. runtimeCondition
  1105. )
  1106. );
  1107. } else {
  1108. initFragments.push(
  1109. this.getReexportFragment(
  1110. module,
  1111. "reexport safe",
  1112. moduleGraph.getExportsInfo(module).getUsedName(name, runtime),
  1113. importVar,
  1114. moduleGraph
  1115. .getExportsInfo(importedModule)
  1116. .getUsedName(ids, runtime),
  1117. runtimeRequirements
  1118. )
  1119. );
  1120. }
  1121. }
  1122. break;
  1123. case "dynamic-reexport": {
  1124. const ignored = mode.hidden
  1125. ? combine(
  1126. /** @type {ExportModeIgnored} */
  1127. (mode.ignored),
  1128. mode.hidden
  1129. )
  1130. : /** @type {ExportModeIgnored} */ (mode.ignored);
  1131. let content =
  1132. "/* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {};\n" +
  1133. `/* harmony reexport (unknown) */ for(${runtimeTemplate.renderConst()} __WEBPACK_IMPORT_KEY__ in ${importVar}) `;
  1134. // Filter out exports which are defined by other exports
  1135. // and filter out default export because it cannot be reexported with *
  1136. if (ignored.size > 1) {
  1137. content += `if(${JSON.stringify([
  1138. ...ignored
  1139. ])}.indexOf(__WEBPACK_IMPORT_KEY__) < 0) `;
  1140. } else if (ignored.size === 1) {
  1141. content += `if(__WEBPACK_IMPORT_KEY__ !== ${JSON.stringify(
  1142. first(ignored)
  1143. )}) `;
  1144. }
  1145. content += "__WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = ";
  1146. content +=
  1147. runtimeTemplate.supportsArrowFunction() &&
  1148. runtimeTemplate.supportsConst()
  1149. ? `() => ${importVar}[__WEBPACK_IMPORT_KEY__]`
  1150. : `function(key) { return ${importVar}[key]; }.bind(0, __WEBPACK_IMPORT_KEY__)`;
  1151. runtimeRequirements.add(RuntimeGlobals.exports);
  1152. runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
  1153. const exportsName = module.exportsArgument;
  1154. initFragments.push(
  1155. new InitFragment(
  1156. `${content}\n/* harmony reexport (unknown) */ ${RuntimeGlobals.definePropertyGetters}(${exportsName}, __WEBPACK_REEXPORT_OBJECT__);\n`,
  1157. moduleGraph.isAsync(importedModule)
  1158. ? InitFragment.STAGE_ASYNC_HARMONY_IMPORTS
  1159. : InitFragment.STAGE_HARMONY_IMPORTS,
  1160. /** @type {number} */ (dep.sourceOrder)
  1161. )
  1162. );
  1163. break;
  1164. }
  1165. default:
  1166. throw new Error(`Unknown mode ${mode.type}`);
  1167. }
  1168. }
  1169. /**
  1170. * @param {Module} module the current module
  1171. * @param {string} comment comment
  1172. * @param {UsedName} key key
  1173. * @param {string} name name
  1174. * @param {UsedName | null} valueKey value key
  1175. * @param {RuntimeRequirements} runtimeRequirements runtime requirements
  1176. * @returns {HarmonyExportInitFragment} harmony export init fragment
  1177. */
  1178. getReexportFragment(
  1179. module,
  1180. comment,
  1181. key,
  1182. name,
  1183. valueKey,
  1184. runtimeRequirements
  1185. ) {
  1186. const returnValue = this.getReturnValue(name, valueKey);
  1187. runtimeRequirements.add(RuntimeGlobals.exports);
  1188. runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
  1189. /** @type {ExportMap} */
  1190. const map = new Map();
  1191. map.set(key, `/* ${comment} */ ${returnValue}`);
  1192. return new HarmonyExportInitFragment(module.exportsArgument, map);
  1193. }
  1194. /**
  1195. * @param {Module} module module
  1196. * @param {UsedName} key key
  1197. * @param {string} name name
  1198. * @param {number} fakeType fake type
  1199. * @param {RuntimeRequirements} runtimeRequirements runtime requirements
  1200. * @returns {[InitFragment<GenerateContext>, HarmonyExportInitFragment]} init fragments
  1201. */
  1202. getReexportFakeNamespaceObjectFragments(
  1203. module,
  1204. key,
  1205. name,
  1206. fakeType,
  1207. runtimeRequirements
  1208. ) {
  1209. runtimeRequirements.add(RuntimeGlobals.exports);
  1210. runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
  1211. runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
  1212. /** @type {ExportMap} */
  1213. const map = new Map();
  1214. map.set(
  1215. key,
  1216. `/* reexport fake namespace object from non-harmony */ ${name}_namespace_cache || (${name}_namespace_cache = ${
  1217. RuntimeGlobals.createFakeNamespaceObject
  1218. }(${name}${fakeType ? `, ${fakeType}` : ""}))`
  1219. );
  1220. return [
  1221. new InitFragment(
  1222. `var ${name}_namespace_cache;\n`,
  1223. InitFragment.STAGE_CONSTANTS,
  1224. -1,
  1225. `${name}_namespace_cache`
  1226. ),
  1227. new HarmonyExportInitFragment(module.exportsArgument, map)
  1228. ];
  1229. }
  1230. /**
  1231. * @param {Module} module module
  1232. * @param {ChunkGraph} chunkGraph chunkGraph
  1233. * @param {UsedName} key key
  1234. * @param {string} name name
  1235. * @param {ExportsType} exportsType exportsType
  1236. * @param {RuntimeRequirements} runtimeRequirements runtimeRequirements
  1237. * @returns {InitFragment<GenerateContext>[]} fragments
  1238. */
  1239. getReexportDeferredNamespaceObjectFragments(
  1240. module,
  1241. chunkGraph,
  1242. key,
  1243. name,
  1244. exportsType,
  1245. runtimeRequirements
  1246. ) {
  1247. runtimeRequirements.add(RuntimeGlobals.exports);
  1248. runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
  1249. runtimeRequirements.add(RuntimeGlobals.makeDeferredNamespaceObject);
  1250. /** @type {ExportMap} */
  1251. const map = new Map();
  1252. const moduleId = JSON.stringify(chunkGraph.getModuleId(module));
  1253. const mode = getMakeDeferredNamespaceModeFromExportsType(exportsType);
  1254. map.set(
  1255. key,
  1256. `/* reexport deferred namespace object */ ${name}_deferred_namespace_cache || (${name}_deferred_namespace_cache = ${RuntimeGlobals.makeDeferredNamespaceObject}(${moduleId}, ${mode}))`
  1257. );
  1258. return [
  1259. new InitFragment(
  1260. `var ${name}_deferred_namespace_cache;\n`,
  1261. InitFragment.STAGE_CONSTANTS,
  1262. -1,
  1263. `${name}_deferred_namespace_cache`
  1264. ),
  1265. new HarmonyExportInitFragment(module.exportsArgument, map)
  1266. ];
  1267. }
  1268. /**
  1269. * @param {Module} module module
  1270. * @param {string} key key
  1271. * @param {string} name name
  1272. * @param {string | string[] | false} valueKey value key
  1273. * @param {RuntimeRequirements} runtimeRequirements runtime requirements
  1274. * @returns {string} result
  1275. */
  1276. getConditionalReexportStatement(
  1277. module,
  1278. key,
  1279. name,
  1280. valueKey,
  1281. runtimeRequirements
  1282. ) {
  1283. if (valueKey === false) {
  1284. return "/* unused export */\n";
  1285. }
  1286. const exportsName = module.exportsArgument;
  1287. const returnValue = this.getReturnValue(name, valueKey);
  1288. runtimeRequirements.add(RuntimeGlobals.exports);
  1289. runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
  1290. runtimeRequirements.add(RuntimeGlobals.hasOwnProperty);
  1291. return `if(${RuntimeGlobals.hasOwnProperty}(${name}, ${JSON.stringify(
  1292. valueKey[0]
  1293. )})) ${
  1294. RuntimeGlobals.definePropertyGetters
  1295. }(${exportsName}, { ${propertyName(
  1296. key
  1297. )}: function() { return ${returnValue}; } });\n`;
  1298. }
  1299. /**
  1300. * @param {string} name name
  1301. * @param {null | false | string | string[]} valueKey value key
  1302. * @returns {string | undefined} value
  1303. */
  1304. getReturnValue(name, valueKey) {
  1305. if (valueKey === null) {
  1306. return `${name}_default.a`;
  1307. }
  1308. if (valueKey === "") {
  1309. return name;
  1310. }
  1311. if (valueKey === false) {
  1312. return "/* unused export */ undefined";
  1313. }
  1314. return `${name}${propertyAccess(valueKey)}`;
  1315. }
  1316. };
  1317. class HarmonyStarExportsList {
  1318. constructor() {
  1319. /** @type {HarmonyExportImportedSpecifierDependency[]} */
  1320. this.dependencies = [];
  1321. }
  1322. /**
  1323. * @param {HarmonyExportImportedSpecifierDependency} dep dependency
  1324. * @returns {void}
  1325. */
  1326. push(dep) {
  1327. this.dependencies.push(dep);
  1328. }
  1329. slice() {
  1330. return [...this.dependencies];
  1331. }
  1332. /**
  1333. * @param {ObjectSerializerContext} context context
  1334. */
  1335. serialize({ write, setCircularReference }) {
  1336. setCircularReference(this);
  1337. write(this.dependencies);
  1338. }
  1339. /**
  1340. * @param {ObjectDeserializerContext} context context
  1341. */
  1342. deserialize({ read, setCircularReference }) {
  1343. setCircularReference(this);
  1344. this.dependencies = read();
  1345. }
  1346. }
  1347. makeSerializable(
  1348. HarmonyStarExportsList,
  1349. "webpack/lib/dependencies/HarmonyExportImportedSpecifierDependency",
  1350. "HarmonyStarExportsList"
  1351. );
  1352. module.exports = HarmonyExportImportedSpecifierDependency;
  1353. module.exports.HarmonyStarExportsList = HarmonyStarExportsList;
  1354. module.exports.idsSymbol = idsSymbol;