dinou 2.0.0 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/dinou/client-error.jsx +1 -1
  2. package/package.json +1 -1
  3. package/packages/vendor/react-server-dom-esm/LICENSE +21 -21
  4. package/packages/vendor/react-server-dom-esm/README.md +5 -5
  5. package/packages/vendor/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js +4477 -4477
  6. package/packages/vendor/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js +1783 -1783
  7. package/packages/vendor/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js +4544 -4544
  8. package/packages/vendor/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js +2016 -2016
  9. package/packages/vendor/react-server-dom-esm/cjs/react-server-dom-esm-server.node.development.js +5672 -5672
  10. package/packages/vendor/react-server-dom-esm/cjs/react-server-dom-esm-server.node.production.js +2907 -2907
  11. package/packages/vendor/react-server-dom-esm/client.browser.js +7 -7
  12. package/packages/vendor/react-server-dom-esm/client.js +3 -3
  13. package/packages/vendor/react-server-dom-esm/client.node.js +7 -7
  14. package/packages/vendor/react-server-dom-esm/esm/package.json +3 -3
  15. package/packages/vendor/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js +5586 -5586
  16. package/packages/vendor/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js +2620 -2620
  17. package/packages/vendor/react-server-dom-esm/esm/react-server-dom-esm-node-loader.production.js +515 -515
  18. package/packages/vendor/react-server-dom-esm/index.js +12 -12
  19. package/packages/vendor/react-server-dom-esm/package.json +62 -62
  20. package/packages/vendor/react-server-dom-esm/server.js +6 -6
  21. package/packages/vendor/react-server-dom-esm/server.node.js +17 -17
  22. package/packages/vendor/react-server-dom-esm/static.js +6 -6
  23. package/packages/vendor/react-server-dom-esm/static.node.js +12 -12
  24. package/rollup-plugins/rollup-plugin-react-client-manifest.js +126 -4
