@@ -30,7 +30,8 @@ import {
3030 logUnresolvedEntry ,
3131 logUnresolvedImplicitDependant ,
3232 logUnresolvedImport ,
33- logUnresolvedImportTreatedAsExternal
33+ logUnresolvedImportTreatedAsExternal ,
34+ warnDeprecation
3435} from './utils/logs' ;
3536import {
3637 doAttributesDiffer ,
@@ -42,6 +43,7 @@ import relativeId from './utils/relativeId';
4243import { resolveId } from './utils/resolveId' ;
4344import stripBom from './utils/stripBom' ;
4445import transform from './utils/transform' ;
46+ import { URL_LOAD } from './utils/urls' ;
4547
4648export interface UnresolvedModule {
4749 fileName : string | null ;
@@ -56,6 +58,7 @@ export type ModuleLoaderResolveId = (
5658 customOptions : CustomPluginOptions | undefined ,
5759 isEntry : boolean | undefined ,
5860 attributes : Record < string , string > ,
61+ importerAttributes : Record < string , string > | undefined ,
5962 skip ?: readonly { importer : string | undefined ; plugin : Plugin ; source : string } [ ] | null
6063) => Promise < ResolvedId | null > ;
6164
@@ -107,7 +110,7 @@ export class ModuleLoader {
107110 const result = this . extendLoadModulesPromise (
108111 Promise . all (
109112 unresolvedModules . map ( id =>
110- this . loadEntryModule ( id , false , undefined , null , isAddForManualChunks )
113+ this . loadEntryModule ( id , false , undefined , null , isAddForManualChunks , undefined )
111114 )
112115 )
113116 ) ;
@@ -130,7 +133,7 @@ export class ModuleLoader {
130133 const newEntryModules = await this . extendLoadModulesPromise (
131134 Promise . all (
132135 unresolvedEntryModules . map ( ( { id, importer } ) =>
133- this . loadEntryModule ( id , true , importer , null )
136+ this . loadEntryModule ( id , true , importer , null , undefined , undefined )
134137 )
135138 ) . then ( entryModules => {
136139 for ( const [ index , entryModule ] of entryModules . entries ( ) ) {
@@ -212,6 +215,7 @@ export class ModuleLoader {
212215 customOptions ,
213216 isEntry ,
214217 attributes ,
218+ importerAttributes ,
215219 skip = null
216220 ) =>
217221 this . getResolvedIdWithDefaults (
@@ -228,6 +232,7 @@ export class ModuleLoader {
228232 customOptions ,
229233 typeof isEntry === 'boolean' ? isEntry : ! importer ,
230234 attributes ,
235+ importerAttributes ,
231236 this . options . fs
232237 ) ,
233238 importer ,
@@ -242,32 +247,44 @@ export class ModuleLoader {
242247 ) : Promise < Module > {
243248 const chunkNamePriority = this . nextChunkNamePriority ++ ;
244249 return this . extendLoadModulesPromise (
245- this . loadEntryModule ( unresolvedModule . id , false , unresolvedModule . importer , null ) . then (
246- async entryModule => {
247- addChunkNamesToModule ( entryModule , unresolvedModule , false , chunkNamePriority ) ;
248- if ( ! entryModule . info . isEntry ) {
249- const implicitlyLoadedAfterModules = await Promise . all (
250- implicitlyLoadedAfter . map ( id =>
251- this . loadEntryModule ( id , false , unresolvedModule . importer , entryModule . id )
250+ this . loadEntryModule (
251+ unresolvedModule . id ,
252+ false ,
253+ unresolvedModule . importer ,
254+ null ,
255+ undefined ,
256+ undefined
257+ ) . then ( async entryModule => {
258+ addChunkNamesToModule ( entryModule , unresolvedModule , false , chunkNamePriority ) ;
259+ if ( ! entryModule . info . isEntry ) {
260+ const implicitlyLoadedAfterModules = await Promise . all (
261+ implicitlyLoadedAfter . map ( id =>
262+ this . loadEntryModule (
263+ id ,
264+ false ,
265+ unresolvedModule . importer ,
266+ entryModule . id ,
267+ undefined ,
268+ undefined
252269 )
253- ) ;
254- // We need to check again if this is still an entry module as these
255- // changes need to be performed atomically to avoid race conditions
256- // if the same module is re-emitted as an entry module.
257- // The inverse changes happen in "handleExistingModule"
258- if ( ! entryModule . info . isEntry ) {
259- this . implicitEntryModules . add ( entryModule ) ;
260- for ( const module of implicitlyLoadedAfterModules ) {
261- entryModule . implicitlyLoadedAfter . add ( module ) ;
262- }
263- for ( const dependant of entryModule . implicitlyLoadedAfter ) {
264- dependant . implicitlyLoadedBefore . add ( entryModule ) ;
265- }
270+ )
271+ ) ;
272+ // We need to check again if this is still an entry module as these
273+ // changes need to be performed atomically to avoid race conditions
274+ // if the same module is re-emitted as an entry module.
275+ // The inverse changes happen in "handleExistingModule"
276+ if ( ! entryModule . info . isEntry ) {
277+ this . implicitEntryModules . add ( entryModule ) ;
278+ for ( const module of implicitlyLoadedAfterModules ) {
279+ entryModule . implicitlyLoadedAfter . add ( module ) ;
280+ }
281+ for ( const dependant of entryModule . implicitlyLoadedAfter ) {
282+ dependant . implicitlyLoadedBefore . add ( entryModule ) ;
266283 }
267284 }
268- return entryModule ;
269285 }
270- )
286+ return entryModule ;
287+ } )
271288 ) ;
272289 }
273290
@@ -279,8 +296,21 @@ export class ModuleLoader {
279296 let source : LoadResult ;
280297 try {
281298 source = await this . graph . fileOperationQueue . run ( async ( ) => {
282- const content = await this . pluginDriver . hookFirst ( 'load' , [ id ] ) ;
283- if ( content !== null ) return content ;
299+ const content = await this . pluginDriver . hookFirst ( 'load' , [
300+ id ,
301+ { attributes : module . info . attributes }
302+ ] ) ;
303+ if ( content !== null ) {
304+ if ( typeof content === 'object' && content . attributes ) {
305+ warnDeprecation (
306+ 'Returning attributes from the "load" hook is forbidden.' ,
307+ URL_LOAD ,
308+ false ,
309+ this . options
310+ ) ;
311+ }
312+ return content ;
313+ }
284314 this . graph . watchFiles [ id ] = true ;
285315 return ( await this . options . fs . readFile ( id , { encoding : 'utf8' } ) ) as string ;
286316 } ) ;
@@ -306,6 +336,7 @@ export class ModuleLoader {
306336 ! ( await this . pluginDriver . hookFirst ( 'shouldTransformCachedModule' , [
307337 {
308338 ast : cachedModule . ast ,
339+ attributes : cachedModule . attributes ,
309340 code : cachedModule . code ,
310341 id : cachedModule . id ,
311342 meta : cachedModule . meta ,
@@ -323,7 +354,7 @@ export class ModuleLoader {
323354 } else {
324355 module . updateOptions ( sourceDescription ) ;
325356 await module . setSource (
326- await transform ( sourceDescription , module , this . pluginDriver , this . options . onLog )
357+ await transform ( sourceDescription , module , this . pluginDriver , this . options )
327358 ) ;
328359 }
329360 }
@@ -586,7 +617,14 @@ export class ModuleLoader {
586617 ( module . resolvedIds [ source ] =
587618 module . resolvedIds [ source ] ||
588619 this . handleInvalidResolvedId (
589- await this . resolveId ( source , module . id , EMPTY_OBJECT , false , attributes ) ,
620+ await this . resolveId (
621+ source ,
622+ module . id ,
623+ EMPTY_OBJECT ,
624+ false ,
625+ attributes ,
626+ module . info . attributes
627+ ) ,
590628 source ,
591629 module . id ,
592630 attributes
@@ -666,7 +704,8 @@ export class ModuleLoader {
666704 isEntry : boolean ,
667705 importer : string | undefined ,
668706 implicitlyLoadedBefore : string | null ,
669- isLoadForManualChunks = false
707+ isLoadForManualChunks = false ,
708+ importerAttributes : Record < string , string > | undefined
670709 ) : Promise < Module > {
671710 const resolveIdResult = await resolveId (
672711 unresolvedId ,
@@ -678,6 +717,7 @@ export class ModuleLoader {
678717 EMPTY_OBJECT ,
679718 true ,
680719 EMPTY_OBJECT ,
720+ importerAttributes ,
681721 this . options . fs
682722 ) ;
683723 if ( resolveIdResult == null ) {
@@ -719,7 +759,7 @@ export class ModuleLoader {
719759 const resolution = await this . pluginDriver . hookFirst ( 'resolveDynamicImport' , [
720760 specifier ,
721761 importer ,
722- { attributes }
762+ { attributes, importerAttributes : module . info . attributes }
723763 ] ) ;
724764 if ( typeof specifier !== 'string' ) {
725765 if ( typeof resolution === 'string' ) {
@@ -750,7 +790,14 @@ export class ModuleLoader {
750790 return existingResolution ;
751791 }
752792 return ( module . resolvedIds [ specifier ] = this . handleInvalidResolvedId (
753- await this . resolveId ( specifier , module . id , EMPTY_OBJECT , false , attributes ) ,
793+ await this . resolveId (
794+ specifier ,
795+ module . id ,
796+ EMPTY_OBJECT ,
797+ false ,
798+ attributes ,
799+ module . info . attributes
800+ ) ,
754801 specifier ,
755802 module . id ,
756803 attributes
0 commit comments