@@ -15,8 +15,6 @@ const {
1515 ObjectDefineProperty,
1616 ObjectSetPrototypeOf,
1717 PromiseAll,
18- PromiseResolve,
19- PromisePrototypeThen,
2018 ReflectApply,
2119 RegExpPrototypeExec,
2220 SafeArrayIterator,
@@ -111,14 +109,12 @@ let emittedSpecifierResolutionWarning = false;
111109 * position in the hook chain.
112110 * @param {string } meta.hookName The kind of hook the chain is (ex 'resolve')
113111 * @param {boolean } meta.shortCircuited Whether a hook signaled a short-circuit.
114- * @param {object } validators A wrapper function
112+ * @param {(hookErrIdentifier, hookArgs) => void } validate A wrapper function
115113 * containing all validation of a custom loader hook's intermediary output. Any
116114 * validation within MUST throw.
117- * @param {(hookErrIdentifier, hookArgs) => void } validators.validateArgs
118- * @param {(hookErrIdentifier, output) => void } validators.validateOutput
119115 * @returns {function next<HookName>(...hookArgs) } The next hook in the chain.
120116 */
121- function nextHookFactory ( chain , meta , { validateArgs , validateOutput } ) {
117+ function nextHookFactory ( chain , meta , validate ) {
122118// First, prepare the current
123119const { hookName } = meta ;
124120const {
@@ -141,7 +137,7 @@ function nextHookFactory(chain, meta, { validateArgs, validateOutput }) {
141137// factory generates the next link in the chain.
142138meta . hookIndex -- ;
143139
144- nextNextHook = nextHookFactory ( chain , meta , { validateArgs , validateOutput } ) ;
140+ nextNextHook = nextHookFactory ( chain , meta , validate ) ;
145141} else {
146142// eslint-disable-next-line func-name-matching
147143nextNextHook = function chainAdvancedTooFar ( ) {
@@ -152,36 +148,21 @@ function nextHookFactory(chain, meta, { validateArgs, validateOutput }) {
152148}
153149
154150return ObjectDefineProperty (
155- ( ...args ) => {
151+ async ( ...args ) => {
156152// Update only when hook is invoked to avoid fingering the wrong filePath
157153meta . hookErrIdentifier = `${ hookFilePath } '${ hookName } '` ;
158154
159- validateArgs ( `${ meta . hookErrIdentifier } hook's ${ nextHookName } ()` , args ) ;
160-
161- const outputErrIdentifier = `${ chain [ generatedHookIndex ] . url } '${ hookName } ' hook's ${ nextHookName } ()` ;
155+ validate ( `${ meta . hookErrIdentifier } hook's ${ nextHookName } ()` , args ) ;
162156
163157// Set when next<HookName> is actually called, not just generated.
164158if ( generatedHookIndex === 0 ) { meta . chainFinished = true ; }
165159
166160ArrayPrototypePush ( args , nextNextHook ) ;
167- const output = ReflectApply ( hook , undefined , args ) ;
168-
169- validateOutput ( outputErrIdentifier , output ) ;
161+ const output = await ReflectApply ( hook , undefined , args ) ;
170162
171- function checkShortCircuited ( output ) {
172- if ( output ?. shortCircuit === true ) { meta . shortCircuited = true ; }
173-
174- return output ;
175- }
176-
177- if ( meta . isChainAsync ) {
178- return PromisePrototypeThen (
179- PromiseResolve ( output ) ,
180- checkShortCircuited ,
181- ) ;
182- }
163+ if ( output ?. shortCircuit === true ) { meta . shortCircuited = true ; }
164+ return output ;
183165
184- return checkShortCircuited ( output ) ;
185166} ,
186167'name' ,
187168{ __proto__ : null , value : nextHookName } ,
@@ -440,11 +421,8 @@ class ESMLoader {
440421) ;
441422}
442423
443- const { format, url } = this . resolve (
444- specifier ,
445- parentURL ,
446- importAssertionsForResolve ,
447- ) ;
424+ const { format, url } =
425+ await this . resolve ( specifier , parentURL , importAssertionsForResolve ) ;
448426
449427let job = this . moduleMap . get ( url , importAssertions . type ) ;
450428
@@ -579,11 +557,10 @@ class ESMLoader {
579557hookErrIdentifier : '' ,
580558hookIndex : chain . length - 1 ,
581559hookName : 'load' ,
582- isChainAsync : true ,
583560shortCircuited : false ,
584561} ;
585562
586- const validateArgs = ( hookErrIdentifier , { 0 : nextUrl , 1 : ctx } ) => {
563+ const validate = ( hookErrIdentifier , { 0 : nextUrl , 1 : ctx } ) => {
587564if ( typeof nextUrl !== 'string' ) {
588565// non-strings can be coerced to a url string
589566// validateString() throws a less-specific error
@@ -609,22 +586,19 @@ class ESMLoader {
609586
610587validateObject ( ctx , `${ hookErrIdentifier } context` ) ;
611588} ;
612- const validateOutput = ( hookErrIdentifier , output ) => {
613- if ( typeof output !== 'object' ) { // [2]
614- throw new ERR_INVALID_RETURN_VALUE (
615- 'an object' ,
616- hookErrIdentifier ,
617- output ,
618- ) ;
619- }
620- } ;
621589
622- const nextLoad = nextHookFactory ( chain , meta , { validateArgs , validateOutput } ) ;
590+ const nextLoad = nextHookFactory ( chain , meta , validate ) ;
623591
624592const loaded = await nextLoad ( url , context ) ;
625593const { hookErrIdentifier } = meta ; // Retrieve the value after all settled
626594
627- validateOutput ( hookErrIdentifier , loaded ) ;
595+ if ( typeof loaded !== 'object' ) { // [2]
596+ throw new ERR_INVALID_RETURN_VALUE (
597+ 'an object' ,
598+ hookErrIdentifier ,
599+ loaded ,
600+ ) ;
601+ }
628602
629603if ( loaded ?. shortCircuit === true ) { meta . shortCircuited = true ; }
630604
@@ -804,7 +778,7 @@ class ESMLoader {
804778 * statement or expression.
805779 * @returns {{ format: string, url: URL['href'] } }
806780 */
807- resolve (
781+ async resolve (
808782originalSpecifier ,
809783parentURL ,
810784importAssertions = ObjectCreate ( null )
@@ -828,43 +802,36 @@ class ESMLoader {
828802hookErrIdentifier : '' ,
829803hookIndex : chain . length - 1 ,
830804hookName : 'resolve' ,
831- isChainAsync : false ,
832805shortCircuited : false ,
833806} ;
807+
834808const context = {
835809conditions : DEFAULT_CONDITIONS ,
836810 importAssertions,
837811 parentURL,
838812} ;
813+ const validate = ( hookErrIdentifier , { 0 : suppliedSpecifier , 1 : ctx } ) => {
839814
840- const validateArgs = ( hookErrIdentifier , { 0 : suppliedSpecifier , 1 : ctx } ) => {
841815validateString (
842816suppliedSpecifier ,
843817`${ hookErrIdentifier } specifier` ,
844818) ; // non-strings can be coerced to a url string
845819
846820validateObject ( ctx , `${ hookErrIdentifier } context` ) ;
847821} ;
848- const validateOutput = ( hookErrIdentifier , output ) => {
849- if (
850- typeof output !== 'object' || // [2]
851- output === null ||
852- ( output . url == null && typeof output . then === 'function' )
853- ) {
854- throw new ERR_INVALID_RETURN_VALUE (
855- 'an object' ,
856- hookErrIdentifier ,
857- output ,
858- ) ;
859- }
860- } ;
861822
862- const nextResolve = nextHookFactory ( chain , meta , { validateArgs , validateOutput } ) ;
823+ const nextResolve = nextHookFactory ( chain , meta , validate ) ;
863824
864- const resolution = nextResolve ( originalSpecifier , context ) ;
825+ const resolution = await nextResolve ( originalSpecifier , context ) ;
865826const { hookErrIdentifier } = meta ; // Retrieve the value after all settled
866827
867- validateOutput ( hookErrIdentifier , resolution ) ;
828+ if ( typeof resolution !== 'object' ) { // [2]
829+ throw new ERR_INVALID_RETURN_VALUE (
830+ 'an object' ,
831+ hookErrIdentifier ,
832+ resolution ,
833+ ) ;
834+ }
868835
869836if ( resolution ?. shortCircuit === true ) { meta . shortCircuited = true ; }
870837
0 commit comments