@@ -1,2620 +1,2620 @@
1
- /**
2
- * @license React
3
- * react-server-dom-esm-client.browser.production.js
4
- *
5
- * Copyright (c) Meta Platforms, Inc. and affiliates.
6
- *
7
- * This source code is licensed under the MIT license found in the
8
- * LICENSE file in the root directory of this source tree.
9
- */
10
-
11
- import * as ReactDOM from 'react-dom';
12
-
13
- function createStringDecoder() {
14
- return new TextDecoder();
15
- }
16
- const decoderOptions = {
17
- stream: true
18
- };
19
- function readPartialStringChunk(decoder, buffer) {
20
- return decoder.decode(buffer, decoderOptions);
21
- }
22
- function readFinalStringChunk(decoder, buffer) {
23
- return decoder.decode(buffer);
24
- }
25
-
26
- // Module root path
27
-
28
- function resolveClientReference(bundlerConfig, metadata) {
29
- const baseURL = bundlerConfig;
30
- return {
31
- specifier: baseURL + metadata[0],
32
- name: metadata[1]
33
- };
34
- }
35
- function resolveServerReference(config, id) {
36
- const baseURL = config;
37
- const idx = id.lastIndexOf('#');
38
- const exportName = id.slice(idx + 1);
39
- const fullURL = id.slice(0, idx);
40
- if (!fullURL.startsWith(baseURL)) {
41
- throw new Error('Attempted to load a Server Reference outside the hosted root.');
42
- }
43
- return {
44
- specifier: fullURL,
45
- name: exportName
46
- };
47
- }
48
- const asyncModuleCache = new Map();
49
- function preloadModule(metadata) {
50
- const existingPromise = asyncModuleCache.get(metadata.specifier);
51
- if (existingPromise) {
52
- if (existingPromise.status === 'fulfilled') {
53
- return null;
54
- }
55
- return existingPromise;
56
- } else {
57
- // $FlowFixMe[unsupported-syntax]
58
- const modulePromise = import(metadata.specifier);
59
- modulePromise.then(value => {
60
- const fulfilledThenable = modulePromise;
61
- fulfilledThenable.status = 'fulfilled';
62
- fulfilledThenable.value = value;
63
- }, reason => {
64
- const rejectedThenable = modulePromise;
65
- rejectedThenable.status = 'rejected';
66
- rejectedThenable.reason = reason;
67
- });
68
- asyncModuleCache.set(metadata.specifier, modulePromise);
69
- return modulePromise;
70
- }
71
- }
72
- function requireModule(metadata) {
73
- let moduleExports;
74
- // We assume that preloadModule has been called before, which
75
- // should have added something to the module cache.
76
- const promise = asyncModuleCache.get(metadata.specifier);
77
- if (promise.status === 'fulfilled') {
78
- moduleExports = promise.value;
79
- } else {
80
- throw promise.reason;
81
- }
82
- return moduleExports[metadata.name];
83
- }
84
-
85
- const ReactDOMSharedInternals = ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
86
-
87
- // This client file is in the shared folder because it applies to both SSR and browser contexts.
88
- // It is the configuration of the FlightClient behavior which can run in either environment.
89
-
90
- function dispatchHint(code, model) {
91
- const dispatcher = ReactDOMSharedInternals.d; /* ReactDOMCurrentDispatcher */
92
- switch (code) {
93
- case 'D':
94
- {
95
- const refined = refineModel(code, model);
96
- const href = refined;
97
- dispatcher.D( /* prefetchDNS */href);
98
- return;
99
- }
100
- case 'C':
101
- {
102
- const refined = refineModel(code, model);
103
- if (typeof refined === 'string') {
104
- const href = refined;
105
- dispatcher.C( /* preconnect */href);
106
- } else {
107
- const href = refined[0];
108
- const crossOrigin = refined[1];
109
- dispatcher.C( /* preconnect */href, crossOrigin);
110
- }
111
- return;
112
- }
113
- case 'L':
114
- {
115
- const refined = refineModel(code, model);
116
- const href = refined[0];
117
- const as = refined[1];
118
- if (refined.length === 3) {
119
- const options = refined[2];
120
- dispatcher.L( /* preload */href, as, options);
121
- } else {
122
- dispatcher.L( /* preload */href, as);
123
- }
124
- return;
125
- }
126
- case 'm':
127
- {
128
- const refined = refineModel(code, model);
129
- if (typeof refined === 'string') {
130
- const href = refined;
131
- dispatcher.m( /* preloadModule */href);
132
- } else {
133
- const href = refined[0];
134
- const options = refined[1];
135
- dispatcher.m( /* preloadModule */href, options);
136
- }
137
- return;
138
- }
139
- case 'X':
140
- {
141
- const refined = refineModel(code, model);
142
- if (typeof refined === 'string') {
143
- const href = refined;
144
- dispatcher.X( /* preinitScript */href);
145
- } else {
146
- const href = refined[0];
147
- const options = refined[1];
148
- dispatcher.X( /* preinitScript */href, options);
149
- }
150
- return;
151
- }
152
- case 'S':
153
- {
154
- const refined = refineModel(code, model);
155
- if (typeof refined === 'string') {
156
- const href = refined;
157
- dispatcher.S( /* preinitStyle */href);
158
- } else {
159
- const href = refined[0];
160
- const precedence = refined[1] === 0 ? undefined : refined[1];
161
- const options = refined.length === 3 ? refined[2] : undefined;
162
- dispatcher.S( /* preinitStyle */href, precedence, options);
163
- }
164
- return;
165
- }
166
- case 'M':
167
- {
168
- const refined = refineModel(code, model);
169
- if (typeof refined === 'string') {
170
- const href = refined;
171
- dispatcher.M( /* preinitModuleScript */href);
172
- } else {
173
- const href = refined[0];
174
- const options = refined[1];
175
- dispatcher.M( /* preinitModuleScript */href, options);
176
- }
177
- return;
178
- }
179
- }
180
- }
181
-
182
- // Flow is having trouble refining the HintModels so we help it a bit.
183
- // This should be compiled out in the production build.
184
- function refineModel(code, model) {
185
- return model;
186
- }
187
-
188
- const REACT_ELEMENT_TYPE = Symbol.for('react.transitional.element') ;
189
- const REACT_LAZY_TYPE = Symbol.for('react.lazy');
190
- const REACT_POSTPONE_TYPE = Symbol.for('react.postpone');
191
- const MAYBE_ITERATOR_SYMBOL = Symbol.iterator;
192
- const FAUX_ITERATOR_SYMBOL = '@@iterator';
193
- function getIteratorFn(maybeIterable) {
194
- if (maybeIterable === null || typeof maybeIterable !== 'object') {
195
- return null;
196
- }
197
- const maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];
198
- if (typeof maybeIterator === 'function') {
199
- return maybeIterator;
200
- }
201
- return null;
202
- }
203
- const ASYNC_ITERATOR = Symbol.asyncIterator;
204
-
205
- const isArrayImpl = Array.isArray;
206
- function isArray(a) {
207
- return isArrayImpl(a);
208
- }
209
-
210
- const getPrototypeOf = Object.getPrototypeOf;
211
-
212
- function createTemporaryReferenceSet() {
213
- return new Map();
214
- }
215
- function writeTemporaryReference(set, reference, object) {
216
- set.set(reference, object);
217
- }
218
- function readTemporaryReference(set, reference) {
219
- return set.get(reference);
220
- }
221
-
222
- const ObjectPrototype = Object.prototype;
223
- const knownServerReferences = new WeakMap();
224
-
225
- // Serializable values
226
-
227
- // Thenable<ReactServerValue>
228
-
229
- function serializeByValueID(id) {
230
- return '$' + id.toString(16);
231
- }
232
- function serializePromiseID(id) {
233
- return '$@' + id.toString(16);
234
- }
235
- function serializeServerReferenceID(id) {
236
- return '$F' + id.toString(16);
237
- }
238
- function serializeTemporaryReferenceMarker() {
239
- return '$T';
240
- }
241
- function serializeFormDataReference(id) {
242
- // Why K? F is "Function". D is "Date". What else?
243
- return '$K' + id.toString(16);
244
- }
245
- function serializeNumber(number) {
246
- if (Number.isFinite(number)) {
247
- if (number === 0 && 1 / number === -Infinity) {
248
- return '$-0';
249
- } else {
250
- return number;
251
- }
252
- } else {
253
- if (number === Infinity) {
254
- return '$Infinity';
255
- } else if (number === -Infinity) {
256
- return '$-Infinity';
257
- } else {
258
- return '$NaN';
259
- }
260
- }
261
- }
262
- function serializeUndefined() {
263
- return '$undefined';
264
- }
265
- function serializeDateFromDateJSON(dateJSON) {
266
- // JSON.stringify automatically calls Date.prototype.toJSON which calls toISOString.
267
- // We need only tack on a $D prefix.
268
- return '$D' + dateJSON;
269
- }
270
- function serializeBigInt(n) {
271
- return '$n' + n.toString(10);
272
- }
273
- function serializeMapID(id) {
274
- return '$Q' + id.toString(16);
275
- }
276
- function serializeSetID(id) {
277
- return '$W' + id.toString(16);
278
- }
279
- function serializeBlobID(id) {
280
- return '$B' + id.toString(16);
281
- }
282
- function serializeIteratorID(id) {
283
- return '$i' + id.toString(16);
284
- }
285
- function escapeStringValue(value) {
286
- if (value[0] === '$') {
287
- // We need to escape $ prefixed strings since we use those to encode
288
- // references to IDs and as special symbol values.
289
- return '$' + value;
290
- } else {
291
- return value;
292
- }
293
- }
294
- function processReply(root, formFieldPrefix, temporaryReferences, resolve, reject) {
295
- let nextPartId = 1;
296
- let pendingParts = 0;
297
- let formData = null;
298
- const writtenObjects = new WeakMap();
299
- let modelRoot = root;
300
- function serializeTypedArray(tag, typedArray) {
301
- const blob = new Blob([
302
- // We should be able to pass the buffer straight through but Node < 18 treat
303
- // multi-byte array blobs differently so we first convert it to single-byte.
304
- new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength)]);
305
- const blobId = nextPartId++;
306
- if (formData === null) {
307
- formData = new FormData();
308
- }
309
- formData.append(formFieldPrefix + blobId, blob);
310
- return '$' + tag + blobId.toString(16);
311
- }
312
- function serializeBinaryReader(reader) {
313
- if (formData === null) {
314
- // Upgrade to use FormData to allow us to stream this value.
315
- formData = new FormData();
316
- }
317
- const data = formData;
318
- pendingParts++;
319
- const streamId = nextPartId++;
320
- const buffer = [];
321
- function progress(entry) {
322
- if (entry.done) {
323
- const blobId = nextPartId++;
324
- data.append(formFieldPrefix + blobId, new Blob(buffer));
325
- data.append(formFieldPrefix + streamId, '"$o' + blobId.toString(16) + '"');
326
- data.append(formFieldPrefix + streamId, 'C'); // Close signal
327
- pendingParts--;
328
- if (pendingParts === 0) {
329
- resolve(data);
330
- }
331
- } else {
332
- buffer.push(entry.value);
333
- reader.read(new Uint8Array(1024)).then(progress, reject);
334
- }
335
- }
336
- reader.read(new Uint8Array(1024)).then(progress, reject);
337
- return '$r' + streamId.toString(16);
338
- }
339
- function serializeReader(reader) {
340
- if (formData === null) {
341
- // Upgrade to use FormData to allow us to stream this value.
342
- formData = new FormData();
343
- }
344
- const data = formData;
345
- pendingParts++;
346
- const streamId = nextPartId++;
347
- function progress(entry) {
348
- if (entry.done) {
349
- data.append(formFieldPrefix + streamId, 'C'); // Close signal
350
- pendingParts--;
351
- if (pendingParts === 0) {
352
- resolve(data);
353
- }
354
- } else {
355
- try {
356
- // $FlowFixMe[incompatible-type]: While plain JSON can return undefined we never do here.
357
- const partJSON = JSON.stringify(entry.value, resolveToJSON);
358
- data.append(formFieldPrefix + streamId, partJSON);
359
- reader.read().then(progress, reject);
360
- } catch (x) {
361
- reject(x);
362
- }
363
- }
364
- }
365
- reader.read().then(progress, reject);
366
- return '$R' + streamId.toString(16);
367
- }
368
- function serializeReadableStream(stream) {
369
- // Detect if this is a BYOB stream. BYOB streams should be able to be read as bytes on the
370
- // receiving side. For binary streams, we serialize them as plain Blobs.
371
- let binaryReader;
372
- try {
373
- // $FlowFixMe[extra-arg]: This argument is accepted.
374
- binaryReader = stream.getReader({
375
- mode: 'byob'
376
- });
377
- } catch (x) {
378
- return serializeReader(stream.getReader());
379
- }
380
- return serializeBinaryReader(binaryReader);
381
- }
382
- function serializeAsyncIterable(iterable, iterator) {
383
- if (formData === null) {
384
- // Upgrade to use FormData to allow us to stream this value.
385
- formData = new FormData();
386
- }
387
- const data = formData;
388
- pendingParts++;
389
- const streamId = nextPartId++;
390
-
391
- // Generators/Iterators are Iterables but they're also their own iterator
392
- // functions. If that's the case, we treat them as single-shot. Otherwise,
393
- // we assume that this iterable might be a multi-shot and allow it to be
394
- // iterated more than once on the receiving server.
395
- const isIterator = iterable === iterator;
396
-
397
- // There's a race condition between when the stream is aborted and when the promise
398
- // resolves so we track whether we already aborted it to avoid writing twice.
399
- function progress(entry) {
400
- if (entry.done) {
401
- if (entry.value === undefined) {
402
- data.append(formFieldPrefix + streamId, 'C'); // Close signal
403
- } else {
404
- // Unlike streams, the last value may not be undefined. If it's not
405
- // we outline it and encode a reference to it in the closing instruction.
406
- try {
407
- // $FlowFixMe[incompatible-type]: While plain JSON can return undefined we never do here.
408
- const partJSON = JSON.stringify(entry.value, resolveToJSON);
409
- data.append(formFieldPrefix + streamId, 'C' + partJSON); // Close signal
410
- } catch (x) {
411
- reject(x);
412
- return;
413
- }
414
- }
415
- pendingParts--;
416
- if (pendingParts === 0) {
417
- resolve(data);
418
- }
419
- } else {
420
- try {
421
- // $FlowFixMe[incompatible-type]: While plain JSON can return undefined we never do here.
422
- const partJSON = JSON.stringify(entry.value, resolveToJSON);
423
- data.append(formFieldPrefix + streamId, partJSON);
424
- iterator.next().then(progress, reject);
425
- } catch (x) {
426
- reject(x);
427
- return;
428
- }
429
- }
430
- }
431
- iterator.next().then(progress, reject);
432
- return '$' + (isIterator ? 'x' : 'X') + streamId.toString(16);
433
- }
434
- function resolveToJSON(key, value) {
435
- const parent = this;
436
- if (value === null) {
437
- return null;
438
- }
439
- if (typeof value === 'object') {
440
- switch (value.$$typeof) {
441
- case REACT_ELEMENT_TYPE:
442
- {
443
- if (temporaryReferences !== undefined && key.indexOf(':') === -1) {
444
- // TODO: If the property name contains a colon, we don't dedupe. Escape instead.
445
- const parentReference = writtenObjects.get(parent);
446
- if (parentReference !== undefined) {
447
- // If the parent has a reference, we can refer to this object indirectly
448
- // through the property name inside that parent.
449
- const reference = parentReference + ':' + key;
450
- // Store this object so that the server can refer to it later in responses.
451
- writeTemporaryReference(temporaryReferences, reference, value);
452
- return serializeTemporaryReferenceMarker();
453
- }
454
- }
455
- throw new Error('React Element cannot be passed to Server Functions from the Client without a ' + 'temporary reference set. Pass a TemporaryReferenceSet to the options.' + (''));
456
- }
457
- case REACT_LAZY_TYPE:
458
- {
459
- // Resolve lazy as if it wasn't here. In the future this will be encoded as a Promise.
460
- const lazy = value;
461
- const payload = lazy._payload;
462
- const init = lazy._init;
463
- if (formData === null) {
464
- // Upgrade to use FormData to allow us to stream this value.
465
- formData = new FormData();
466
- }
467
- pendingParts++;
468
- try {
469
- const resolvedModel = init(payload);
470
- // We always outline this as a separate part even though we could inline it
471
- // because it ensures a more deterministic encoding.
472
- const lazyId = nextPartId++;
473
- const partJSON = serializeModel(resolvedModel, lazyId);
474
- // $FlowFixMe[incompatible-type] We know it's not null because we assigned it above.
475
- const data = formData;
476
- data.append(formFieldPrefix + lazyId, partJSON);
477
- return serializeByValueID(lazyId);
478
- } catch (x) {
479
- if (typeof x === 'object' && x !== null && typeof x.then === 'function') {
480
- // Suspended
481
- pendingParts++;
482
- const lazyId = nextPartId++;
483
- const thenable = x;
484
- const retry = function () {
485
- // While the first promise resolved, its value isn't necessarily what we'll
486
- // resolve into because we might suspend again.
487
- try {
488
- const partJSON = serializeModel(value, lazyId);
489
- // $FlowFixMe[incompatible-type] We know it's not null because we assigned it above.
490
- const data = formData;
491
- data.append(formFieldPrefix + lazyId, partJSON);
492
- pendingParts--;
493
- if (pendingParts === 0) {
494
- resolve(data);
495
- }
496
- } catch (reason) {
497
- reject(reason);
498
- }
499
- };
500
- thenable.then(retry, retry);
501
- return serializeByValueID(lazyId);
502
- } else {
503
- // In the future we could consider serializing this as an error
504
- // that throws on the server instead.
505
- reject(x);
506
- return null;
507
- }
508
- } finally {
509
- pendingParts--;
510
- }
511
- }
512
- }
513
-
514
- // $FlowFixMe[method-unbinding]
515
- if (typeof value.then === 'function') {
516
- // We assume that any object with a .then property is a "Thenable" type,
517
- // or a Promise type. Either of which can be represented by a Promise.
518
- if (formData === null) {
519
- // Upgrade to use FormData to allow us to stream this value.
520
- formData = new FormData();
521
- }
522
- pendingParts++;
523
- const promiseId = nextPartId++;
524
- const thenable = value;
525
- thenable.then(partValue => {
526
- try {
527
- const partJSON = serializeModel(partValue, promiseId);
528
- // $FlowFixMe[incompatible-type] We know it's not null because we assigned it above.
529
- const data = formData;
530
- data.append(formFieldPrefix + promiseId, partJSON);
531
- pendingParts--;
532
- if (pendingParts === 0) {
533
- resolve(data);
534
- }
535
- } catch (reason) {
536
- reject(reason);
537
- }
538
- },
539
- // In the future we could consider serializing this as an error
540
- // that throws on the server instead.
541
- reject);
542
- return serializePromiseID(promiseId);
543
- }
544
- const existingReference = writtenObjects.get(value);
545
- if (existingReference !== undefined) {
546
- if (modelRoot === value) {
547
- // This is the ID we're currently emitting so we need to write it
548
- // once but if we discover it again, we refer to it by id.
549
- modelRoot = null;
550
- } else {
551
- // We've already emitted this as an outlined object, so we can
552
- // just refer to that by its existing ID.
553
- return existingReference;
554
- }
555
- } else if (key.indexOf(':') === -1) {
556
- // TODO: If the property name contains a colon, we don't dedupe. Escape instead.
557
- const parentReference = writtenObjects.get(parent);
558
- if (parentReference !== undefined) {
559
- // If the parent has a reference, we can refer to this object indirectly
560
- // through the property name inside that parent.
561
- const reference = parentReference + ':' + key;
562
- writtenObjects.set(value, reference);
563
- if (temporaryReferences !== undefined) {
564
- // Store this object so that the server can refer to it later in responses.
565
- writeTemporaryReference(temporaryReferences, reference, value);
566
- }
567
- }
568
- }
569
- if (isArray(value)) {
570
- // $FlowFixMe[incompatible-return]
571
- return value;
572
- }
573
- // TODO: Should we the Object.prototype.toString.call() to test for cross-realm objects?
574
- if (value instanceof FormData) {
575
- if (formData === null) {
576
- // Upgrade to use FormData to allow us to use rich objects as its values.
577
- formData = new FormData();
578
- }
579
- const data = formData;
580
- const refId = nextPartId++;
581
- // Copy all the form fields with a prefix for this reference.
582
- // These must come first in the form order because we assume that all the
583
- // fields are available before this is referenced.
584
- const prefix = formFieldPrefix + refId + '_';
585
- // $FlowFixMe[prop-missing]: FormData has forEach.
586
- value.forEach((originalValue, originalKey) => {
587
- // $FlowFixMe[incompatible-call]
588
- data.append(prefix + originalKey, originalValue);
589
- });
590
- return serializeFormDataReference(refId);
591
- }
592
- if (value instanceof Map) {
593
- const mapId = nextPartId++;
594
- const partJSON = serializeModel(Array.from(value), mapId);
595
- if (formData === null) {
596
- formData = new FormData();
597
- }
598
- formData.append(formFieldPrefix + mapId, partJSON);
599
- return serializeMapID(mapId);
600
- }
601
- if (value instanceof Set) {
602
- const setId = nextPartId++;
603
- const partJSON = serializeModel(Array.from(value), setId);
604
- if (formData === null) {
605
- formData = new FormData();
606
- }
607
- formData.append(formFieldPrefix + setId, partJSON);
608
- return serializeSetID(setId);
609
- }
610
- if (value instanceof ArrayBuffer) {
611
- const blob = new Blob([value]);
612
- const blobId = nextPartId++;
613
- if (formData === null) {
614
- formData = new FormData();
615
- }
616
- formData.append(formFieldPrefix + blobId, blob);
617
- return '$' + 'A' + blobId.toString(16);
618
- }
619
- if (value instanceof Int8Array) {
620
- // char
621
- return serializeTypedArray('O', value);
622
- }
623
- if (value instanceof Uint8Array) {
624
- // unsigned char
625
- return serializeTypedArray('o', value);
626
- }
627
- if (value instanceof Uint8ClampedArray) {
628
- // unsigned clamped char
629
- return serializeTypedArray('U', value);
630
- }
631
- if (value instanceof Int16Array) {
632
- // sort
633
- return serializeTypedArray('S', value);
634
- }
635
- if (value instanceof Uint16Array) {
636
- // unsigned short
637
- return serializeTypedArray('s', value);
638
- }
639
- if (value instanceof Int32Array) {
640
- // long
641
- return serializeTypedArray('L', value);
642
- }
643
- if (value instanceof Uint32Array) {
644
- // unsigned long
645
- return serializeTypedArray('l', value);
646
- }
647
- if (value instanceof Float32Array) {
648
- // float
649
- return serializeTypedArray('G', value);
650
- }
651
- if (value instanceof Float64Array) {
652
- // double
653
- return serializeTypedArray('g', value);
654
- }
655
- if (value instanceof BigInt64Array) {
656
- // number
657
- return serializeTypedArray('M', value);
658
- }
659
- if (value instanceof BigUint64Array) {
660
- // unsigned number
661
- // We use "m" instead of "n" since JSON can start with "null"
662
- return serializeTypedArray('m', value);
663
- }
664
- if (value instanceof DataView) {
665
- return serializeTypedArray('V', value);
666
- }
667
- // TODO: Blob is not available in old Node/browsers. Remove the typeof check later.
668
- if (typeof Blob === 'function' && value instanceof Blob) {
669
- if (formData === null) {
670
- formData = new FormData();
671
- }
672
- const blobId = nextPartId++;
673
- formData.append(formFieldPrefix + blobId, value);
674
- return serializeBlobID(blobId);
675
- }
676
- const iteratorFn = getIteratorFn(value);
677
- if (iteratorFn) {
678
- const iterator = iteratorFn.call(value);
679
- if (iterator === value) {
680
- // Iterator, not Iterable
681
- const iteratorId = nextPartId++;
682
- const partJSON = serializeModel(Array.from(iterator), iteratorId);
683
- if (formData === null) {
684
- formData = new FormData();
685
- }
686
- formData.append(formFieldPrefix + iteratorId, partJSON);
687
- return serializeIteratorID(iteratorId);
688
- }
689
- return Array.from(iterator);
690
- }
691
-
692
- // TODO: ReadableStream is not available in old Node. Remove the typeof check later.
693
- if (typeof ReadableStream === 'function' && value instanceof ReadableStream) {
694
- return serializeReadableStream(value);
695
- }
696
- const getAsyncIterator = value[ASYNC_ITERATOR];
697
- if (typeof getAsyncIterator === 'function') {
698
- // We treat AsyncIterables as a Fragment and as such we might need to key them.
699
- return serializeAsyncIterable(value, getAsyncIterator.call(value));
700
- }
701
-
702
- // Verify that this is a simple plain object.
703
- const proto = getPrototypeOf(value);
704
- if (proto !== ObjectPrototype && (proto === null || getPrototypeOf(proto) !== null)) {
705
- if (temporaryReferences === undefined) {
706
- throw new Error('Only plain objects, and a few built-ins, can be passed to Server Functions. ' + 'Classes or null prototypes are not supported.' + (''));
707
- }
708
- // We will have written this object to the temporary reference set above
709
- // so we can replace it with a marker to refer to this slot later.
710
- return serializeTemporaryReferenceMarker();
711
- }
712
-
713
- // $FlowFixMe[incompatible-return]
714
- return value;
715
- }
716
- if (typeof value === 'string') {
717
- // TODO: Maybe too clever. If we support URL there's no similar trick.
718
- if (value[value.length - 1] === 'Z') {
719
- // Possibly a Date, whose toJSON automatically calls toISOString
720
- // $FlowFixMe[incompatible-use]
721
- const originalValue = parent[key];
722
- if (originalValue instanceof Date) {
723
- return serializeDateFromDateJSON(value);
724
- }
725
- }
726
- return escapeStringValue(value);
727
- }
728
- if (typeof value === 'boolean') {
729
- return value;
730
- }
731
- if (typeof value === 'number') {
732
- return serializeNumber(value);
733
- }
734
- if (typeof value === 'undefined') {
735
- return serializeUndefined();
736
- }
737
- if (typeof value === 'function') {
738
- const referenceClosure = knownServerReferences.get(value);
739
- if (referenceClosure !== undefined) {
740
- const id = referenceClosure.id,
741
- bound = referenceClosure.bound;
742
- const referenceClosureJSON = JSON.stringify({
743
- id,
744
- bound
745
- }, resolveToJSON);
746
- if (formData === null) {
747
- // Upgrade to use FormData to allow us to stream this value.
748
- formData = new FormData();
749
- }
750
- // The reference to this function came from the same client so we can pass it back.
751
- const refId = nextPartId++;
752
- formData.set(formFieldPrefix + refId, referenceClosureJSON);
753
- return serializeServerReferenceID(refId);
754
- }
755
- if (temporaryReferences !== undefined && key.indexOf(':') === -1) {
756
- // TODO: If the property name contains a colon, we don't dedupe. Escape instead.
757
- const parentReference = writtenObjects.get(parent);
758
- if (parentReference !== undefined) {
759
- // If the parent has a reference, we can refer to this object indirectly
760
- // through the property name inside that parent.
761
- const reference = parentReference + ':' + key;
762
- // Store this object so that the server can refer to it later in responses.
763
- writeTemporaryReference(temporaryReferences, reference, value);
764
- return serializeTemporaryReferenceMarker();
765
- }
766
- }
767
- throw new Error('Client Functions cannot be passed directly to Server Functions. ' + 'Only Functions passed from the Server can be passed back again.');
768
- }
769
- if (typeof value === 'symbol') {
770
- if (temporaryReferences !== undefined && key.indexOf(':') === -1) {
771
- // TODO: If the property name contains a colon, we don't dedupe. Escape instead.
772
- const parentReference = writtenObjects.get(parent);
773
- if (parentReference !== undefined) {
774
- // If the parent has a reference, we can refer to this object indirectly
775
- // through the property name inside that parent.
776
- const reference = parentReference + ':' + key;
777
- // Store this object so that the server can refer to it later in responses.
778
- writeTemporaryReference(temporaryReferences, reference, value);
779
- return serializeTemporaryReferenceMarker();
780
- }
781
- }
782
- throw new Error('Symbols cannot be passed to a Server Function without a ' + 'temporary reference set. Pass a TemporaryReferenceSet to the options.' + (''));
783
- }
784
- if (typeof value === 'bigint') {
785
- return serializeBigInt(value);
786
- }
787
- throw new Error("Type " + typeof value + " is not supported as an argument to a Server Function.");
788
- }
789
- function serializeModel(model, id) {
790
- if (typeof model === 'object' && model !== null) {
791
- const reference = serializeByValueID(id);
792
- writtenObjects.set(model, reference);
793
- if (temporaryReferences !== undefined) {
794
- // Store this object so that the server can refer to it later in responses.
795
- writeTemporaryReference(temporaryReferences, reference, model);
796
- }
797
- }
798
- modelRoot = model;
799
- // $FlowFixMe[incompatible-return] it's not going to be undefined because we'll encode it.
800
- return JSON.stringify(model, resolveToJSON);
801
- }
802
- function abort(reason) {
803
- if (pendingParts > 0) {
804
- pendingParts = 0; // Don't resolve again later.
805
- // Resolve with what we have so far, which may have holes at this point.
806
- // They'll error when the stream completes on the server.
807
- if (formData === null) {
808
- resolve(json);
809
- } else {
810
- resolve(formData);
811
- }
812
- }
813
- }
814
- const json = serializeModel(root, 0);
815
- if (formData === null) {
816
- // If it's a simple data structure, we just use plain JSON.
817
- resolve(json);
818
- } else {
819
- // Otherwise, we use FormData to let us stream in the result.
820
- formData.set(formFieldPrefix + '0', json);
821
- if (pendingParts === 0) {
822
- // $FlowFixMe[incompatible-call] this has already been refined.
823
- resolve(formData);
824
- }
825
- }
826
- return abort;
827
- }
828
- function registerBoundServerReference(reference, id, bound, encodeFormAction) {
829
- if (knownServerReferences.has(reference)) {
830
- return;
831
- }
832
- knownServerReferences.set(reference, {
833
- id,
834
- originalBind: reference.bind,
835
- bound
836
- });
837
- }
838
- function registerServerReference(reference, id, encodeFormAction) {
839
- registerBoundServerReference(reference, id, null);
840
- return reference;
841
- }
842
- function createBoundServerReference(metaData, callServer, encodeFormAction, findSourceMapURL // DEV-only
843
- ) {
844
- const id = metaData.id;
845
- const bound = metaData.bound;
846
- let action = function () {
847
- // $FlowFixMe[method-unbinding]
848
- const args = Array.prototype.slice.call(arguments);
849
- const p = bound;
850
- if (!p) {
851
- return callServer(id, args);
852
- }
853
- if (p.status === 'fulfilled') {
854
- const boundArgs = p.value;
855
- return callServer(id, boundArgs.concat(args));
856
- }
857
- // Since this is a fake Promise whose .then doesn't chain, we have to wrap it.
858
- // TODO: Remove the wrapper once that's fixed.
859
- return Promise.resolve(p).then(function (boundArgs) {
860
- return callServer(id, boundArgs.concat(args));
861
- });
862
- };
863
- registerBoundServerReference(action, id, bound);
864
- return action;
865
- }
866
- function createServerReference(id, callServer, encodeFormAction, findSourceMapURL,
867
- // DEV-only
868
- functionName) {
869
- let action = function () {
870
- // $FlowFixMe[method-unbinding]
871
- const args = Array.prototype.slice.call(arguments);
872
- return callServer(id, args);
873
- };
874
- registerBoundServerReference(action, id, null);
875
- return action;
876
- }
877
-
878
- const ROW_ID = 0;
879
- const ROW_TAG = 1;
880
- const ROW_LENGTH = 2;
881
- const ROW_CHUNK_BY_NEWLINE = 3;
882
- const ROW_CHUNK_BY_LENGTH = 4;
883
- const PENDING = 'pending';
884
- const BLOCKED = 'blocked';
885
- const RESOLVED_MODEL = 'resolved_model';
886
- const RESOLVED_MODULE = 'resolved_module';
887
- const INITIALIZED = 'fulfilled';
888
- const ERRORED = 'rejected';
889
- const HALTED = 'halted'; // DEV-only. Means it never resolves even if connection closes.
890
-
891
- // $FlowFixMe[missing-this-annot]
892
- function ReactPromise(status, value, reason) {
893
- this.status = status;
894
- this.value = value;
895
- this.reason = reason;
896
- }
897
- // We subclass Promise.prototype so that we get other methods like .catch
898
- ReactPromise.prototype = Object.create(Promise.prototype);
899
- // TODO: This doesn't return a new Promise chain unlike the real .then
900
- ReactPromise.prototype.then = function (resolve, reject) {
901
- const chunk = this;
902
- // If we have resolved content, we try to initialize it first which
903
- // might put us back into one of the other states.
904
- switch (chunk.status) {
905
- case RESOLVED_MODEL:
906
- initializeModelChunk(chunk);
907
- break;
908
- case RESOLVED_MODULE:
909
- initializeModuleChunk(chunk);
910
- break;
911
- }
912
- // The status might have changed after initialization.
913
- switch (chunk.status) {
914
- case INITIALIZED:
915
- if (typeof resolve === 'function') {
916
- resolve(chunk.value);
917
- }
918
- break;
919
- case PENDING:
920
- case BLOCKED:
921
- if (typeof resolve === 'function') {
922
- if (chunk.value === null) {
923
- chunk.value = [];
924
- }
925
- chunk.value.push(resolve);
926
- }
927
- if (typeof reject === 'function') {
928
- if (chunk.reason === null) {
929
- chunk.reason = [];
930
- }
931
- chunk.reason.push(reject);
932
- }
933
- break;
934
- case HALTED:
935
- {
936
- break;
937
- }
938
- default:
939
- if (typeof reject === 'function') {
940
- reject(chunk.reason);
941
- }
942
- break;
943
- }
944
- };
945
- function unwrapWeakResponse(weakResponse) {
946
- {
947
- return weakResponse; // In prod we just use the real Response directly.
948
- }
949
- }
950
- function getWeakResponse(response) {
951
- {
952
- return response; // In prod we just use the real Response directly.
953
- }
954
- }
955
- function readChunk(chunk) {
956
- // If we have resolved content, we try to initialize it first which
957
- // might put us back into one of the other states.
958
- switch (chunk.status) {
959
- case RESOLVED_MODEL:
960
- initializeModelChunk(chunk);
961
- break;
962
- case RESOLVED_MODULE:
963
- initializeModuleChunk(chunk);
964
- break;
965
- }
966
- // The status might have changed after initialization.
967
- switch (chunk.status) {
968
- case INITIALIZED:
969
- return chunk.value;
970
- case PENDING:
971
- case BLOCKED:
972
- case HALTED:
973
- // eslint-disable-next-line no-throw-literal
974
- throw chunk;
975
- default:
976
- throw chunk.reason;
977
- }
978
- }
979
- function getRoot(weakResponse) {
980
- const response = unwrapWeakResponse(weakResponse);
981
- const chunk = getChunk(response, 0);
982
- return chunk;
983
- }
984
- function createPendingChunk(response) {
985
- // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
986
- return new ReactPromise(PENDING, null, null);
987
- }
988
- function createBlockedChunk(response) {
989
- // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
990
- return new ReactPromise(BLOCKED, null, null);
991
- }
992
- function createErrorChunk(response, error) {
993
- // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
994
- return new ReactPromise(ERRORED, null, error);
995
- }
996
- function wakeChunk(listeners, value) {
997
- for (let i = 0; i < listeners.length; i++) {
998
- const listener = listeners[i];
999
- if (typeof listener === 'function') {
1000
- listener(value);
1001
- } else {
1002
- fulfillReference(listener, value);
1003
- }
1004
- }
1005
- }
1006
- function rejectChunk(listeners, error) {
1007
- for (let i = 0; i < listeners.length; i++) {
1008
- const listener = listeners[i];
1009
- if (typeof listener === 'function') {
1010
- listener(error);
1011
- } else {
1012
- rejectReference(listener, error);
1013
- }
1014
- }
1015
- }
1016
- function resolveBlockedCycle(resolvedChunk, reference) {
1017
- const referencedChunk = reference.handler.chunk;
1018
- if (referencedChunk === null) {
1019
- return null;
1020
- }
1021
- if (referencedChunk === resolvedChunk) {
1022
- // We found the cycle. We can resolve the blocked cycle now.
1023
- return reference.handler;
1024
- }
1025
- const resolveListeners = referencedChunk.value;
1026
- if (resolveListeners !== null) {
1027
- for (let i = 0; i < resolveListeners.length; i++) {
1028
- const listener = resolveListeners[i];
1029
- if (typeof listener !== 'function') {
1030
- const foundHandler = resolveBlockedCycle(resolvedChunk, listener);
1031
- if (foundHandler !== null) {
1032
- return foundHandler;
1033
- }
1034
- }
1035
- }
1036
- }
1037
- return null;
1038
- }
1039
- function wakeChunkIfInitialized(chunk, resolveListeners, rejectListeners) {
1040
- switch (chunk.status) {
1041
- case INITIALIZED:
1042
- wakeChunk(resolveListeners, chunk.value);
1043
- break;
1044
- case BLOCKED:
1045
- // It is possible that we're blocked on our own chunk if it's a cycle.
1046
- // Before adding back the listeners to the chunk, let's check if it would
1047
- // result in a cycle.
1048
- for (let i = 0; i < resolveListeners.length; i++) {
1049
- const listener = resolveListeners[i];
1050
- if (typeof listener !== 'function') {
1051
- const reference = listener;
1052
- const cyclicHandler = resolveBlockedCycle(chunk, reference);
1053
- if (cyclicHandler !== null) {
1054
- // This reference points back to this chunk. We can resolve the cycle by
1055
- // using the value from that handler.
1056
- fulfillReference(reference, cyclicHandler.value);
1057
- resolveListeners.splice(i, 1);
1058
- i--;
1059
- if (rejectListeners !== null) {
1060
- const rejectionIdx = rejectListeners.indexOf(reference);
1061
- if (rejectionIdx !== -1) {
1062
- rejectListeners.splice(rejectionIdx, 1);
1063
- }
1064
- }
1065
- }
1066
- }
1067
- }
1068
- // Fallthrough
1069
- case PENDING:
1070
- if (chunk.value) {
1071
- for (let i = 0; i < resolveListeners.length; i++) {
1072
- chunk.value.push(resolveListeners[i]);
1073
- }
1074
- } else {
1075
- chunk.value = resolveListeners;
1076
- }
1077
- if (chunk.reason) {
1078
- if (rejectListeners) {
1079
- for (let i = 0; i < rejectListeners.length; i++) {
1080
- chunk.reason.push(rejectListeners[i]);
1081
- }
1082
- }
1083
- } else {
1084
- chunk.reason = rejectListeners;
1085
- }
1086
- break;
1087
- case ERRORED:
1088
- if (rejectListeners) {
1089
- rejectChunk(rejectListeners, chunk.reason);
1090
- }
1091
- break;
1092
- }
1093
- }
1094
- function triggerErrorOnChunk(response, chunk, error) {
1095
- if (chunk.status !== PENDING && chunk.status !== BLOCKED) {
1096
- // If we get more data to an already resolved ID, we assume that it's
1097
- // a stream chunk since any other row shouldn't have more than one entry.
1098
- const streamChunk = chunk;
1099
- const controller = streamChunk.reason;
1100
- // $FlowFixMe[incompatible-call]: The error method should accept mixed.
1101
- controller.error(error);
1102
- return;
1103
- }
1104
- const listeners = chunk.reason;
1105
- const erroredChunk = chunk;
1106
- erroredChunk.status = ERRORED;
1107
- erroredChunk.reason = error;
1108
- if (listeners !== null) {
1109
- rejectChunk(listeners, error);
1110
- }
1111
- }
1112
- function createResolvedModelChunk(response, value) {
1113
- // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
1114
- return new ReactPromise(RESOLVED_MODEL, value, response);
1115
- }
1116
- function createResolvedModuleChunk(response, value) {
1117
- // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
1118
- return new ReactPromise(RESOLVED_MODULE, value, null);
1119
- }
1120
- function createInitializedTextChunk(response, value) {
1121
- // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
1122
- return new ReactPromise(INITIALIZED, value, null);
1123
- }
1124
- function createInitializedBufferChunk(response, value) {
1125
- // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
1126
- return new ReactPromise(INITIALIZED, value, null);
1127
- }
1128
- function createInitializedIteratorResultChunk(response, value, done) {
1129
- // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
1130
- return new ReactPromise(INITIALIZED, {
1131
- done: done,
1132
- value: value
1133
- }, null);
1134
- }
1135
- function createInitializedStreamChunk(response, value, controller) {
1136
- // We use the reason field to stash the controller since we already have that
1137
- // field. It's a bit of a hack but efficient.
1138
- // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
1139
- return new ReactPromise(INITIALIZED, value, controller);
1140
- }
1141
- function createResolvedIteratorResultChunk(response, value, done) {
1142
- // To reuse code as much code as possible we add the wrapper element as part of the JSON.
1143
- const iteratorResultJSON = (done ? '{"done":true,"value":' : '{"done":false,"value":') + value + '}';
1144
- // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
1145
- return new ReactPromise(RESOLVED_MODEL, iteratorResultJSON, response);
1146
- }
1147
- function resolveIteratorResultChunk(response, chunk, value, done) {
1148
- // To reuse code as much code as possible we add the wrapper element as part of the JSON.
1149
- const iteratorResultJSON = (done ? '{"done":true,"value":' : '{"done":false,"value":') + value + '}';
1150
- resolveModelChunk(response, chunk, iteratorResultJSON);
1151
- }
1152
- function resolveModelChunk(response, chunk, value) {
1153
- if (chunk.status !== PENDING) {
1154
- // If we get more data to an already resolved ID, we assume that it's
1155
- // a stream chunk since any other row shouldn't have more than one entry.
1156
- const streamChunk = chunk;
1157
- const controller = streamChunk.reason;
1158
- controller.enqueueModel(value);
1159
- return;
1160
- }
1161
- const resolveListeners = chunk.value;
1162
- const rejectListeners = chunk.reason;
1163
- const resolvedChunk = chunk;
1164
- resolvedChunk.status = RESOLVED_MODEL;
1165
- resolvedChunk.value = value;
1166
- resolvedChunk.reason = response;
1167
- if (resolveListeners !== null) {
1168
- // This is unfortunate that we're reading this eagerly if
1169
- // we already have listeners attached since they might no
1170
- // longer be rendered or might not be the highest pri.
1171
- initializeModelChunk(resolvedChunk);
1172
- // The status might have changed after initialization.
1173
- wakeChunkIfInitialized(chunk, resolveListeners, rejectListeners);
1174
- }
1175
- }
1176
- function resolveModuleChunk(response, chunk, value) {
1177
- if (chunk.status !== PENDING && chunk.status !== BLOCKED) {
1178
- // We already resolved. We didn't expect to see this.
1179
- return;
1180
- }
1181
- const resolveListeners = chunk.value;
1182
- const rejectListeners = chunk.reason;
1183
- const resolvedChunk = chunk;
1184
- resolvedChunk.status = RESOLVED_MODULE;
1185
- resolvedChunk.value = value;
1186
- if (resolveListeners !== null) {
1187
- initializeModuleChunk(resolvedChunk);
1188
- wakeChunkIfInitialized(chunk, resolveListeners, rejectListeners);
1189
- }
1190
- }
1191
- let initializingHandler = null;
1192
- function initializeModelChunk(chunk) {
1193
- const prevHandler = initializingHandler;
1194
- initializingHandler = null;
1195
- const resolvedModel = chunk.value;
1196
- const response = chunk.reason;
1197
-
1198
- // We go to the BLOCKED state until we've fully resolved this.
1199
- // We do this before parsing in case we try to initialize the same chunk
1200
- // while parsing the model. Such as in a cyclic reference.
1201
- const cyclicChunk = chunk;
1202
- cyclicChunk.status = BLOCKED;
1203
- cyclicChunk.value = null;
1204
- cyclicChunk.reason = null;
1205
- try {
1206
- const value = parseModel(response, resolvedModel);
1207
- // Invoke any listeners added while resolving this model. I.e. cyclic
1208
- // references. This may or may not fully resolve the model depending on
1209
- // if they were blocked.
1210
- const resolveListeners = cyclicChunk.value;
1211
- if (resolveListeners !== null) {
1212
- cyclicChunk.value = null;
1213
- cyclicChunk.reason = null;
1214
- wakeChunk(resolveListeners, value);
1215
- }
1216
- if (initializingHandler !== null) {
1217
- if (initializingHandler.errored) {
1218
- throw initializingHandler.reason;
1219
- }
1220
- if (initializingHandler.deps > 0) {
1221
- // We discovered new dependencies on modules that are not yet resolved.
1222
- // We have to keep the BLOCKED state until they're resolved.
1223
- initializingHandler.value = value;
1224
- initializingHandler.chunk = cyclicChunk;
1225
- return;
1226
- }
1227
- }
1228
- const initializedChunk = chunk;
1229
- initializedChunk.status = INITIALIZED;
1230
- initializedChunk.value = value;
1231
- } catch (error) {
1232
- const erroredChunk = chunk;
1233
- erroredChunk.status = ERRORED;
1234
- erroredChunk.reason = error;
1235
- } finally {
1236
- initializingHandler = prevHandler;
1237
- }
1238
- }
1239
- function initializeModuleChunk(chunk) {
1240
- try {
1241
- const value = requireModule(chunk.value);
1242
- const initializedChunk = chunk;
1243
- initializedChunk.status = INITIALIZED;
1244
- initializedChunk.value = value;
1245
- } catch (error) {
1246
- const erroredChunk = chunk;
1247
- erroredChunk.status = ERRORED;
1248
- erroredChunk.reason = error;
1249
- }
1250
- }
1251
-
1252
- // Report that any missing chunks in the model is now going to throw this
1253
- // error upon read. Also notify any pending promises.
1254
- function reportGlobalError(weakResponse, error) {
1255
- const response = unwrapWeakResponse(weakResponse);
1256
- response._closed = true;
1257
- response._closedReason = error;
1258
- response._chunks.forEach(chunk => {
1259
- // If this chunk was already resolved or errored, it won't
1260
- // trigger an error but if it wasn't then we need to
1261
- // because we won't be getting any new data to resolve it.
1262
- if (chunk.status === PENDING) {
1263
- triggerErrorOnChunk(response, chunk, error);
1264
- }
1265
- });
1266
- }
1267
- function createElement(response, type, key, props, owner,
1268
- // DEV-only
1269
- stack,
1270
- // DEV-only
1271
- validated // DEV-only
1272
- ) {
1273
- let element;
1274
- {
1275
- element = {
1276
- // This tag allows us to uniquely identify this as a React Element
1277
- $$typeof: REACT_ELEMENT_TYPE,
1278
- type,
1279
- key,
1280
- ref: null,
1281
- props
1282
- };
1283
- }
1284
- if (initializingHandler !== null) {
1285
- const handler = initializingHandler;
1286
- // We pop the stack to the previous outer handler before leaving the Element.
1287
- // This is effectively the complete phase.
1288
- initializingHandler = handler.parent;
1289
- if (handler.errored) {
1290
- // Something errored inside this Element's props. We can turn this Element
1291
- // into a Lazy so that we can still render up until that Lazy is rendered.
1292
- const erroredChunk = createErrorChunk(response, handler.reason);
1293
- return createLazyChunkWrapper(erroredChunk);
1294
- }
1295
- if (handler.deps > 0) {
1296
- // We have blocked references inside this Element but we can turn this into
1297
- // a Lazy node referencing this Element to let everything around it proceed.
1298
- const blockedChunk = createBlockedChunk();
1299
- handler.value = element;
1300
- handler.chunk = blockedChunk;
1301
- return createLazyChunkWrapper(blockedChunk);
1302
- }
1303
- }
1304
- return element;
1305
- }
1306
- function createLazyChunkWrapper(chunk) {
1307
- const lazyType = {
1308
- $$typeof: REACT_LAZY_TYPE,
1309
- _payload: chunk,
1310
- _init: readChunk
1311
- };
1312
- return lazyType;
1313
- }
1314
- function getChunk(response, id) {
1315
- const chunks = response._chunks;
1316
- let chunk = chunks.get(id);
1317
- if (!chunk) {
1318
- if (response._closed) {
1319
- // We have already errored the response and we're not going to get
1320
- // anything more streaming in so this will immediately error.
1321
- chunk = createErrorChunk(response, response._closedReason);
1322
- } else {
1323
- chunk = createPendingChunk();
1324
- }
1325
- chunks.set(id, chunk);
1326
- }
1327
- return chunk;
1328
- }
1329
- function fulfillReference(reference, value) {
1330
- const response = reference.response,
1331
- handler = reference.handler,
1332
- parentObject = reference.parentObject,
1333
- key = reference.key,
1334
- map = reference.map,
1335
- path = reference.path;
1336
- for (let i = 1; i < path.length; i++) {
1337
- while (value.$$typeof === REACT_LAZY_TYPE) {
1338
- // We never expect to see a Lazy node on this path because we encode those as
1339
- // separate models. This must mean that we have inserted an extra lazy node
1340
- // e.g. to replace a blocked element. We must instead look for it inside.
1341
- const referencedChunk = value._payload;
1342
- if (referencedChunk === handler.chunk) {
1343
- // This is a reference to the thing we're currently blocking. We can peak
1344
- // inside of it to get the value.
1345
- value = handler.value;
1346
- continue;
1347
- } else {
1348
- switch (referencedChunk.status) {
1349
- case RESOLVED_MODEL:
1350
- initializeModelChunk(referencedChunk);
1351
- break;
1352
- case RESOLVED_MODULE:
1353
- initializeModuleChunk(referencedChunk);
1354
- break;
1355
- }
1356
- switch (referencedChunk.status) {
1357
- case INITIALIZED:
1358
- {
1359
- value = referencedChunk.value;
1360
- continue;
1361
- }
1362
- case BLOCKED:
1363
- {
1364
- // It is possible that we're blocked on our own chunk if it's a cycle.
1365
- // Before adding the listener to the inner chunk, let's check if it would
1366
- // result in a cycle.
1367
- const cyclicHandler = resolveBlockedCycle(referencedChunk, reference);
1368
- if (cyclicHandler !== null) {
1369
- // This reference points back to this chunk. We can resolve the cycle by
1370
- // using the value from that handler.
1371
- value = cyclicHandler.value;
1372
- continue;
1373
- }
1374
- // Fallthrough
1375
- }
1376
- case PENDING:
1377
- {
1378
- // If we're not yet initialized we need to skip what we've already drilled
1379
- // through and then wait for the next value to become available.
1380
- path.splice(0, i - 1);
1381
- // Add "listener" to our new chunk dependency.
1382
- if (referencedChunk.value === null) {
1383
- referencedChunk.value = [reference];
1384
- } else {
1385
- referencedChunk.value.push(reference);
1386
- }
1387
- if (referencedChunk.reason === null) {
1388
- referencedChunk.reason = [reference];
1389
- } else {
1390
- referencedChunk.reason.push(reference);
1391
- }
1392
- return;
1393
- }
1394
- case HALTED:
1395
- {
1396
- // Do nothing. We couldn't fulfill.
1397
- // TODO: Mark downstreams as halted too.
1398
- return;
1399
- }
1400
- default:
1401
- {
1402
- rejectReference(reference, referencedChunk.reason);
1403
- return;
1404
- }
1405
- }
1406
- }
1407
- }
1408
- value = value[path[i]];
1409
- }
1410
- const mappedValue = map(response, value, parentObject, key);
1411
- parentObject[key] = mappedValue;
1412
-
1413
- // If this is the root object for a model reference, where `handler.value`
1414
- // is a stale `null`, the resolved value can be used directly.
1415
- if (key === '' && handler.value === null) {
1416
- handler.value = mappedValue;
1417
- }
1418
-
1419
- // If the parent object is an unparsed React element tuple, we also need to
1420
- // update the props and owner of the parsed element object (i.e.
1421
- // handler.value).
1422
- if (parentObject[0] === REACT_ELEMENT_TYPE && typeof handler.value === 'object' && handler.value !== null && handler.value.$$typeof === REACT_ELEMENT_TYPE) {
1423
- const element = handler.value;
1424
- switch (key) {
1425
- case '3':
1426
- element.props = mappedValue;
1427
- break;
1428
- }
1429
- }
1430
- handler.deps--;
1431
- if (handler.deps === 0) {
1432
- const chunk = handler.chunk;
1433
- if (chunk === null || chunk.status !== BLOCKED) {
1434
- return;
1435
- }
1436
- const resolveListeners = chunk.value;
1437
- const initializedChunk = chunk;
1438
- initializedChunk.status = INITIALIZED;
1439
- initializedChunk.value = handler.value;
1440
- initializedChunk.reason = handler.reason; // Used by streaming chunks
1441
- if (resolveListeners !== null) {
1442
- wakeChunk(resolveListeners, handler.value);
1443
- }
1444
- }
1445
- }
1446
- function rejectReference(reference, error) {
1447
- const handler = reference.handler,
1448
- response = reference.response;
1449
- if (handler.errored) {
1450
- // We've already errored. We could instead build up an AggregateError
1451
- // but if there are multiple errors we just take the first one like
1452
- // Promise.all.
1453
- return;
1454
- }
1455
- handler.errored = true;
1456
- handler.value = null;
1457
- handler.reason = error;
1458
- const chunk = handler.chunk;
1459
- if (chunk === null || chunk.status !== BLOCKED) {
1460
- return;
1461
- }
1462
- triggerErrorOnChunk(response, chunk, error);
1463
- }
1464
- function waitForReference(referencedChunk, parentObject, key, response, map, path) {
1465
- let handler;
1466
- if (initializingHandler) {
1467
- handler = initializingHandler;
1468
- handler.deps++;
1469
- } else {
1470
- handler = initializingHandler = {
1471
- parent: null,
1472
- chunk: null,
1473
- value: null,
1474
- reason: null,
1475
- deps: 1,
1476
- errored: false
1477
- };
1478
- }
1479
- const reference = {
1480
- response,
1481
- handler,
1482
- parentObject,
1483
- key,
1484
- map,
1485
- path
1486
- };
1487
-
1488
- // Add "listener".
1489
- if (referencedChunk.value === null) {
1490
- referencedChunk.value = [reference];
1491
- } else {
1492
- referencedChunk.value.push(reference);
1493
- }
1494
- if (referencedChunk.reason === null) {
1495
- referencedChunk.reason = [reference];
1496
- } else {
1497
- referencedChunk.reason.push(reference);
1498
- }
1499
-
1500
- // Return a place holder value for now.
1501
- return null;
1502
- }
1503
- function loadServerReference(response, metaData, parentObject, key) {
1504
- if (!response._serverReferenceConfig) {
1505
- // In the normal case, we can't load this Server Reference in the current environment and
1506
- // we just return a proxy to it.
1507
- return createBoundServerReference(metaData, response._callServer);
1508
- }
1509
- // If we have a module mapping we can load the real version of this Server Reference.
1510
- const serverReference = resolveServerReference(response._serverReferenceConfig, metaData.id);
1511
- let promise = preloadModule(serverReference);
1512
- if (!promise) {
1513
- if (!metaData.bound) {
1514
- const resolvedValue = requireModule(serverReference);
1515
- registerBoundServerReference(resolvedValue, metaData.id, metaData.bound);
1516
- return resolvedValue;
1517
- } else {
1518
- promise = Promise.resolve(metaData.bound);
1519
- }
1520
- } else if (metaData.bound) {
1521
- promise = Promise.all([promise, metaData.bound]);
1522
- }
1523
- let handler;
1524
- if (initializingHandler) {
1525
- handler = initializingHandler;
1526
- handler.deps++;
1527
- } else {
1528
- handler = initializingHandler = {
1529
- parent: null,
1530
- chunk: null,
1531
- value: null,
1532
- reason: null,
1533
- deps: 1,
1534
- errored: false
1535
- };
1536
- }
1537
- function fulfill() {
1538
- let resolvedValue = requireModule(serverReference);
1539
- if (metaData.bound) {
1540
- // This promise is coming from us and should have initilialized by now.
1541
- const boundArgs = metaData.bound.value.slice(0);
1542
- boundArgs.unshift(null); // this
1543
- resolvedValue = resolvedValue.bind.apply(resolvedValue, boundArgs);
1544
- }
1545
- registerBoundServerReference(resolvedValue, metaData.id, metaData.bound);
1546
- parentObject[key] = resolvedValue;
1547
-
1548
- // If this is the root object for a model reference, where `handler.value`
1549
- // is a stale `null`, the resolved value can be used directly.
1550
- if (key === '' && handler.value === null) {
1551
- handler.value = resolvedValue;
1552
- }
1553
-
1554
- // If the parent object is an unparsed React element tuple, we also need to
1555
- // update the props and owner of the parsed element object (i.e.
1556
- // handler.value).
1557
- if (parentObject[0] === REACT_ELEMENT_TYPE && typeof handler.value === 'object' && handler.value !== null && handler.value.$$typeof === REACT_ELEMENT_TYPE) {
1558
- const element = handler.value;
1559
- switch (key) {
1560
- case '3':
1561
- element.props = resolvedValue;
1562
- break;
1563
- }
1564
- }
1565
- handler.deps--;
1566
- if (handler.deps === 0) {
1567
- const chunk = handler.chunk;
1568
- if (chunk === null || chunk.status !== BLOCKED) {
1569
- return;
1570
- }
1571
- const resolveListeners = chunk.value;
1572
- const initializedChunk = chunk;
1573
- initializedChunk.status = INITIALIZED;
1574
- initializedChunk.value = handler.value;
1575
- if (resolveListeners !== null) {
1576
- wakeChunk(resolveListeners, handler.value);
1577
- }
1578
- }
1579
- }
1580
- function reject(error) {
1581
- if (handler.errored) {
1582
- // We've already errored. We could instead build up an AggregateError
1583
- // but if there are multiple errors we just take the first one like
1584
- // Promise.all.
1585
- return;
1586
- }
1587
- handler.errored = true;
1588
- handler.value = null;
1589
- handler.reason = error;
1590
- const chunk = handler.chunk;
1591
- if (chunk === null || chunk.status !== BLOCKED) {
1592
- return;
1593
- }
1594
- triggerErrorOnChunk(response, chunk, error);
1595
- }
1596
- promise.then(fulfill, reject);
1597
-
1598
- // Return a place holder value for now.
1599
- return null;
1600
- }
1601
- function getOutlinedModel(response, reference, parentObject, key, map) {
1602
- const path = reference.split(':');
1603
- const id = parseInt(path[0], 16);
1604
- const chunk = getChunk(response, id);
1605
- switch (chunk.status) {
1606
- case RESOLVED_MODEL:
1607
- initializeModelChunk(chunk);
1608
- break;
1609
- case RESOLVED_MODULE:
1610
- initializeModuleChunk(chunk);
1611
- break;
1612
- }
1613
- // The status might have changed after initialization.
1614
- switch (chunk.status) {
1615
- case INITIALIZED:
1616
- let value = chunk.value;
1617
- for (let i = 1; i < path.length; i++) {
1618
- while (value.$$typeof === REACT_LAZY_TYPE) {
1619
- const referencedChunk = value._payload;
1620
- switch (referencedChunk.status) {
1621
- case RESOLVED_MODEL:
1622
- initializeModelChunk(referencedChunk);
1623
- break;
1624
- case RESOLVED_MODULE:
1625
- initializeModuleChunk(referencedChunk);
1626
- break;
1627
- }
1628
- switch (referencedChunk.status) {
1629
- case INITIALIZED:
1630
- {
1631
- value = referencedChunk.value;
1632
- break;
1633
- }
1634
- case BLOCKED:
1635
- case PENDING:
1636
- {
1637
- return waitForReference(referencedChunk, parentObject, key, response, map, path.slice(i - 1));
1638
- }
1639
- case HALTED:
1640
- {
1641
- // Add a dependency that will never resolve.
1642
- // TODO: Mark downstreams as halted too.
1643
- let handler;
1644
- if (initializingHandler) {
1645
- handler = initializingHandler;
1646
- handler.deps++;
1647
- } else {
1648
- handler = initializingHandler = {
1649
- parent: null,
1650
- chunk: null,
1651
- value: null,
1652
- reason: null,
1653
- deps: 1,
1654
- errored: false
1655
- };
1656
- }
1657
- return null;
1658
- }
1659
- default:
1660
- {
1661
- // This is an error. Instead of erroring directly, we're going to encode this on
1662
- // an initialization handler so that we can catch it at the nearest Element.
1663
- if (initializingHandler) {
1664
- initializingHandler.errored = true;
1665
- initializingHandler.value = null;
1666
- initializingHandler.reason = referencedChunk.reason;
1667
- } else {
1668
- initializingHandler = {
1669
- parent: null,
1670
- chunk: null,
1671
- value: null,
1672
- reason: referencedChunk.reason,
1673
- deps: 0,
1674
- errored: true
1675
- };
1676
- }
1677
- return null;
1678
- }
1679
- }
1680
- }
1681
- value = value[path[i]];
1682
- }
1683
- const chunkValue = map(response, value, parentObject, key);
1684
- return chunkValue;
1685
- case PENDING:
1686
- case BLOCKED:
1687
- return waitForReference(chunk, parentObject, key, response, map, path);
1688
- case HALTED:
1689
- {
1690
- // Add a dependency that will never resolve.
1691
- // TODO: Mark downstreams as halted too.
1692
- let handler;
1693
- if (initializingHandler) {
1694
- handler = initializingHandler;
1695
- handler.deps++;
1696
- } else {
1697
- handler = initializingHandler = {
1698
- parent: null,
1699
- chunk: null,
1700
- value: null,
1701
- reason: null,
1702
- deps: 1,
1703
- errored: false
1704
- };
1705
- }
1706
- return null;
1707
- }
1708
- default:
1709
- // This is an error. Instead of erroring directly, we're going to encode this on
1710
- // an initialization handler so that we can catch it at the nearest Element.
1711
- if (initializingHandler) {
1712
- initializingHandler.errored = true;
1713
- initializingHandler.value = null;
1714
- initializingHandler.reason = chunk.reason;
1715
- } else {
1716
- initializingHandler = {
1717
- parent: null,
1718
- chunk: null,
1719
- value: null,
1720
- reason: chunk.reason,
1721
- deps: 0,
1722
- errored: true
1723
- };
1724
- }
1725
- // Placeholder
1726
- return null;
1727
- }
1728
- }
1729
- function createMap(response, model) {
1730
- return new Map(model);
1731
- }
1732
- function createSet(response, model) {
1733
- return new Set(model);
1734
- }
1735
- function createBlob(response, model) {
1736
- return new Blob(model.slice(1), {
1737
- type: model[0]
1738
- });
1739
- }
1740
- function createFormData(response, model) {
1741
- const formData = new FormData();
1742
- for (let i = 0; i < model.length; i++) {
1743
- formData.append(model[i][0], model[i][1]);
1744
- }
1745
- return formData;
1746
- }
1747
- function extractIterator(response, model) {
1748
- // $FlowFixMe[incompatible-use]: This uses raw Symbols because we're extracting from a native array.
1749
- return model[Symbol.iterator]();
1750
- }
1751
- function createModel(response, model) {
1752
- return model;
1753
- }
1754
- function parseModelString(response, parentObject, key, value) {
1755
- if (value[0] === '$') {
1756
- if (value === '$') {
1757
- // A very common symbol.
1758
- if (initializingHandler !== null && key === '0') {
1759
- // We we already have an initializing handler and we're abound to enter
1760
- // a new element, we need to shadow it because we're now in a new scope.
1761
- // This is effectively the "begin" or "push" phase of Element parsing.
1762
- // We'll pop later when we parse the array itself.
1763
- initializingHandler = {
1764
- parent: initializingHandler,
1765
- chunk: null,
1766
- value: null,
1767
- reason: null,
1768
- deps: 0,
1769
- errored: false
1770
- };
1771
- }
1772
- return REACT_ELEMENT_TYPE;
1773
- }
1774
- switch (value[1]) {
1775
- case '$':
1776
- {
1777
- // This was an escaped string value.
1778
- return value.slice(1);
1779
- }
1780
- case 'L':
1781
- {
1782
- // Lazy node
1783
- const id = parseInt(value.slice(2), 16);
1784
- const chunk = getChunk(response, id);
1785
- // We create a React.lazy wrapper around any lazy values.
1786
- // When passed into React, we'll know how to suspend on this.
1787
- return createLazyChunkWrapper(chunk);
1788
- }
1789
- case '@':
1790
- {
1791
- // Promise
1792
- const id = parseInt(value.slice(2), 16);
1793
- const chunk = getChunk(response, id);
1794
- return chunk;
1795
- }
1796
- case 'S':
1797
- {
1798
- // Symbol
1799
- return Symbol.for(value.slice(2));
1800
- }
1801
- case 'F':
1802
- {
1803
- // Server Reference
1804
- const ref = value.slice(2);
1805
- return getOutlinedModel(response, ref, parentObject, key, loadServerReference);
1806
- }
1807
- case 'T':
1808
- {
1809
- // Temporary Reference
1810
- const reference = '$' + value.slice(2);
1811
- const temporaryReferences = response._tempRefs;
1812
- if (temporaryReferences == null) {
1813
- throw new Error('Missing a temporary reference set but the RSC response returned a temporary reference. ' + 'Pass a temporaryReference option with the set that was used with the reply.');
1814
- }
1815
- return readTemporaryReference(temporaryReferences, reference);
1816
- }
1817
- case 'Q':
1818
- {
1819
- // Map
1820
- const ref = value.slice(2);
1821
- return getOutlinedModel(response, ref, parentObject, key, createMap);
1822
- }
1823
- case 'W':
1824
- {
1825
- // Set
1826
- const ref = value.slice(2);
1827
- return getOutlinedModel(response, ref, parentObject, key, createSet);
1828
- }
1829
- case 'B':
1830
- {
1831
- // Blob
1832
- const ref = value.slice(2);
1833
- return getOutlinedModel(response, ref, parentObject, key, createBlob);
1834
- }
1835
- case 'K':
1836
- {
1837
- // FormData
1838
- const ref = value.slice(2);
1839
- return getOutlinedModel(response, ref, parentObject, key, createFormData);
1840
- }
1841
- case 'Z':
1842
- {
1843
- // Error
1844
- {
1845
- return resolveErrorProd();
1846
- }
1847
- }
1848
- case 'i':
1849
- {
1850
- // Iterator
1851
- const ref = value.slice(2);
1852
- return getOutlinedModel(response, ref, parentObject, key, extractIterator);
1853
- }
1854
- case 'I':
1855
- {
1856
- // $Infinity
1857
- return Infinity;
1858
- }
1859
- case '-':
1860
- {
1861
- // $-0 or $-Infinity
1862
- if (value === '$-0') {
1863
- return -0;
1864
- } else {
1865
- return -Infinity;
1866
- }
1867
- }
1868
- case 'N':
1869
- {
1870
- // $NaN
1871
- return NaN;
1872
- }
1873
- case 'u':
1874
- {
1875
- // matches "$undefined"
1876
- // Special encoding for `undefined` which can't be serialized as JSON otherwise.
1877
- return undefined;
1878
- }
1879
- case 'D':
1880
- {
1881
- // Date
1882
- return new Date(Date.parse(value.slice(2)));
1883
- }
1884
- case 'n':
1885
- {
1886
- // BigInt
1887
- return BigInt(value.slice(2));
1888
- }
1889
- case 'P':
1890
- case 'E':
1891
- case 'Y':
1892
- default:
1893
- {
1894
- // We assume that anything else is a reference ID.
1895
- const ref = value.slice(1);
1896
- return getOutlinedModel(response, ref, parentObject, key, createModel);
1897
- }
1898
- }
1899
- }
1900
- return value;
1901
- }
1902
- function parseModelTuple(response, value) {
1903
- const tuple = value;
1904
- if (tuple[0] === REACT_ELEMENT_TYPE) {
1905
- // TODO: Consider having React just directly accept these arrays as elements.
1906
- // Or even change the ReactElement type to be an array.
1907
- return createElement(response, tuple[1], tuple[2], tuple[3]);
1908
- }
1909
- return value;
1910
- }
1911
- function missingCall() {
1912
- throw new Error('Trying to call a function from "use server" but the callServer option ' + 'was not implemented in your router runtime.');
1913
- }
1914
- function ResponseInstance(bundlerConfig, serverReferenceConfig, moduleLoading, callServer, encodeFormAction, nonce, temporaryReferences, findSourceMapURL,
1915
- // DEV-only
1916
- replayConsole,
1917
- // DEV-only
1918
- environmentName,
1919
- // DEV-only
1920
- debugChannel // DEV-only
1921
- ) {
1922
- const chunks = new Map();
1923
- this._bundlerConfig = bundlerConfig;
1924
- this._serverReferenceConfig = serverReferenceConfig;
1925
- this._moduleLoading = moduleLoading;
1926
- this._callServer = callServer !== undefined ? callServer : missingCall;
1927
- this._encodeFormAction = encodeFormAction;
1928
- this._nonce = nonce;
1929
- this._chunks = chunks;
1930
- this._stringDecoder = createStringDecoder();
1931
- this._fromJSON = null;
1932
- this._closed = false;
1933
- this._closedReason = null;
1934
- this._tempRefs = temporaryReferences;
1935
-
1936
- // Don't inline this call because it causes closure to outline the call above.
1937
- this._fromJSON = createFromJSONCallback(this);
1938
- }
1939
- function createResponse(bundlerConfig, serverReferenceConfig, moduleLoading, callServer, encodeFormAction, nonce, temporaryReferences, findSourceMapURL,
1940
- // DEV-only
1941
- replayConsole,
1942
- // DEV-only
1943
- environmentName,
1944
- // DEV-only
1945
- debugChannel // DEV-only
1946
- ) {
1947
- return getWeakResponse(
1948
- // $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors
1949
- new ResponseInstance(bundlerConfig, serverReferenceConfig, moduleLoading, callServer, encodeFormAction, nonce, temporaryReferences));
1950
- }
1951
- function createStreamState() {
1952
- return {
1953
- _rowState: 0,
1954
- _rowID: 0,
1955
- _rowTag: 0,
1956
- _rowLength: 0,
1957
- _buffer: []
1958
- };
1959
- }
1960
- function resolveModel(response, id, model) {
1961
- const chunks = response._chunks;
1962
- const chunk = chunks.get(id);
1963
- if (!chunk) {
1964
- chunks.set(id, createResolvedModelChunk(response, model));
1965
- } else {
1966
- resolveModelChunk(response, chunk, model);
1967
- }
1968
- }
1969
- function resolveText(response, id, text) {
1970
- const chunks = response._chunks;
1971
- const chunk = chunks.get(id);
1972
- if (chunk && chunk.status !== PENDING) {
1973
- // If we get more data to an already resolved ID, we assume that it's
1974
- // a stream chunk since any other row shouldn't have more than one entry.
1975
- const streamChunk = chunk;
1976
- const controller = streamChunk.reason;
1977
- controller.enqueueValue(text);
1978
- return;
1979
- }
1980
- chunks.set(id, createInitializedTextChunk(response, text));
1981
- }
1982
- function resolveBuffer(response, id, buffer) {
1983
- const chunks = response._chunks;
1984
- const chunk = chunks.get(id);
1985
- if (chunk && chunk.status !== PENDING) {
1986
- // If we get more data to an already resolved ID, we assume that it's
1987
- // a stream chunk since any other row shouldn't have more than one entry.
1988
- const streamChunk = chunk;
1989
- const controller = streamChunk.reason;
1990
- controller.enqueueValue(buffer);
1991
- return;
1992
- }
1993
- chunks.set(id, createInitializedBufferChunk(response, buffer));
1994
- }
1995
- function resolveModule(response, id, model) {
1996
- const chunks = response._chunks;
1997
- const chunk = chunks.get(id);
1998
- const clientReferenceMetadata = parseModel(response, model);
1999
- const clientReference = resolveClientReference(response._bundlerConfig, clientReferenceMetadata);
2000
-
2001
- // TODO: Add an option to encode modules that are lazy loaded.
2002
- // For now we preload all modules as early as possible since it's likely
2003
- // that we'll need them.
2004
- const promise = preloadModule(clientReference);
2005
- if (promise) {
2006
- let blockedChunk;
2007
- if (!chunk) {
2008
- // Technically, we should just treat promise as the chunk in this
2009
- // case. Because it'll just behave as any other promise.
2010
- blockedChunk = createBlockedChunk();
2011
- chunks.set(id, blockedChunk);
2012
- } else {
2013
- // This can't actually happen because we don't have any forward
2014
- // references to modules.
2015
- blockedChunk = chunk;
2016
- blockedChunk.status = BLOCKED;
2017
- }
2018
- promise.then(() => resolveModuleChunk(response, blockedChunk, clientReference), error => triggerErrorOnChunk(response, blockedChunk, error));
2019
- } else {
2020
- if (!chunk) {
2021
- chunks.set(id, createResolvedModuleChunk(response, clientReference));
2022
- } else {
2023
- // This can't actually happen because we don't have any forward
2024
- // references to modules.
2025
- resolveModuleChunk(response, chunk, clientReference);
2026
- }
2027
- }
2028
- }
2029
- function resolveStream(response, id, stream, controller) {
2030
- const chunks = response._chunks;
2031
- const chunk = chunks.get(id);
2032
- if (!chunk) {
2033
- chunks.set(id, createInitializedStreamChunk(response, stream, controller));
2034
- return;
2035
- }
2036
- if (chunk.status !== PENDING) {
2037
- // We already resolved. We didn't expect to see this.
2038
- return;
2039
- }
2040
- const resolveListeners = chunk.value;
2041
- const resolvedChunk = chunk;
2042
- resolvedChunk.status = INITIALIZED;
2043
- resolvedChunk.value = stream;
2044
- resolvedChunk.reason = controller;
2045
- if (resolveListeners !== null) {
2046
- wakeChunk(resolveListeners, chunk.value);
2047
- }
2048
- }
2049
- function startReadableStream(response, id, type) {
2050
- let controller = null;
2051
- const stream = new ReadableStream({
2052
- type: type,
2053
- start(c) {
2054
- controller = c;
2055
- }
2056
- });
2057
- let previousBlockedChunk = null;
2058
- const flightController = {
2059
- enqueueValue(value) {
2060
- if (previousBlockedChunk === null) {
2061
- controller.enqueue(value);
2062
- } else {
2063
- // We're still waiting on a previous chunk so we can't enqueue quite yet.
2064
- previousBlockedChunk.then(function () {
2065
- controller.enqueue(value);
2066
- });
2067
- }
2068
- },
2069
- enqueueModel(json) {
2070
- if (previousBlockedChunk === null) {
2071
- // If we're not blocked on any other chunks, we can try to eagerly initialize
2072
- // this as a fast-path to avoid awaiting them.
2073
- const chunk = createResolvedModelChunk(response, json);
2074
- initializeModelChunk(chunk);
2075
- const initializedChunk = chunk;
2076
- if (initializedChunk.status === INITIALIZED) {
2077
- controller.enqueue(initializedChunk.value);
2078
- } else {
2079
- chunk.then(v => controller.enqueue(v), e => controller.error(e));
2080
- previousBlockedChunk = chunk;
2081
- }
2082
- } else {
2083
- // We're still waiting on a previous chunk so we can't enqueue quite yet.
2084
- const blockedChunk = previousBlockedChunk;
2085
- const chunk = createPendingChunk();
2086
- chunk.then(v => controller.enqueue(v), e => controller.error(e));
2087
- previousBlockedChunk = chunk;
2088
- blockedChunk.then(function () {
2089
- if (previousBlockedChunk === chunk) {
2090
- // We were still the last chunk so we can now clear the queue and return
2091
- // to synchronous emitting.
2092
- previousBlockedChunk = null;
2093
- }
2094
- resolveModelChunk(response, chunk, json);
2095
- });
2096
- }
2097
- },
2098
- close(json) {
2099
- if (previousBlockedChunk === null) {
2100
- controller.close();
2101
- } else {
2102
- const blockedChunk = previousBlockedChunk;
2103
- // We shouldn't get any more enqueues after this so we can set it back to null.
2104
- previousBlockedChunk = null;
2105
- blockedChunk.then(() => controller.close());
2106
- }
2107
- },
2108
- error(error) {
2109
- if (previousBlockedChunk === null) {
2110
- // $FlowFixMe[incompatible-call]
2111
- controller.error(error);
2112
- } else {
2113
- const blockedChunk = previousBlockedChunk;
2114
- // We shouldn't get any more enqueues after this so we can set it back to null.
2115
- previousBlockedChunk = null;
2116
- blockedChunk.then(() => controller.error(error));
2117
- }
2118
- }
2119
- };
2120
- resolveStream(response, id, stream, flightController);
2121
- }
2122
- function asyncIterator() {
2123
- // Self referencing iterator.
2124
- return this;
2125
- }
2126
- function createIterator(next) {
2127
- const iterator = {
2128
- next: next
2129
- // TODO: Add return/throw as options for aborting.
2130
- };
2131
- // TODO: The iterator could inherit the AsyncIterator prototype which is not exposed as
2132
- // a global but exists as a prototype of an AsyncGenerator. However, it's not needed
2133
- // to satisfy the iterable protocol.
2134
- iterator[ASYNC_ITERATOR] = asyncIterator;
2135
- return iterator;
2136
- }
2137
- function startAsyncIterable(response, id, iterator) {
2138
- const buffer = [];
2139
- let closed = false;
2140
- let nextWriteIndex = 0;
2141
- const flightController = {
2142
- enqueueValue(value) {
2143
- if (nextWriteIndex === buffer.length) {
2144
- buffer[nextWriteIndex] = createInitializedIteratorResultChunk(response, value, false);
2145
- } else {
2146
- const chunk = buffer[nextWriteIndex];
2147
- const resolveListeners = chunk.value;
2148
- const rejectListeners = chunk.reason;
2149
- const initializedChunk = chunk;
2150
- initializedChunk.status = INITIALIZED;
2151
- initializedChunk.value = {
2152
- done: false,
2153
- value: value
2154
- };
2155
- if (resolveListeners !== null) {
2156
- wakeChunkIfInitialized(chunk, resolveListeners, rejectListeners);
2157
- }
2158
- }
2159
- nextWriteIndex++;
2160
- },
2161
- enqueueModel(value) {
2162
- if (nextWriteIndex === buffer.length) {
2163
- buffer[nextWriteIndex] = createResolvedIteratorResultChunk(response, value, false);
2164
- } else {
2165
- resolveIteratorResultChunk(response, buffer[nextWriteIndex], value, false);
2166
- }
2167
- nextWriteIndex++;
2168
- },
2169
- close(value) {
2170
- closed = true;
2171
- if (nextWriteIndex === buffer.length) {
2172
- buffer[nextWriteIndex] = createResolvedIteratorResultChunk(response, value, true);
2173
- } else {
2174
- resolveIteratorResultChunk(response, buffer[nextWriteIndex], value, true);
2175
- }
2176
- nextWriteIndex++;
2177
- while (nextWriteIndex < buffer.length) {
2178
- // In generators, any extra reads from the iterator have the value undefined.
2179
- resolveIteratorResultChunk(response, buffer[nextWriteIndex++], '"$undefined"', true);
2180
- }
2181
- },
2182
- error(error) {
2183
- closed = true;
2184
- if (nextWriteIndex === buffer.length) {
2185
- buffer[nextWriteIndex] = createPendingChunk();
2186
- }
2187
- while (nextWriteIndex < buffer.length) {
2188
- triggerErrorOnChunk(response, buffer[nextWriteIndex++], error);
2189
- }
2190
- }
2191
- };
2192
- const iterable = {};
2193
- // $FlowFixMe[cannot-write]
2194
- iterable[ASYNC_ITERATOR] = () => {
2195
- let nextReadIndex = 0;
2196
- return createIterator(arg => {
2197
- if (arg !== undefined) {
2198
- throw new Error('Values cannot be passed to next() of AsyncIterables passed to Client Components.');
2199
- }
2200
- if (nextReadIndex === buffer.length) {
2201
- if (closed) {
2202
- // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
2203
- return new ReactPromise(INITIALIZED, {
2204
- done: true,
2205
- value: undefined
2206
- }, null);
2207
- }
2208
- buffer[nextReadIndex] = createPendingChunk();
2209
- }
2210
- return buffer[nextReadIndex++];
2211
- });
2212
- };
2213
-
2214
- // TODO: If it's a single shot iterator we can optimize memory by cleaning up the buffer after
2215
- // reading through the end, but currently we favor code size over this optimization.
2216
- resolveStream(response, id, iterator ? iterable[ASYNC_ITERATOR]() : iterable, flightController);
2217
- }
2218
- function stopStream(response, id, row) {
2219
- const chunks = response._chunks;
2220
- const chunk = chunks.get(id);
2221
- if (!chunk || chunk.status !== INITIALIZED) {
2222
- // We didn't expect not to have an existing stream;
2223
- return;
2224
- }
2225
- const streamChunk = chunk;
2226
- const controller = streamChunk.reason;
2227
- controller.close(row === '' ? '"$undefined"' : row);
2228
- }
2229
- function resolveErrorProd(response) {
2230
- const error = new Error('An error occurred in the Server Components render. The specific message is omitted in production' + ' builds to avoid leaking sensitive details. A digest property is included on this error instance which' + ' may provide additional details about the nature of the error.');
2231
- error.stack = 'Error: ' + error.message;
2232
- return error;
2233
- }
2234
- function resolvePostponeProd(response, id) {
2235
- const error = new Error('A Server Component was postponed. The reason is omitted in production' + ' builds to avoid leaking sensitive details.');
2236
- const postponeInstance = error;
2237
- postponeInstance.$$typeof = REACT_POSTPONE_TYPE;
2238
- postponeInstance.stack = 'Error: ' + error.message;
2239
- const chunks = response._chunks;
2240
- const chunk = chunks.get(id);
2241
- if (!chunk) {
2242
- chunks.set(id, createErrorChunk(response, postponeInstance));
2243
- } else {
2244
- triggerErrorOnChunk(response, chunk, postponeInstance);
2245
- }
2246
- }
2247
- function resolveErrorModel(response, id, row) {
2248
- const chunks = response._chunks;
2249
- const chunk = chunks.get(id);
2250
- const errorInfo = JSON.parse(row);
2251
- let error;
2252
- {
2253
- error = resolveErrorProd();
2254
- }
2255
- error.digest = errorInfo.digest;
2256
- const errorWithDigest = error;
2257
- if (!chunk) {
2258
- chunks.set(id, createErrorChunk(response, errorWithDigest));
2259
- } else {
2260
- triggerErrorOnChunk(response, chunk, errorWithDigest);
2261
- }
2262
- }
2263
- function resolveHint(response, code, model) {
2264
- const hintModel = parseModel(response, model);
2265
- dispatchHint(code, hintModel);
2266
- }
2267
- function mergeBuffer(buffer, lastChunk) {
2268
- const l = buffer.length;
2269
- // Count the bytes we'll need
2270
- let byteLength = lastChunk.length;
2271
- for (let i = 0; i < l; i++) {
2272
- byteLength += buffer[i].byteLength;
2273
- }
2274
- // Allocate enough contiguous space
2275
- const result = new Uint8Array(byteLength);
2276
- let offset = 0;
2277
- // Copy all the buffers into it.
2278
- for (let i = 0; i < l; i++) {
2279
- const chunk = buffer[i];
2280
- result.set(chunk, offset);
2281
- offset += chunk.byteLength;
2282
- }
2283
- result.set(lastChunk, offset);
2284
- return result;
2285
- }
2286
- function resolveTypedArray(response, id, buffer, lastChunk, constructor, bytesPerElement) {
2287
- // If the view fits into one original buffer, we just reuse that buffer instead of
2288
- // copying it out to a separate copy. This means that it's not always possible to
2289
- // transfer these values to other threads without copying first since they may
2290
- // share array buffer. For this to work, it must also have bytes aligned to a
2291
- // multiple of a size of the type.
2292
- const chunk = buffer.length === 0 && lastChunk.byteOffset % bytesPerElement === 0 ? lastChunk : mergeBuffer(buffer, lastChunk);
2293
- // TODO: The transfer protocol of RSC is little-endian. If the client isn't little-endian
2294
- // we should convert it instead. In practice big endian isn't really Web compatible so it's
2295
- // somewhat safe to assume that browsers aren't going to run it, but maybe there's some SSR
2296
- // server that's affected.
2297
- const view = new constructor(chunk.buffer, chunk.byteOffset, chunk.byteLength / bytesPerElement);
2298
- resolveBuffer(response, id, view);
2299
- }
2300
- function processFullBinaryRow(response, id, tag, buffer, chunk) {
2301
- switch (tag) {
2302
- case 65 /* "A" */:
2303
- // We must always clone to extract it into a separate buffer instead of just a view.
2304
- resolveBuffer(response, id, mergeBuffer(buffer, chunk).buffer);
2305
- return;
2306
- case 79 /* "O" */:
2307
- resolveTypedArray(response, id, buffer, chunk, Int8Array, 1);
2308
- return;
2309
- case 111 /* "o" */:
2310
- resolveBuffer(response, id, buffer.length === 0 ? chunk : mergeBuffer(buffer, chunk));
2311
- return;
2312
- case 85 /* "U" */:
2313
- resolveTypedArray(response, id, buffer, chunk, Uint8ClampedArray, 1);
2314
- return;
2315
- case 83 /* "S" */:
2316
- resolveTypedArray(response, id, buffer, chunk, Int16Array, 2);
2317
- return;
2318
- case 115 /* "s" */:
2319
- resolveTypedArray(response, id, buffer, chunk, Uint16Array, 2);
2320
- return;
2321
- case 76 /* "L" */:
2322
- resolveTypedArray(response, id, buffer, chunk, Int32Array, 4);
2323
- return;
2324
- case 108 /* "l" */:
2325
- resolveTypedArray(response, id, buffer, chunk, Uint32Array, 4);
2326
- return;
2327
- case 71 /* "G" */:
2328
- resolveTypedArray(response, id, buffer, chunk, Float32Array, 4);
2329
- return;
2330
- case 103 /* "g" */:
2331
- resolveTypedArray(response, id, buffer, chunk, Float64Array, 8);
2332
- return;
2333
- case 77 /* "M" */:
2334
- resolveTypedArray(response, id, buffer, chunk, BigInt64Array, 8);
2335
- return;
2336
- case 109 /* "m" */:
2337
- resolveTypedArray(response, id, buffer, chunk, BigUint64Array, 8);
2338
- return;
2339
- case 86 /* "V" */:
2340
- resolveTypedArray(response, id, buffer, chunk, DataView, 1);
2341
- return;
2342
- }
2343
- const stringDecoder = response._stringDecoder;
2344
- let row = '';
2345
- for (let i = 0; i < buffer.length; i++) {
2346
- row += readPartialStringChunk(stringDecoder, buffer[i]);
2347
- }
2348
- row += readFinalStringChunk(stringDecoder, chunk);
2349
- processFullStringRow(response, id, tag, row);
2350
- }
2351
- function processFullStringRow(response, id, tag, row) {
2352
- switch (tag) {
2353
- case 73 /* "I" */:
2354
- {
2355
- resolveModule(response, id, row);
2356
- return;
2357
- }
2358
- case 72 /* "H" */:
2359
- {
2360
- const code = row[0];
2361
- resolveHint(response, code, row.slice(1));
2362
- return;
2363
- }
2364
- case 69 /* "E" */:
2365
- {
2366
- resolveErrorModel(response, id, row);
2367
- return;
2368
- }
2369
- case 84 /* "T" */:
2370
- {
2371
- resolveText(response, id, row);
2372
- return;
2373
- }
2374
- case 78 /* "N" */:
2375
- case 68 /* "D" */:
2376
- case 74 /* "J" */:
2377
- case 87 /* "W" */:
2378
- {
2379
- throw new Error('Failed to read a RSC payload created by a development version of React ' + 'on the server while using a production version on the client. Always use ' + 'matching versions on the server and the client.');
2380
- }
2381
- case 82 /* "R" */:
2382
- {
2383
- startReadableStream(response, id, undefined);
2384
- return;
2385
- }
2386
- // Fallthrough
2387
- case 114 /* "r" */:
2388
- {
2389
- startReadableStream(response, id, 'bytes');
2390
- return;
2391
- }
2392
- // Fallthrough
2393
- case 88 /* "X" */:
2394
- {
2395
- startAsyncIterable(response, id, false);
2396
- return;
2397
- }
2398
- // Fallthrough
2399
- case 120 /* "x" */:
2400
- {
2401
- startAsyncIterable(response, id, true);
2402
- return;
2403
- }
2404
- // Fallthrough
2405
- case 67 /* "C" */:
2406
- {
2407
- stopStream(response, id, row);
2408
- return;
2409
- }
2410
- // Fallthrough
2411
- case 80 /* "P" */:
2412
- {
2413
- {
2414
- {
2415
- resolvePostponeProd(response, id);
2416
- }
2417
- return;
2418
- }
2419
- }
2420
- // Fallthrough
2421
- default:
2422
- /* """ "{" "[" "t" "f" "n" "0" - "9" */{
2423
- // We assume anything else is JSON.
2424
- resolveModel(response, id, row);
2425
- return;
2426
- }
2427
- }
2428
- }
2429
- function processBinaryChunk(weakResponse, streamState, chunk) {
2430
- const response = unwrapWeakResponse(weakResponse);
2431
- let i = 0;
2432
- let rowState = streamState._rowState;
2433
- let rowID = streamState._rowID;
2434
- let rowTag = streamState._rowTag;
2435
- let rowLength = streamState._rowLength;
2436
- const buffer = streamState._buffer;
2437
- const chunkLength = chunk.length;
2438
- while (i < chunkLength) {
2439
- let lastIdx = -1;
2440
- switch (rowState) {
2441
- case ROW_ID:
2442
- {
2443
- const byte = chunk[i++];
2444
- if (byte === 58 /* ":" */) {
2445
- // Finished the rowID, next we'll parse the tag.
2446
- rowState = ROW_TAG;
2447
- } else {
2448
- rowID = rowID << 4 | (byte > 96 ? byte - 87 : byte - 48);
2449
- }
2450
- continue;
2451
- }
2452
- case ROW_TAG:
2453
- {
2454
- const resolvedRowTag = chunk[i];
2455
- if (resolvedRowTag === 84 /* "T" */ || resolvedRowTag === 65 /* "A" */ || resolvedRowTag === 79 /* "O" */ || resolvedRowTag === 111 /* "o" */ || resolvedRowTag === 85 /* "U" */ || resolvedRowTag === 83 /* "S" */ || resolvedRowTag === 115 /* "s" */ || resolvedRowTag === 76 /* "L" */ || resolvedRowTag === 108 /* "l" */ || resolvedRowTag === 71 /* "G" */ || resolvedRowTag === 103 /* "g" */ || resolvedRowTag === 77 /* "M" */ || resolvedRowTag === 109 /* "m" */ || resolvedRowTag === 86 /* "V" */) {
2456
- rowTag = resolvedRowTag;
2457
- rowState = ROW_LENGTH;
2458
- i++;
2459
- } else if (resolvedRowTag > 64 && resolvedRowTag < 91 /* "A"-"Z" */ || resolvedRowTag === 35 /* "#" */ || resolvedRowTag === 114 /* "r" */ || resolvedRowTag === 120 /* "x" */) {
2460
- rowTag = resolvedRowTag;
2461
- rowState = ROW_CHUNK_BY_NEWLINE;
2462
- i++;
2463
- } else {
2464
- rowTag = 0;
2465
- rowState = ROW_CHUNK_BY_NEWLINE;
2466
- // This was an unknown tag so it was probably part of the data.
2467
- }
2468
- continue;
2469
- }
2470
- case ROW_LENGTH:
2471
- {
2472
- const byte = chunk[i++];
2473
- if (byte === 44 /* "," */) {
2474
- // Finished the rowLength, next we'll buffer up to that length.
2475
- rowState = ROW_CHUNK_BY_LENGTH;
2476
- } else {
2477
- rowLength = rowLength << 4 | (byte > 96 ? byte - 87 : byte - 48);
2478
- }
2479
- continue;
2480
- }
2481
- case ROW_CHUNK_BY_NEWLINE:
2482
- {
2483
- // We're looking for a newline
2484
- lastIdx = chunk.indexOf(10 /* "\n" */, i);
2485
- break;
2486
- }
2487
- case ROW_CHUNK_BY_LENGTH:
2488
- {
2489
- // We're looking for the remaining byte length
2490
- lastIdx = i + rowLength;
2491
- if (lastIdx > chunk.length) {
2492
- lastIdx = -1;
2493
- }
2494
- break;
2495
- }
2496
- }
2497
- const offset = chunk.byteOffset + i;
2498
- if (lastIdx > -1) {
2499
- // We found the last chunk of the row
2500
- const length = lastIdx - i;
2501
- const lastChunk = new Uint8Array(chunk.buffer, offset, length);
2502
- processFullBinaryRow(response, rowID, rowTag, buffer, lastChunk);
2503
- // Reset state machine for a new row
2504
- i = lastIdx;
2505
- if (rowState === ROW_CHUNK_BY_NEWLINE) {
2506
- // If we're trailing by a newline we need to skip it.
2507
- i++;
2508
- }
2509
- rowState = ROW_ID;
2510
- rowTag = 0;
2511
- rowID = 0;
2512
- rowLength = 0;
2513
- buffer.length = 0;
2514
- } else {
2515
- // The rest of this row is in a future chunk. We stash the rest of the
2516
- // current chunk until we can process the full row.
2517
- const length = chunk.byteLength - i;
2518
- const remainingSlice = new Uint8Array(chunk.buffer, offset, length);
2519
- buffer.push(remainingSlice);
2520
- // Update how many bytes we're still waiting for. If we're looking for
2521
- // a newline, this doesn't hurt since we'll just ignore it.
2522
- rowLength -= remainingSlice.byteLength;
2523
- break;
2524
- }
2525
- }
2526
- streamState._rowState = rowState;
2527
- streamState._rowID = rowID;
2528
- streamState._rowTag = rowTag;
2529
- streamState._rowLength = rowLength;
2530
- }
2531
- function parseModel(response, json) {
2532
- return JSON.parse(json, response._fromJSON);
2533
- }
2534
- function createFromJSONCallback(response) {
2535
- // $FlowFixMe[missing-this-annot]
2536
- return function (key, value) {
2537
- if (typeof value === 'string') {
2538
- // We can't use .bind here because we need the "this" value.
2539
- return parseModelString(response, this, key, value);
2540
- }
2541
- if (typeof value === 'object' && value !== null) {
2542
- return parseModelTuple(response, value);
2543
- }
2544
- return value;
2545
- };
2546
- }
2547
- function close(weakResponse) {
2548
- // In case there are any remaining unresolved chunks, they won't
2549
- // be resolved now. So we need to issue an error to those.
2550
- // Ideally we should be able to early bail out if we kept a
2551
- // ref count of pending chunks.
2552
- reportGlobalError(weakResponse, new Error('Connection closed.'));
2553
- }
2554
-
2555
- function createResponseFromOptions(options) {
2556
- return createResponse(options && options.moduleBaseURL ? options.moduleBaseURL : '', null, null, options && options.callServer ? options.callServer : undefined, undefined,
2557
- // encodeFormAction
2558
- undefined,
2559
- // nonce
2560
- options && options.temporaryReferences ? options.temporaryReferences : undefined);
2561
- }
2562
- function startReadingFromStream(response, stream, isSecondaryStream) {
2563
- const streamState = createStreamState();
2564
- const reader = stream.getReader();
2565
- function progress(_ref2) {
2566
- let done = _ref2.done,
2567
- value = _ref2.value;
2568
- if (done) {
2569
- // If we're the secondary stream, then we don't close the response until the debug channel closes.
2570
- if (!isSecondaryStream) {
2571
- close(response);
2572
- }
2573
- return;
2574
- }
2575
- const buffer = value;
2576
- processBinaryChunk(response, streamState, buffer);
2577
- return reader.read().then(progress).catch(error);
2578
- }
2579
- function error(e) {
2580
- reportGlobalError(response, e);
2581
- }
2582
- reader.read().then(progress).catch(error);
2583
- }
2584
- function createFromReadableStream(stream, options) {
2585
- const response = createResponseFromOptions(options);
2586
- {
2587
- startReadingFromStream(response, stream, false);
2588
- }
2589
- return getRoot(response);
2590
- }
2591
- function createFromFetch(promiseForResponse, options) {
2592
- const response = createResponseFromOptions(options);
2593
- promiseForResponse.then(function (r) {
2594
- {
2595
- startReadingFromStream(response, r.body, false);
2596
- }
2597
- }, function (e) {
2598
- reportGlobalError(response, e);
2599
- });
2600
- return getRoot(response);
2601
- }
2602
- function encodeReply(value, options) /* We don't use URLSearchParams yet but maybe */{
2603
- return new Promise((resolve, reject) => {
2604
- const abort = processReply(value, '', options && options.temporaryReferences ? options.temporaryReferences : undefined, resolve, reject);
2605
- if (options && options.signal) {
2606
- const signal = options.signal;
2607
- if (signal.aborted) {
2608
- abort(signal.reason);
2609
- } else {
2610
- const listener = () => {
2611
- abort(signal.reason);
2612
- signal.removeEventListener('abort', listener);
2613
- };
2614
- signal.addEventListener('abort', listener);
2615
- }
2616
- }
2617
- });
2618
- }
2619
-
2620
- export { createFromFetch, createFromReadableStream, createServerReference, createTemporaryReferenceSet, encodeReply, registerServerReference };
1
+ /**
2
+ * @license React
3
+ * react-server-dom-esm-client.browser.production.js
4
+ *
5
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */
10
+
11
+ import * as ReactDOM from 'react-dom';
12
+
13
+ function createStringDecoder() {
14
+ return new TextDecoder();
15
+ }
16
+ const decoderOptions = {
17
+ stream: true
18
+ };
19
+ function readPartialStringChunk(decoder, buffer) {
20
+ return decoder.decode(buffer, decoderOptions);
21
+ }
22
+ function readFinalStringChunk(decoder, buffer) {
23
+ return decoder.decode(buffer);
24
+ }
25
+
26
+ // Module root path
27
+
28
+ function resolveClientReference(bundlerConfig, metadata) {
29
+ const baseURL = bundlerConfig;
30
+ return {
31
+ specifier: baseURL + metadata[0],
32
+ name: metadata[1]
33
+ };
34
+ }
35
+ function resolveServerReference(config, id) {
36
+ const baseURL = config;
37
+ const idx = id.lastIndexOf('#');
38
+ const exportName = id.slice(idx + 1);
39
+ const fullURL = id.slice(0, idx);
40
+ if (!fullURL.startsWith(baseURL)) {
41
+ throw new Error('Attempted to load a Server Reference outside the hosted root.');
42
+ }
43
+ return {
44
+ specifier: fullURL,
45
+ name: exportName
46
+ };
47
+ }
48
+ const asyncModuleCache = new Map();
49
+ function preloadModule(metadata) {
50
+ const existingPromise = asyncModuleCache.get(metadata.specifier);
51
+ if (existingPromise) {
52
+ if (existingPromise.status === 'fulfilled') {
53
+ return null;
54
+ }
55
+ return existingPromise;
56
+ } else {
57
+ // $FlowFixMe[unsupported-syntax]
58
+ const modulePromise = import(metadata.specifier);
59
+ modulePromise.then(value => {
60
+ const fulfilledThenable = modulePromise;
61
+ fulfilledThenable.status = 'fulfilled';
62
+ fulfilledThenable.value = value;
63
+ }, reason => {
64
+ const rejectedThenable = modulePromise;
65
+ rejectedThenable.status = 'rejected';
66
+ rejectedThenable.reason = reason;
67
+ });
68
+ asyncModuleCache.set(metadata.specifier, modulePromise);
69
+ return modulePromise;
70
+ }
71
+ }
72
+ function requireModule(metadata) {
73
+ let moduleExports;
74
+ // We assume that preloadModule has been called before, which
75
+ // should have added something to the module cache.
76
+ const promise = asyncModuleCache.get(metadata.specifier);
77
+ if (promise.status === 'fulfilled') {
78
+ moduleExports = promise.value;
79
+ } else {
80
+ throw promise.reason;
81
+ }
82
+ return moduleExports[metadata.name];
83
+ }
84
+
85
+ const ReactDOMSharedInternals = ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
86
+
87
+ // This client file is in the shared folder because it applies to both SSR and browser contexts.
88
+ // It is the configuration of the FlightClient behavior which can run in either environment.
89
+
90
+ function dispatchHint(code, model) {
91
+ const dispatcher = ReactDOMSharedInternals.d; /* ReactDOMCurrentDispatcher */
92
+ switch (code) {
93
+ case 'D':
94
+ {
95
+ const refined = refineModel(code, model);
96
+ const href = refined;
97
+ dispatcher.D( /* prefetchDNS */href);
98
+ return;
99
+ }
100
+ case 'C':
101
+ {
102
+ const refined = refineModel(code, model);
103
+ if (typeof refined === 'string') {
104
+ const href = refined;
105
+ dispatcher.C( /* preconnect */href);
106
+ } else {
107
+ const href = refined[0];
108
+ const crossOrigin = refined[1];
109
+ dispatcher.C( /* preconnect */href, crossOrigin);
110
+ }
111
+ return;
112
+ }
113
+ case 'L':
114
+ {
115
+ const refined = refineModel(code, model);
116
+ const href = refined[0];
117
+ const as = refined[1];
118
+ if (refined.length === 3) {
119
+ const options = refined[2];
120
+ dispatcher.L( /* preload */href, as, options);
121
+ } else {
122
+ dispatcher.L( /* preload */href, as);
123
+ }
124
+ return;
125
+ }
126
+ case 'm':
127
+ {
128
+ const refined = refineModel(code, model);
129
+ if (typeof refined === 'string') {
130
+ const href = refined;
131
+ dispatcher.m( /* preloadModule */href);
132
+ } else {
133
+ const href = refined[0];
134
+ const options = refined[1];
135
+ dispatcher.m( /* preloadModule */href, options);
136
+ }
137
+ return;
138
+ }
139
+ case 'X':
140
+ {
141
+ const refined = refineModel(code, model);
142
+ if (typeof refined === 'string') {
143
+ const href = refined;
144
+ dispatcher.X( /* preinitScript */href);
145
+ } else {
146
+ const href = refined[0];
147
+ const options = refined[1];
148
+ dispatcher.X( /* preinitScript */href, options);
149
+ }
150
+ return;
151
+ }
152
+ case 'S':
153
+ {
154
+ const refined = refineModel(code, model);
155
+ if (typeof refined === 'string') {
156
+ const href = refined;
157
+ dispatcher.S( /* preinitStyle */href);
158
+ } else {
159
+ const href = refined[0];
160
+ const precedence = refined[1] === 0 ? undefined : refined[1];
161
+ const options = refined.length === 3 ? refined[2] : undefined;
162
+ dispatcher.S( /* preinitStyle */href, precedence, options);
163
+ }
164
+ return;
165
+ }
166
+ case 'M':
167
+ {
168
+ const refined = refineModel(code, model);
169
+ if (typeof refined === 'string') {
170
+ const href = refined;
171
+ dispatcher.M( /* preinitModuleScript */href);
172
+ } else {
173
+ const href = refined[0];
174
+ const options = refined[1];
175
+ dispatcher.M( /* preinitModuleScript */href, options);
176
+ }
177
+ return;
178
+ }
179
+ }
180
+ }
181
+
182
+ // Flow is having trouble refining the HintModels so we help it a bit.
183
+ // This should be compiled out in the production build.
184
+ function refineModel(code, model) {
185
+ return model;
186
+ }
187
+
188
+ const REACT_ELEMENT_TYPE = Symbol.for('react.transitional.element') ;
189
+ const REACT_LAZY_TYPE = Symbol.for('react.lazy');
190
+ const REACT_POSTPONE_TYPE = Symbol.for('react.postpone');
191
+ const MAYBE_ITERATOR_SYMBOL = Symbol.iterator;
192
+ const FAUX_ITERATOR_SYMBOL = '@@iterator';
193
+ function getIteratorFn(maybeIterable) {
194
+ if (maybeIterable === null || typeof maybeIterable !== 'object') {
195
+ return null;
196
+ }
197
+ const maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];
198
+ if (typeof maybeIterator === 'function') {
199
+ return maybeIterator;
200
+ }
201
+ return null;
202
+ }
203
+ const ASYNC_ITERATOR = Symbol.asyncIterator;
204
+
205
+ const isArrayImpl = Array.isArray;
206
+ function isArray(a) {
207
+ return isArrayImpl(a);
208
+ }
209
+
210
+ const getPrototypeOf = Object.getPrototypeOf;
211
+
212
+ function createTemporaryReferenceSet() {
213
+ return new Map();
214
+ }
215
+ function writeTemporaryReference(set, reference, object) {
216
+ set.set(reference, object);
217
+ }
218
+ function readTemporaryReference(set, reference) {
219
+ return set.get(reference);
220
+ }
221
+
222
+ const ObjectPrototype = Object.prototype;
223
+ const knownServerReferences = new WeakMap();
224
+
225
+ // Serializable values
226
+
227
+ // Thenable<ReactServerValue>
228
+
229
+ function serializeByValueID(id) {
230
+ return '$' + id.toString(16);
231
+ }
232
+ function serializePromiseID(id) {
233
+ return '$@' + id.toString(16);
234
+ }
235
+ function serializeServerReferenceID(id) {
236
+ return '$F' + id.toString(16);
237
+ }
238
+ function serializeTemporaryReferenceMarker() {
239
+ return '$T';
240
+ }
241
+ function serializeFormDataReference(id) {
242
+ // Why K? F is "Function". D is "Date". What else?
243
+ return '$K' + id.toString(16);
244
+ }
245
+ function serializeNumber(number) {
246
+ if (Number.isFinite(number)) {
247
+ if (number === 0 && 1 / number === -Infinity) {
248
+ return '$-0';
249
+ } else {
250
+ return number;
251
+ }
252
+ } else {
253
+ if (number === Infinity) {
254
+ return '$Infinity';
255
+ } else if (number === -Infinity) {
256
+ return '$-Infinity';
257
+ } else {
258
+ return '$NaN';
259
+ }
260
+ }
261
+ }
262
+ function serializeUndefined() {
263
+ return '$undefined';
264
+ }
265
+ function serializeDateFromDateJSON(dateJSON) {
266
+ // JSON.stringify automatically calls Date.prototype.toJSON which calls toISOString.
267
+ // We need only tack on a $D prefix.
268
+ return '$D' + dateJSON;
269
+ }
270
+ function serializeBigInt(n) {
271
+ return '$n' + n.toString(10);
272
+ }
273
+ function serializeMapID(id) {
274
+ return '$Q' + id.toString(16);
275
+ }
276
+ function serializeSetID(id) {
277
+ return '$W' + id.toString(16);
278
+ }
279
+ function serializeBlobID(id) {
280
+ return '$B' + id.toString(16);
281
+ }
282
+ function serializeIteratorID(id) {
283
+ return '$i' + id.toString(16);
284
+ }
285
+ function escapeStringValue(value) {
286
+ if (value[0] === '$') {
287
+ // We need to escape $ prefixed strings since we use those to encode
288
+ // references to IDs and as special symbol values.
289
+ return '$' + value;
290
+ } else {
291
+ return value;
292
+ }
293
+ }
294
+ function processReply(root, formFieldPrefix, temporaryReferences, resolve, reject) {
295
+ let nextPartId = 1;
296
+ let pendingParts = 0;
297
+ let formData = null;
298
+ const writtenObjects = new WeakMap();
299
+ let modelRoot = root;
300
+ function serializeTypedArray(tag, typedArray) {
301
+ const blob = new Blob([
302
+ // We should be able to pass the buffer straight through but Node < 18 treat
303
+ // multi-byte array blobs differently so we first convert it to single-byte.
304
+ new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength)]);
305
+ const blobId = nextPartId++;
306
+ if (formData === null) {
307
+ formData = new FormData();
308
+ }
309
+ formData.append(formFieldPrefix + blobId, blob);
310
+ return '$' + tag + blobId.toString(16);
311
+ }
312
+ function serializeBinaryReader(reader) {
313
+ if (formData === null) {
314
+ // Upgrade to use FormData to allow us to stream this value.
315
+ formData = new FormData();
316
+ }
317
+ const data = formData;
318
+ pendingParts++;
319
+ const streamId = nextPartId++;
320
+ const buffer = [];
321
+ function progress(entry) {
322
+ if (entry.done) {
323
+ const blobId = nextPartId++;
324
+ data.append(formFieldPrefix + blobId, new Blob(buffer));
325
+ data.append(formFieldPrefix + streamId, '"$o' + blobId.toString(16) + '"');
326
+ data.append(formFieldPrefix + streamId, 'C'); // Close signal
327
+ pendingParts--;
328
+ if (pendingParts === 0) {
329
+ resolve(data);
330
+ }
331
+ } else {
332
+ buffer.push(entry.value);
333
+ reader.read(new Uint8Array(1024)).then(progress, reject);
334
+ }
335
+ }
336
+ reader.read(new Uint8Array(1024)).then(progress, reject);
337
+ return '$r' + streamId.toString(16);
338
+ }
339
+ function serializeReader(reader) {
340
+ if (formData === null) {
341
+ // Upgrade to use FormData to allow us to stream this value.
342
+ formData = new FormData();
343
+ }
344
+ const data = formData;
345
+ pendingParts++;
346
+ const streamId = nextPartId++;
347
+ function progress(entry) {
348
+ if (entry.done) {
349
+ data.append(formFieldPrefix + streamId, 'C'); // Close signal
350
+ pendingParts--;
351
+ if (pendingParts === 0) {
352
+ resolve(data);
353
+ }
354
+ } else {
355
+ try {
356
+ // $FlowFixMe[incompatible-type]: While plain JSON can return undefined we never do here.
357
+ const partJSON = JSON.stringify(entry.value, resolveToJSON);
358
+ data.append(formFieldPrefix + streamId, partJSON);
359
+ reader.read().then(progress, reject);
360
+ } catch (x) {
361
+ reject(x);
362
+ }
363
+ }
364
+ }
365
+ reader.read().then(progress, reject);
366
+ return '$R' + streamId.toString(16);
367
+ }
368
+ function serializeReadableStream(stream) {
369
+ // Detect if this is a BYOB stream. BYOB streams should be able to be read as bytes on the
370
+ // receiving side. For binary streams, we serialize them as plain Blobs.
371
+ let binaryReader;
372
+ try {
373
+ // $FlowFixMe[extra-arg]: This argument is accepted.
374
+ binaryReader = stream.getReader({
375
+ mode: 'byob'
376
+ });
377
+ } catch (x) {
378
+ return serializeReader(stream.getReader());
379
+ }
380
+ return serializeBinaryReader(binaryReader);
381
+ }
382
+ function serializeAsyncIterable(iterable, iterator) {
383
+ if (formData === null) {
384
+ // Upgrade to use FormData to allow us to stream this value.
385
+ formData = new FormData();
386
+ }
387
+ const data = formData;
388
+ pendingParts++;
389
+ const streamId = nextPartId++;
390
+
391
+ // Generators/Iterators are Iterables but they're also their own iterator
392
+ // functions. If that's the case, we treat them as single-shot. Otherwise,
393
+ // we assume that this iterable might be a multi-shot and allow it to be
394
+ // iterated more than once on the receiving server.
395
+ const isIterator = iterable === iterator;
396
+
397
+ // There's a race condition between when the stream is aborted and when the promise
398
+ // resolves so we track whether we already aborted it to avoid writing twice.
399
+ function progress(entry) {
400
+ if (entry.done) {
401
+ if (entry.value === undefined) {
402
+ data.append(formFieldPrefix + streamId, 'C'); // Close signal
403
+ } else {
404
+ // Unlike streams, the last value may not be undefined. If it's not
405
+ // we outline it and encode a reference to it in the closing instruction.
406
+ try {
407
+ // $FlowFixMe[incompatible-type]: While plain JSON can return undefined we never do here.
408
+ const partJSON = JSON.stringify(entry.value, resolveToJSON);
409
+ data.append(formFieldPrefix + streamId, 'C' + partJSON); // Close signal
410
+ } catch (x) {
411
+ reject(x);
412
+ return;
413
+ }
414
+ }
415
+ pendingParts--;
416
+ if (pendingParts === 0) {
417
+ resolve(data);
418
+ }
419
+ } else {
420
+ try {
421
+ // $FlowFixMe[incompatible-type]: While plain JSON can return undefined we never do here.
422
+ const partJSON = JSON.stringify(entry.value, resolveToJSON);
423
+ data.append(formFieldPrefix + streamId, partJSON);
424
+ iterator.next().then(progress, reject);
425
+ } catch (x) {
426
+ reject(x);
427
+ return;
428
+ }
429
+ }
430
+ }
431
+ iterator.next().then(progress, reject);
432
+ return '$' + (isIterator ? 'x' : 'X') + streamId.toString(16);
433
+ }
434
+ function resolveToJSON(key, value) {
435
+ const parent = this;
436
+ if (value === null) {
437
+ return null;
438
+ }
439
+ if (typeof value === 'object') {
440
+ switch (value.$$typeof) {
441
+ case REACT_ELEMENT_TYPE:
442
+ {
443
+ if (temporaryReferences !== undefined && key.indexOf(':') === -1) {
444
+ // TODO: If the property name contains a colon, we don't dedupe. Escape instead.
445
+ const parentReference = writtenObjects.get(parent);
446
+ if (parentReference !== undefined) {
447
+ // If the parent has a reference, we can refer to this object indirectly
448
+ // through the property name inside that parent.
449
+ const reference = parentReference + ':' + key;
450
+ // Store this object so that the server can refer to it later in responses.
451
+ writeTemporaryReference(temporaryReferences, reference, value);
452
+ return serializeTemporaryReferenceMarker();
453
+ }
454
+ }
455
+ throw new Error('React Element cannot be passed to Server Functions from the Client without a ' + 'temporary reference set. Pass a TemporaryReferenceSet to the options.' + (''));
456
+ }
457
+ case REACT_LAZY_TYPE:
458
+ {
459
+ // Resolve lazy as if it wasn't here. In the future this will be encoded as a Promise.
460
+ const lazy = value;
461
+ const payload = lazy._payload;
462
+ const init = lazy._init;
463
+ if (formData === null) {
464
+ // Upgrade to use FormData to allow us to stream this value.
465
+ formData = new FormData();
466
+ }
467
+ pendingParts++;
468
+ try {
469
+ const resolvedModel = init(payload);
470
+ // We always outline this as a separate part even though we could inline it
471
+ // because it ensures a more deterministic encoding.
472
+ const lazyId = nextPartId++;
473
+ const partJSON = serializeModel(resolvedModel, lazyId);
474
+ // $FlowFixMe[incompatible-type] We know it's not null because we assigned it above.
475
+ const data = formData;
476
+ data.append(formFieldPrefix + lazyId, partJSON);
477
+ return serializeByValueID(lazyId);
478
+ } catch (x) {
479
+ if (typeof x === 'object' && x !== null && typeof x.then === 'function') {
480
+ // Suspended
481
+ pendingParts++;
482
+ const lazyId = nextPartId++;
483
+ const thenable = x;
484
+ const retry = function () {
485
+ // While the first promise resolved, its value isn't necessarily what we'll
486
+ // resolve into because we might suspend again.
487
+ try {
488
+ const partJSON = serializeModel(value, lazyId);
489
+ // $FlowFixMe[incompatible-type] We know it's not null because we assigned it above.
490
+ const data = formData;
491
+ data.append(formFieldPrefix + lazyId, partJSON);
492
+ pendingParts--;
493
+ if (pendingParts === 0) {
494
+ resolve(data);
495
+ }
496
+ } catch (reason) {
497
+ reject(reason);
498
+ }
499
+ };
500
+ thenable.then(retry, retry);
501
+ return serializeByValueID(lazyId);
502
+ } else {
503
+ // In the future we could consider serializing this as an error
504
+ // that throws on the server instead.
505
+ reject(x);
506
+ return null;
507
+ }
508
+ } finally {
509
+ pendingParts--;
510
+ }
511
+ }
512
+ }
513
+
514
+ // $FlowFixMe[method-unbinding]
515
+ if (typeof value.then === 'function') {
516
+ // We assume that any object with a .then property is a "Thenable" type,
517
+ // or a Promise type. Either of which can be represented by a Promise.
518
+ if (formData === null) {
519
+ // Upgrade to use FormData to allow us to stream this value.
520
+ formData = new FormData();
521
+ }
522
+ pendingParts++;
523
+ const promiseId = nextPartId++;
524
+ const thenable = value;
525
+ thenable.then(partValue => {
526
+ try {
527
+ const partJSON = serializeModel(partValue, promiseId);
528
+ // $FlowFixMe[incompatible-type] We know it's not null because we assigned it above.
529
+ const data = formData;
530
+ data.append(formFieldPrefix + promiseId, partJSON);
531
+ pendingParts--;
532
+ if (pendingParts === 0) {
533
+ resolve(data);
534
+ }
535
+ } catch (reason) {
536
+ reject(reason);
537
+ }
538
+ },
539
+ // In the future we could consider serializing this as an error
540
+ // that throws on the server instead.
541
+ reject);
542
+ return serializePromiseID(promiseId);
543
+ }
544
+ const existingReference = writtenObjects.get(value);
545
+ if (existingReference !== undefined) {
546
+ if (modelRoot === value) {
547
+ // This is the ID we're currently emitting so we need to write it
548
+ // once but if we discover it again, we refer to it by id.
549
+ modelRoot = null;
550
+ } else {
551
+ // We've already emitted this as an outlined object, so we can
552
+ // just refer to that by its existing ID.
553
+ return existingReference;
554
+ }
555
+ } else if (key.indexOf(':') === -1) {
556
+ // TODO: If the property name contains a colon, we don't dedupe. Escape instead.
557
+ const parentReference = writtenObjects.get(parent);
558
+ if (parentReference !== undefined) {
559
+ // If the parent has a reference, we can refer to this object indirectly
560
+ // through the property name inside that parent.
561
+ const reference = parentReference + ':' + key;
562
+ writtenObjects.set(value, reference);
563
+ if (temporaryReferences !== undefined) {
564
+ // Store this object so that the server can refer to it later in responses.
565
+ writeTemporaryReference(temporaryReferences, reference, value);
566
+ }
567
+ }
568
+ }
569
+ if (isArray(value)) {
570
+ // $FlowFixMe[incompatible-return]
571
+ return value;
572
+ }
573
+ // TODO: Should we the Object.prototype.toString.call() to test for cross-realm objects?
574
+ if (value instanceof FormData) {
575
+ if (formData === null) {
576
+ // Upgrade to use FormData to allow us to use rich objects as its values.
577
+ formData = new FormData();
578
+ }
579
+ const data = formData;
580
+ const refId = nextPartId++;
581
+ // Copy all the form fields with a prefix for this reference.
582
+ // These must come first in the form order because we assume that all the
583
+ // fields are available before this is referenced.
584
+ const prefix = formFieldPrefix + refId + '_';
585
+ // $FlowFixMe[prop-missing]: FormData has forEach.
586
+ value.forEach((originalValue, originalKey) => {
587
+ // $FlowFixMe[incompatible-call]
588
+ data.append(prefix + originalKey, originalValue);
589
+ });
590
+ return serializeFormDataReference(refId);
591
+ }
592
+ if (value instanceof Map) {
593
+ const mapId = nextPartId++;
594
+ const partJSON = serializeModel(Array.from(value), mapId);
595
+ if (formData === null) {
596
+ formData = new FormData();
597
+ }
598
+ formData.append(formFieldPrefix + mapId, partJSON);
599
+ return serializeMapID(mapId);
600
+ }
601
+ if (value instanceof Set) {
602
+ const setId = nextPartId++;
603
+ const partJSON = serializeModel(Array.from(value), setId);
604
+ if (formData === null) {
605
+ formData = new FormData();
606
+ }
607
+ formData.append(formFieldPrefix + setId, partJSON);
608
+ return serializeSetID(setId);
609
+ }
610
+ if (value instanceof ArrayBuffer) {
611
+ const blob = new Blob([value]);
612
+ const blobId = nextPartId++;
613
+ if (formData === null) {
614
+ formData = new FormData();
615
+ }
616
+ formData.append(formFieldPrefix + blobId, blob);
617
+ return '$' + 'A' + blobId.toString(16);
618
+ }
619
+ if (value instanceof Int8Array) {
620
+ // char
621
+ return serializeTypedArray('O', value);
622
+ }
623
+ if (value instanceof Uint8Array) {
624
+ // unsigned char
625
+ return serializeTypedArray('o', value);
626
+ }
627
+ if (value instanceof Uint8ClampedArray) {
628
+ // unsigned clamped char
629
+ return serializeTypedArray('U', value);
630
+ }
631
+ if (value instanceof Int16Array) {
632
+ // sort
633
+ return serializeTypedArray('S', value);
634
+ }
635
+ if (value instanceof Uint16Array) {
636
+ // unsigned short
637
+ return serializeTypedArray('s', value);
638
+ }
639
+ if (value instanceof Int32Array) {
640
+ // long
641
+ return serializeTypedArray('L', value);
642
+ }
643
+ if (value instanceof Uint32Array) {
644
+ // unsigned long
645
+ return serializeTypedArray('l', value);
646
+ }
647
+ if (value instanceof Float32Array) {
648
+ // float
649
+ return serializeTypedArray('G', value);
650
+ }
651
+ if (value instanceof Float64Array) {
652
+ // double
653
+ return serializeTypedArray('g', value);
654
+ }
655
+ if (value instanceof BigInt64Array) {
656
+ // number
657
+ return serializeTypedArray('M', value);
658
+ }
659
+ if (value instanceof BigUint64Array) {
660
+ // unsigned number
661
+ // We use "m" instead of "n" since JSON can start with "null"
662
+ return serializeTypedArray('m', value);
663
+ }
664
+ if (value instanceof DataView) {
665
+ return serializeTypedArray('V', value);
666
+ }
667
+ // TODO: Blob is not available in old Node/browsers. Remove the typeof check later.
668
+ if (typeof Blob === 'function' && value instanceof Blob) {
669
+ if (formData === null) {
670
+ formData = new FormData();
671
+ }
672
+ const blobId = nextPartId++;
673
+ formData.append(formFieldPrefix + blobId, value);
674
+ return serializeBlobID(blobId);
675
+ }
676
+ const iteratorFn = getIteratorFn(value);
677
+ if (iteratorFn) {
678
+ const iterator = iteratorFn.call(value);
679
+ if (iterator === value) {
680
+ // Iterator, not Iterable
681
+ const iteratorId = nextPartId++;
682
+ const partJSON = serializeModel(Array.from(iterator), iteratorId);
683
+ if (formData === null) {
684
+ formData = new FormData();
685
+ }
686
+ formData.append(formFieldPrefix + iteratorId, partJSON);
687
+ return serializeIteratorID(iteratorId);
688
+ }
689
+ return Array.from(iterator);
690
+ }
691
+
692
+ // TODO: ReadableStream is not available in old Node. Remove the typeof check later.
693
+ if (typeof ReadableStream === 'function' && value instanceof ReadableStream) {
694
+ return serializeReadableStream(value);
695
+ }
696
+ const getAsyncIterator = value[ASYNC_ITERATOR];
697
+ if (typeof getAsyncIterator === 'function') {
698
+ // We treat AsyncIterables as a Fragment and as such we might need to key them.
699
+ return serializeAsyncIterable(value, getAsyncIterator.call(value));
700
+ }
701
+
702
+ // Verify that this is a simple plain object.
703
+ const proto = getPrototypeOf(value);
704
+ if (proto !== ObjectPrototype && (proto === null || getPrototypeOf(proto) !== null)) {
705
+ if (temporaryReferences === undefined) {
706
+ throw new Error('Only plain objects, and a few built-ins, can be passed to Server Functions. ' + 'Classes or null prototypes are not supported.' + (''));
707
+ }
708
+ // We will have written this object to the temporary reference set above
709
+ // so we can replace it with a marker to refer to this slot later.
710
+ return serializeTemporaryReferenceMarker();
711
+ }
712
+
713
+ // $FlowFixMe[incompatible-return]
714
+ return value;
715
+ }
716
+ if (typeof value === 'string') {
717
+ // TODO: Maybe too clever. If we support URL there's no similar trick.
718
+ if (value[value.length - 1] === 'Z') {
719
+ // Possibly a Date, whose toJSON automatically calls toISOString
720
+ // $FlowFixMe[incompatible-use]
721
+ const originalValue = parent[key];
722
+ if (originalValue instanceof Date) {
723
+ return serializeDateFromDateJSON(value);
724
+ }
725
+ }
726
+ return escapeStringValue(value);
727
+ }
728
+ if (typeof value === 'boolean') {
729
+ return value;
730
+ }
731
+ if (typeof value === 'number') {
732
+ return serializeNumber(value);
733
+ }
734
+ if (typeof value === 'undefined') {
735
+ return serializeUndefined();
736
+ }
737
+ if (typeof value === 'function') {
738
+ const referenceClosure = knownServerReferences.get(value);
739
+ if (referenceClosure !== undefined) {
740
+ const id = referenceClosure.id,
741
+ bound = referenceClosure.bound;
742
+ const referenceClosureJSON = JSON.stringify({
743
+ id,
744
+ bound
745
+ }, resolveToJSON);
746
+ if (formData === null) {
747
+ // Upgrade to use FormData to allow us to stream this value.
748
+ formData = new FormData();
749
+ }
750
+ // The reference to this function came from the same client so we can pass it back.
751
+ const refId = nextPartId++;
752
+ formData.set(formFieldPrefix + refId, referenceClosureJSON);
753
+ return serializeServerReferenceID(refId);
754
+ }
755
+ if (temporaryReferences !== undefined && key.indexOf(':') === -1) {
756
+ // TODO: If the property name contains a colon, we don't dedupe. Escape instead.
757
+ const parentReference = writtenObjects.get(parent);
758
+ if (parentReference !== undefined) {
759
+ // If the parent has a reference, we can refer to this object indirectly
760
+ // through the property name inside that parent.
761
+ const reference = parentReference + ':' + key;
762
+ // Store this object so that the server can refer to it later in responses.
763
+ writeTemporaryReference(temporaryReferences, reference, value);
764
+ return serializeTemporaryReferenceMarker();
765
+ }
766
+ }
767
+ throw new Error('Client Functions cannot be passed directly to Server Functions. ' + 'Only Functions passed from the Server can be passed back again.');
768
+ }
769
+ if (typeof value === 'symbol') {
770
+ if (temporaryReferences !== undefined && key.indexOf(':') === -1) {
771
+ // TODO: If the property name contains a colon, we don't dedupe. Escape instead.
772
+ const parentReference = writtenObjects.get(parent);
773
+ if (parentReference !== undefined) {
774
+ // If the parent has a reference, we can refer to this object indirectly
775
+ // through the property name inside that parent.
776
+ const reference = parentReference + ':' + key;
777
+ // Store this object so that the server can refer to it later in responses.
778
+ writeTemporaryReference(temporaryReferences, reference, value);
779
+ return serializeTemporaryReferenceMarker();
780
+ }
781
+ }
782
+ throw new Error('Symbols cannot be passed to a Server Function without a ' + 'temporary reference set. Pass a TemporaryReferenceSet to the options.' + (''));
783
+ }
784
+ if (typeof value === 'bigint') {
785
+ return serializeBigInt(value);
786
+ }
787
+ throw new Error("Type " + typeof value + " is not supported as an argument to a Server Function.");
788
+ }
789
+ function serializeModel(model, id) {
790
+ if (typeof model === 'object' && model !== null) {
791
+ const reference = serializeByValueID(id);
792
+ writtenObjects.set(model, reference);
793
+ if (temporaryReferences !== undefined) {
794
+ // Store this object so that the server can refer to it later in responses.
795
+ writeTemporaryReference(temporaryReferences, reference, model);
796
+ }
797
+ }
798
+ modelRoot = model;
799
+ // $FlowFixMe[incompatible-return] it's not going to be undefined because we'll encode it.
800
+ return JSON.stringify(model, resolveToJSON);
801
+ }
802
+ function abort(reason) {
803
+ if (pendingParts > 0) {
804
+ pendingParts = 0; // Don't resolve again later.
805
+ // Resolve with what we have so far, which may have holes at this point.
806
+ // They'll error when the stream completes on the server.
807
+ if (formData === null) {
808
+ resolve(json);
809
+ } else {
810
+ resolve(formData);
811
+ }
812
+ }
813
+ }
814
+ const json = serializeModel(root, 0);
815
+ if (formData === null) {
816
+ // If it's a simple data structure, we just use plain JSON.
817
+ resolve(json);
818
+ } else {
819
+ // Otherwise, we use FormData to let us stream in the result.
820
+ formData.set(formFieldPrefix + '0', json);
821
+ if (pendingParts === 0) {
822
+ // $FlowFixMe[incompatible-call] this has already been refined.
823
+ resolve(formData);
824
+ }
825
+ }
826
+ return abort;
827
+ }
828
+ function registerBoundServerReference(reference, id, bound, encodeFormAction) {
829
+ if (knownServerReferences.has(reference)) {
830
+ return;
831
+ }
832
+ knownServerReferences.set(reference, {
833
+ id,
834
+ originalBind: reference.bind,
835
+ bound
836
+ });
837
+ }
838
+ function registerServerReference(reference, id, encodeFormAction) {
839
+ registerBoundServerReference(reference, id, null);
840
+ return reference;
841
+ }
842
+ function createBoundServerReference(metaData, callServer, encodeFormAction, findSourceMapURL // DEV-only
843
+ ) {
844
+ const id = metaData.id;
845
+ const bound = metaData.bound;
846
+ let action = function () {
847
+ // $FlowFixMe[method-unbinding]
848
+ const args = Array.prototype.slice.call(arguments);
849
+ const p = bound;
850
+ if (!p) {
851
+ return callServer(id, args);
852
+ }
853
+ if (p.status === 'fulfilled') {
854
+ const boundArgs = p.value;
855
+ return callServer(id, boundArgs.concat(args));
856
+ }
857
+ // Since this is a fake Promise whose .then doesn't chain, we have to wrap it.
858
+ // TODO: Remove the wrapper once that's fixed.
859
+ return Promise.resolve(p).then(function (boundArgs) {
860
+ return callServer(id, boundArgs.concat(args));
861
+ });
862
+ };
863
+ registerBoundServerReference(action, id, bound);
864
+ return action;
865
+ }
866
+ function createServerReference(id, callServer, encodeFormAction, findSourceMapURL,
867
+ // DEV-only
868
+ functionName) {
869
+ let action = function () {
870
+ // $FlowFixMe[method-unbinding]
871
+ const args = Array.prototype.slice.call(arguments);
872
+ return callServer(id, args);
873
+ };
874
+ registerBoundServerReference(action, id, null);
875
+ return action;
876
+ }
877
+
878
+ const ROW_ID = 0;
879
+ const ROW_TAG = 1;
880
+ const ROW_LENGTH = 2;
881
+ const ROW_CHUNK_BY_NEWLINE = 3;
882
+ const ROW_CHUNK_BY_LENGTH = 4;
883
+ const PENDING = 'pending';
884
+ const BLOCKED = 'blocked';
885
+ const RESOLVED_MODEL = 'resolved_model';
886
+ const RESOLVED_MODULE = 'resolved_module';
887
+ const INITIALIZED = 'fulfilled';
888
+ const ERRORED = 'rejected';
889
+ const HALTED = 'halted'; // DEV-only. Means it never resolves even if connection closes.
890
+
891
+ // $FlowFixMe[missing-this-annot]
892
+ function ReactPromise(status, value, reason) {
893
+ this.status = status;
894
+ this.value = value;
895
+ this.reason = reason;
896
+ }
897
+ // We subclass Promise.prototype so that we get other methods like .catch
898
+ ReactPromise.prototype = Object.create(Promise.prototype);
899
+ // TODO: This doesn't return a new Promise chain unlike the real .then
900
+ ReactPromise.prototype.then = function (resolve, reject) {
901
+ const chunk = this;
902
+ // If we have resolved content, we try to initialize it first which
903
+ // might put us back into one of the other states.
904
+ switch (chunk.status) {
905
+ case RESOLVED_MODEL:
906
+ initializeModelChunk(chunk);
907
+ break;
908
+ case RESOLVED_MODULE:
909
+ initializeModuleChunk(chunk);
910
+ break;
911
+ }
912
+ // The status might have changed after initialization.
913
+ switch (chunk.status) {
914
+ case INITIALIZED:
915
+ if (typeof resolve === 'function') {
916
+ resolve(chunk.value);
917
+ }
918
+ break;
919
+ case PENDING:
920
+ case BLOCKED:
921
+ if (typeof resolve === 'function') {
922
+ if (chunk.value === null) {
923
+ chunk.value = [];
924
+ }
925
+ chunk.value.push(resolve);
926
+ }
927
+ if (typeof reject === 'function') {
928
+ if (chunk.reason === null) {
929
+ chunk.reason = [];
930
+ }
931
+ chunk.reason.push(reject);
932
+ }
933
+ break;
934
+ case HALTED:
935
+ {
936
+ break;
937
+ }
938
+ default:
939
+ if (typeof reject === 'function') {
940
+ reject(chunk.reason);
941
+ }
942
+ break;
943
+ }
944
+ };
945
+ function unwrapWeakResponse(weakResponse) {
946
+ {
947
+ return weakResponse; // In prod we just use the real Response directly.
948
+ }
949
+ }
950
+ function getWeakResponse(response) {
951
+ {
952
+ return response; // In prod we just use the real Response directly.
953
+ }
954
+ }
955
+ function readChunk(chunk) {
956
+ // If we have resolved content, we try to initialize it first which
957
+ // might put us back into one of the other states.
958
+ switch (chunk.status) {
959
+ case RESOLVED_MODEL:
960
+ initializeModelChunk(chunk);
961
+ break;
962
+ case RESOLVED_MODULE:
963
+ initializeModuleChunk(chunk);
964
+ break;
965
+ }
966
+ // The status might have changed after initialization.
967
+ switch (chunk.status) {
968
+ case INITIALIZED:
969
+ return chunk.value;
970
+ case PENDING:
971
+ case BLOCKED:
972
+ case HALTED:
973
+ // eslint-disable-next-line no-throw-literal
974
+ throw chunk;
975
+ default:
976
+ throw chunk.reason;
977
+ }
978
+ }
979
+ function getRoot(weakResponse) {
980
+ const response = unwrapWeakResponse(weakResponse);
981
+ const chunk = getChunk(response, 0);
982
+ return chunk;
983
+ }
984
+ function createPendingChunk(response) {
985
+ // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
986
+ return new ReactPromise(PENDING, null, null);
987
+ }
988
+ function createBlockedChunk(response) {
989
+ // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
990
+ return new ReactPromise(BLOCKED, null, null);
991
+ }
992
+ function createErrorChunk(response, error) {
993
+ // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
994
+ return new ReactPromise(ERRORED, null, error);
995
+ }
996
+ function wakeChunk(listeners, value) {
997
+ for (let i = 0; i < listeners.length; i++) {
998
+ const listener = listeners[i];
999
+ if (typeof listener === 'function') {
1000
+ listener(value);
1001
+ } else {
1002
+ fulfillReference(listener, value);
1003
+ }
1004
+ }
1005
+ }
1006
+ function rejectChunk(listeners, error) {
1007
+ for (let i = 0; i < listeners.length; i++) {
1008
+ const listener = listeners[i];
1009
+ if (typeof listener === 'function') {
1010
+ listener(error);
1011
+ } else {
1012
+ rejectReference(listener, error);
1013
+ }
1014
+ }
1015
+ }
1016
+ function resolveBlockedCycle(resolvedChunk, reference) {
1017
+ const referencedChunk = reference.handler.chunk;
1018
+ if (referencedChunk === null) {
1019
+ return null;
1020
+ }
1021
+ if (referencedChunk === resolvedChunk) {
1022
+ // We found the cycle. We can resolve the blocked cycle now.
1023
+ return reference.handler;
1024
+ }
1025
+ const resolveListeners = referencedChunk.value;
1026
+ if (resolveListeners !== null) {
1027
+ for (let i = 0; i < resolveListeners.length; i++) {
1028
+ const listener = resolveListeners[i];
1029
+ if (typeof listener !== 'function') {
1030
+ const foundHandler = resolveBlockedCycle(resolvedChunk, listener);
1031
+ if (foundHandler !== null) {
1032
+ return foundHandler;
1033
+ }
1034
+ }
1035
+ }
1036
+ }
1037
+ return null;
1038
+ }
1039
+ function wakeChunkIfInitialized(chunk, resolveListeners, rejectListeners) {
1040
+ switch (chunk.status) {
1041
+ case INITIALIZED:
1042
+ wakeChunk(resolveListeners, chunk.value);
1043
+ break;
1044
+ case BLOCKED:
1045
+ // It is possible that we're blocked on our own chunk if it's a cycle.
1046
+ // Before adding back the listeners to the chunk, let's check if it would
1047
+ // result in a cycle.
1048
+ for (let i = 0; i < resolveListeners.length; i++) {
1049
+ const listener = resolveListeners[i];
1050
+ if (typeof listener !== 'function') {
1051
+ const reference = listener;
1052
+ const cyclicHandler = resolveBlockedCycle(chunk, reference);
1053
+ if (cyclicHandler !== null) {
1054
+ // This reference points back to this chunk. We can resolve the cycle by
1055
+ // using the value from that handler.
1056
+ fulfillReference(reference, cyclicHandler.value);
1057
+ resolveListeners.splice(i, 1);
1058
+ i--;
1059
+ if (rejectListeners !== null) {
1060
+ const rejectionIdx = rejectListeners.indexOf(reference);
1061
+ if (rejectionIdx !== -1) {
1062
+ rejectListeners.splice(rejectionIdx, 1);
1063
+ }
1064
+ }
1065
+ }
1066
+ }
1067
+ }
1068
+ // Fallthrough
1069
+ case PENDING:
1070
+ if (chunk.value) {
1071
+ for (let i = 0; i < resolveListeners.length; i++) {
1072
+ chunk.value.push(resolveListeners[i]);
1073
+ }
1074
+ } else {
1075
+ chunk.value = resolveListeners;
1076
+ }
1077
+ if (chunk.reason) {
1078
+ if (rejectListeners) {
1079
+ for (let i = 0; i < rejectListeners.length; i++) {
1080
+ chunk.reason.push(rejectListeners[i]);
1081
+ }
1082
+ }
1083
+ } else {
1084
+ chunk.reason = rejectListeners;
1085
+ }
1086
+ break;
1087
+ case ERRORED:
1088
+ if (rejectListeners) {
1089
+ rejectChunk(rejectListeners, chunk.reason);
1090
+ }
1091
+ break;
1092
+ }
1093
+ }
1094
+ function triggerErrorOnChunk(response, chunk, error) {
1095
+ if (chunk.status !== PENDING && chunk.status !== BLOCKED) {
1096
+ // If we get more data to an already resolved ID, we assume that it's
1097
+ // a stream chunk since any other row shouldn't have more than one entry.
1098
+ const streamChunk = chunk;
1099
+ const controller = streamChunk.reason;
1100
+ // $FlowFixMe[incompatible-call]: The error method should accept mixed.
1101
+ controller.error(error);
1102
+ return;
1103
+ }
1104
+ const listeners = chunk.reason;
1105
+ const erroredChunk = chunk;
1106
+ erroredChunk.status = ERRORED;
1107
+ erroredChunk.reason = error;
1108
+ if (listeners !== null) {
1109
+ rejectChunk(listeners, error);
1110
+ }
1111
+ }
1112
+ function createResolvedModelChunk(response, value) {
1113
+ // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
1114
+ return new ReactPromise(RESOLVED_MODEL, value, response);
1115
+ }
1116
+ function createResolvedModuleChunk(response, value) {
1117
+ // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
1118
+ return new ReactPromise(RESOLVED_MODULE, value, null);
1119
+ }
1120
+ function createInitializedTextChunk(response, value) {
1121
+ // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
1122
+ return new ReactPromise(INITIALIZED, value, null);
1123
+ }
1124
+ function createInitializedBufferChunk(response, value) {
1125
+ // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
1126
+ return new ReactPromise(INITIALIZED, value, null);
1127
+ }
1128
+ function createInitializedIteratorResultChunk(response, value, done) {
1129
+ // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
1130
+ return new ReactPromise(INITIALIZED, {
1131
+ done: done,
1132
+ value: value
1133
+ }, null);
1134
+ }
1135
+ function createInitializedStreamChunk(response, value, controller) {
1136
+ // We use the reason field to stash the controller since we already have that
1137
+ // field. It's a bit of a hack but efficient.
1138
+ // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
1139
+ return new ReactPromise(INITIALIZED, value, controller);
1140
+ }
1141
+ function createResolvedIteratorResultChunk(response, value, done) {
1142
+ // To reuse code as much code as possible we add the wrapper element as part of the JSON.
1143
+ const iteratorResultJSON = (done ? '{"done":true,"value":' : '{"done":false,"value":') + value + '}';
1144
+ // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
1145
+ return new ReactPromise(RESOLVED_MODEL, iteratorResultJSON, response);
1146
+ }
1147
+ function resolveIteratorResultChunk(response, chunk, value, done) {
1148
+ // To reuse code as much code as possible we add the wrapper element as part of the JSON.
1149
+ const iteratorResultJSON = (done ? '{"done":true,"value":' : '{"done":false,"value":') + value + '}';
1150
+ resolveModelChunk(response, chunk, iteratorResultJSON);
1151
+ }
1152
+ function resolveModelChunk(response, chunk, value) {
1153
+ if (chunk.status !== PENDING) {
1154
+ // If we get more data to an already resolved ID, we assume that it's
1155
+ // a stream chunk since any other row shouldn't have more than one entry.
1156
+ const streamChunk = chunk;
1157
+ const controller = streamChunk.reason;
1158
+ controller.enqueueModel(value);
1159
+ return;
1160
+ }
1161
+ const resolveListeners = chunk.value;
1162
+ const rejectListeners = chunk.reason;
1163
+ const resolvedChunk = chunk;
1164
+ resolvedChunk.status = RESOLVED_MODEL;
1165
+ resolvedChunk.value = value;
1166
+ resolvedChunk.reason = response;
1167
+ if (resolveListeners !== null) {
1168
+ // This is unfortunate that we're reading this eagerly if
1169
+ // we already have listeners attached since they might no
1170
+ // longer be rendered or might not be the highest pri.
1171
+ initializeModelChunk(resolvedChunk);
1172
+ // The status might have changed after initialization.
1173
+ wakeChunkIfInitialized(chunk, resolveListeners, rejectListeners);
1174
+ }
1175
+ }
1176
+ function resolveModuleChunk(response, chunk, value) {
1177
+ if (chunk.status !== PENDING && chunk.status !== BLOCKED) {
1178
+ // We already resolved. We didn't expect to see this.
1179
+ return;
1180
+ }
1181
+ const resolveListeners = chunk.value;
1182
+ const rejectListeners = chunk.reason;
1183
+ const resolvedChunk = chunk;
1184
+ resolvedChunk.status = RESOLVED_MODULE;
1185
+ resolvedChunk.value = value;
1186
+ if (resolveListeners !== null) {
1187
+ initializeModuleChunk(resolvedChunk);
1188
+ wakeChunkIfInitialized(chunk, resolveListeners, rejectListeners);
1189
+ }
1190
+ }
1191
+ let initializingHandler = null;
1192
+ function initializeModelChunk(chunk) {
1193
+ const prevHandler = initializingHandler;
1194
+ initializingHandler = null;
1195
+ const resolvedModel = chunk.value;
1196
+ const response = chunk.reason;
1197
+
1198
+ // We go to the BLOCKED state until we've fully resolved this.
1199
+ // We do this before parsing in case we try to initialize the same chunk
1200
+ // while parsing the model. Such as in a cyclic reference.
1201
+ const cyclicChunk = chunk;
1202
+ cyclicChunk.status = BLOCKED;
1203
+ cyclicChunk.value = null;
1204
+ cyclicChunk.reason = null;
1205
+ try {
1206
+ const value = parseModel(response, resolvedModel);
1207
+ // Invoke any listeners added while resolving this model. I.e. cyclic
1208
+ // references. This may or may not fully resolve the model depending on
1209
+ // if they were blocked.
1210
+ const resolveListeners = cyclicChunk.value;
1211
+ if (resolveListeners !== null) {
1212
+ cyclicChunk.value = null;
1213
+ cyclicChunk.reason = null;
1214
+ wakeChunk(resolveListeners, value);
1215
+ }
1216
+ if (initializingHandler !== null) {
1217
+ if (initializingHandler.errored) {
1218
+ throw initializingHandler.reason;
1219
+ }
1220
+ if (initializingHandler.deps > 0) {
1221
+ // We discovered new dependencies on modules that are not yet resolved.
1222
+ // We have to keep the BLOCKED state until they're resolved.
1223
+ initializingHandler.value = value;
1224
+ initializingHandler.chunk = cyclicChunk;
1225
+ return;
1226
+ }
1227
+ }
1228
+ const initializedChunk = chunk;
1229
+ initializedChunk.status = INITIALIZED;
1230
+ initializedChunk.value = value;
1231
+ } catch (error) {
1232
+ const erroredChunk = chunk;
1233
+ erroredChunk.status = ERRORED;
1234
+ erroredChunk.reason = error;
1235
+ } finally {
1236
+ initializingHandler = prevHandler;
1237
+ }
1238
+ }
1239
+ function initializeModuleChunk(chunk) {
1240
+ try {
1241
+ const value = requireModule(chunk.value);
1242
+ const initializedChunk = chunk;
1243
+ initializedChunk.status = INITIALIZED;
1244
+ initializedChunk.value = value;
1245
+ } catch (error) {
1246
+ const erroredChunk = chunk;
1247
+ erroredChunk.status = ERRORED;
1248
+ erroredChunk.reason = error;
1249
+ }
1250
+ }
1251
+
1252
+ // Report that any missing chunks in the model is now going to throw this
1253
+ // error upon read. Also notify any pending promises.
1254
+ function reportGlobalError(weakResponse, error) {
1255
+ const response = unwrapWeakResponse(weakResponse);
1256
+ response._closed = true;
1257
+ response._closedReason = error;
1258
+ response._chunks.forEach(chunk => {
1259
+ // If this chunk was already resolved or errored, it won't
1260
+ // trigger an error but if it wasn't then we need to
1261
+ // because we won't be getting any new data to resolve it.
1262
+ if (chunk.status === PENDING) {
1263
+ triggerErrorOnChunk(response, chunk, error);
1264
+ }
1265
+ });
1266
+ }
1267
+ function createElement(response, type, key, props, owner,
1268
+ // DEV-only
1269
+ stack,
1270
+ // DEV-only
1271
+ validated // DEV-only
1272
+ ) {
1273
+ let element;
1274
+ {
1275
+ element = {
1276
+ // This tag allows us to uniquely identify this as a React Element
1277
+ $$typeof: REACT_ELEMENT_TYPE,
1278
+ type,
1279
+ key,
1280
+ ref: null,
1281
+ props
1282
+ };
1283
+ }
1284
+ if (initializingHandler !== null) {
1285
+ const handler = initializingHandler;
1286
+ // We pop the stack to the previous outer handler before leaving the Element.
1287
+ // This is effectively the complete phase.
1288
+ initializingHandler = handler.parent;
1289
+ if (handler.errored) {
1290
+ // Something errored inside this Element's props. We can turn this Element
1291
+ // into a Lazy so that we can still render up until that Lazy is rendered.
1292
+ const erroredChunk = createErrorChunk(response, handler.reason);
1293
+ return createLazyChunkWrapper(erroredChunk);
1294
+ }
1295
+ if (handler.deps > 0) {
1296
+ // We have blocked references inside this Element but we can turn this into
1297
+ // a Lazy node referencing this Element to let everything around it proceed.
1298
+ const blockedChunk = createBlockedChunk();
1299
+ handler.value = element;
1300
+ handler.chunk = blockedChunk;
1301
+ return createLazyChunkWrapper(blockedChunk);
1302
+ }
1303
+ }
1304
+ return element;
1305
+ }
1306
+ function createLazyChunkWrapper(chunk) {
1307
+ const lazyType = {
1308
+ $$typeof: REACT_LAZY_TYPE,
1309
+ _payload: chunk,
1310
+ _init: readChunk
1311
+ };
1312
+ return lazyType;
1313
+ }
1314
+ function getChunk(response, id) {
1315
+ const chunks = response._chunks;
1316
+ let chunk = chunks.get(id);
1317
+ if (!chunk) {
1318
+ if (response._closed) {
1319
+ // We have already errored the response and we're not going to get
1320
+ // anything more streaming in so this will immediately error.
1321
+ chunk = createErrorChunk(response, response._closedReason);
1322
+ } else {
1323
+ chunk = createPendingChunk();
1324
+ }
1325
+ chunks.set(id, chunk);
1326
+ }
1327
+ return chunk;
1328
+ }
1329
+ function fulfillReference(reference, value) {
1330
+ const response = reference.response,
1331
+ handler = reference.handler,
1332
+ parentObject = reference.parentObject,
1333
+ key = reference.key,
1334
+ map = reference.map,
1335
+ path = reference.path;
1336
+ for (let i = 1; i < path.length; i++) {
1337
+ while (value.$$typeof === REACT_LAZY_TYPE) {
1338
+ // We never expect to see a Lazy node on this path because we encode those as
1339
+ // separate models. This must mean that we have inserted an extra lazy node
1340
+ // e.g. to replace a blocked element. We must instead look for it inside.
1341
+ const referencedChunk = value._payload;
1342
+ if (referencedChunk === handler.chunk) {
1343
+ // This is a reference to the thing we're currently blocking. We can peak
1344
+ // inside of it to get the value.
1345
+ value = handler.value;
1346
+ continue;
1347
+ } else {
1348
+ switch (referencedChunk.status) {
1349
+ case RESOLVED_MODEL:
1350
+ initializeModelChunk(referencedChunk);
1351
+ break;
1352
+ case RESOLVED_MODULE:
1353
+ initializeModuleChunk(referencedChunk);
1354
+ break;
1355
+ }
1356
+ switch (referencedChunk.status) {
1357
+ case INITIALIZED:
1358
+ {
1359
+ value = referencedChunk.value;
1360
+ continue;
1361
+ }
1362
+ case BLOCKED:
1363
+ {
1364
+ // It is possible that we're blocked on our own chunk if it's a cycle.
1365
+ // Before adding the listener to the inner chunk, let's check if it would
1366
+ // result in a cycle.
1367
+ const cyclicHandler = resolveBlockedCycle(referencedChunk, reference);
1368
+ if (cyclicHandler !== null) {
1369
+ // This reference points back to this chunk. We can resolve the cycle by
1370
+ // using the value from that handler.
1371
+ value = cyclicHandler.value;
1372
+ continue;
1373
+ }
1374
+ // Fallthrough
1375
+ }
1376
+ case PENDING:
1377
+ {
1378
+ // If we're not yet initialized we need to skip what we've already drilled
1379
+ // through and then wait for the next value to become available.
1380
+ path.splice(0, i - 1);
1381
+ // Add "listener" to our new chunk dependency.
1382
+ if (referencedChunk.value === null) {
1383
+ referencedChunk.value = [reference];
1384
+ } else {
1385
+ referencedChunk.value.push(reference);
1386
+ }
1387
+ if (referencedChunk.reason === null) {
1388
+ referencedChunk.reason = [reference];
1389
+ } else {
1390
+ referencedChunk.reason.push(reference);
1391
+ }
1392
+ return;
1393
+ }
1394
+ case HALTED:
1395
+ {
1396
+ // Do nothing. We couldn't fulfill.
1397
+ // TODO: Mark downstreams as halted too.
1398
+ return;
1399
+ }
1400
+ default:
1401
+ {
1402
+ rejectReference(reference, referencedChunk.reason);
1403
+ return;
1404
+ }
1405
+ }
1406
+ }
1407
+ }
1408
+ value = value[path[i]];
1409
+ }
1410
+ const mappedValue = map(response, value, parentObject, key);
1411
+ parentObject[key] = mappedValue;
1412
+
1413
+ // If this is the root object for a model reference, where `handler.value`
1414
+ // is a stale `null`, the resolved value can be used directly.
1415
+ if (key === '' && handler.value === null) {
1416
+ handler.value = mappedValue;
1417
+ }
1418
+
1419
+ // If the parent object is an unparsed React element tuple, we also need to
1420
+ // update the props and owner of the parsed element object (i.e.
1421
+ // handler.value).
1422
+ if (parentObject[0] === REACT_ELEMENT_TYPE && typeof handler.value === 'object' && handler.value !== null && handler.value.$$typeof === REACT_ELEMENT_TYPE) {
1423
+ const element = handler.value;
1424
+ switch (key) {
1425
+ case '3':
1426
+ element.props = mappedValue;
1427
+ break;
1428
+ }
1429
+ }
1430
+ handler.deps--;
1431
+ if (handler.deps === 0) {
1432
+ const chunk = handler.chunk;
1433
+ if (chunk === null || chunk.status !== BLOCKED) {
1434
+ return;
1435
+ }
1436
+ const resolveListeners = chunk.value;
1437
+ const initializedChunk = chunk;
1438
+ initializedChunk.status = INITIALIZED;
1439
+ initializedChunk.value = handler.value;
1440
+ initializedChunk.reason = handler.reason; // Used by streaming chunks
1441
+ if (resolveListeners !== null) {
1442
+ wakeChunk(resolveListeners, handler.value);
1443
+ }
1444
+ }
1445
+ }
1446
+ function rejectReference(reference, error) {
1447
+ const handler = reference.handler,
1448
+ response = reference.response;
1449
+ if (handler.errored) {
1450
+ // We've already errored. We could instead build up an AggregateError
1451
+ // but if there are multiple errors we just take the first one like
1452
+ // Promise.all.
1453
+ return;
1454
+ }
1455
+ handler.errored = true;
1456
+ handler.value = null;
1457
+ handler.reason = error;
1458
+ const chunk = handler.chunk;
1459
+ if (chunk === null || chunk.status !== BLOCKED) {
1460
+ return;
1461
+ }
1462
+ triggerErrorOnChunk(response, chunk, error);
1463
+ }
1464
+ function waitForReference(referencedChunk, parentObject, key, response, map, path) {
1465
+ let handler;
1466
+ if (initializingHandler) {
1467
+ handler = initializingHandler;
1468
+ handler.deps++;
1469
+ } else {
1470
+ handler = initializingHandler = {
1471
+ parent: null,
1472
+ chunk: null,
1473
+ value: null,
1474
+ reason: null,
1475
+ deps: 1,
1476
+ errored: false
1477
+ };
1478
+ }
1479
+ const reference = {
1480
+ response,
1481
+ handler,
1482
+ parentObject,
1483
+ key,
1484
+ map,
1485
+ path
1486
+ };
1487
+
1488
+ // Add "listener".
1489
+ if (referencedChunk.value === null) {
1490
+ referencedChunk.value = [reference];
1491
+ } else {
1492
+ referencedChunk.value.push(reference);
1493
+ }
1494
+ if (referencedChunk.reason === null) {
1495
+ referencedChunk.reason = [reference];
1496
+ } else {
1497
+ referencedChunk.reason.push(reference);
1498
+ }
1499
+
1500
+ // Return a place holder value for now.
1501
+ return null;
1502
+ }
1503
+ function loadServerReference(response, metaData, parentObject, key) {
1504
+ if (!response._serverReferenceConfig) {
1505
+ // In the normal case, we can't load this Server Reference in the current environment and
1506
+ // we just return a proxy to it.
1507
+ return createBoundServerReference(metaData, response._callServer);
1508
+ }
1509
+ // If we have a module mapping we can load the real version of this Server Reference.
1510
+ const serverReference = resolveServerReference(response._serverReferenceConfig, metaData.id);
1511
+ let promise = preloadModule(serverReference);
1512
+ if (!promise) {
1513
+ if (!metaData.bound) {
1514
+ const resolvedValue = requireModule(serverReference);
1515
+ registerBoundServerReference(resolvedValue, metaData.id, metaData.bound);
1516
+ return resolvedValue;
1517
+ } else {
1518
+ promise = Promise.resolve(metaData.bound);
1519
+ }
1520
+ } else if (metaData.bound) {
1521
+ promise = Promise.all([promise, metaData.bound]);
1522
+ }
1523
+ let handler;
1524
+ if (initializingHandler) {
1525
+ handler = initializingHandler;
1526
+ handler.deps++;
1527
+ } else {
1528
+ handler = initializingHandler = {
1529
+ parent: null,
1530
+ chunk: null,
1531
+ value: null,
1532
+ reason: null,
1533
+ deps: 1,
1534
+ errored: false
1535
+ };
1536
+ }
1537
+ function fulfill() {
1538
+ let resolvedValue = requireModule(serverReference);
1539
+ if (metaData.bound) {
1540
+ // This promise is coming from us and should have initilialized by now.
1541
+ const boundArgs = metaData.bound.value.slice(0);
1542
+ boundArgs.unshift(null); // this
1543
+ resolvedValue = resolvedValue.bind.apply(resolvedValue, boundArgs);
1544
+ }
1545
+ registerBoundServerReference(resolvedValue, metaData.id, metaData.bound);
1546
+ parentObject[key] = resolvedValue;
1547
+
1548
+ // If this is the root object for a model reference, where `handler.value`
1549
+ // is a stale `null`, the resolved value can be used directly.
1550
+ if (key === '' && handler.value === null) {
1551
+ handler.value = resolvedValue;
1552
+ }
1553
+
1554
+ // If the parent object is an unparsed React element tuple, we also need to
1555
+ // update the props and owner of the parsed element object (i.e.
1556
+ // handler.value).
1557
+ if (parentObject[0] === REACT_ELEMENT_TYPE && typeof handler.value === 'object' && handler.value !== null && handler.value.$$typeof === REACT_ELEMENT_TYPE) {
1558
+ const element = handler.value;
1559
+ switch (key) {
1560
+ case '3':
1561
+ element.props = resolvedValue;
1562
+ break;
1563
+ }
1564
+ }
1565
+ handler.deps--;
1566
+ if (handler.deps === 0) {
1567
+ const chunk = handler.chunk;
1568
+ if (chunk === null || chunk.status !== BLOCKED) {
1569
+ return;
1570
+ }
1571
+ const resolveListeners = chunk.value;
1572
+ const initializedChunk = chunk;
1573
+ initializedChunk.status = INITIALIZED;
1574
+ initializedChunk.value = handler.value;
1575
+ if (resolveListeners !== null) {
1576
+ wakeChunk(resolveListeners, handler.value);
1577
+ }
1578
+ }
1579
+ }
1580
+ function reject(error) {
1581
+ if (handler.errored) {
1582
+ // We've already errored. We could instead build up an AggregateError
1583
+ // but if there are multiple errors we just take the first one like
1584
+ // Promise.all.
1585
+ return;
1586
+ }
1587
+ handler.errored = true;
1588
+ handler.value = null;
1589
+ handler.reason = error;
1590
+ const chunk = handler.chunk;
1591
+ if (chunk === null || chunk.status !== BLOCKED) {
1592
+ return;
1593
+ }
1594
+ triggerErrorOnChunk(response, chunk, error);
1595
+ }
1596
+ promise.then(fulfill, reject);
1597
+
1598
+ // Return a place holder value for now.
1599
+ return null;
1600
+ }
1601
+ function getOutlinedModel(response, reference, parentObject, key, map) {
1602
+ const path = reference.split(':');
1603
+ const id = parseInt(path[0], 16);
1604
+ const chunk = getChunk(response, id);
1605
+ switch (chunk.status) {
1606
+ case RESOLVED_MODEL:
1607
+ initializeModelChunk(chunk);
1608
+ break;
1609
+ case RESOLVED_MODULE:
1610
+ initializeModuleChunk(chunk);
1611
+ break;
1612
+ }
1613
+ // The status might have changed after initialization.
1614
+ switch (chunk.status) {
1615
+ case INITIALIZED:
1616
+ let value = chunk.value;
1617
+ for (let i = 1; i < path.length; i++) {
1618
+ while (value.$$typeof === REACT_LAZY_TYPE) {
1619
+ const referencedChunk = value._payload;
1620
+ switch (referencedChunk.status) {
1621
+ case RESOLVED_MODEL:
1622
+ initializeModelChunk(referencedChunk);
1623
+ break;
1624
+ case RESOLVED_MODULE:
1625
+ initializeModuleChunk(referencedChunk);
1626
+ break;
1627
+ }
1628
+ switch (referencedChunk.status) {
1629
+ case INITIALIZED:
1630
+ {
1631
+ value = referencedChunk.value;
1632
+ break;
1633
+ }
1634
+ case BLOCKED:
1635
+ case PENDING:
1636
+ {
1637
+ return waitForReference(referencedChunk, parentObject, key, response, map, path.slice(i - 1));
1638
+ }
1639
+ case HALTED:
1640
+ {
1641
+ // Add a dependency that will never resolve.
1642
+ // TODO: Mark downstreams as halted too.
1643
+ let handler;
1644
+ if (initializingHandler) {
1645
+ handler = initializingHandler;
1646
+ handler.deps++;
1647
+ } else {
1648
+ handler = initializingHandler = {
1649
+ parent: null,
1650
+ chunk: null,
1651
+ value: null,
1652
+ reason: null,
1653
+ deps: 1,
1654
+ errored: false
1655
+ };
1656
+ }
1657
+ return null;
1658
+ }
1659
+ default:
1660
+ {
1661
+ // This is an error. Instead of erroring directly, we're going to encode this on
1662
+ // an initialization handler so that we can catch it at the nearest Element.
1663
+ if (initializingHandler) {
1664
+ initializingHandler.errored = true;
1665
+ initializingHandler.value = null;
1666
+ initializingHandler.reason = referencedChunk.reason;
1667
+ } else {
1668
+ initializingHandler = {
1669
+ parent: null,
1670
+ chunk: null,
1671
+ value: null,
1672
+ reason: referencedChunk.reason,
1673
+ deps: 0,
1674
+ errored: true
1675
+ };
1676
+ }
1677
+ return null;
1678
+ }
1679
+ }
1680
+ }
1681
+ value = value[path[i]];
1682
+ }
1683
+ const chunkValue = map(response, value, parentObject, key);
1684
+ return chunkValue;
1685
+ case PENDING:
1686
+ case BLOCKED:
1687
+ return waitForReference(chunk, parentObject, key, response, map, path);
1688
+ case HALTED:
1689
+ {
1690
+ // Add a dependency that will never resolve.
1691
+ // TODO: Mark downstreams as halted too.
1692
+ let handler;
1693
+ if (initializingHandler) {
1694
+ handler = initializingHandler;
1695
+ handler.deps++;
1696
+ } else {
1697
+ handler = initializingHandler = {
1698
+ parent: null,
1699
+ chunk: null,
1700
+ value: null,
1701
+ reason: null,
1702
+ deps: 1,
1703
+ errored: false
1704
+ };
1705
+ }
1706
+ return null;
1707
+ }
1708
+ default:
1709
+ // This is an error. Instead of erroring directly, we're going to encode this on
1710
+ // an initialization handler so that we can catch it at the nearest Element.
1711
+ if (initializingHandler) {
1712
+ initializingHandler.errored = true;
1713
+ initializingHandler.value = null;
1714
+ initializingHandler.reason = chunk.reason;
1715
+ } else {
1716
+ initializingHandler = {
1717
+ parent: null,
1718
+ chunk: null,
1719
+ value: null,
1720
+ reason: chunk.reason,
1721
+ deps: 0,
1722
+ errored: true
1723
+ };
1724
+ }
1725
+ // Placeholder
1726
+ return null;
1727
+ }
1728
+ }
1729
+ function createMap(response, model) {
1730
+ return new Map(model);
1731
+ }
1732
+ function createSet(response, model) {
1733
+ return new Set(model);
1734
+ }
1735
+ function createBlob(response, model) {
1736
+ return new Blob(model.slice(1), {
1737
+ type: model[0]
1738
+ });
1739
+ }
1740
+ function createFormData(response, model) {
1741
+ const formData = new FormData();
1742
+ for (let i = 0; i < model.length; i++) {
1743
+ formData.append(model[i][0], model[i][1]);
1744
+ }
1745
+ return formData;
1746
+ }
1747
+ function extractIterator(response, model) {
1748
+ // $FlowFixMe[incompatible-use]: This uses raw Symbols because we're extracting from a native array.
1749
+ return model[Symbol.iterator]();
1750
+ }
1751
+ function createModel(response, model) {
1752
+ return model;
1753
+ }
1754
+ function parseModelString(response, parentObject, key, value) {
1755
+ if (value[0] === '$') {
1756
+ if (value === '$') {
1757
+ // A very common symbol.
1758
+ if (initializingHandler !== null && key === '0') {
1759
+ // We we already have an initializing handler and we're abound to enter
1760
+ // a new element, we need to shadow it because we're now in a new scope.
1761
+ // This is effectively the "begin" or "push" phase of Element parsing.
1762
+ // We'll pop later when we parse the array itself.
1763
+ initializingHandler = {
1764
+ parent: initializingHandler,
1765
+ chunk: null,
1766
+ value: null,
1767
+ reason: null,
1768
+ deps: 0,
1769
+ errored: false
1770
+ };
1771
+ }
1772
+ return REACT_ELEMENT_TYPE;
1773
+ }
1774
+ switch (value[1]) {
1775
+ case '$':
1776
+ {
1777
+ // This was an escaped string value.
1778
+ return value.slice(1);
1779
+ }
1780
+ case 'L':
1781
+ {
1782
+ // Lazy node
1783
+ const id = parseInt(value.slice(2), 16);
1784
+ const chunk = getChunk(response, id);
1785
+ // We create a React.lazy wrapper around any lazy values.
1786
+ // When passed into React, we'll know how to suspend on this.
1787
+ return createLazyChunkWrapper(chunk);
1788
+ }
1789
+ case '@':
1790
+ {
1791
+ // Promise
1792
+ const id = parseInt(value.slice(2), 16);
1793
+ const chunk = getChunk(response, id);
1794
+ return chunk;
1795
+ }
1796
+ case 'S':
1797
+ {
1798
+ // Symbol
1799
+ return Symbol.for(value.slice(2));
1800
+ }
1801
+ case 'F':
1802
+ {
1803
+ // Server Reference
1804
+ const ref = value.slice(2);
1805
+ return getOutlinedModel(response, ref, parentObject, key, loadServerReference);
1806
+ }
1807
+ case 'T':
1808
+ {
1809
+ // Temporary Reference
1810
+ const reference = '$' + value.slice(2);
1811
+ const temporaryReferences = response._tempRefs;
1812
+ if (temporaryReferences == null) {
1813
+ throw new Error('Missing a temporary reference set but the RSC response returned a temporary reference. ' + 'Pass a temporaryReference option with the set that was used with the reply.');
1814
+ }
1815
+ return readTemporaryReference(temporaryReferences, reference);
1816
+ }
1817
+ case 'Q':
1818
+ {
1819
+ // Map
1820
+ const ref = value.slice(2);
1821
+ return getOutlinedModel(response, ref, parentObject, key, createMap);
1822
+ }
1823
+ case 'W':
1824
+ {
1825
+ // Set
1826
+ const ref = value.slice(2);
1827
+ return getOutlinedModel(response, ref, parentObject, key, createSet);
1828
+ }
1829
+ case 'B':
1830
+ {
1831
+ // Blob
1832
+ const ref = value.slice(2);
1833
+ return getOutlinedModel(response, ref, parentObject, key, createBlob);
1834
+ }
1835
+ case 'K':
1836
+ {
1837
+ // FormData
1838
+ const ref = value.slice(2);
1839
+ return getOutlinedModel(response, ref, parentObject, key, createFormData);
1840
+ }
1841
+ case 'Z':
1842
+ {
1843
+ // Error
1844
+ {
1845
+ return resolveErrorProd();
1846
+ }
1847
+ }
1848
+ case 'i':
1849
+ {
1850
+ // Iterator
1851
+ const ref = value.slice(2);
1852
+ return getOutlinedModel(response, ref, parentObject, key, extractIterator);
1853
+ }
1854
+ case 'I':
1855
+ {
1856
+ // $Infinity
1857
+ return Infinity;
1858
+ }
1859
+ case '-':
1860
+ {
1861
+ // $-0 or $-Infinity
1862
+ if (value === '$-0') {
1863
+ return -0;
1864
+ } else {
1865
+ return -Infinity;
1866
+ }
1867
+ }
1868
+ case 'N':
1869
+ {
1870
+ // $NaN
1871
+ return NaN;
1872
+ }
1873
+ case 'u':
1874
+ {
1875
+ // matches "$undefined"
1876
+ // Special encoding for `undefined` which can't be serialized as JSON otherwise.
1877
+ return undefined;
1878
+ }
1879
+ case 'D':
1880
+ {
1881
+ // Date
1882
+ return new Date(Date.parse(value.slice(2)));
1883
+ }
1884
+ case 'n':
1885
+ {
1886
+ // BigInt
1887
+ return BigInt(value.slice(2));
1888
+ }
1889
+ case 'P':
1890
+ case 'E':
1891
+ case 'Y':
1892
+ default:
1893
+ {
1894
+ // We assume that anything else is a reference ID.
1895
+ const ref = value.slice(1);
1896
+ return getOutlinedModel(response, ref, parentObject, key, createModel);
1897
+ }
1898
+ }
1899
+ }
1900
+ return value;
1901
+ }
1902
+ function parseModelTuple(response, value) {
1903
+ const tuple = value;
1904
+ if (tuple[0] === REACT_ELEMENT_TYPE) {
1905
+ // TODO: Consider having React just directly accept these arrays as elements.
1906
+ // Or even change the ReactElement type to be an array.
1907
+ return createElement(response, tuple[1], tuple[2], tuple[3]);
1908
+ }
1909
+ return value;
1910
+ }
1911
+ function missingCall() {
1912
+ throw new Error('Trying to call a function from "use server" but the callServer option ' + 'was not implemented in your router runtime.');
1913
+ }
1914
+ function ResponseInstance(bundlerConfig, serverReferenceConfig, moduleLoading, callServer, encodeFormAction, nonce, temporaryReferences, findSourceMapURL,
1915
+ // DEV-only
1916
+ replayConsole,
1917
+ // DEV-only
1918
+ environmentName,
1919
+ // DEV-only
1920
+ debugChannel // DEV-only
1921
+ ) {
1922
+ const chunks = new Map();
1923
+ this._bundlerConfig = bundlerConfig;
1924
+ this._serverReferenceConfig = serverReferenceConfig;
1925
+ this._moduleLoading = moduleLoading;
1926
+ this._callServer = callServer !== undefined ? callServer : missingCall;
1927
+ this._encodeFormAction = encodeFormAction;
1928
+ this._nonce = nonce;
1929
+ this._chunks = chunks;
1930
+ this._stringDecoder = createStringDecoder();
1931
+ this._fromJSON = null;
1932
+ this._closed = false;
1933
+ this._closedReason = null;
1934
+ this._tempRefs = temporaryReferences;
1935
+
1936
+ // Don't inline this call because it causes closure to outline the call above.
1937
+ this._fromJSON = createFromJSONCallback(this);
1938
+ }
1939
+ function createResponse(bundlerConfig, serverReferenceConfig, moduleLoading, callServer, encodeFormAction, nonce, temporaryReferences, findSourceMapURL,
1940
+ // DEV-only
1941
+ replayConsole,
1942
+ // DEV-only
1943
+ environmentName,
1944
+ // DEV-only
1945
+ debugChannel // DEV-only
1946
+ ) {
1947
+ return getWeakResponse(
1948
+ // $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors
1949
+ new ResponseInstance(bundlerConfig, serverReferenceConfig, moduleLoading, callServer, encodeFormAction, nonce, temporaryReferences));
1950
+ }
1951
+ function createStreamState() {
1952
+ return {
1953
+ _rowState: 0,
1954
+ _rowID: 0,
1955
+ _rowTag: 0,
1956
+ _rowLength: 0,
1957
+ _buffer: []
1958
+ };
1959
+ }
1960
+ function resolveModel(response, id, model) {
1961
+ const chunks = response._chunks;
1962
+ const chunk = chunks.get(id);
1963
+ if (!chunk) {
1964
+ chunks.set(id, createResolvedModelChunk(response, model));
1965
+ } else {
1966
+ resolveModelChunk(response, chunk, model);
1967
+ }
1968
+ }
1969
+ function resolveText(response, id, text) {
1970
+ const chunks = response._chunks;
1971
+ const chunk = chunks.get(id);
1972
+ if (chunk && chunk.status !== PENDING) {
1973
+ // If we get more data to an already resolved ID, we assume that it's
1974
+ // a stream chunk since any other row shouldn't have more than one entry.
1975
+ const streamChunk = chunk;
1976
+ const controller = streamChunk.reason;
1977
+ controller.enqueueValue(text);
1978
+ return;
1979
+ }
1980
+ chunks.set(id, createInitializedTextChunk(response, text));
1981
+ }
1982
+ function resolveBuffer(response, id, buffer) {
1983
+ const chunks = response._chunks;
1984
+ const chunk = chunks.get(id);
1985
+ if (chunk && chunk.status !== PENDING) {
1986
+ // If we get more data to an already resolved ID, we assume that it's
1987
+ // a stream chunk since any other row shouldn't have more than one entry.
1988
+ const streamChunk = chunk;
1989
+ const controller = streamChunk.reason;
1990
+ controller.enqueueValue(buffer);
1991
+ return;
1992
+ }
1993
+ chunks.set(id, createInitializedBufferChunk(response, buffer));
1994
+ }
1995
+ function resolveModule(response, id, model) {
1996
+ const chunks = response._chunks;
1997
+ const chunk = chunks.get(id);
1998
+ const clientReferenceMetadata = parseModel(response, model);
1999
+ const clientReference = resolveClientReference(response._bundlerConfig, clientReferenceMetadata);
2000
+
2001
+ // TODO: Add an option to encode modules that are lazy loaded.
2002
+ // For now we preload all modules as early as possible since it's likely
2003
+ // that we'll need them.
2004
+ const promise = preloadModule(clientReference);
2005
+ if (promise) {
2006
+ let blockedChunk;
2007
+ if (!chunk) {
2008
+ // Technically, we should just treat promise as the chunk in this
2009
+ // case. Because it'll just behave as any other promise.
2010
+ blockedChunk = createBlockedChunk();
2011
+ chunks.set(id, blockedChunk);
2012
+ } else {
2013
+ // This can't actually happen because we don't have any forward
2014
+ // references to modules.
2015
+ blockedChunk = chunk;
2016
+ blockedChunk.status = BLOCKED;
2017
+ }
2018
+ promise.then(() => resolveModuleChunk(response, blockedChunk, clientReference), error => triggerErrorOnChunk(response, blockedChunk, error));
2019
+ } else {
2020
+ if (!chunk) {
2021
+ chunks.set(id, createResolvedModuleChunk(response, clientReference));
2022
+ } else {
2023
+ // This can't actually happen because we don't have any forward
2024
+ // references to modules.
2025
+ resolveModuleChunk(response, chunk, clientReference);
2026
+ }
2027
+ }
2028
+ }
2029
+ function resolveStream(response, id, stream, controller) {
2030
+ const chunks = response._chunks;
2031
+ const chunk = chunks.get(id);
2032
+ if (!chunk) {
2033
+ chunks.set(id, createInitializedStreamChunk(response, stream, controller));
2034
+ return;
2035
+ }
2036
+ if (chunk.status !== PENDING) {
2037
+ // We already resolved. We didn't expect to see this.
2038
+ return;
2039
+ }
2040
+ const resolveListeners = chunk.value;
2041
+ const resolvedChunk = chunk;
2042
+ resolvedChunk.status = INITIALIZED;
2043
+ resolvedChunk.value = stream;
2044
+ resolvedChunk.reason = controller;
2045
+ if (resolveListeners !== null) {
2046
+ wakeChunk(resolveListeners, chunk.value);
2047
+ }
2048
+ }
2049
+ function startReadableStream(response, id, type) {
2050
+ let controller = null;
2051
+ const stream = new ReadableStream({
2052
+ type: type,
2053
+ start(c) {
2054
+ controller = c;
2055
+ }
2056
+ });
2057
+ let previousBlockedChunk = null;
2058
+ const flightController = {
2059
+ enqueueValue(value) {
2060
+ if (previousBlockedChunk === null) {
2061
+ controller.enqueue(value);
2062
+ } else {
2063
+ // We're still waiting on a previous chunk so we can't enqueue quite yet.
2064
+ previousBlockedChunk.then(function () {
2065
+ controller.enqueue(value);
2066
+ });
2067
+ }
2068
+ },
2069
+ enqueueModel(json) {
2070
+ if (previousBlockedChunk === null) {
2071
+ // If we're not blocked on any other chunks, we can try to eagerly initialize
2072
+ // this as a fast-path to avoid awaiting them.
2073
+ const chunk = createResolvedModelChunk(response, json);
2074
+ initializeModelChunk(chunk);
2075
+ const initializedChunk = chunk;
2076
+ if (initializedChunk.status === INITIALIZED) {
2077
+ controller.enqueue(initializedChunk.value);
2078
+ } else {
2079
+ chunk.then(v => controller.enqueue(v), e => controller.error(e));
2080
+ previousBlockedChunk = chunk;
2081
+ }
2082
+ } else {
2083
+ // We're still waiting on a previous chunk so we can't enqueue quite yet.
2084
+ const blockedChunk = previousBlockedChunk;
2085
+ const chunk = createPendingChunk();
2086
+ chunk.then(v => controller.enqueue(v), e => controller.error(e));
2087
+ previousBlockedChunk = chunk;
2088
+ blockedChunk.then(function () {
2089
+ if (previousBlockedChunk === chunk) {
2090
+ // We were still the last chunk so we can now clear the queue and return
2091
+ // to synchronous emitting.
2092
+ previousBlockedChunk = null;
2093
+ }
2094
+ resolveModelChunk(response, chunk, json);
2095
+ });
2096
+ }
2097
+ },
2098
+ close(json) {
2099
+ if (previousBlockedChunk === null) {
2100
+ controller.close();
2101
+ } else {
2102
+ const blockedChunk = previousBlockedChunk;
2103
+ // We shouldn't get any more enqueues after this so we can set it back to null.
2104
+ previousBlockedChunk = null;
2105
+ blockedChunk.then(() => controller.close());
2106
+ }
2107
+ },
2108
+ error(error) {
2109
+ if (previousBlockedChunk === null) {
2110
+ // $FlowFixMe[incompatible-call]
2111
+ controller.error(error);
2112
+ } else {
2113
+ const blockedChunk = previousBlockedChunk;
2114
+ // We shouldn't get any more enqueues after this so we can set it back to null.
2115
+ previousBlockedChunk = null;
2116
+ blockedChunk.then(() => controller.error(error));
2117
+ }
2118
+ }
2119
+ };
2120
+ resolveStream(response, id, stream, flightController);
2121
+ }
2122
+ function asyncIterator() {
2123
+ // Self referencing iterator.
2124
+ return this;
2125
+ }
2126
+ function createIterator(next) {
2127
+ const iterator = {
2128
+ next: next
2129
+ // TODO: Add return/throw as options for aborting.
2130
+ };
2131
+ // TODO: The iterator could inherit the AsyncIterator prototype which is not exposed as
2132
+ // a global but exists as a prototype of an AsyncGenerator. However, it's not needed
2133
+ // to satisfy the iterable protocol.
2134
+ iterator[ASYNC_ITERATOR] = asyncIterator;
2135
+ return iterator;
2136
+ }
2137
+ function startAsyncIterable(response, id, iterator) {
2138
+ const buffer = [];
2139
+ let closed = false;
2140
+ let nextWriteIndex = 0;
2141
+ const flightController = {
2142
+ enqueueValue(value) {
2143
+ if (nextWriteIndex === buffer.length) {
2144
+ buffer[nextWriteIndex] = createInitializedIteratorResultChunk(response, value, false);
2145
+ } else {
2146
+ const chunk = buffer[nextWriteIndex];
2147
+ const resolveListeners = chunk.value;
2148
+ const rejectListeners = chunk.reason;
2149
+ const initializedChunk = chunk;
2150
+ initializedChunk.status = INITIALIZED;
2151
+ initializedChunk.value = {
2152
+ done: false,
2153
+ value: value
2154
+ };
2155
+ if (resolveListeners !== null) {
2156
+ wakeChunkIfInitialized(chunk, resolveListeners, rejectListeners);
2157
+ }
2158
+ }
2159
+ nextWriteIndex++;
2160
+ },
2161
+ enqueueModel(value) {
2162
+ if (nextWriteIndex === buffer.length) {
2163
+ buffer[nextWriteIndex] = createResolvedIteratorResultChunk(response, value, false);
2164
+ } else {
2165
+ resolveIteratorResultChunk(response, buffer[nextWriteIndex], value, false);
2166
+ }
2167
+ nextWriteIndex++;
2168
+ },
2169
+ close(value) {
2170
+ closed = true;
2171
+ if (nextWriteIndex === buffer.length) {
2172
+ buffer[nextWriteIndex] = createResolvedIteratorResultChunk(response, value, true);
2173
+ } else {
2174
+ resolveIteratorResultChunk(response, buffer[nextWriteIndex], value, true);
2175
+ }
2176
+ nextWriteIndex++;
2177
+ while (nextWriteIndex < buffer.length) {
2178
+ // In generators, any extra reads from the iterator have the value undefined.
2179
+ resolveIteratorResultChunk(response, buffer[nextWriteIndex++], '"$undefined"', true);
2180
+ }
2181
+ },
2182
+ error(error) {
2183
+ closed = true;
2184
+ if (nextWriteIndex === buffer.length) {
2185
+ buffer[nextWriteIndex] = createPendingChunk();
2186
+ }
2187
+ while (nextWriteIndex < buffer.length) {
2188
+ triggerErrorOnChunk(response, buffer[nextWriteIndex++], error);
2189
+ }
2190
+ }
2191
+ };
2192
+ const iterable = {};
2193
+ // $FlowFixMe[cannot-write]
2194
+ iterable[ASYNC_ITERATOR] = () => {
2195
+ let nextReadIndex = 0;
2196
+ return createIterator(arg => {
2197
+ if (arg !== undefined) {
2198
+ throw new Error('Values cannot be passed to next() of AsyncIterables passed to Client Components.');
2199
+ }
2200
+ if (nextReadIndex === buffer.length) {
2201
+ if (closed) {
2202
+ // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
2203
+ return new ReactPromise(INITIALIZED, {
2204
+ done: true,
2205
+ value: undefined
2206
+ }, null);
2207
+ }
2208
+ buffer[nextReadIndex] = createPendingChunk();
2209
+ }
2210
+ return buffer[nextReadIndex++];
2211
+ });
2212
+ };
2213
+
2214
+ // TODO: If it's a single shot iterator we can optimize memory by cleaning up the buffer after
2215
+ // reading through the end, but currently we favor code size over this optimization.
2216
+ resolveStream(response, id, iterator ? iterable[ASYNC_ITERATOR]() : iterable, flightController);
2217
+ }
2218
+ function stopStream(response, id, row) {
2219
+ const chunks = response._chunks;
2220
+ const chunk = chunks.get(id);
2221
+ if (!chunk || chunk.status !== INITIALIZED) {
2222
+ // We didn't expect not to have an existing stream;
2223
+ return;
2224
+ }
2225
+ const streamChunk = chunk;
2226
+ const controller = streamChunk.reason;
2227
+ controller.close(row === '' ? '"$undefined"' : row);
2228
+ }
2229
+ function resolveErrorProd(response) {
2230
+ const error = new Error('An error occurred in the Server Components render. The specific message is omitted in production' + ' builds to avoid leaking sensitive details. A digest property is included on this error instance which' + ' may provide additional details about the nature of the error.');
2231
+ error.stack = 'Error: ' + error.message;
2232
+ return error;
2233
+ }
2234
+ function resolvePostponeProd(response, id) {
2235
+ const error = new Error('A Server Component was postponed. The reason is omitted in production' + ' builds to avoid leaking sensitive details.');
2236
+ const postponeInstance = error;
2237
+ postponeInstance.$$typeof = REACT_POSTPONE_TYPE;
2238
+ postponeInstance.stack = 'Error: ' + error.message;
2239
+ const chunks = response._chunks;
2240
+ const chunk = chunks.get(id);
2241
+ if (!chunk) {
2242
+ chunks.set(id, createErrorChunk(response, postponeInstance));
2243
+ } else {
2244
+ triggerErrorOnChunk(response, chunk, postponeInstance);
2245
+ }
2246
+ }
2247
+ function resolveErrorModel(response, id, row) {
2248
+ const chunks = response._chunks;
2249
+ const chunk = chunks.get(id);
2250
+ const errorInfo = JSON.parse(row);
2251
+ let error;
2252
+ {
2253
+ error = resolveErrorProd();
2254
+ }
2255
+ error.digest = errorInfo.digest;
2256
+ const errorWithDigest = error;
2257
+ if (!chunk) {
2258
+ chunks.set(id, createErrorChunk(response, errorWithDigest));
2259
+ } else {
2260
+ triggerErrorOnChunk(response, chunk, errorWithDigest);
2261
+ }
2262
+ }
2263
+ function resolveHint(response, code, model) {
2264
+ const hintModel = parseModel(response, model);
2265
+ dispatchHint(code, hintModel);
2266
+ }
2267
+ function mergeBuffer(buffer, lastChunk) {
2268
+ const l = buffer.length;
2269
+ // Count the bytes we'll need
2270
+ let byteLength = lastChunk.length;
2271
+ for (let i = 0; i < l; i++) {
2272
+ byteLength += buffer[i].byteLength;
2273
+ }
2274
+ // Allocate enough contiguous space
2275
+ const result = new Uint8Array(byteLength);
2276
+ let offset = 0;
2277
+ // Copy all the buffers into it.
2278
+ for (let i = 0; i < l; i++) {
2279
+ const chunk = buffer[i];
2280
+ result.set(chunk, offset);
2281
+ offset += chunk.byteLength;
2282
+ }
2283
+ result.set(lastChunk, offset);
2284
+ return result;
2285
+ }
2286
+ function resolveTypedArray(response, id, buffer, lastChunk, constructor, bytesPerElement) {
2287
+ // If the view fits into one original buffer, we just reuse that buffer instead of
2288
+ // copying it out to a separate copy. This means that it's not always possible to
2289
+ // transfer these values to other threads without copying first since they may
2290
+ // share array buffer. For this to work, it must also have bytes aligned to a
2291
+ // multiple of a size of the type.
2292
+ const chunk = buffer.length === 0 && lastChunk.byteOffset % bytesPerElement === 0 ? lastChunk : mergeBuffer(buffer, lastChunk);
2293
+ // TODO: The transfer protocol of RSC is little-endian. If the client isn't little-endian
2294
+ // we should convert it instead. In practice big endian isn't really Web compatible so it's
2295
+ // somewhat safe to assume that browsers aren't going to run it, but maybe there's some SSR
2296
+ // server that's affected.
2297
+ const view = new constructor(chunk.buffer, chunk.byteOffset, chunk.byteLength / bytesPerElement);
2298
+ resolveBuffer(response, id, view);
2299
+ }
2300
+ function processFullBinaryRow(response, id, tag, buffer, chunk) {
2301
+ switch (tag) {
2302
+ case 65 /* "A" */:
2303
+ // We must always clone to extract it into a separate buffer instead of just a view.
2304
+ resolveBuffer(response, id, mergeBuffer(buffer, chunk).buffer);
2305
+ return;
2306
+ case 79 /* "O" */:
2307
+ resolveTypedArray(response, id, buffer, chunk, Int8Array, 1);
2308
+ return;
2309
+ case 111 /* "o" */:
2310
+ resolveBuffer(response, id, buffer.length === 0 ? chunk : mergeBuffer(buffer, chunk));
2311
+ return;
2312
+ case 85 /* "U" */:
2313
+ resolveTypedArray(response, id, buffer, chunk, Uint8ClampedArray, 1);
2314
+ return;
2315
+ case 83 /* "S" */:
2316
+ resolveTypedArray(response, id, buffer, chunk, Int16Array, 2);
2317
+ return;
2318
+ case 115 /* "s" */:
2319
+ resolveTypedArray(response, id, buffer, chunk, Uint16Array, 2);
2320
+ return;
2321
+ case 76 /* "L" */:
2322
+ resolveTypedArray(response, id, buffer, chunk, Int32Array, 4);
2323
+ return;
2324
+ case 108 /* "l" */:
2325
+ resolveTypedArray(response, id, buffer, chunk, Uint32Array, 4);
2326
+ return;
2327
+ case 71 /* "G" */:
2328
+ resolveTypedArray(response, id, buffer, chunk, Float32Array, 4);
2329
+ return;
2330
+ case 103 /* "g" */:
2331
+ resolveTypedArray(response, id, buffer, chunk, Float64Array, 8);
2332
+ return;
2333
+ case 77 /* "M" */:
2334
+ resolveTypedArray(response, id, buffer, chunk, BigInt64Array, 8);
2335
+ return;
2336
+ case 109 /* "m" */:
2337
+ resolveTypedArray(response, id, buffer, chunk, BigUint64Array, 8);
2338
+ return;
2339
+ case 86 /* "V" */:
2340
+ resolveTypedArray(response, id, buffer, chunk, DataView, 1);
2341
+ return;
2342
+ }
2343
+ const stringDecoder = response._stringDecoder;
2344
+ let row = '';
2345
+ for (let i = 0; i < buffer.length; i++) {
2346
+ row += readPartialStringChunk(stringDecoder, buffer[i]);
2347
+ }
2348
+ row += readFinalStringChunk(stringDecoder, chunk);
2349
+ processFullStringRow(response, id, tag, row);
2350
+ }
2351
+ function processFullStringRow(response, id, tag, row) {
2352
+ switch (tag) {
2353
+ case 73 /* "I" */:
2354
+ {
2355
+ resolveModule(response, id, row);
2356
+ return;
2357
+ }
2358
+ case 72 /* "H" */:
2359
+ {
2360
+ const code = row[0];
2361
+ resolveHint(response, code, row.slice(1));
2362
+ return;
2363
+ }
2364
+ case 69 /* "E" */:
2365
+ {
2366
+ resolveErrorModel(response, id, row);
2367
+ return;
2368
+ }
2369
+ case 84 /* "T" */:
2370
+ {
2371
+ resolveText(response, id, row);
2372
+ return;
2373
+ }
2374
+ case 78 /* "N" */:
2375
+ case 68 /* "D" */:
2376
+ case 74 /* "J" */:
2377
+ case 87 /* "W" */:
2378
+ {
2379
+ throw new Error('Failed to read a RSC payload created by a development version of React ' + 'on the server while using a production version on the client. Always use ' + 'matching versions on the server and the client.');
2380
+ }
2381
+ case 82 /* "R" */:
2382
+ {
2383
+ startReadableStream(response, id, undefined);
2384
+ return;
2385
+ }
2386
+ // Fallthrough
2387
+ case 114 /* "r" */:
2388
+ {
2389
+ startReadableStream(response, id, 'bytes');
2390
+ return;
2391
+ }
2392
+ // Fallthrough
2393
+ case 88 /* "X" */:
2394
+ {
2395
+ startAsyncIterable(response, id, false);
2396
+ return;
2397
+ }
2398
+ // Fallthrough
2399
+ case 120 /* "x" */:
2400
+ {
2401
+ startAsyncIterable(response, id, true);
2402
+ return;
2403
+ }
2404
+ // Fallthrough
2405
+ case 67 /* "C" */:
2406
+ {
2407
+ stopStream(response, id, row);
2408
+ return;
2409
+ }
2410
+ // Fallthrough
2411
+ case 80 /* "P" */:
2412
+ {
2413
+ {
2414
+ {
2415
+ resolvePostponeProd(response, id);
2416
+ }
2417
+ return;
2418
+ }
2419
+ }
2420
+ // Fallthrough
2421
+ default:
2422
+ /* """ "{" "[" "t" "f" "n" "0" - "9" */{
2423
+ // We assume anything else is JSON.
2424
+ resolveModel(response, id, row);
2425
+ return;
2426
+ }
2427
+ }
2428
+ }
2429
+ function processBinaryChunk(weakResponse, streamState, chunk) {
2430
+ const response = unwrapWeakResponse(weakResponse);
2431
+ let i = 0;
2432
+ let rowState = streamState._rowState;
2433
+ let rowID = streamState._rowID;
2434
+ let rowTag = streamState._rowTag;
2435
+ let rowLength = streamState._rowLength;
2436
+ const buffer = streamState._buffer;
2437
+ const chunkLength = chunk.length;
2438
+ while (i < chunkLength) {
2439
+ let lastIdx = -1;
2440
+ switch (rowState) {
2441
+ case ROW_ID:
2442
+ {
2443
+ const byte = chunk[i++];
2444
+ if (byte === 58 /* ":" */) {
2445
+ // Finished the rowID, next we'll parse the tag.
2446
+ rowState = ROW_TAG;
2447
+ } else {
2448
+ rowID = rowID << 4 | (byte > 96 ? byte - 87 : byte - 48);
2449
+ }
2450
+ continue;
2451
+ }
2452
+ case ROW_TAG:
2453
+ {
2454
+ const resolvedRowTag = chunk[i];
2455
+ if (resolvedRowTag === 84 /* "T" */ || resolvedRowTag === 65 /* "A" */ || resolvedRowTag === 79 /* "O" */ || resolvedRowTag === 111 /* "o" */ || resolvedRowTag === 85 /* "U" */ || resolvedRowTag === 83 /* "S" */ || resolvedRowTag === 115 /* "s" */ || resolvedRowTag === 76 /* "L" */ || resolvedRowTag === 108 /* "l" */ || resolvedRowTag === 71 /* "G" */ || resolvedRowTag === 103 /* "g" */ || resolvedRowTag === 77 /* "M" */ || resolvedRowTag === 109 /* "m" */ || resolvedRowTag === 86 /* "V" */) {
2456
+ rowTag = resolvedRowTag;
2457
+ rowState = ROW_LENGTH;
2458
+ i++;
2459
+ } else if (resolvedRowTag > 64 && resolvedRowTag < 91 /* "A"-"Z" */ || resolvedRowTag === 35 /* "#" */ || resolvedRowTag === 114 /* "r" */ || resolvedRowTag === 120 /* "x" */) {
2460
+ rowTag = resolvedRowTag;
2461
+ rowState = ROW_CHUNK_BY_NEWLINE;
2462
+ i++;
2463
+ } else {
2464
+ rowTag = 0;
2465
+ rowState = ROW_CHUNK_BY_NEWLINE;
2466
+ // This was an unknown tag so it was probably part of the data.
2467
+ }
2468
+ continue;
2469
+ }
2470
+ case ROW_LENGTH:
2471
+ {
2472
+ const byte = chunk[i++];
2473
+ if (byte === 44 /* "," */) {
2474
+ // Finished the rowLength, next we'll buffer up to that length.
2475
+ rowState = ROW_CHUNK_BY_LENGTH;
2476
+ } else {
2477
+ rowLength = rowLength << 4 | (byte > 96 ? byte - 87 : byte - 48);
2478
+ }
2479
+ continue;
2480
+ }
2481
+ case ROW_CHUNK_BY_NEWLINE:
2482
+ {
2483
+ // We're looking for a newline
2484
+ lastIdx = chunk.indexOf(10 /* "\n" */, i);
2485
+ break;
2486
+ }
2487
+ case ROW_CHUNK_BY_LENGTH:
2488
+ {
2489
+ // We're looking for the remaining byte length
2490
+ lastIdx = i + rowLength;
2491
+ if (lastIdx > chunk.length) {
2492
+ lastIdx = -1;
2493
+ }
2494
+ break;
2495
+ }
2496
+ }
2497
+ const offset = chunk.byteOffset + i;
2498
+ if (lastIdx > -1) {
2499
+ // We found the last chunk of the row
2500
+ const length = lastIdx - i;
2501
+ const lastChunk = new Uint8Array(chunk.buffer, offset, length);
2502
+ processFullBinaryRow(response, rowID, rowTag, buffer, lastChunk);
2503
+ // Reset state machine for a new row
2504
+ i = lastIdx;
2505
+ if (rowState === ROW_CHUNK_BY_NEWLINE) {
2506
+ // If we're trailing by a newline we need to skip it.
2507
+ i++;
2508
+ }
2509
+ rowState = ROW_ID;
2510
+ rowTag = 0;
2511
+ rowID = 0;
2512
+ rowLength = 0;
2513
+ buffer.length = 0;
2514
+ } else {
2515
+ // The rest of this row is in a future chunk. We stash the rest of the
2516
+ // current chunk until we can process the full row.
2517
+ const length = chunk.byteLength - i;
2518
+ const remainingSlice = new Uint8Array(chunk.buffer, offset, length);
2519
+ buffer.push(remainingSlice);
2520
+ // Update how many bytes we're still waiting for. If we're looking for
2521
+ // a newline, this doesn't hurt since we'll just ignore it.
2522
+ rowLength -= remainingSlice.byteLength;
2523
+ break;
2524
+ }
2525
+ }
2526
+ streamState._rowState = rowState;
2527
+ streamState._rowID = rowID;
2528
+ streamState._rowTag = rowTag;
2529
+ streamState._rowLength = rowLength;
2530
+ }
2531
+ function parseModel(response, json) {
2532
+ return JSON.parse(json, response._fromJSON);
2533
+ }
2534
+ function createFromJSONCallback(response) {
2535
+ // $FlowFixMe[missing-this-annot]
2536
+ return function (key, value) {
2537
+ if (typeof value === 'string') {
2538
+ // We can't use .bind here because we need the "this" value.
2539
+ return parseModelString(response, this, key, value);
2540
+ }
2541
+ if (typeof value === 'object' && value !== null) {
2542
+ return parseModelTuple(response, value);
2543
+ }
2544
+ return value;
2545
+ };
2546
+ }
2547
+ function close(weakResponse) {
2548
+ // In case there are any remaining unresolved chunks, they won't
2549
+ // be resolved now. So we need to issue an error to those.
2550
+ // Ideally we should be able to early bail out if we kept a
2551
+ // ref count of pending chunks.
2552
+ reportGlobalError(weakResponse, new Error('Connection closed.'));
2553
+ }
2554
+
2555
+ function createResponseFromOptions(options) {
2556
+ return createResponse(options && options.moduleBaseURL ? options.moduleBaseURL : '', null, null, options && options.callServer ? options.callServer : undefined, undefined,
2557
+ // encodeFormAction
2558
+ undefined,
2559
+ // nonce
2560
+ options && options.temporaryReferences ? options.temporaryReferences : undefined);
2561
+ }
2562
+ function startReadingFromStream(response, stream, isSecondaryStream) {
2563
+ const streamState = createStreamState();
2564
+ const reader = stream.getReader();
2565
+ function progress(_ref2) {
2566
+ let done = _ref2.done,
2567
+ value = _ref2.value;
2568
+ if (done) {
2569
+ // If we're the secondary stream, then we don't close the response until the debug channel closes.
2570
+ if (!isSecondaryStream) {
2571
+ close(response);
2572
+ }
2573
+ return;
2574
+ }
2575
+ const buffer = value;
2576
+ processBinaryChunk(response, streamState, buffer);
2577
+ return reader.read().then(progress).catch(error);
2578
+ }
2579
+ function error(e) {
2580
+ reportGlobalError(response, e);
2581
+ }
2582
+ reader.read().then(progress).catch(error);
2583
+ }
2584
+ function createFromReadableStream(stream, options) {
2585
+ const response = createResponseFromOptions(options);
2586
+ {
2587
+ startReadingFromStream(response, stream, false);
2588
+ }
2589
+ return getRoot(response);
2590
+ }
2591
+ function createFromFetch(promiseForResponse, options) {
2592
+ const response = createResponseFromOptions(options);
2593
+ promiseForResponse.then(function (r) {
2594
+ {
2595
+ startReadingFromStream(response, r.body, false);
2596
+ }
2597
+ }, function (e) {
2598
+ reportGlobalError(response, e);
2599
+ });
2600
+ return getRoot(response);
2601
+ }
2602
+ function encodeReply(value, options) /* We don't use URLSearchParams yet but maybe */{
2603
+ return new Promise((resolve, reject) => {
2604
+ const abort = processReply(value, '', options && options.temporaryReferences ? options.temporaryReferences : undefined, resolve, reject);
2605
+ if (options && options.signal) {
2606
+ const signal = options.signal;
2607
+ if (signal.aborted) {
2608
+ abort(signal.reason);
2609
+ } else {
2610
+ const listener = () => {
2611
+ abort(signal.reason);
2612
+ signal.removeEventListener('abort', listener);
2613
+ };
2614
+ signal.addEventListener('abort', listener);
2615
+ }
2616
+ }
2617
+ });
2618
+ }
2619
+
2620
+ export { createFromFetch, createFromReadableStream, createServerReference, createTemporaryReferenceSet, encodeReply, registerServerReference };