HarmonyExportImportedSpecifierDependency.js 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808
  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 InitFragment = require("../InitFragment");
  10. const RuntimeGlobals = require("../RuntimeGlobals");
  11. const Template = require("../Template");
  12. const {
  13. InlinedUsedName,
  14. isExportInlined,
  15. isInlineEnabled
  16. } = require("../optimize/InlineExports");
  17. const {
  18. getMakeDeferredNamespaceModeFromExportsType
  19. } = require("../runtime/MakeDeferredNamespaceObjectRuntime");
  20. const { countIterable } = require("../util/IterableHelpers");
  21. const { combine, first } = require("../util/SetHelpers");
  22. const makeSerializable = require("../util/makeSerializable");
  23. const { propertyAccess, propertyName } = require("../util/property");
  24. const {
  25. filterRuntime,
  26. getRuntimeKey,
  27. keyToRuntime
  28. } = require("../util/runtime");
  29. const HarmonyExportInitFragment = require("./HarmonyExportInitFragment");
  30. const HarmonyImportDependency = require("./HarmonyImportDependency");
  31. const HarmonyLinkingError = require("./HarmonyLinkingError");
  32. const { ImportPhaseUtils } = require("./ImportPhase");
  33. const processExportInfo = require("./processExportInfo");
  34. /** @import { ReplaceSource } from "webpack-sources" */
  35. /** @import ChunkGraph from "../ChunkGraph" */
  36. /**
  37. * @import {
  38. * ExportsSpec,
  39. * GetConditionFn,
  40. * LazyUntil,
  41. * RawReferencedExports,
  42. * ReferencedExports,
  43. * TRANSITIVE,
  44. * ExportInfoName
  45. * } from "../Dependency"
  46. */
  47. /** @import { DependencyTemplateContext } from "../DependencyTemplate" */
  48. /** @import ExportsInfo, { ExportInfo, UsedName } from "../ExportsInfo" */
  49. /** @import { GenerateContext } from "../Generator" */
  50. /**
  51. * @import Module, {
  52. * BuildMeta,
  53. * RuntimeRequirements,
  54. * ExportsType
  55. * } from "../Module"
  56. */
  57. /** @import ModuleGraph from "../ModuleGraph" */
  58. /**
  59. * @import ModuleGraphConnection, {
  60. * ConnectionState
  61. * } from "../ModuleGraphConnection"
  62. */
  63. /** @import RuntimeTemplate from "../RuntimeTemplate" */
  64. /** @import WebpackError from "../errors/WebpackError" */
  65. /** @import { ImportAttributes } from "../javascript/JavascriptParser" */
  66. /** @typedef {[Ids, string | null, Set<string>, ReadonlyArray<HarmonyExportImportedSpecifierDependency> | null, ExportPresenceMode, HarmonyStarExportsList | null]} SerializedData */
  67. /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext<SerializedData>} ObjectDeserializerContext */
  68. /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext<SerializedData>} ObjectSerializerContext */
  69. /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext<[HarmonyExportImportedSpecifierDependency[]]>} StarListDeserializerContext */
  70. /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext<[HarmonyExportImportedSpecifierDependency[]]>} StarListSerializerContext */
  71. /** @import { RuntimeSpec } from "../util/runtime" */
  72. /** @import { Ids, ExportPresenceMode } from "./HarmonyImportDependency" */
  73. /** @import { ExportMap } from "./HarmonyExportInitFragment" */
  74. /** @import { ImportPhaseType } from "../dependencies/ImportPhase" */
  75. /**
  76. * @import {
  77. * JavascriptModuleBuildMeta
  78. * } from "../javascript/JavascriptModule"
  79. */
  80. /** @import ConcatenationScope from "../ConcatenationScope" */
  81. /** @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 */
  82. const { ExportPresenceModes } = HarmonyImportDependency;
  83. const idsSymbol = /** @type {symbol} */ (
  84. Symbol("HarmonyExportImportedSpecifierDependency.ids")
  85. );
  86. class NormalReexportItem {
  87. /**
  88. * Creates an instance of NormalReexportItem.
  89. * @param {string} name export name
  90. * @param {Ids} ids reexported ids from other module
  91. * @param {InstanceType<ExportInfo>} exportInfo export info from other module
  92. * @param {boolean} checked true, if it should be checked at runtime if this export exists
  93. * @param {boolean} hidden true, if it is hidden behind another active export in the same module
  94. */
  95. constructor(name, ids, exportInfo, checked, hidden) {
  96. /** @type {string} */
  97. this.name = name;
  98. /** @type {Ids} */
  99. this.ids = ids;
  100. /** @type {InstanceType<ExportInfo>} */
  101. this.exportInfo = exportInfo;
  102. /** @type {boolean} */
  103. this.checked = checked;
  104. /** @type {boolean} */
  105. this.hidden = hidden;
  106. }
  107. }
  108. /** @typedef {Set<string>} ExportModeIgnored */
  109. /** @typedef {Set<string>} ExportModeHidden */
  110. class ExportMode {
  111. /**
  112. * Creates an instance of ExportMode.
  113. * @param {ExportModeType} type type of the mode
  114. */
  115. constructor(type) {
  116. /** @type {ExportModeType} */
  117. this.type = type;
  118. // for "normal-reexport":
  119. /** @type {NormalReexportItem[] | null} */
  120. this.items = null;
  121. // for "reexport-named-default" | "reexport-fake-namespace-object" | "reexport-namespace-object"
  122. /** @type {string | null} */
  123. this.name = null;
  124. /** @type {InstanceType<ExportInfo> | null} */
  125. this.partialNamespaceExportInfo = null;
  126. // for "dynamic-reexport":
  127. /** @type {ExportModeIgnored | null} */
  128. this.ignored = null;
  129. // for "dynamic-reexport" | "empty-star":
  130. /** @type {ExportModeHidden | undefined | null} */
  131. this.hidden = null;
  132. // for "missing":
  133. /** @type {string | null} */
  134. this.userRequest = null;
  135. // for "reexport-fake-namespace-object":
  136. /** @type {number} */
  137. this.fakeType = 0;
  138. }
  139. }
  140. /** @typedef {number[]} DependencyIndices */
  141. const RETURNS_TRUE = () => true;
  142. /**
  143. * Detect a per-name cycle when collecting `export *` contributions from
  144. * `exportInfo`'s module into `parentModule`. The TC39 `ResolveExport`
  145. * algorithm tracks a `resolveSet` of `(module, exportName)` pairs and
  146. * returns null when an entry is revisited — letting the `StarExportEntries`
  147. * loop fall through to a non-cyclic source. Webpack's static export graph
  148. * does not run that resolution algorithm, so we approximate it: if the
  149. * imported module's same-named export ultimately re-exports from
  150. * `parentModule` under the same name, the star contribution is cyclic and
  151. * must be skipped. The non-cyclic alternative (a sibling `export *` that
  152. * provides a real binding) then wins.
  153. *
  154. * We walk the target chain one hop at a time using `findTarget` with a
  155. * "match anything" filter so we can guard against namespace targets
  156. * (`export * as ns from`, where `target.export` is undefined) and against
  157. * unrelated cycles in the graph that would otherwise loop forever inside
  158. * `_findTarget`.
  159. * @param {ModuleGraph} moduleGraph the module graph
  160. * @param {InstanceType<ExportInfo>} exportInfo export info on the imported module
  161. * @param {Module} parentModule the module that contains the star reexport
  162. * @returns {boolean} true when this export reexports back to the parent module under the same name
  163. */
  164. const isStarReexportBackToParent = (moduleGraph, exportInfo, parentModule) => {
  165. // Fast path: probe the first hop directly. The overwhelmingly common case
  166. // in real builds is a terminal local binding (no `_target`) — `findTarget`
  167. // returns `undefined` and we exit without allocating a `visited` set.
  168. const firstTarget = exportInfo.findTarget(moduleGraph, RETURNS_TRUE);
  169. if (!firstTarget || typeof firstTarget !== "object") return false;
  170. const name = exportInfo.name;
  171. if (
  172. firstTarget.module === parentModule &&
  173. Array.isArray(firstTarget.export) &&
  174. firstTarget.export.length === 1 &&
  175. firstTarget.export[0] === name
  176. ) {
  177. return true;
  178. }
  179. if (!Array.isArray(firstTarget.export) || firstTarget.export.length === 0) {
  180. return false;
  181. }
  182. // Multi-hop chain — allocate visited tracking now. The set protects against
  183. // unrelated cycles in the graph that would otherwise spin inside
  184. // `_findTarget` (its `alreadyVisited` is only seeded for the entry node).
  185. let current = moduleGraph
  186. .getExportsInfo(firstTarget.module)
  187. .getReadOnlyExportInfo(firstTarget.export[0]);
  188. // Allocated lazily: a single-extra-hop chain that terminates (the common
  189. // `barrel -> leaf local binding` case) returns before `next` is ever
  190. // computed, so the visited set is pure waste there.
  191. /** @type {Set<InstanceType<ExportInfo>> | undefined} */
  192. let visited;
  193. for (;;) {
  194. const target = current.findTarget(moduleGraph, RETURNS_TRUE);
  195. if (!target || typeof target !== "object") return false;
  196. if (
  197. target.module === parentModule &&
  198. Array.isArray(target.export) &&
  199. target.export.length === 1 &&
  200. target.export[0] === name
  201. ) {
  202. return true;
  203. }
  204. if (!Array.isArray(target.export) || target.export.length === 0) {
  205. return false;
  206. }
  207. const next = moduleGraph
  208. .getExportsInfo(target.module)
  209. .getReadOnlyExportInfo(target.export[0]);
  210. if (visited === undefined) visited = new Set([exportInfo, current]);
  211. if (visited.has(next)) return false;
  212. visited.add(next);
  213. current = next;
  214. }
  215. };
  216. /**
  217. * Determine export assignments.
  218. * @param {ModuleGraph} moduleGraph module graph
  219. * @param {HarmonyExportImportedSpecifierDependency[]} dependencies dependencies
  220. * @param {HarmonyExportImportedSpecifierDependency=} additionalDependency additional dependency
  221. * @returns {{ names: ExportInfoName[], dependencyIndices: DependencyIndices }} result
  222. */
  223. const determineExportAssignments = (
  224. moduleGraph,
  225. dependencies,
  226. additionalDependency
  227. ) => {
  228. /** @type {Set<ExportInfoName>} */
  229. const names = new Set();
  230. /** @type {DependencyIndices} */
  231. const dependencyIndices = [];
  232. if (additionalDependency) {
  233. dependencies = [...dependencies, additionalDependency];
  234. }
  235. const referenceDep = dependencies[0] || additionalDependency;
  236. const parentModule = referenceDep
  237. ? moduleGraph.getParentModule(referenceDep)
  238. : null;
  239. for (const dep of dependencies) {
  240. const i = dependencyIndices.length;
  241. dependencyIndices[i] = names.size;
  242. const otherImportedModule = moduleGraph.getModule(dep);
  243. if (otherImportedModule) {
  244. const exportsInfo = moduleGraph.getExportsInfo(otherImportedModule);
  245. for (const exportInfo of exportsInfo.exports) {
  246. if (
  247. exportInfo.provided === true &&
  248. exportInfo.name !== "default" &&
  249. !names.has(exportInfo.name) &&
  250. !(
  251. parentModule &&
  252. isStarReexportBackToParent(moduleGraph, exportInfo, parentModule)
  253. )
  254. ) {
  255. names.add(exportInfo.name);
  256. dependencyIndices[i] = names.size;
  257. }
  258. }
  259. }
  260. }
  261. dependencyIndices.push(names.size);
  262. return { names: [...names], dependencyIndices };
  263. };
  264. /**
  265. * Finds dependency for name.
  266. * @param {object} options options
  267. * @param {ExportInfoName[]} options.names names
  268. * @param {DependencyIndices} options.dependencyIndices dependency indices
  269. * @param {string} name name
  270. * @param {ReadonlyArray<HarmonyExportImportedSpecifierDependency>} dependencies dependencies
  271. * @returns {HarmonyExportImportedSpecifierDependency | undefined} found dependency or nothing
  272. */
  273. const findDependencyForName = (
  274. { names, dependencyIndices },
  275. name,
  276. dependencies
  277. ) => {
  278. const dependenciesIt = dependencies[Symbol.iterator]();
  279. const dependencyIndicesIt = dependencyIndices[Symbol.iterator]();
  280. let dependenciesItResult = dependenciesIt.next();
  281. let dependencyIndicesItResult = dependencyIndicesIt.next();
  282. if (dependencyIndicesItResult.done) return;
  283. for (let i = 0; i < names.length; i++) {
  284. while (i >= dependencyIndicesItResult.value) {
  285. dependenciesItResult = dependenciesIt.next();
  286. dependencyIndicesItResult = dependencyIndicesIt.next();
  287. if (dependencyIndicesItResult.done) return;
  288. }
  289. if (names[i] === name) return dependenciesItResult.value;
  290. }
  291. return undefined;
  292. };
  293. /**
  294. * Returns the export mode.
  295. * @param {ModuleGraph} moduleGraph the module graph
  296. * @param {HarmonyExportImportedSpecifierDependency} dep the dependency
  297. * @param {string} runtimeKey the runtime key
  298. * @returns {ExportMode} the export mode
  299. */
  300. const getMode = (moduleGraph, dep, runtimeKey) => {
  301. const importedModule = moduleGraph.getModule(dep);
  302. if (!importedModule) {
  303. const mode = new ExportMode("missing");
  304. mode.userRequest = dep.userRequest;
  305. return mode;
  306. }
  307. const name = dep.name;
  308. const runtime = keyToRuntime(runtimeKey);
  309. const parentModule = /** @type {Module} */ (moduleGraph.getParentModule(dep));
  310. const exportsInfo = moduleGraph.getExportsInfo(parentModule);
  311. if (
  312. name
  313. ? exportsInfo.getUsed(name, runtime) === UsageState.Unused
  314. : exportsInfo.isUsed(runtime) === false
  315. ) {
  316. const mode = new ExportMode("unused");
  317. mode.name = name || "*";
  318. return mode;
  319. }
  320. const importedExportsType = importedModule.getExportsType(
  321. moduleGraph,
  322. /** @type {BuildMeta} */
  323. (parentModule.buildMeta).strictHarmonyModule
  324. );
  325. const ids = dep.getIds(moduleGraph);
  326. // Special handling for reexporting the default export
  327. // from non-namespace modules
  328. if (name && ids.length > 0 && ids[0] === "default") {
  329. switch (importedExportsType) {
  330. case "dynamic": {
  331. const mode = new ExportMode("reexport-dynamic-default");
  332. mode.name = name;
  333. return mode;
  334. }
  335. case "default-only":
  336. case "default-with-named": {
  337. const exportInfo = exportsInfo.getReadOnlyExportInfo(name);
  338. const mode = new ExportMode("reexport-named-default");
  339. mode.name = name;
  340. mode.partialNamespaceExportInfo = exportInfo;
  341. return mode;
  342. }
  343. }
  344. }
  345. // reexporting with a fixed name
  346. if (name) {
  347. /** @type {ExportMode} */
  348. let mode;
  349. const exportInfo = exportsInfo.getReadOnlyExportInfo(name);
  350. if (ids.length > 0) {
  351. // export { name as name }
  352. switch (importedExportsType) {
  353. case "default-only":
  354. mode = new ExportMode("reexport-undefined");
  355. mode.name = name;
  356. break;
  357. default:
  358. mode = new ExportMode("normal-reexport");
  359. mode.items = [
  360. new NormalReexportItem(name, ids, exportInfo, false, false)
  361. ];
  362. break;
  363. }
  364. } else {
  365. // export * as name
  366. switch (importedExportsType) {
  367. case "default-only":
  368. mode = new ExportMode("reexport-fake-namespace-object");
  369. mode.name = name;
  370. mode.partialNamespaceExportInfo = exportInfo;
  371. mode.fakeType = 0;
  372. break;
  373. case "default-with-named":
  374. mode = new ExportMode("reexport-fake-namespace-object");
  375. mode.name = name;
  376. mode.partialNamespaceExportInfo = exportInfo;
  377. mode.fakeType = 2;
  378. break;
  379. case "dynamic":
  380. default:
  381. mode = new ExportMode("reexport-namespace-object");
  382. mode.name = name;
  383. mode.partialNamespaceExportInfo = exportInfo;
  384. }
  385. }
  386. return mode;
  387. }
  388. // Star reexporting
  389. const { ignoredExports, exports, checked, hidden } = dep.getStarReexports(
  390. moduleGraph,
  391. runtime,
  392. exportsInfo,
  393. importedModule
  394. );
  395. if (!exports) {
  396. // We have too few info about the modules
  397. // Delegate the logic to the runtime code
  398. const mode = new ExportMode("dynamic-reexport");
  399. mode.ignored = ignoredExports;
  400. mode.hidden = hidden;
  401. return mode;
  402. }
  403. if (exports.size === 0) {
  404. const mode = new ExportMode("empty-star");
  405. mode.hidden = hidden;
  406. return mode;
  407. }
  408. const mode = new ExportMode("normal-reexport");
  409. mode.items = Array.from(
  410. exports,
  411. (exportName) =>
  412. new NormalReexportItem(
  413. exportName,
  414. [exportName],
  415. exportsInfo.getReadOnlyExportInfo(exportName),
  416. /** @type {Checked} */
  417. (checked).has(exportName),
  418. false
  419. )
  420. );
  421. if (hidden !== undefined) {
  422. for (const exportName of hidden) {
  423. mode.items.push(
  424. new NormalReexportItem(
  425. exportName,
  426. [exportName],
  427. exportsInfo.getReadOnlyExportInfo(exportName),
  428. false,
  429. true
  430. )
  431. );
  432. }
  433. }
  434. return mode;
  435. };
  436. /** @typedef {Set<string>} Exports */
  437. /** @typedef {Set<string>} Checked */
  438. /** @typedef {Set<string>} Hidden */
  439. /** @typedef {Set<string>} IgnoredExports */
  440. class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
  441. /**
  442. * Creates an instance of HarmonyExportImportedSpecifierDependency.
  443. * @param {string} request the request string
  444. * @param {number} sourceOrder the order in the original source file
  445. * @param {Ids} ids the requested export name of the imported module
  446. * @param {string | null} name the export name of for this module
  447. * @param {Set<string>} activeExports other named exports in the module
  448. * @param {ReadonlyArray<HarmonyExportImportedSpecifierDependency> | null} otherStarExports other star exports in the module before this import
  449. * @param {ExportPresenceMode} exportPresenceMode mode of checking export names
  450. * @param {HarmonyStarExportsList | null} allStarExports all star exports in the module
  451. * @param {ImportPhaseType} phase import phase
  452. * @param {ImportAttributes=} attributes import attributes
  453. */
  454. constructor(
  455. request,
  456. sourceOrder,
  457. ids,
  458. name,
  459. activeExports,
  460. otherStarExports,
  461. exportPresenceMode,
  462. allStarExports,
  463. phase,
  464. attributes
  465. ) {
  466. super(request, sourceOrder, phase, attributes);
  467. /** @type {Ids} */
  468. this.ids = ids;
  469. /** @type {string | null} */
  470. this.name = name;
  471. /** @type {Set<string>} */
  472. this.activeExports = activeExports;
  473. this.otherStarExports = otherStarExports;
  474. /** @type {ExportPresenceMode} */
  475. this.exportPresenceMode = exportPresenceMode;
  476. /** @type {HarmonyStarExportsList | null} */
  477. this.allStarExports = allStarExports;
  478. }
  479. /**
  480. * Could affect referencing module.
  481. * @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
  482. */
  483. couldAffectReferencingModule() {
  484. return Dependency.TRANSITIVE;
  485. }
  486. // TODO webpack 6 remove
  487. /**
  488. * Returns id.
  489. * @deprecated
  490. */
  491. get id() {
  492. throw new Error("id was renamed to ids and type changed to string[]");
  493. }
  494. // TODO webpack 6 remove
  495. /**
  496. * Returns id.
  497. * @deprecated
  498. */
  499. getId() {
  500. throw new Error("id was renamed to ids and type changed to string[]");
  501. }
  502. // TODO webpack 6 remove
  503. /**
  504. * Updates id.
  505. * @deprecated
  506. */
  507. setId() {
  508. throw new Error("id was renamed to ids and type changed to string[]");
  509. }
  510. get type() {
  511. return "harmony export imported specifier";
  512. }
  513. /**
  514. * Returns the export name this dependency requests from its target module (lazy barrel optimization).
  515. * @returns {string | true | null} export name, true for all exports, null for none
  516. */
  517. getForwardId() {
  518. return this.ids.length > 0 ? this.ids[0] : true;
  519. }
  520. /**
  521. * Returns how this dependency may be deferred when its parent module is side-effect-free (lazy barrel optimization).
  522. * @returns {LazyUntil | null} lazy classification, null when it must be processed eagerly
  523. */
  524. getLazyUntil() {
  525. return this.name !== null
  526. ? Dependency.LAZY_UNTIL_ID
  527. : Dependency.LAZY_UNTIL_FALLBACK;
  528. }
  529. /**
  530. * Returns the export name for a `LAZY_UNTIL_LOCAL`/`LAZY_UNTIL_ID` classification (lazy barrel optimization).
  531. * @returns {string | null} export name, null when not applicable
  532. */
  533. getLazyName() {
  534. return this.name;
  535. }
  536. /**
  537. * Returns the imported id.
  538. * @param {ModuleGraph} moduleGraph the module graph
  539. * @returns {Ids} the imported id
  540. */
  541. getIds(moduleGraph) {
  542. return moduleGraph.getMeta(this)[idsSymbol] || this.ids;
  543. }
  544. /**
  545. * Updates ids using the provided module graph.
  546. * @param {ModuleGraph} moduleGraph the module graph
  547. * @param {Ids} ids the imported ids
  548. * @returns {void}
  549. */
  550. setIds(moduleGraph, ids) {
  551. moduleGraph.getMeta(this)[idsSymbol] = ids;
  552. }
  553. /**
  554. * Returns the export mode.
  555. * @param {ModuleGraph} moduleGraph the module graph
  556. * @param {RuntimeSpec} runtime the runtime
  557. * @returns {ExportMode} the export mode
  558. */
  559. getMode(moduleGraph, runtime) {
  560. return moduleGraph.dependencyCacheProvide(
  561. this,
  562. getRuntimeKey(runtime),
  563. getMode
  564. );
  565. }
  566. /**
  567. * Gets star reexports.
  568. * @param {ModuleGraph} moduleGraph the module graph
  569. * @param {RuntimeSpec} runtime the runtime
  570. * @param {ExportsInfo} exportsInfo exports info about the current module (optional)
  571. * @param {Module} importedModule the imported module (optional)
  572. * @returns {{ exports?: Exports, checked?: Checked, ignoredExports: IgnoredExports, hidden?: Hidden }} information
  573. */
  574. getStarReexports(
  575. moduleGraph,
  576. runtime,
  577. exportsInfo = moduleGraph.getExportsInfo(
  578. /** @type {Module} */ (moduleGraph.getParentModule(this))
  579. ),
  580. importedModule = /** @type {Module} */ (moduleGraph.getModule(this))
  581. ) {
  582. const importedExportsInfo = moduleGraph.getExportsInfo(importedModule);
  583. const noExtraExports =
  584. importedExportsInfo.otherExportsInfo.provided === false;
  585. const noExtraImports =
  586. exportsInfo.otherExportsInfo.getUsed(runtime) === UsageState.Unused;
  587. /** @type {IgnoredExports} */
  588. const ignoredExports = new Set(this.activeExports);
  589. ignoredExports.add("default");
  590. /** @type {Hidden | undefined} */
  591. let hiddenExports;
  592. const otherStarExports =
  593. this._discoverActiveExportsFromOtherStarExports(moduleGraph);
  594. if (otherStarExports !== undefined) {
  595. hiddenExports = new Set();
  596. for (let i = 0; i < otherStarExports.namesSlice; i++) {
  597. hiddenExports.add(otherStarExports.names[i]);
  598. }
  599. for (const e of ignoredExports) hiddenExports.delete(e);
  600. }
  601. if (!noExtraExports && !noExtraImports) {
  602. return {
  603. ignoredExports,
  604. hidden: hiddenExports
  605. };
  606. }
  607. /** @type {Exports} */
  608. const exports = new Set();
  609. /** @type {Checked} */
  610. const checked = new Set();
  611. /** @type {Hidden | undefined} */
  612. const hidden = hiddenExports !== undefined ? new Set() : undefined;
  613. const parentModule = /** @type {Module} */ (
  614. moduleGraph.getParentModule(this)
  615. );
  616. if (noExtraImports) {
  617. for (const exportInfo of exportsInfo.orderedExports) {
  618. const name = exportInfo.name;
  619. if (ignoredExports.has(name)) continue;
  620. if (exportInfo.getUsed(runtime) === UsageState.Unused) continue;
  621. const importedExportInfo =
  622. importedExportsInfo.getReadOnlyExportInfo(name);
  623. if (importedExportInfo.provided === false) continue;
  624. if (hiddenExports !== undefined && hiddenExports.has(name)) {
  625. // Earlier star deps already provided this name non-cyclically
  626. // (`determineExportAssignments` filters cyclic candidates), so
  627. // the cycle check below would be wasted work.
  628. /** @type {Hidden} */
  629. (hidden).add(name);
  630. continue;
  631. }
  632. if (
  633. isStarReexportBackToParent(
  634. moduleGraph,
  635. importedExportInfo,
  636. parentModule
  637. )
  638. ) {
  639. continue;
  640. }
  641. exports.add(name);
  642. if (importedExportInfo.provided === true) continue;
  643. checked.add(name);
  644. }
  645. } else if (noExtraExports) {
  646. for (const importedExportInfo of importedExportsInfo.orderedExports) {
  647. const name = importedExportInfo.name;
  648. if (ignoredExports.has(name)) continue;
  649. if (importedExportInfo.provided === false) continue;
  650. const exportInfo = exportsInfo.getReadOnlyExportInfo(name);
  651. if (exportInfo.getUsed(runtime) === UsageState.Unused) continue;
  652. if (hiddenExports !== undefined && hiddenExports.has(name)) {
  653. /** @type {ExportModeHidden} */
  654. (hidden).add(name);
  655. continue;
  656. }
  657. if (
  658. isStarReexportBackToParent(
  659. moduleGraph,
  660. importedExportInfo,
  661. parentModule
  662. )
  663. ) {
  664. continue;
  665. }
  666. exports.add(name);
  667. if (importedExportInfo.provided === true) continue;
  668. checked.add(name);
  669. }
  670. }
  671. return { ignoredExports, exports, checked, hidden };
  672. }
  673. /**
  674. * Returns function to determine if the connection is active.
  675. * @param {ModuleGraph} moduleGraph module graph
  676. * @returns {null | false | GetConditionFn} function to determine if the connection is active
  677. */
  678. getCondition(moduleGraph) {
  679. return (connection, runtime) => {
  680. const mode = this.getMode(moduleGraph, runtime);
  681. const active = mode.type !== "unused" && mode.type !== "empty-star";
  682. if (!active) return active;
  683. const module = connection.module;
  684. if (!isInlineEnabled(module)) return true;
  685. if (mode.type !== "normal-reexport") return true;
  686. const exportsInfo = moduleGraph.getExportsInfo(module);
  687. if (exportsInfo.otherExportsInfo.getUsed(runtime) !== UsageState.Unused) {
  688. return true;
  689. }
  690. for (const item of /** @type {NormalReexportItem[]} */ (mode.items)) {
  691. // Hidden/checked items can't be statically inlined away
  692. if (item.hidden || item.checked) return true;
  693. if (!isExportInlined(moduleGraph, module, item.ids, runtime)) {
  694. return true;
  695. }
  696. }
  697. return false;
  698. };
  699. }
  700. /**
  701. * Gets module evaluation side effects state.
  702. * @param {ModuleGraph} moduleGraph the module graph
  703. * @returns {ConnectionState} how this dependency connects the module to referencing modules
  704. */
  705. getModuleEvaluationSideEffectsState(moduleGraph) {
  706. return false;
  707. }
  708. /**
  709. * Returns list of exports referenced by this dependency
  710. * @param {ModuleGraph} moduleGraph module graph
  711. * @param {RuntimeSpec} runtime the runtime for which the module is analysed
  712. * @returns {ReferencedExports} referenced exports
  713. */
  714. getReferencedExports(moduleGraph, runtime) {
  715. const mode = this.getMode(moduleGraph, runtime);
  716. switch (mode.type) {
  717. case "missing":
  718. case "unused":
  719. case "empty-star":
  720. case "reexport-undefined":
  721. return Dependency.NO_EXPORTS_REFERENCED;
  722. case "reexport-dynamic-default":
  723. return Dependency.EXPORTS_OBJECT_REFERENCED;
  724. case "reexport-named-default": {
  725. if (!mode.partialNamespaceExportInfo) {
  726. return Dependency.EXPORTS_OBJECT_REFERENCED;
  727. }
  728. /** @type {RawReferencedExports} */
  729. const referencedExports = [];
  730. processExportInfo(
  731. runtime,
  732. referencedExports,
  733. [],
  734. /** @type {InstanceType<ExportInfo>} */ (
  735. mode.partialNamespaceExportInfo
  736. )
  737. );
  738. return referencedExports;
  739. }
  740. case "reexport-namespace-object":
  741. case "reexport-fake-namespace-object": {
  742. if (!mode.partialNamespaceExportInfo) {
  743. return Dependency.EXPORTS_OBJECT_REFERENCED;
  744. }
  745. /** @type {RawReferencedExports} */
  746. const referencedExports = [];
  747. processExportInfo(
  748. runtime,
  749. referencedExports,
  750. [],
  751. /** @type {InstanceType<ExportInfo>} */ (
  752. mode.partialNamespaceExportInfo
  753. ),
  754. mode.type === "reexport-fake-namespace-object"
  755. );
  756. return referencedExports;
  757. }
  758. case "dynamic-reexport":
  759. return Dependency.EXPORTS_OBJECT_REFERENCED;
  760. case "normal-reexport": {
  761. /** @type {RawReferencedExports} */
  762. const referencedExports = [];
  763. for (const {
  764. ids,
  765. exportInfo,
  766. hidden
  767. } of /** @type {NormalReexportItem[]} */ (mode.items)) {
  768. if (hidden) continue;
  769. processExportInfo(runtime, referencedExports, ids, exportInfo, false);
  770. }
  771. return referencedExports;
  772. }
  773. default:
  774. throw new Error(`Unknown mode ${mode.type}`);
  775. }
  776. }
  777. /**
  778. * Discover active exports from other star exports.
  779. * @param {ModuleGraph} moduleGraph the module graph
  780. * @returns {{ names: ExportInfoName[], namesSlice: number, dependencyIndices: DependencyIndices, dependencyIndex: number } | undefined} exported names and their origin dependency
  781. */
  782. _discoverActiveExportsFromOtherStarExports(moduleGraph) {
  783. if (!this.otherStarExports) return;
  784. const i =
  785. "length" in this.otherStarExports
  786. ? this.otherStarExports.length
  787. : countIterable(this.otherStarExports);
  788. if (i === 0) return;
  789. if (this.allStarExports) {
  790. const { names, dependencyIndices } = moduleGraph.cached(
  791. determineExportAssignments,
  792. this.allStarExports.dependencies
  793. );
  794. return {
  795. names,
  796. namesSlice: dependencyIndices[i - 1],
  797. dependencyIndices,
  798. dependencyIndex: i
  799. };
  800. }
  801. const { names, dependencyIndices } = moduleGraph.cached(
  802. determineExportAssignments,
  803. /** @type {HarmonyExportImportedSpecifierDependency[]} */
  804. (this.otherStarExports),
  805. this
  806. );
  807. return {
  808. names,
  809. namesSlice: dependencyIndices[i - 1],
  810. dependencyIndices,
  811. dependencyIndex: i
  812. };
  813. }
  814. /**
  815. * Returns the exported names
  816. * @param {ModuleGraph} moduleGraph module graph
  817. * @returns {ExportsSpec | undefined} export names
  818. */
  819. getExports(moduleGraph) {
  820. const mode = this.getMode(moduleGraph, undefined);
  821. switch (mode.type) {
  822. case "missing":
  823. return;
  824. case "dynamic-reexport": {
  825. const from =
  826. /** @type {ModuleGraphConnection} */
  827. (moduleGraph.getConnection(this));
  828. return {
  829. exports: true,
  830. from,
  831. canMangle: false,
  832. excludeExports: mode.hidden
  833. ? combine(
  834. /** @type {ExportModeIgnored} */ (mode.ignored),
  835. mode.hidden
  836. )
  837. : /** @type {ExportModeIgnored} */ (mode.ignored),
  838. hideExports: mode.hidden,
  839. dependencies: [from.module]
  840. };
  841. }
  842. case "empty-star":
  843. return {
  844. exports: [],
  845. hideExports: mode.hidden,
  846. dependencies: [/** @type {Module} */ (moduleGraph.getModule(this))]
  847. };
  848. // falls through
  849. case "normal-reexport": {
  850. const from =
  851. /** @type {ModuleGraphConnection} */
  852. (moduleGraph.getConnection(this));
  853. return {
  854. exports: Array.from(
  855. /** @type {NormalReexportItem[]} */ (mode.items),
  856. (item) => ({
  857. name: item.name,
  858. from,
  859. export: item.ids,
  860. hidden: item.hidden
  861. })
  862. ),
  863. priority: 1,
  864. dependencies: [from.module]
  865. };
  866. }
  867. case "reexport-dynamic-default": {
  868. const from =
  869. /** @type {ModuleGraphConnection} */
  870. (moduleGraph.getConnection(this));
  871. return {
  872. exports: [
  873. {
  874. name: /** @type {string} */ (mode.name),
  875. from,
  876. export: ["default"]
  877. }
  878. ],
  879. priority: 1,
  880. dependencies: [from.module]
  881. };
  882. }
  883. case "reexport-undefined":
  884. return {
  885. exports: [/** @type {string} */ (mode.name)],
  886. dependencies: [/** @type {Module} */ (moduleGraph.getModule(this))]
  887. };
  888. case "reexport-fake-namespace-object": {
  889. const from =
  890. /** @type {ModuleGraphConnection} */
  891. (moduleGraph.getConnection(this));
  892. return {
  893. exports: [
  894. {
  895. name: /** @type {string} */ (mode.name),
  896. from,
  897. export: null,
  898. exports: [
  899. {
  900. name: "default",
  901. canMangle: false,
  902. from,
  903. export: null
  904. }
  905. ]
  906. }
  907. ],
  908. priority: 1,
  909. dependencies: [from.module]
  910. };
  911. }
  912. case "reexport-namespace-object": {
  913. const from =
  914. /** @type {ModuleGraphConnection} */
  915. (moduleGraph.getConnection(this));
  916. return {
  917. exports: [
  918. {
  919. name: /** @type {string} */ (mode.name),
  920. from,
  921. export: null
  922. }
  923. ],
  924. priority: 1,
  925. dependencies: [from.module]
  926. };
  927. }
  928. case "reexport-named-default": {
  929. const from =
  930. /** @type {ModuleGraphConnection} */
  931. (moduleGraph.getConnection(this));
  932. return {
  933. exports: [
  934. {
  935. name: /** @type {string} */ (mode.name),
  936. from,
  937. export: ["default"]
  938. }
  939. ],
  940. priority: 1,
  941. dependencies: [from.module]
  942. };
  943. }
  944. default:
  945. throw new Error(`Unknown mode ${mode.type}`);
  946. }
  947. }
  948. /**
  949. * Get effective export presence level.
  950. * @param {ModuleGraph} moduleGraph module graph
  951. * @returns {ExportPresenceMode} effective mode
  952. */
  953. _getEffectiveExportPresenceLevel(moduleGraph) {
  954. if (this.exportPresenceMode !== ExportPresenceModes.AUTO) {
  955. return this.exportPresenceMode;
  956. }
  957. const module = /** @type {Module} */ (moduleGraph.getParentModule(this));
  958. return /** @type {BuildMeta} */ (module.buildMeta).strictHarmonyModule
  959. ? ExportPresenceModes.ERROR
  960. : ExportPresenceModes.WARN;
  961. }
  962. /**
  963. * Returns warnings.
  964. * @param {ModuleGraph} moduleGraph module graph
  965. * @returns {WebpackError[] | null | undefined} warnings
  966. */
  967. getWarnings(moduleGraph) {
  968. const exportsPresence = this._getEffectiveExportPresenceLevel(moduleGraph);
  969. if (exportsPresence === ExportPresenceModes.WARN) {
  970. return this._getErrors(moduleGraph);
  971. }
  972. return null;
  973. }
  974. /**
  975. * Returns errors.
  976. * @param {ModuleGraph} moduleGraph module graph
  977. * @returns {WebpackError[] | null | undefined} errors
  978. */
  979. getErrors(moduleGraph) {
  980. const exportsPresence = this._getEffectiveExportPresenceLevel(moduleGraph);
  981. if (exportsPresence === ExportPresenceModes.ERROR) {
  982. return this._getErrors(moduleGraph);
  983. }
  984. return null;
  985. }
  986. /**
  987. * Returns errors.
  988. * @param {ModuleGraph} moduleGraph module graph
  989. * @returns {WebpackError[] | undefined} errors
  990. */
  991. _getErrors(moduleGraph) {
  992. const ids = this.getIds(moduleGraph);
  993. let errors = this.getLinkingErrors(
  994. moduleGraph,
  995. ids,
  996. `(reexported as '${this.name}')`
  997. );
  998. if (ids.length === 0 && this.name === null) {
  999. const potentialConflicts =
  1000. this._discoverActiveExportsFromOtherStarExports(moduleGraph);
  1001. if (potentialConflicts && potentialConflicts.namesSlice > 0) {
  1002. const ownNames = new Set(
  1003. potentialConflicts.names.slice(
  1004. potentialConflicts.namesSlice,
  1005. potentialConflicts.dependencyIndices[
  1006. potentialConflicts.dependencyIndex
  1007. ]
  1008. )
  1009. );
  1010. const importedModule = moduleGraph.getModule(this);
  1011. if (importedModule) {
  1012. const exportsInfo = moduleGraph.getExportsInfo(importedModule);
  1013. /** @type {Map<string, ExportInfoName[]>} */
  1014. const conflicts = new Map();
  1015. for (const exportInfo of exportsInfo.orderedExports) {
  1016. if (exportInfo.provided !== true) continue;
  1017. if (exportInfo.name === "default") continue;
  1018. if (this.activeExports.has(exportInfo.name)) continue;
  1019. if (ownNames.has(exportInfo.name)) continue;
  1020. const conflictingDependency = findDependencyForName(
  1021. potentialConflicts,
  1022. exportInfo.name,
  1023. this.allStarExports
  1024. ? this.allStarExports.dependencies
  1025. : [
  1026. .../** @type {ReadonlyArray<HarmonyExportImportedSpecifierDependency>} */
  1027. (this.otherStarExports),
  1028. this
  1029. ]
  1030. );
  1031. if (!conflictingDependency) continue;
  1032. const target = exportInfo.getTerminalBinding(moduleGraph);
  1033. if (!target) continue;
  1034. const conflictingModule =
  1035. /** @type {Module} */
  1036. (moduleGraph.getModule(conflictingDependency));
  1037. if (conflictingModule === importedModule) continue;
  1038. const conflictingExportInfo = moduleGraph.getExportInfo(
  1039. conflictingModule,
  1040. exportInfo.name
  1041. );
  1042. const conflictingTarget =
  1043. conflictingExportInfo.getTerminalBinding(moduleGraph);
  1044. if (!conflictingTarget) continue;
  1045. if (target === conflictingTarget) continue;
  1046. const list = conflicts.get(conflictingDependency.request);
  1047. if (list === undefined) {
  1048. conflicts.set(conflictingDependency.request, [exportInfo.name]);
  1049. } else {
  1050. list.push(exportInfo.name);
  1051. }
  1052. }
  1053. for (const [request, exports] of conflicts) {
  1054. if (!errors) errors = [];
  1055. errors.push(
  1056. new HarmonyLinkingError(
  1057. `The requested module '${
  1058. this.request
  1059. }' contains conflicting star exports for the ${
  1060. exports.length > 1 ? "names" : "name"
  1061. } ${exports
  1062. .map((e) => `'${e}'`)
  1063. .join(", ")} with the previous requested module '${request}'`
  1064. )
  1065. );
  1066. }
  1067. }
  1068. }
  1069. }
  1070. return errors;
  1071. }
  1072. /**
  1073. * Serializes this instance into the provided serializer context.
  1074. * @param {ObjectSerializerContext} context context
  1075. */
  1076. serialize(context) {
  1077. context.setCircularReference(this);
  1078. context
  1079. .write(this.ids)
  1080. .write(this.name)
  1081. .write(this.activeExports)
  1082. .write(this.otherStarExports)
  1083. .write(this.exportPresenceMode)
  1084. .write(this.allStarExports);
  1085. super.serialize(context);
  1086. }
  1087. /**
  1088. * Restores this instance from the provided deserializer context.
  1089. * @param {ObjectDeserializerContext} context context
  1090. */
  1091. deserialize(context) {
  1092. context.setCircularReference(this);
  1093. this.ids = context.read();
  1094. const c1 = context.rest;
  1095. this.name = c1.read();
  1096. const c2 = c1.rest;
  1097. this.activeExports = c2.read();
  1098. const c3 = c2.rest;
  1099. this.otherStarExports = c3.read();
  1100. const c4 = c3.rest;
  1101. this.exportPresenceMode = c4.read();
  1102. const c5 = c4.rest;
  1103. this.allStarExports = c5.read();
  1104. super.deserialize(c5.rest);
  1105. }
  1106. }
  1107. makeSerializable(
  1108. HarmonyExportImportedSpecifierDependency,
  1109. "webpack/lib/dependencies/HarmonyExportImportedSpecifierDependency"
  1110. );
  1111. HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedSpecifierDependencyTemplate extends (
  1112. HarmonyImportDependency.Template
  1113. ) {
  1114. /**
  1115. * Applies the plugin by registering its hooks on the compiler.
  1116. * @param {Dependency} dependency the dependency for which the template should be applied
  1117. * @param {ReplaceSource} source the current replace source which can be modified
  1118. * @param {DependencyTemplateContext} templateContext the context object
  1119. * @returns {void}
  1120. */
  1121. apply(dependency, source, templateContext) {
  1122. const { moduleGraph, runtime, concatenationScope } = templateContext;
  1123. const dep = /** @type {HarmonyExportImportedSpecifierDependency} */ (
  1124. dependency
  1125. );
  1126. const mode = dep.getMode(moduleGraph, runtime);
  1127. // a wrapped module has no shared-scope symbols to redirect reexports to
  1128. if (concatenationScope && !concatenationScope.isWrapped()) {
  1129. switch (mode.type) {
  1130. case "reexport-undefined":
  1131. concatenationScope.registerRawExport(
  1132. /** @type {NonNullable<ExportMode["name"]>} */ (mode.name),
  1133. "/* reexport non-default export from non-harmony */ undefined"
  1134. );
  1135. }
  1136. return;
  1137. }
  1138. if (mode.type !== "unused" && mode.type !== "empty-star") {
  1139. const importedModule = moduleGraph.getModule(dep);
  1140. // an in-scope target has no standalone module left to import from
  1141. if (
  1142. concatenationScope === undefined ||
  1143. importedModule === null ||
  1144. !concatenationScope.isModuleInScope(importedModule)
  1145. ) {
  1146. super.apply(dependency, source, templateContext);
  1147. }
  1148. this._addExportFragments(
  1149. templateContext.initFragments,
  1150. dep,
  1151. mode,
  1152. templateContext.module,
  1153. moduleGraph,
  1154. templateContext.chunkGraph,
  1155. runtime,
  1156. templateContext.runtimeTemplate,
  1157. templateContext.runtimeRequirements,
  1158. concatenationScope
  1159. );
  1160. }
  1161. }
  1162. /**
  1163. * Add export fragments.
  1164. * @param {InitFragment<GenerateContext>[]} initFragments target array for init fragments
  1165. * @param {HarmonyExportImportedSpecifierDependency} dep dependency
  1166. * @param {ExportMode} mode the export mode
  1167. * @param {Module} module the current module
  1168. * @param {ModuleGraph} moduleGraph the module graph
  1169. * @param {ChunkGraph} chunkGraph the chunk graph
  1170. * @param {RuntimeSpec} runtime the runtime
  1171. * @param {RuntimeTemplate} runtimeTemplate the runtime template
  1172. * @param {RuntimeRequirements} runtimeRequirements runtime requirements
  1173. * @param {ConcatenationScope=} concatenationScope concatenation scope of a wrapped module
  1174. * @returns {void}
  1175. */
  1176. _addExportFragments(
  1177. initFragments,
  1178. dep,
  1179. mode,
  1180. module,
  1181. moduleGraph,
  1182. chunkGraph,
  1183. runtime,
  1184. runtimeTemplate,
  1185. runtimeRequirements,
  1186. concatenationScope
  1187. ) {
  1188. const importedModule = /** @type {Module} */ (moduleGraph.getModule(dep));
  1189. // an in-scope target has no import statement, read it through a reference
  1190. const inScope =
  1191. concatenationScope !== undefined &&
  1192. concatenationScope.isModuleInScope(importedModule);
  1193. const importVar = inScope
  1194. ? /** @type {ConcatenationScope} */ (
  1195. concatenationScope
  1196. ).createModuleReference(importedModule, { asiSafe: true })
  1197. : dep.getImportVar(moduleGraph);
  1198. // whole-namespace modes need the original export names, not mangled ones
  1199. const namespaceImportVar = inScope
  1200. ? /** @type {ConcatenationScope} */ (
  1201. concatenationScope
  1202. ).createModuleReference(importedModule, {
  1203. asiSafe: true,
  1204. mangleableNamespace: true
  1205. })
  1206. : importVar;
  1207. const isDeferred =
  1208. ImportPhaseUtils.isDefer(dep.phase) &&
  1209. !(/** @type {BuildMeta} */ (importedModule.buildMeta).async);
  1210. if (
  1211. (mode.type === "reexport-namespace-object" ||
  1212. mode.type === "reexport-fake-namespace-object") &&
  1213. isDeferred
  1214. ) {
  1215. initFragments.push(
  1216. ...this.getReexportDeferredNamespaceObjectFragments(
  1217. importedModule,
  1218. chunkGraph,
  1219. moduleGraph
  1220. .getExportsInfo(module)
  1221. .getUsedName(mode.name ? mode.name : [], runtime),
  1222. namespaceImportVar,
  1223. importedModule.getExportsType(
  1224. moduleGraph,
  1225. module.buildMeta &&
  1226. /** @type {JavascriptModuleBuildMeta} */ (module.buildMeta)
  1227. .strictHarmonyModule
  1228. ),
  1229. runtimeRequirements
  1230. )
  1231. );
  1232. return;
  1233. }
  1234. switch (mode.type) {
  1235. case "missing":
  1236. case "empty-star":
  1237. initFragments.push(
  1238. new InitFragment(
  1239. "/* empty/unused harmony star reexport */\n",
  1240. InitFragment.STAGE_HARMONY_EXPORTS,
  1241. 1
  1242. )
  1243. );
  1244. break;
  1245. case "unused":
  1246. initFragments.push(
  1247. new InitFragment(
  1248. `${Template.toNormalComment(
  1249. `unused harmony reexport ${mode.name}`
  1250. )}\n`,
  1251. InitFragment.STAGE_HARMONY_EXPORTS,
  1252. 1
  1253. )
  1254. );
  1255. break;
  1256. case "reexport-dynamic-default": {
  1257. // `${importVar}_default` names the interop variable that the import
  1258. // statement declares. An in-scope target has no import statement, so
  1259. // reference its default export and let the concatenation resolve it.
  1260. const defaultAccess = inScope
  1261. ? /** @type {ConcatenationScope} */ (
  1262. concatenationScope
  1263. ).createModuleReference(importedModule, {
  1264. ids: ["default"],
  1265. asiSafe: true
  1266. })
  1267. : importVar;
  1268. initFragments.push(
  1269. this.getReexportFragment(
  1270. module,
  1271. "reexport default from dynamic",
  1272. moduleGraph
  1273. .getExportsInfo(module)
  1274. .getUsedName(/** @type {string} */ (mode.name), runtime),
  1275. defaultAccess,
  1276. inScope ? "" : null,
  1277. runtimeRequirements
  1278. )
  1279. );
  1280. break;
  1281. }
  1282. case "reexport-fake-namespace-object":
  1283. // `${name}_namespace_cache` needs an identifier to suffix, but an
  1284. // in-scope target is an expression. The concatenation already builds
  1285. // the same object, memoized: its interop namespace picks the mode from
  1286. // the exports type, which is what `fakeType` mirrors.
  1287. if (inScope) {
  1288. initFragments.push(
  1289. this.getReexportFragment(
  1290. module,
  1291. "reexport fake namespace object from non-harmony",
  1292. moduleGraph
  1293. .getExportsInfo(module)
  1294. .getUsedName(/** @type {string} */ (mode.name), runtime),
  1295. /** @type {ConcatenationScope} */ (
  1296. concatenationScope
  1297. ).createModuleReference(importedModule, { asiSafe: true }),
  1298. "",
  1299. runtimeRequirements
  1300. )
  1301. );
  1302. } else {
  1303. initFragments.push(
  1304. ...this.getReexportFakeNamespaceObjectFragments(
  1305. module,
  1306. moduleGraph
  1307. .getExportsInfo(module)
  1308. .getUsedName(/** @type {string} */ (mode.name), runtime),
  1309. namespaceImportVar,
  1310. mode.fakeType,
  1311. runtimeRequirements
  1312. )
  1313. );
  1314. }
  1315. break;
  1316. case "reexport-undefined":
  1317. initFragments.push(
  1318. this.getReexportFragment(
  1319. module,
  1320. "reexport non-default export from non-harmony",
  1321. moduleGraph
  1322. .getExportsInfo(module)
  1323. .getUsedName(/** @type {string} */ (mode.name), runtime),
  1324. "undefined",
  1325. "",
  1326. runtimeRequirements
  1327. )
  1328. );
  1329. break;
  1330. case "reexport-named-default":
  1331. initFragments.push(
  1332. this.getReexportFragment(
  1333. module,
  1334. "reexport default export from named module",
  1335. moduleGraph
  1336. .getExportsInfo(module)
  1337. .getUsedName(/** @type {string} */ (mode.name), runtime),
  1338. importVar,
  1339. "",
  1340. runtimeRequirements
  1341. )
  1342. );
  1343. break;
  1344. case "reexport-namespace-object":
  1345. initFragments.push(
  1346. this.getReexportFragment(
  1347. module,
  1348. "reexport module object",
  1349. moduleGraph
  1350. .getExportsInfo(module)
  1351. .getUsedName(/** @type {string} */ (mode.name), runtime),
  1352. namespaceImportVar,
  1353. "",
  1354. runtimeRequirements
  1355. )
  1356. );
  1357. break;
  1358. case "normal-reexport": {
  1359. // loop-invariants hoisted out of the per-item loop below (a barrel
  1360. // re-exporting N names otherwise repeats these lookups N times)
  1361. const connection = moduleGraph.getConnection(dep);
  1362. const selfExportsInfo = moduleGraph.getExportsInfo(module);
  1363. const importedExportsInfo = moduleGraph.getExportsInfo(importedModule);
  1364. for (const {
  1365. name,
  1366. ids,
  1367. checked,
  1368. hidden
  1369. } of /** @type {NormalReexportItem[]} */ (mode.items)) {
  1370. if (hidden) continue;
  1371. if (checked) {
  1372. const key = `harmony reexport (checked) ${importVar} ${name}`;
  1373. const runtimeCondition = dep.weak
  1374. ? false
  1375. : connection
  1376. ? filterRuntime(runtime, (r) => connection.isTargetActive(r))
  1377. : true;
  1378. initFragments.push(
  1379. new ConditionalInitFragment(
  1380. `/* harmony reexport (checked) */ ${this.getConditionalReexportStatement(
  1381. module,
  1382. name,
  1383. importVar,
  1384. ids,
  1385. runtimeRequirements
  1386. )}`,
  1387. moduleGraph.isAsync(importedModule)
  1388. ? InitFragment.STAGE_ASYNC_HARMONY_IMPORTS
  1389. : InitFragment.STAGE_HARMONY_IMPORTS,
  1390. /** @type {number} */ (dep.sourceOrder),
  1391. key,
  1392. runtimeCondition
  1393. )
  1394. );
  1395. } else {
  1396. initFragments.push(
  1397. this.getReexportFragment(
  1398. module,
  1399. "reexport safe",
  1400. selfExportsInfo.getUsedName(name, runtime),
  1401. importVar,
  1402. importedExportsInfo.getUsedName(ids, runtime),
  1403. runtimeRequirements,
  1404. ids
  1405. )
  1406. );
  1407. }
  1408. }
  1409. break;
  1410. }
  1411. case "dynamic-reexport": {
  1412. const ignored = mode.hidden
  1413. ? combine(
  1414. /** @type {ExportModeIgnored} */
  1415. (mode.ignored),
  1416. mode.hidden
  1417. )
  1418. : /** @type {ExportModeIgnored} */ (mode.ignored);
  1419. let content =
  1420. "/* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {};\n" +
  1421. `/* harmony reexport (unknown) */ for(${runtimeTemplate.renderConst()} __WEBPACK_IMPORT_KEY__ in ${namespaceImportVar}) `;
  1422. // Filter out exports which are defined by other exports
  1423. // and filter out default export because it cannot be reexported with *
  1424. if (ignored.size > 1) {
  1425. content += `if(${JSON.stringify([
  1426. ...ignored
  1427. ])}.indexOf(__WEBPACK_IMPORT_KEY__) < 0) `;
  1428. } else if (ignored.size === 1) {
  1429. content += `if(__WEBPACK_IMPORT_KEY__ !== ${JSON.stringify(
  1430. first(ignored)
  1431. )}) `;
  1432. }
  1433. content += "__WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = ";
  1434. content +=
  1435. runtimeTemplate.supportsArrowFunction() &&
  1436. runtimeTemplate.supportsConst()
  1437. ? `() => ${namespaceImportVar}[__WEBPACK_IMPORT_KEY__]`
  1438. : `function(key) { return ${namespaceImportVar}[key]; }.bind(0, __WEBPACK_IMPORT_KEY__)`;
  1439. runtimeRequirements.add(RuntimeGlobals.exports);
  1440. runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
  1441. const exportsName = module.exportsArgument;
  1442. initFragments.push(
  1443. new InitFragment(
  1444. `${content}\n/* harmony reexport (unknown) */ ${RuntimeGlobals.definePropertyGetters}(${exportsName}, __WEBPACK_REEXPORT_OBJECT__);\n`,
  1445. moduleGraph.isAsync(importedModule)
  1446. ? InitFragment.STAGE_ASYNC_HARMONY_IMPORTS
  1447. : InitFragment.STAGE_HARMONY_IMPORTS,
  1448. /** @type {number} */ (dep.sourceOrder)
  1449. )
  1450. );
  1451. break;
  1452. }
  1453. default:
  1454. throw new Error(`Unknown mode ${mode.type}`);
  1455. }
  1456. }
  1457. /**
  1458. * Gets reexport fragment.
  1459. * @param {Module} module the current module
  1460. * @param {string} comment comment
  1461. * @param {UsedName} key key
  1462. * @param {string} name name
  1463. * @param {UsedName | null} valueKey value key
  1464. * @param {RuntimeRequirements} runtimeRequirements runtime requirements
  1465. * @param {string[]=} ids original ids on the imported side (for inline-rendering comment)
  1466. * @returns {HarmonyExportInitFragment} harmony export init fragment
  1467. */
  1468. getReexportFragment(
  1469. module,
  1470. comment,
  1471. key,
  1472. name,
  1473. valueKey,
  1474. runtimeRequirements,
  1475. ids
  1476. ) {
  1477. const returnValue = this.getReturnValue(name, valueKey, ids);
  1478. runtimeRequirements.add(RuntimeGlobals.exports);
  1479. runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
  1480. /** @type {ExportMap} */
  1481. const map = new Map();
  1482. map.set(key, `/* ${comment} */ ${returnValue}`);
  1483. return new HarmonyExportInitFragment(module.exportsArgument, map);
  1484. }
  1485. /**
  1486. * Gets reexport fake namespace object fragments.
  1487. * @param {Module} module module
  1488. * @param {UsedName} key key
  1489. * @param {string} name name
  1490. * @param {number} fakeType fake type
  1491. * @param {RuntimeRequirements} runtimeRequirements runtime requirements
  1492. * @returns {[InitFragment<GenerateContext>, HarmonyExportInitFragment]} init fragments
  1493. */
  1494. getReexportFakeNamespaceObjectFragments(
  1495. module,
  1496. key,
  1497. name,
  1498. fakeType,
  1499. runtimeRequirements
  1500. ) {
  1501. runtimeRequirements.add(RuntimeGlobals.exports);
  1502. runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
  1503. runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
  1504. /** @type {ExportMap} */
  1505. const map = new Map();
  1506. map.set(
  1507. key,
  1508. `/* reexport fake namespace object from non-harmony */ ${name}_namespace_cache || (${name}_namespace_cache = ${
  1509. RuntimeGlobals.createFakeNamespaceObject
  1510. }(${name}${fakeType ? `, ${fakeType}` : ""}))`
  1511. );
  1512. return [
  1513. new InitFragment(
  1514. `var ${name}_namespace_cache;\n`,
  1515. InitFragment.STAGE_CONSTANTS,
  1516. -1,
  1517. `${name}_namespace_cache`
  1518. ),
  1519. new HarmonyExportInitFragment(module.exportsArgument, map)
  1520. ];
  1521. }
  1522. /**
  1523. * Gets reexport deferred namespace object fragments.
  1524. * @param {Module} module module
  1525. * @param {ChunkGraph} chunkGraph chunkGraph
  1526. * @param {UsedName} key key
  1527. * @param {string} name name
  1528. * @param {ExportsType} exportsType exportsType
  1529. * @param {RuntimeRequirements} runtimeRequirements runtimeRequirements
  1530. * @returns {InitFragment<GenerateContext>[]} fragments
  1531. */
  1532. getReexportDeferredNamespaceObjectFragments(
  1533. module,
  1534. chunkGraph,
  1535. key,
  1536. name,
  1537. exportsType,
  1538. runtimeRequirements
  1539. ) {
  1540. runtimeRequirements.add(RuntimeGlobals.exports);
  1541. runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
  1542. runtimeRequirements.add(RuntimeGlobals.makeDeferredNamespaceObject);
  1543. /** @type {ExportMap} */
  1544. const map = new Map();
  1545. const moduleId = JSON.stringify(chunkGraph.getModuleId(module));
  1546. const mode = getMakeDeferredNamespaceModeFromExportsType(exportsType);
  1547. map.set(
  1548. key,
  1549. `/* reexport deferred namespace object */ ${name}_deferred_namespace_cache || (${name}_deferred_namespace_cache = ${RuntimeGlobals.makeDeferredNamespaceObject}(${moduleId}, ${mode}))`
  1550. );
  1551. return [
  1552. new InitFragment(
  1553. `var ${name}_deferred_namespace_cache;\n`,
  1554. InitFragment.STAGE_CONSTANTS,
  1555. -1,
  1556. `${name}_deferred_namespace_cache`
  1557. ),
  1558. new HarmonyExportInitFragment(module.exportsArgument, map)
  1559. ];
  1560. }
  1561. /**
  1562. * Gets conditional reexport statement.
  1563. * @param {Module} module module
  1564. * @param {string} key key
  1565. * @param {string} name name
  1566. * @param {string | string[] | false} valueKey value key
  1567. * @param {RuntimeRequirements} runtimeRequirements runtime requirements
  1568. * @returns {string} result
  1569. */
  1570. getConditionalReexportStatement(
  1571. module,
  1572. key,
  1573. name,
  1574. valueKey,
  1575. runtimeRequirements
  1576. ) {
  1577. if (valueKey === false) {
  1578. return "/* unused export */\n";
  1579. }
  1580. const exportsName = module.exportsArgument;
  1581. const returnValue = this.getReturnValue(name, valueKey);
  1582. runtimeRequirements.add(RuntimeGlobals.exports);
  1583. runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
  1584. runtimeRequirements.add(RuntimeGlobals.hasOwnProperty);
  1585. return `if(${RuntimeGlobals.hasOwnProperty}(${name}, ${JSON.stringify(
  1586. valueKey[0]
  1587. )})) ${
  1588. RuntimeGlobals.definePropertyGetters
  1589. }(${exportsName}, { ${propertyName(
  1590. key
  1591. )}: function() { return ${returnValue}; } });\n`;
  1592. }
  1593. /**
  1594. * Returns value.
  1595. * @param {string} name name
  1596. * @param {null | false | string | string[] | import("../optimize/InlineExports").InlinedUsedName} valueKey value key
  1597. * @param {string[]=} ids original imported ids (for inline-rendering comment)
  1598. * @returns {string | undefined} value
  1599. */
  1600. getReturnValue(name, valueKey, ids) {
  1601. if (valueKey === null) {
  1602. return `${name}_default.a`;
  1603. }
  1604. if (valueKey === "") {
  1605. return name;
  1606. }
  1607. if (valueKey === false) {
  1608. return "/* unused export */ undefined";
  1609. }
  1610. if (valueKey instanceof InlinedUsedName) {
  1611. // Re-export forwards the source export's inlined literal as its own runtime value
  1612. return valueKey.render(
  1613. Template.toNormalComment(`inlined export ${propertyAccess(ids || [])}`)
  1614. );
  1615. }
  1616. return `${name}${propertyAccess(Array.isArray(valueKey) ? valueKey : [valueKey])}`;
  1617. }
  1618. };
  1619. class HarmonyStarExportsList {
  1620. constructor() {
  1621. /** @type {HarmonyExportImportedSpecifierDependency[]} */
  1622. this.dependencies = [];
  1623. }
  1624. /**
  1625. * Processes the provided dep.
  1626. * @param {HarmonyExportImportedSpecifierDependency} dep dependency
  1627. * @returns {void}
  1628. */
  1629. push(dep) {
  1630. this.dependencies.push(dep);
  1631. }
  1632. slice() {
  1633. return [...this.dependencies];
  1634. }
  1635. /**
  1636. * Serializes this instance into the provided serializer context.
  1637. * @param {StarListSerializerContext} context context
  1638. */
  1639. serialize({ write, setCircularReference }) {
  1640. setCircularReference(this);
  1641. write(this.dependencies);
  1642. }
  1643. /**
  1644. * Restores this instance from the provided deserializer context.
  1645. * @param {StarListDeserializerContext} context context
  1646. */
  1647. deserialize({ read, setCircularReference }) {
  1648. setCircularReference(this);
  1649. this.dependencies = read();
  1650. }
  1651. }
  1652. makeSerializable(
  1653. HarmonyStarExportsList,
  1654. "webpack/lib/dependencies/HarmonyExportImportedSpecifierDependency",
  1655. "HarmonyStarExportsList"
  1656. );
  1657. HarmonyExportImportedSpecifierDependency.HarmonyStarExportsList =
  1658. HarmonyStarExportsList;
  1659. HarmonyExportImportedSpecifierDependency.idsSymbol = idsSymbol;
  1660. module.exports = HarmonyExportImportedSpecifierDependency;