@@ -111,7 +111,33 @@ export function resolveServerReference<T>(
111
111
// in Webpack but unfortunately it's not exposed so we have to
112
112
// replicate it in user space. null means that it has already loaded.
113
113
const chunkCache : Map < string , null | Promise < any > > = new Map ( ) ;
114
- const asyncModuleCache : Map < string , Thenable < any > > = new Map ( ) ;
114
+
115
+ function requireAsyncModule ( id : string ) : null | Thenable < any > {
116
+ // We've already loaded all the chunks. We can require the module.
117
+ const promise = __webpack_require__ ( id ) ;
118
+ if ( typeof promise . then !== 'function' ) {
119
+ // This wasn't a promise after all.
120
+ return null ;
121
+ } else if ( promise . status === 'fulfilled' ) {
122
+ // This module was already resolved earlier.
123
+ return null ;
124
+ } else {
125
+ // Instrument the Promise to stash the result.
126
+ promise . then (
127
+ value => {
128
+ const fulfilledThenable : FulfilledThenable < mixed > = (promise: any);
129
+ fulfilledThenable.status = 'fulfilled';
130
+ fulfilledThenable.value = value;
131
+ } ,
132
+ reason => {
133
+ const rejectedThenable : RejectedThenable < mixed > = (promise: any);
134
+ rejectedThenable.status = 'rejected';
135
+ rejectedThenable.reason = reason;
136
+ } ,
137
+ ) ;
138
+ return promise ;
139
+ }
140
+ }
115
141
116
142
function ignoreReject ( ) {
117
143
// We rely on rejected promises to be handled by another listener.
@@ -138,32 +164,12 @@ export function preloadModule<T>(
138
164
}
139
165
}
140
166
if ( metadata . async ) {
141
- const existingPromise = asyncModuleCache . get ( metadata . id ) ;
142
- if ( existingPromise ) {
143
- if ( existingPromise . status === 'fulfilled' ) {
144
- return null ;
145
- }
146
- return existingPromise ;
167
+ if ( promises . length === 0 ) {
168
+ return requireAsyncModule ( metadata . id ) ;
147
169
} else {
148
- const modulePromise : Thenable < T > = Promise.all(promises).then(() => {
149
- return __webpack_require__ ( metadata . id ) ;
170
+ return Promise . all ( promises ) . then ( ( ) => {
171
+ return requireAsyncModule ( metadata . id ) ;
150
172
} ) ;
151
- modulePromise.then(
152
- value => {
153
- const fulfilledThenable : FulfilledThenable < mixed > =
154
- ( modulePromise : any ) ;
155
- fulfilledThenable . status = 'fulfilled' ;
156
- fulfilledThenable . value = value ;
157
- } ,
158
- reason => {
159
- const rejectedThenable : RejectedThenable < mixed > =
160
- ( modulePromise : any ) ;
161
- rejectedThenable . status = 'rejected' ;
162
- rejectedThenable . reason = reason ;
163
- } ,
164
- );
165
- asyncModuleCache.set(metadata.id, modulePromise);
166
- return modulePromise;
167
173
}
168
174
} else if ( promises . length > 0 ) {
169
175
return Promise . all ( promises ) ;
@@ -175,18 +181,16 @@ export function preloadModule<T>(
175
181
// Actually require the module or suspend if it's not yet ready.
176
182
// Increase priority if necessary.
177
183
export function requireModule < T > ( metadata : ClientReference < T > ) : T {
178
- let moduleExports ;
184
+ let moduleExports = __webpack_require__ ( metadata . id ) ;
179
185
if ( metadata . async ) {
180
- // We assume that preloadModule has been called before, which
181
- // should have added something to the module cache .
182
- const promise : any = asyncModuleCache . get ( metadata . id ) ;
183
- if ( promise . status === 'fulfilled' ) {
184
- moduleExports = promise . value ;
186
+ if ( typeof moduleExports . then !== 'function' ) {
187
+ // This wasn't a promise after all .
188
+ } else if ( moduleExports . status === 'fulfilled' ) {
189
+ // This Promise should've been instrumented by preloadModule.
190
+ moduleExports = moduleExports . value ;
185
191
} else {
186
- throw promise . reason ;
192
+ throw moduleExports . reason ;
187
193
}
188
- } else {
189
- moduleExports = __webpack_require__ ( metadata . id ) ;
190
194
}
191
195
if ( metadata . name === '*' ) {
192
196
// This is a placeholder value that represents that the caller imported this
0 commit comments