77
88const { ConcatSource } = require ( "webpack-sources" ) ;
99const { UsageState } = require ( "../ExportsInfo" ) ;
10+ const ExternalModule = require ( "../ExternalModule" ) ;
1011const RuntimeGlobals = require ( "../RuntimeGlobals" ) ;
1112const Template = require ( "../Template" ) ;
13+ const HarmonyExportImportedSpecifierDependency = require ( "../dependencies/HarmonyExportImportedSpecifierDependency" ) ;
1214const ConcatenatedModule = require ( "../optimize/ConcatenatedModule" ) ;
1315const propertyAccess = require ( "../util/propertyAccess" ) ;
1416const { getEntryRuntime } = require ( "../util/runtime" ) ;
@@ -20,11 +22,14 @@ const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
2022/** @typedef {import("../../declarations/WebpackOptions").LibraryExport } LibraryExport */
2123/** @typedef {import("../Chunk") } Chunk */
2224/** @typedef {import("../Compiler") } Compiler */
25+ /** @typedef {import("../ModuleGraph") } ModuleGraph */
2326/** @typedef {import("../Module") } Module */
2427/** @typedef {import("../Module").BuildMeta } BuildMeta */
2528/** @typedef {import("../Module").RuntimeRequirements } RuntimeRequirements */
2629/** @typedef {import("../javascript/JavascriptModulesPlugin").StartupRenderContext } StartupRenderContext */
2730/** @typedef {import("../javascript/JavascriptModulesPlugin").ModuleRenderContext } ModuleRenderContext */
31+ /** @typedef {import("../util/runtime").RuntimeSpec } RuntimeSpec */
32+ /** @typedef {import("../RuntimeTemplate") } RuntimeTemplate */
2833
2934/**
3035 * @template T
@@ -116,8 +121,13 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
116121 exportsInfo . canMangleUse = false ;
117122 } else {
118123 const exportsInfo = moduleGraph . getExportsInfo ( module ) ;
119- // If the entry module is commonjs, its exports cannot be mangled
120- if ( module . buildMeta && module . buildMeta . treatAsCommonJs ) {
124+
125+ if (
126+ // If the entry module is commonjs, its exports cannot be mangled
127+ ( module . buildMeta && module . buildMeta . treatAsCommonJs ) ||
128+ // The entry module provides unknown exports
129+ exportsInfo . _otherExportsInfo . provided === null
130+ ) {
121131 exportsInfo . setUsedInUnknownWay ( runtime ) ;
122132 } else {
123133 exportsInfo . setAllKnownExportsUsed ( runtime ) ;
@@ -144,6 +154,94 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
144154 } ;
145155 }
146156
157+ /**
158+ * @param {Source } source source
159+ * @param {Module } module module
160+ * @param {ModuleGraph } moduleGraph moduleGraph
161+ * @param {RuntimeSpec } runtime chunk runtime
162+ * @param {[string, string][] } exports exports
163+ * @param {Set<string> } alreadyRenderedExports already rendered exports
164+ * @returns {ConcatSource } source with null provided exports
165+ */
166+ _analyzeUnknownProvidedExports (
167+ source ,
168+ module ,
169+ moduleGraph ,
170+ runtime ,
171+ exports ,
172+ alreadyRenderedExports
173+ ) {
174+ const result = new ConcatSource ( source ) ;
175+ /** @type {Set<string> } */
176+ const moduleRequests = new Set ( ) ;
177+ /** @type {Map<string, string> } */
178+ const unknownProvidedExports = new Map ( ) ;
179+
180+ /**
181+ * @param {Module } module the module
182+ * @param {boolean } isDynamicReexport if module is dynamic reexported
183+ */
184+ const resolveDynamicStarReexport = ( module , isDynamicReexport ) => {
185+ for ( const connection of moduleGraph . getOutgoingConnections ( module ) ) {
186+ const dep = connection . dependency ;
187+
188+ // Only handle star-reexport statement
189+ if (
190+ dep instanceof HarmonyExportImportedSpecifierDependency &&
191+ dep . name === null
192+ ) {
193+ const importedModule = connection . resolvedModule ;
194+ const importedModuleExportsInfo =
195+ moduleGraph . getExportsInfo ( importedModule ) ;
196+
197+ // The imported module provides unknown exports
198+ // So keep the reexports rendered in the bundle
199+ if (
200+ dep . getMode ( moduleGraph , runtime ) . type === "dynamic-reexport" &&
201+ importedModuleExportsInfo . _otherExportsInfo . provided === null
202+ ) {
203+ // Handle export * from 'external'
204+ if ( importedModule instanceof ExternalModule ) {
205+ moduleRequests . add ( importedModule . userRequest ) ;
206+ } else {
207+ resolveDynamicStarReexport ( importedModule , true ) ;
208+ }
209+ }
210+ // If importer modules existing `dynamic-reexport` dependency
211+ // We should keep export statement rendered in the bundle
212+ else if ( isDynamicReexport ) {
213+ for ( const exportInfo of importedModuleExportsInfo . orderedExports ) {
214+ if ( ! exportInfo . provided || exportInfo . name === "default" ) {
215+ continue ;
216+ }
217+ const originalName = exportInfo . name ;
218+ const usedName = exportInfo . getUsedName ( originalName , runtime ) ;
219+
220+ if ( ! alreadyRenderedExports . has ( originalName ) && usedName ) {
221+ unknownProvidedExports . set ( originalName , usedName ) ;
222+ }
223+ }
224+ }
225+ }
226+ }
227+ } ;
228+
229+ resolveDynamicStarReexport ( module , false ) ;
230+
231+ for ( const request of moduleRequests ) {
232+ result . add ( `export * from "${ request } ";\n` ) ;
233+ }
234+
235+ for ( const [ origin , used ] of unknownProvidedExports ) {
236+ exports . push ( [
237+ origin ,
238+ `${ RuntimeGlobals . exports } ${ propertyAccess ( [ used ] ) } `
239+ ] ) ;
240+ }
241+
242+ return result ;
243+ }
244+
147245 /**
148246 * @param {Source } source source
149247 * @param {Module } module module
@@ -164,9 +262,8 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
164262 } ,
165263 { options, compilation }
166264 ) {
167- const result = new ConcatSource ( source ) ;
168-
169- const exportsInfo = options . export
265+ let result = new ConcatSource ( source ) ;
266+ const exportInfos = options . export
170267 ? [
171268 moduleGraph . getExportInfo (
172269 module ,
@@ -188,6 +285,9 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
188285 const shortHandedExports = [ ] ;
189286 /** @type {[string, string][] } */
190287 const exports = [ ] ;
288+ /** @type {Set<string> } */
289+ const alreadyRenderedExports = new Set ( ) ;
290+
191291 const isAsync = moduleGraph . isAsync ( module ) ;
192292
193293 const treatAsCommonJs =
@@ -200,7 +300,7 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
200300 ) ;
201301 }
202302
203- outer: for ( const exportInfo of exportsInfo ) {
303+ outer: for ( const exportInfo of exportInfos ) {
204304 if ( ! exportInfo . provided ) continue ;
205305
206306 const originalName = exportInfo . name ;
@@ -273,6 +373,8 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
273373 : `${ finalName } as ${ originalName } `
274374 ) ;
275375 }
376+
377+ alreadyRenderedExports . add ( originalName ) ;
276378 }
277379
278380 if ( treatAsCommonJs ) {
@@ -283,6 +385,15 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
283385 result . add ( `export { ${ shortHandedExports . join ( ", " ) } };\n` ) ;
284386 }
285387
388+ result = this . _analyzeUnknownProvidedExports (
389+ result ,
390+ module ,
391+ moduleGraph ,
392+ chunk . runtime ,
393+ exports ,
394+ alreadyRenderedExports
395+ ) ;
396+
286397 for ( const [ exportName , final ] of exports ) {
287398 result . add (
288399 `export ${ runtimeTemplate . renderConst ( ) } ${ exportName } = ${ final } ;\n`
0 commit comments