801
return ref;
802
}
803
804
+ const deferredDebugObjects = request.deferredDebugObjects;
805
+ if (deferredDebugObjects !== null) {
806
+ // For Promises that are not yet resolved, we always defer them. They are async anyway so it's
807
+ // safe to defer them. This also ensures that we don't eagerly call .then() on a Promise that
808
+ // otherwise wouldn't have initialized. It also ensures that we don't "handle" a rejection
809
+ // that otherwise would have triggered unhandled rejection.
810
+ deferredDebugObjects.retained.set(id, (thenable: any));
811
+ const deferredRef = '$Y@' + id.toString(16);
812
+ // We can now refer to the deferred object in the future.
813
+ request.writtenDebugObjects.set(thenable, deferredRef);
814
+ return deferredRef;
815
+ }
816
+
817
let cancelled = false;
818
819
thenable.then(
866
return ref;
867
}
868
869
+function emitRequestedDebugThenable(
870
+ request: Request,
871
+ id: number,
872
+ counter: {objectLimit: number},
873
+ thenable: Thenable<any>,
874
+): void {
875
+ thenable.then(
876
+ value => {
877
+ if (request.status === ABORTING) {
878
+ emitDebugHaltChunk(request, id);
879
+ enqueueFlush(request);
880
+ return;
881
+ }
882
+ emitOutlinedDebugModelChunk(request, id, counter, value);
883
+ enqueueFlush(request);
884
+ },
885
+ reason => {
886
+ if (request.status === ABORTING) {
887
+ emitDebugHaltChunk(request, id);
888
+ enqueueFlush(request);
889
+ return;
890
+ }
891
+ // We don't log these errors since they didn't actually throw into Flight.
892
+ const digest = '';
893
+ emitErrorChunk(request, id, digest, reason, true);
894
+ enqueueFlush(request);
895
+ },
896
+ );
897
+}
898
+
899
function serializeThenable(
900
request: Request,
901
task: Task,
4427
} else if (debugNoOutline !== value) {
4428
// If this isn't the root object (like meta data) and we don't have an id for it, outline
4429
// it so that we can dedupe it by reference later.
4387
- const outlinedId = outlineDebugModel(request, counter, value);
4388
- return serializeByValueID(outlinedId);
4430
+ // $FlowFixMe[method-unbinding]
4431
+ if (typeof value.then === 'function') {
4432
+ // If this is a Promise we're going to assign it an external ID anyway which can be deduped.
4433
+ const thenable: Thenable<any> = (value: any);
4434
+ return serializeDebugThenable(request, counter, thenable);
4435
+ } else {
4436
+ const outlinedId = outlineDebugModel(request, counter, value);
4437
+ return serializeByValueID(outlinedId);
4438
+ }
4439
}
4440
}
4441
5837
}
5838
}
5839
break;
5840
+ case 80 /* "P" */:
5841
+ // Query Promise IDs
5842
+ for (let i = 0; i < ids.length; i++) {
5843
+ const id = ids[i];
5844
+ const retainedValue = deferredDebugObjects.retained.get(id);
5845
+ if (retainedValue !== undefined) {
5846
+ // If we still have this Promise, and haven't emitted it before, wait for it
5847
+ // and then emit it on the stream.
5848
+ const counter = {objectLimit: 10};
5849
+ deferredDebugObjects.retained.delete(id);
5850
+ emitRequestedDebugThenable(
5851
+ request,
5852
+ id,
5853
+ counter,
5854
+ (retainedValue: any),
5855
+ );
5856
+ }
5857
+ }
5858
+ break;
5859
default:
5860
throw new Error(
5861
'Unknown command. The debugChannel was not wired up properly.',