41
42
const PENDING = 0;
43
const RESOLVED_MODEL = 1;
44
-const INITIALIZED = 2;
45
-const ERRORED = 3;
44
+const RESOLVED_MODULE = 2;
45
+const INITIALIZED = 3;
46
+const ERRORED = 4;
47
48
type PendingChunk = {
49
_status: 0,
57
_response: Response,
58
then(resolve: () => mixed): void,
59
};
59
-type InitializedChunk<T> = {
60
+type ResolvedModuleChunk<T> = {
61
_status: 2,
62
+ _value: ModuleReference<T>,
63
+ _response: Response,
64
+ then(resolve: () => mixed): void,
65
+};
66
+type InitializedChunk<T> = {
67
+ _status: 3,
68
_value: T,
69
_response: Response,
70
then(resolve: () => mixed): void,
71
};
72
type ErroredChunk = {
66
- _status: 3,
73
+ _status: 4,
74
_value: Error,
75
_response: Response,
76
then(resolve: () => mixed): void,
78
type SomeChunk<T> =
79
| PendingChunk
80
| ResolvedModelChunk
81
+ | ResolvedModuleChunk<T>
82
| InitializedChunk<T>
83
| ErroredChunk;
84
113
return chunk._value;
114
case RESOLVED_MODEL:
115
return initializeModelChunk(chunk);
116
+ case RESOLVED_MODULE:
117
+ return initializeModuleChunk(chunk);
118
case PENDING:
119
// eslint-disable-next-line no-throw-literal
120
throw (chunk: Wakeable);
165
return new Chunk(RESOLVED_MODEL, value, response);
166
}
167
168
+function createResolvedModuleChunk<T>(
169
+ response: Response,
170
+ value: ModuleReference<T>,
171
+): ResolvedModuleChunk<T> {
172
+ return new Chunk(RESOLVED_MODULE, value, response);
173
+}
174
+
175
function resolveModelChunk<T>(
176
chunk: SomeChunk<T>,
177
value: UninitializedModel,
187
wakeChunk(listeners);
188
}
189
190
+function resolveModuleChunk<T>(
191
+ chunk: SomeChunk<T>,
192
+ value: ModuleReference<T>,
193
+): void {
194
+ if (chunk._status !== PENDING) {
195
+ // We already resolved. We didn't expect to see this.
196
+ return;
197
+ }
198
+ const listeners = chunk._value;
199
+ const resolvedChunk: ResolvedModuleChunk<T> = (chunk: any);
200
+ resolvedChunk._status = RESOLVED_MODULE;
201
+ resolvedChunk._value = value;
202
+ wakeChunk(listeners);
203
+}
204
+
205
function initializeModelChunk<T>(chunk: ResolvedModelChunk): T {
206
const value: T = parseModel(chunk._response, chunk._value);
207
const initializedChunk: InitializedChunk<T> = (chunk: any);
210
return value;
211
}
212
213
+function initializeModuleChunk<T>(chunk: ResolvedModuleChunk<T>): T {
214
+ const value: T = requireModule(chunk._value);
215
+ const initializedChunk: InitializedChunk<T> = (chunk: any);
216
+ initializedChunk._status = INITIALIZED;
217
+ initializedChunk._value = value;
218
+ return value;
219
+}
220
+
221
// Report that any missing chunks in the model is now going to throw this
222
// error upon read. Also notify any pending promises.
223
export function reportGlobalError(response: Response, error: Error): void {
281
282
type UninitializedBlockPayload<Data> = [
283
mixed,
244
- ModuleMetaData | SomeChunk<ModuleMetaData>,
284
+ BlockRenderFunction<any, Data> | SomeChunk<BlockRenderFunction<any, Data>>,
285
Data | SomeChunk<Data>,
286
Response,
287
];
290
tuple: UninitializedBlockPayload<Data>,
291
): BlockComponent<Props, Data> {
292
// Require module first and then data. The ordering matters.
253
- const moduleMetaData: ModuleMetaData = readMaybeChunk(tuple[1]);
254
- const moduleReference: ModuleReference<
255
- BlockRenderFunction<Props, Data>,
256
- > = resolveModuleReference(moduleMetaData);
257
- // TODO: Do this earlier, as the chunk is resolved.
258
- preloadModule(moduleReference);
259
-
260
- const moduleExport = requireModule(moduleReference);
293
+ const moduleExport = readMaybeChunk(tuple[1]);
294
295
// The ordering here is important because this call might suspend.
296
// We don't want that to prevent the module graph for being initialized.
396
}
397
}
398
399
+export function resolveModule(
400
+ response: Response,
401
+ id: number,
402
+ model: UninitializedModel,
403
+): void {
404
+ const chunks = response._chunks;
405
+ const chunk = chunks.get(id);
406
+ const moduleMetaData: ModuleMetaData = parseModel(response, model);
407
+ const moduleReference = resolveModuleReference(moduleMetaData);
408
+
409
+ // TODO: Add an option to encode modules that are lazy loaded.
410
+ // For now we preload all modules as early as possible since it's likely
411
+ // that we'll need them.
412
+ preloadModule(moduleReference);
413
+
414
+ if (!chunk) {
415
+ chunks.set(id, createResolvedModuleChunk(response, moduleReference));
416
+ } else {
417
+ resolveModuleChunk(chunk, moduleReference);
418
+ }
419
+}
420
+
421
export function resolveError(
422
response: Response,
423
id: number,