Skip to content

Commit 56e8469

Browse files
authored
[Flight] Exclude RSC Stream if the stream resolves in a task (#34838)
1 parent 19b7167 commit 56e8469

5 files changed

Lines changed: 236 additions & 267 deletions

File tree

‎packages/react-client/src/ReactFlightClient.js‎

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ type Response = {
367367
_debugRootStack?: null|Error,// DEV-only
368368
_debugRootTask?: null|ConsoleTask,// DEV-only
369369
_debugStartTime: number,// DEV-only
370+
_debugIOStarted: boolean,// DEV-only
370371
_debugFindSourceMapURL?: void|FindSourceMapURLCallback,// DEV-only
371372
_debugChannel?: void|DebugChannel,// DEV-only
372373
_blockedConsole?: null|SomeChunk<ConsoleEntry>,// DEV-only
@@ -500,7 +501,7 @@ function createErrorChunk<T>(
500501
}
501502

502503
function moveDebugInfoFromChunkToInnerValue<T>(
503-
chunk: InitializedChunk<T>,
504+
chunk: InitializedChunk<T> | InitializedStreamChunk<any>,
504505
value: T,
505506
): void {
506507
// Remove the debug info from the initialized chunk, and add it to the inner
@@ -1569,6 +1570,10 @@ function fulfillReference(
15691570
initializedChunk.reason=handler.reason;// Used by streaming chunks
15701571
if(resolveListeners!==null){
15711572
wakeChunk(resolveListeners,handler.value,initializedChunk);
1573+
}else{
1574+
if(__DEV__){
1575+
moveDebugInfoFromChunkToInnerValue(initializedChunk,handler.value);
1576+
}
15721577
}
15731578
}
15741579
}
@@ -1818,6 +1823,10 @@ function loadServerReference<A: Iterable<any>, T>(
18181823
initializedChunk.value=handler.value;
18191824
if(resolveListeners!==null){
18201825
wakeChunk(resolveListeners,handler.value,initializedChunk);
1826+
}else{
1827+
if(__DEV__){
1828+
moveDebugInfoFromChunkToInnerValue(initializedChunk,handler.value);
1829+
}
18211830
}
18221831
}
18231832
}
@@ -2536,6 +2545,10 @@ function missingCall() {
25362545
);
25372546
}
25382547

2548+
functionmarkIOStarted(this: Response){
2549+
this._debugIOStarted=true;
2550+
}
2551+
25392552
functionResponseInstance(
25402553
this: $FlowFixMe,
25412554
bundlerConfig: ServerConsumerModuleMap,
@@ -2609,6 +2622,10 @@ function ResponseInstance(
26092622
// where as if you use createFromReadableStream from the body of the fetch
26102623
// then the start time is when the headers resolved.
26112624
this._debugStartTime=performance.now();
2625+
this._debugIOStarted=false;
2626+
// We consider everything before the first setTimeout task to be cached data
2627+
// and is not considered I/O required to load the stream.
2628+
setTimeout(markIOStarted.bind(this),0);
26122629
}
26132630
this._debugFindSourceMapURL=findSourceMapURL;
26142631
this._debugChannel=debugChannel;
@@ -2762,7 +2779,7 @@ function incrementChunkDebugInfo(
27622779
}
27632780
}
27642781

2765-
functionaddDebugInfo(chunk: SomeChunk<any>,debugInfo: ReactDebugInfo): void{
2782+
functionaddAsyncInfo(chunk: SomeChunk<any>,asyncInfo: ReactAsyncInfo): void{
27662783
constvalue=resolveLazy(chunk.value);
27672784
if(
27682785
typeofvalue==='object'&&
@@ -2774,34 +2791,39 @@ function addDebugInfo(chunk: SomeChunk<any>, debugInfo: ReactDebugInfo): void {
27742791
){
27752792
if(isArray(value._debugInfo)){
27762793
// $FlowFixMe[method-unbinding]
2777-
value._debugInfo.push.apply(value._debugInfo,debugInfo);
2794+
value._debugInfo.push(asyncInfo);
27782795
}else{
27792796
Object.defineProperty((value: any),'_debugInfo',{
27802797
configurable: false,
27812798
enumerable: false,
27822799
writable: true,
2783-
value: debugInfo,
2800+
value: [asyncInfo],
27842801
});
27852802
}
27862803
}else{
27872804
// $FlowFixMe[method-unbinding]
2788-
chunk._debugInfo.push.apply(chunk._debugInfo,debugInfo);
2805+
chunk._debugInfo.push(asyncInfo);
27892806
}
27902807
}
27912808

27922809
functionresolveChunkDebugInfo(
2810+
response: Response,
27932811
streamState: StreamState,
27942812
chunk: SomeChunk<any>,
27952813
): void{
27962814
if(__DEV__&&enableAsyncDebugInfo){
2797-
// Add the currently resolving chunk's debug info representing the stream
2798-
// to the Promise that was waiting on the stream, or its underlying value.
2799-
constdebugInfo: ReactDebugInfo=[{awaited: streamState._debugInfo}];
2800-
if(chunk.status===PENDING||chunk.status===BLOCKED){
2801-
const boundAddDebugInfo =addDebugInfo.bind(null,chunk,debugInfo);
2802-
chunk.then(boundAddDebugInfo,boundAddDebugInfo);
2803-
}else{
2804-
addDebugInfo(chunk,debugInfo);
2815+
// Only include stream information after a macrotask. Any chunk processed
2816+
// before that is considered cached data.
2817+
if(response._debugIOStarted){
2818+
// Add the currently resolving chunk's debug info representing the stream
2819+
// to the Promise that was waiting on the stream, or its underlying value.
2820+
constasyncInfo: ReactAsyncInfo={awaited: streamState._debugInfo};
2821+
if(chunk.status===PENDING||chunk.status===BLOCKED){
2822+
constboundAddAsyncInfo=addAsyncInfo.bind(null,chunk,asyncInfo);
2823+
chunk.then(boundAddAsyncInfo,boundAddAsyncInfo);
2824+
}else{
2825+
addAsyncInfo(chunk,asyncInfo);
2826+
}
28052827
}
28062828
}
28072829
}
@@ -2837,12 +2859,12 @@ function resolveModel(
28372859
model,
28382860
);
28392861
if(__DEV__){
2840-
resolveChunkDebugInfo(streamState,newChunk);
2862+
resolveChunkDebugInfo(response,streamState,newChunk);
28412863
}
28422864
chunks.set(id,newChunk);
28432865
}else{
28442866
if(__DEV__){
2845-
resolveChunkDebugInfo(streamState,chunk);
2867+
resolveChunkDebugInfo(response,streamState,chunk);
28462868
}
28472869
resolveModelChunk(response,chunk,model);
28482870
}
@@ -2869,7 +2891,7 @@ function resolveText(
28692891
}
28702892
constnewChunk=createInitializedTextChunk(response,text);
28712893
if(__DEV__){
2872-
resolveChunkDebugInfo(streamState,newChunk);
2894+
resolveChunkDebugInfo(response,streamState,newChunk);
28732895
}
28742896
chunks.set(id,newChunk);
28752897
}
@@ -2895,7 +2917,7 @@ function resolveBuffer(
28952917
}
28962918
constnewChunk=createInitializedBufferChunk(response,buffer);
28972919
if(__DEV__){
2898-
resolveChunkDebugInfo(streamState,newChunk);
2920+
resolveChunkDebugInfo(response,streamState,newChunk);
28992921
}
29002922
chunks.set(id,newChunk);
29012923
}
@@ -2942,7 +2964,7 @@ function resolveModule(
29422964
blockedChunk.status=BLOCKED;
29432965
}
29442966
if(__DEV__){
2945-
resolveChunkDebugInfo(streamState,blockedChunk);
2967+
resolveChunkDebugInfo(response,streamState,blockedChunk);
29462968
}
29472969
promise.then(
29482970
()=>resolveModuleChunk(response,blockedChunk,clientReference),
@@ -2952,12 +2974,12 @@ function resolveModule(
29522974
if(!chunk){
29532975
constnewChunk=createResolvedModuleChunk(response,clientReference);
29542976
if(__DEV__){
2955-
resolveChunkDebugInfo(streamState,newChunk);
2977+
resolveChunkDebugInfo(response,streamState,newChunk);
29562978
}
29572979
chunks.set(id,newChunk);
29582980
}else{
29592981
if(__DEV__){
2960-
resolveChunkDebugInfo(streamState,chunk);
2982+
resolveChunkDebugInfo(response,streamState,chunk);
29612983
}
29622984
// This can't actually happen because we don't have any forward
29632985
// references to modules.
@@ -2978,13 +3000,13 @@ function resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(
29783000
if(!chunk){
29793001
constnewChunk=createInitializedStreamChunk(response,stream,controller);
29803002
if(__DEV__){
2981-
resolveChunkDebugInfo(streamState,newChunk);
3003+
resolveChunkDebugInfo(response,streamState,newChunk);
29823004
}
29833005
chunks.set(id,newChunk);
29843006
return;
29853007
}
29863008
if(__DEV__){
2987-
resolveChunkDebugInfo(streamState,chunk);
3009+
resolveChunkDebugInfo(response,streamState,chunk);
29883010
}
29893011
if(chunk.status!==PENDING){
29903012
// We already resolved. We didn't expect to see this.
@@ -3034,6 +3056,10 @@ function resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(
30343056
resolvedChunk.reason = controller;
30353057
if (resolveListeners !== null) {
30363058
wakeChunk(resolveListeners,chunk.value,(chunk: any));
3059+
} else {
3060+
if(__DEV__){
3061+
moveDebugInfoFromChunkToInnerValue(resolvedChunk,stream);
3062+
}
30373063
}
30383064
}
30393065

@@ -3433,12 +3459,12 @@ function resolvePostponeDev(
34333459
postponeInstance,
34343460
);
34353461
if(__DEV__){
3436-
resolveChunkDebugInfo(streamState,newChunk);
3462+
resolveChunkDebugInfo(response,streamState,newChunk);
34373463
}
34383464
chunks.set(id,newChunk);
34393465
}else{
34403466
if(__DEV__){
3441-
resolveChunkDebugInfo(streamState,chunk);
3467+
resolveChunkDebugInfo(response,streamState,chunk);
34423468
}
34433469
triggerErrorOnChunk(response,chunk,postponeInstance);
34443470
}
@@ -3467,12 +3493,12 @@ function resolveErrorModel(
34673493
errorWithDigest,
34683494
);
34693495
if (__DEV__) {
3470-
resolveChunkDebugInfo(streamState,newChunk);
3496+
resolveChunkDebugInfo(response,streamState,newChunk);
34713497
}
34723498
chunks.set(id, newChunk);
34733499
}else{
34743500
if(__DEV__){
3475-
resolveChunkDebugInfo(streamState,chunk);
3501+
resolveChunkDebugInfo(response,streamState,chunk);
34763502
}
34773503
triggerErrorOnChunk(response, chunk, errorWithDigest);
34783504
}

‎packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js‎

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3035,18 +3035,6 @@ describe('ReactFlightDOMBrowser', () => {
30353035
{
30363036
"time": 0,
30373037
},
3038-
{
3039-
"awaited": {
3040-
"byteSize": 0,
3041-
"end": 0,
3042-
"name": "RSC stream",
3043-
"owner": null,
3044-
"start": 0,
3045-
"value": {
3046-
"value": "stream",
3047-
},
3048-
},
3049-
},
30503038
]
30513039
`);
30523040
}

‎packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMEdge-test.js‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,11 +1248,6 @@ describe('ReactFlightDOMEdge', () => {
12481248
owner: greetInfo,
12491249
}),
12501250
{time: 14},
1251-
expect.objectContaining({
1252-
awaited: expect.objectContaining({
1253-
name: 'RSC stream',
1254-
}),
1255-
}),
12561251
]);
12571252
}
12581253
// The owner that created the span was the outer server component.

‎packages/react-server/src/ReactFlightServer.js‎

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2325,9 +2325,15 @@ function visitAsyncNode(
23252325
returnnull;
23262326
}
23272327
visited.add(node);
2328+
if (node.end >=0&&node.end<=request.timeOrigin){
2329+
// This was already resolved when we started this render. It must have been either something
2330+
// that's part of a start up sequence or externally cached data. We exclude that information.
2331+
// The technique for debugging the effects of uncached data on the render is to simply uncache it.
2332+
returnnull;
2333+
}
23282334
let previousIONode = null;
23292335
// First visit anything that blocked this sequence to start in the first place.
2330-
if (node.previous !== null&&node.end>request.timeOrigin){
2336+
if (node.previous !== null) {
23312337
previousIONode=visitAsyncNode(
23322338
request,
23332339
task,
@@ -2349,12 +2355,6 @@ function visitAsyncNode(
23492355
returnpreviousIONode;
23502356
}
23512357
case PROMISE_NODE: {
2352-
if(node.end<=request.timeOrigin){
2353-
// This was already resolved when we started this render. It must have been either something
2354-
// that's part of a start up sequence or externally cached data. We exclude that information.
2355-
// The technique for debugging the effects of uncached data on the render is to simply uncache it.
2356-
returnpreviousIONode;
2357-
}
23582358
constawaited=node.awaited;
23592359
letmatch: void|null|PromiseNode|IONode=previousIONode;
23602360
constpromise=node.promise.deref();
@@ -2437,11 +2437,7 @@ function visitAsyncNode(
24372437
}elseif(ioNode!==null){
24382438
conststartTime: number=node.start;
24392439
constendTime: number=node.end;
2440-
if(endTime<=request.timeOrigin){
2441-
// This was already resolved when we started this render. It must have been either something
2442-
// that's part of a start up sequence or externally cached data. We exclude that information.
2443-
return null;
2444-
}elseif(startTime<cutOff){
2440+
if(startTime<cutOff){
24452441
// We started awaiting this node before we started rendering this sequence.
24462442
// This means that this particular await was never part of the current sequence.
24472443
// If we have another await higher up in the chain it might have a more actionable stack

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
[Flight] Exclude RSC Stream if the stream resolves in a task (#34838) · react/react@56e8469 · GitHub
Skip to content

Commit 56e8469

Browse files
authored
[Flight] Exclude RSC Stream if the stream resolves in a task (#34838)
1 parent 19b7167 commit 56e8469

5 files changed

Lines changed: 236 additions & 267 deletions

File tree

‎packages/react-client/src/ReactFlightClient.js‎

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ type Response = {
367367
_debugRootStack?: null|Error,// DEV-only
368368
_debugRootTask?: null|ConsoleTask,// DEV-only
369369
_debugStartTime: number,// DEV-only
370+
_debugIOStarted: boolean,// DEV-only
370371
_debugFindSourceMapURL?: void|FindSourceMapURLCallback,// DEV-only
371372
_debugChannel?: void|DebugChannel,// DEV-only
372373
_blockedConsole?: null|SomeChunk<ConsoleEntry>,// DEV-only
@@ -500,7 +501,7 @@ function createErrorChunk<T>(
500501
}
501502

502503
function moveDebugInfoFromChunkToInnerValue<T>(
503-
chunk: InitializedChunk<T>,
504+
chunk: InitializedChunk<T> | InitializedStreamChunk<any>,
504505
value: T,
505506
): void {
506507
// Remove the debug info from the initialized chunk, and add it to the inner
@@ -1569,6 +1570,10 @@ function fulfillReference(
15691570
initializedChunk.reason=handler.reason;// Used by streaming chunks
15701571
if(resolveListeners!==null){
15711572
wakeChunk(resolveListeners,handler.value,initializedChunk);
1573+
}else{
1574+
if(__DEV__){
1575+
moveDebugInfoFromChunkToInnerValue(initializedChunk,handler.value);
1576+
}
15721577
}
15731578
}
15741579
}
@@ -1818,6 +1823,10 @@ function loadServerReference<A: Iterable<any>, T>(
18181823
initializedChunk.value=handler.value;
18191824
if(resolveListeners!==null){
18201825
wakeChunk(resolveListeners,handler.value,initializedChunk);
1826+
}else{
1827+
if(__DEV__){
1828+
moveDebugInfoFromChunkToInnerValue(initializedChunk,handler.value);
1829+
}
18211830
}
18221831
}
18231832
}
@@ -2536,6 +2545,10 @@ function missingCall() {
25362545
);
25372546
}
25382547

2548+
functionmarkIOStarted(this: Response){
2549+
this._debugIOStarted=true;
2550+
}
2551+
25392552
functionResponseInstance(
25402553
this: $FlowFixMe,
25412554
bundlerConfig: ServerConsumerModuleMap,
@@ -2609,6 +2622,10 @@ function ResponseInstance(
26092622
// where as if you use createFromReadableStream from the body of the fetch
26102623
// then the start time is when the headers resolved.
26112624
this._debugStartTime=performance.now();
2625+
this._debugIOStarted=false;
2626+
// We consider everything before the first setTimeout task to be cached data
2627+
// and is not considered I/O required to load the stream.
2628+
setTimeout(markIOStarted.bind(this),0);
26122629
}
26132630
this._debugFindSourceMapURL=findSourceMapURL;
26142631
this._debugChannel=debugChannel;
@@ -2762,7 +2779,7 @@ function incrementChunkDebugInfo(
27622779
}
27632780
}
27642781

2765-
functionaddDebugInfo(chunk: SomeChunk<any>,debugInfo: ReactDebugInfo): void{
2782+
functionaddAsyncInfo(chunk: SomeChunk<any>,asyncInfo: ReactAsyncInfo): void{
27662783
constvalue=resolveLazy(chunk.value);
27672784
if(
27682785
typeofvalue==='object'&&
@@ -2774,34 +2791,39 @@ function addDebugInfo(chunk: SomeChunk<any>, debugInfo: ReactDebugInfo): void {
27742791
){
27752792
if(isArray(value._debugInfo)){
27762793
// $FlowFixMe[method-unbinding]
2777-
value._debugInfo.push.apply(value._debugInfo,debugInfo);
2794+
value._debugInfo.push(asyncInfo);
27782795
}else{
27792796
Object.defineProperty((value: any),'_debugInfo',{
27802797
configurable: false,
27812798
enumerable: false,
27822799
writable: true,
2783-
value: debugInfo,
2800+
value: [asyncInfo],
27842801
});
27852802
}
27862803
}else{
27872804
// $FlowFixMe[method-unbinding]
2788-
chunk._debugInfo.push.apply(chunk._debugInfo,debugInfo);
2805+
chunk._debugInfo.push(asyncInfo);
27892806
}
27902807
}
27912808

27922809
functionresolveChunkDebugInfo(
2810+
response: Response,
27932811
streamState: StreamState,
27942812
chunk: SomeChunk<any>,
27952813
): void{
27962814
if(__DEV__&&enableAsyncDebugInfo){
2797-
// Add the currently resolving chunk's debug info representing the stream
2798-
// to the Promise that was waiting on the stream, or its underlying value.
2799-
constdebugInfo: ReactDebugInfo=[{awaited: streamState._debugInfo}];
2800-
if(chunk.status===PENDING||chunk.status===BLOCKED){
2801-
const boundAddDebugInfo =addDebugInfo.bind(null,chunk,debugInfo);
2802-
chunk.then(boundAddDebugInfo,boundAddDebugInfo);
2803-
}else{
2804-
addDebugInfo(chunk,debugInfo);
2815+
// Only include stream information after a macrotask. Any chunk processed
2816+
// before that is considered cached data.
2817+
if(response._debugIOStarted){
2818+
// Add the currently resolving chunk's debug info representing the stream
2819+
// to the Promise that was waiting on the stream, or its underlying value.
2820+
constasyncInfo: ReactAsyncInfo={awaited: streamState._debugInfo};
2821+
if(chunk.status===PENDING||chunk.status===BLOCKED){
2822+
constboundAddAsyncInfo=addAsyncInfo.bind(null,chunk,asyncInfo);
2823+
chunk.then(boundAddAsyncInfo,boundAddAsyncInfo);
2824+
}else{
2825+
addAsyncInfo(chunk,asyncInfo);
2826+
}
28052827
}
28062828
}
28072829
}
@@ -2837,12 +2859,12 @@ function resolveModel(
28372859
model,
28382860
);
28392861
if(__DEV__){
2840-
resolveChunkDebugInfo(streamState,newChunk);
2862+
resolveChunkDebugInfo(response,streamState,newChunk);
28412863
}
28422864
chunks.set(id,newChunk);
28432865
}else{
28442866
if(__DEV__){
2845-
resolveChunkDebugInfo(streamState,chunk);
2867+
resolveChunkDebugInfo(response,streamState,chunk);
28462868
}
28472869
resolveModelChunk(response,chunk,model);
28482870
}
@@ -2869,7 +2891,7 @@ function resolveText(
28692891
}
28702892
constnewChunk=createInitializedTextChunk(response,text);
28712893
if(__DEV__){
2872-
resolveChunkDebugInfo(streamState,newChunk);
2894+
resolveChunkDebugInfo(response,streamState,newChunk);
28732895
}
28742896
chunks.set(id,newChunk);
28752897
}
@@ -2895,7 +2917,7 @@ function resolveBuffer(
28952917
}
28962918
constnewChunk=createInitializedBufferChunk(response,buffer);
28972919
if(__DEV__){
2898-
resolveChunkDebugInfo(streamState,newChunk);
2920+
resolveChunkDebugInfo(response,streamState,newChunk);
28992921
}
29002922
chunks.set(id,newChunk);
29012923
}
@@ -2942,7 +2964,7 @@ function resolveModule(
29422964
blockedChunk.status=BLOCKED;
29432965
}
29442966
if(__DEV__){
2945-
resolveChunkDebugInfo(streamState,blockedChunk);
2967+
resolveChunkDebugInfo(response,streamState,blockedChunk);
29462968
}
29472969
promise.then(
29482970
()=>resolveModuleChunk(response,blockedChunk,clientReference),
@@ -2952,12 +2974,12 @@ function resolveModule(
29522974
if(!chunk){
29532975
constnewChunk=createResolvedModuleChunk(response,clientReference);
29542976
if(__DEV__){
2955-
resolveChunkDebugInfo(streamState,newChunk);
2977+
resolveChunkDebugInfo(response,streamState,newChunk);
29562978
}
29572979
chunks.set(id,newChunk);
29582980
}else{
29592981
if(__DEV__){
2960-
resolveChunkDebugInfo(streamState,chunk);
2982+
resolveChunkDebugInfo(response,streamState,chunk);
29612983
}
29622984
// This can't actually happen because we don't have any forward
29632985
// references to modules.
@@ -2978,13 +3000,13 @@ function resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(
29783000
if(!chunk){
29793001
constnewChunk=createInitializedStreamChunk(response,stream,controller);
29803002
if(__DEV__){
2981-
resolveChunkDebugInfo(streamState,newChunk);
3003+
resolveChunkDebugInfo(response,streamState,newChunk);
29823004
}
29833005
chunks.set(id,newChunk);
29843006
return;
29853007
}
29863008
if(__DEV__){
2987-
resolveChunkDebugInfo(streamState,chunk);
3009+
resolveChunkDebugInfo(response,streamState,chunk);
29883010
}
29893011
if(chunk.status!==PENDING){
29903012
// We already resolved. We didn't expect to see this.
@@ -3034,6 +3056,10 @@ function resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(
30343056
resolvedChunk.reason = controller;
30353057
if (resolveListeners !== null) {
30363058
wakeChunk(resolveListeners,chunk.value,(chunk: any));
3059+
} else {
3060+
if(__DEV__){
3061+
moveDebugInfoFromChunkToInnerValue(resolvedChunk,stream);
3062+
}
30373063
}
30383064
}
30393065

@@ -3433,12 +3459,12 @@ function resolvePostponeDev(
34333459
postponeInstance,
34343460
);
34353461
if(__DEV__){
3436-
resolveChunkDebugInfo(streamState,newChunk);
3462+
resolveChunkDebugInfo(response,streamState,newChunk);
34373463
}
34383464
chunks.set(id,newChunk);
34393465
}else{
34403466
if(__DEV__){
3441-
resolveChunkDebugInfo(streamState,chunk);
3467+
resolveChunkDebugInfo(response,streamState,chunk);
34423468
}
34433469
triggerErrorOnChunk(response,chunk,postponeInstance);
34443470
}
@@ -3467,12 +3493,12 @@ function resolveErrorModel(
34673493
errorWithDigest,
34683494
);
34693495
if (__DEV__) {
3470-
resolveChunkDebugInfo(streamState,newChunk);
3496+
resolveChunkDebugInfo(response,streamState,newChunk);
34713497
}
34723498
chunks.set(id, newChunk);
34733499
}else{
34743500
if(__DEV__){
3475-
resolveChunkDebugInfo(streamState,chunk);
3501+
resolveChunkDebugInfo(response,streamState,chunk);
34763502
}
34773503
triggerErrorOnChunk(response, chunk, errorWithDigest);
34783504
}

‎packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js‎

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3035,18 +3035,6 @@ describe('ReactFlightDOMBrowser', () => {
30353035
{
30363036
"time": 0,
30373037
},
3038-
{
3039-
"awaited": {
3040-
"byteSize": 0,
3041-
"end": 0,
3042-
"name": "RSC stream",
3043-
"owner": null,
3044-
"start": 0,
3045-
"value": {
3046-
"value": "stream",
3047-
},
3048-
},
3049-
},
30503038
]
30513039
`);
30523040
}

‎packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMEdge-test.js‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,11 +1248,6 @@ describe('ReactFlightDOMEdge', () => {
12481248
owner: greetInfo,
12491249
}),
12501250
{time: 14},
1251-
expect.objectContaining({
1252-
awaited: expect.objectContaining({
1253-
name: 'RSC stream',
1254-
}),
1255-
}),
12561251
]);
12571252
}
12581253
// The owner that created the span was the outer server component.

‎packages/react-server/src/ReactFlightServer.js‎

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2325,9 +2325,15 @@ function visitAsyncNode(
23252325
returnnull;
23262326
}
23272327
visited.add(node);
2328+
if (node.end >=0&&node.end<=request.timeOrigin){
2329+
// This was already resolved when we started this render. It must have been either something
2330+
// that's part of a start up sequence or externally cached data. We exclude that information.
2331+
// The technique for debugging the effects of uncached data on the render is to simply uncache it.
2332+
returnnull;
2333+
}
23282334
let previousIONode = null;
23292335
// First visit anything that blocked this sequence to start in the first place.
2330-
if (node.previous !== null&&node.end>request.timeOrigin){
2336+
if (node.previous !== null) {
23312337
previousIONode=visitAsyncNode(
23322338
request,
23332339
task,
@@ -2349,12 +2355,6 @@ function visitAsyncNode(
23492355
returnpreviousIONode;
23502356
}
23512357
case PROMISE_NODE: {
2352-
if(node.end<=request.timeOrigin){
2353-
// This was already resolved when we started this render. It must have been either something
2354-
// that's part of a start up sequence or externally cached data. We exclude that information.
2355-
// The technique for debugging the effects of uncached data on the render is to simply uncache it.
2356-
returnpreviousIONode;
2357-
}
23582358
constawaited=node.awaited;
23592359
letmatch: void|null|PromiseNode|IONode=previousIONode;
23602360
constpromise=node.promise.deref();
@@ -2437,11 +2437,7 @@ function visitAsyncNode(
24372437
}elseif(ioNode!==null){
24382438
conststartTime: number=node.start;
24392439
constendTime: number=node.end;
2440-
if(endTime<=request.timeOrigin){
2441-
// This was already resolved when we started this render. It must have been either something
2442-
// that's part of a start up sequence or externally cached data. We exclude that information.
2443-
return null;
2444-
}elseif(startTime<cutOff){
2440+
if(startTime<cutOff){
24452441
// We started awaiting this node before we started rendering this sequence.
24462442
// This means that this particular await was never part of the current sequence.
24472443
// If we have another await higher up in the chain it might have a more actionable stack

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' [Flight] Exclude RSC Stream if the stream resolves in a task (#34838) · react/react@56e8469 · GitHub
Skip to content

Commit 56e8469

Browse files
authored
[Flight] Exclude RSC Stream if the stream resolves in a task (#34838)
1 parent 19b7167 commit 56e8469

5 files changed

Lines changed: 236 additions & 267 deletions

File tree

‎packages/react-client/src/ReactFlightClient.js‎

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ type Response = {
367367
_debugRootStack?: null|Error,// DEV-only
368368
_debugRootTask?: null|ConsoleTask,// DEV-only
369369
_debugStartTime: number,// DEV-only
370+
_debugIOStarted: boolean,// DEV-only
370371
_debugFindSourceMapURL?: void|FindSourceMapURLCallback,// DEV-only
371372
_debugChannel?: void|DebugChannel,// DEV-only
372373
_blockedConsole?: null|SomeChunk<ConsoleEntry>,// DEV-only
@@ -500,7 +501,7 @@ function createErrorChunk<T>(
500501
}
501502

502503
function moveDebugInfoFromChunkToInnerValue<T>(
503-
chunk: InitializedChunk<T>,
504+
chunk: InitializedChunk<T> | InitializedStreamChunk<any>,
504505
value: T,
505506
): void {
506507
// Remove the debug info from the initialized chunk, and add it to the inner
@@ -1569,6 +1570,10 @@ function fulfillReference(
15691570
initializedChunk.reason=handler.reason;// Used by streaming chunks
15701571
if(resolveListeners!==null){
15711572
wakeChunk(resolveListeners,handler.value,initializedChunk);
1573+
}else{
1574+
if(__DEV__){
1575+
moveDebugInfoFromChunkToInnerValue(initializedChunk,handler.value);
1576+
}
15721577
}
15731578
}
15741579
}
@@ -1818,6 +1823,10 @@ function loadServerReference<A: Iterable<any>, T>(
18181823
initializedChunk.value=handler.value;
18191824
if(resolveListeners!==null){
18201825
wakeChunk(resolveListeners,handler.value,initializedChunk);
1826+
}else{
1827+
if(__DEV__){
1828+
moveDebugInfoFromChunkToInnerValue(initializedChunk,handler.value);
1829+
}
18211830
}
18221831
}
18231832
}
@@ -2536,6 +2545,10 @@ function missingCall() {
25362545
);
25372546
}
25382547

2548+
functionmarkIOStarted(this: Response){
2549+
this._debugIOStarted=true;
2550+
}
2551+
25392552
functionResponseInstance(
25402553
this: $FlowFixMe,
25412554
bundlerConfig: ServerConsumerModuleMap,
@@ -2609,6 +2622,10 @@ function ResponseInstance(
26092622
// where as if you use createFromReadableStream from the body of the fetch
26102623
// then the start time is when the headers resolved.
26112624
this._debugStartTime=performance.now();
2625+
this._debugIOStarted=false;
2626+
// We consider everything before the first setTimeout task to be cached data
2627+
// and is not considered I/O required to load the stream.
2628+
setTimeout(markIOStarted.bind(this),0);
26122629
}
26132630
this._debugFindSourceMapURL=findSourceMapURL;
26142631
this._debugChannel=debugChannel;
@@ -2762,7 +2779,7 @@ function incrementChunkDebugInfo(
27622779
}
27632780
}
27642781

2765-
functionaddDebugInfo(chunk: SomeChunk<any>,debugInfo: ReactDebugInfo): void{
2782+
functionaddAsyncInfo(chunk: SomeChunk<any>,asyncInfo: ReactAsyncInfo): void{
27662783
constvalue=resolveLazy(chunk.value);
27672784
if(
27682785
typeofvalue==='object'&&
@@ -2774,34 +2791,39 @@ function addDebugInfo(chunk: SomeChunk<any>, debugInfo: ReactDebugInfo): void {
27742791
){
27752792
if(isArray(value._debugInfo)){
27762793
// $FlowFixMe[method-unbinding]
2777-
value._debugInfo.push.apply(value._debugInfo,debugInfo);
2794+
value._debugInfo.push(asyncInfo);
27782795
}else{
27792796
Object.defineProperty((value: any),'_debugInfo',{
27802797
configurable: false,
27812798
enumerable: false,
27822799
writable: true,
2783-
value: debugInfo,
2800+
value: [asyncInfo],
27842801
});
27852802
}
27862803
}else{
27872804
// $FlowFixMe[method-unbinding]
2788-
chunk._debugInfo.push.apply(chunk._debugInfo,debugInfo);
2805+
chunk._debugInfo.push(asyncInfo);
27892806
}
27902807
}
27912808

27922809
functionresolveChunkDebugInfo(
2810+
response: Response,
27932811
streamState: StreamState,
27942812
chunk: SomeChunk<any>,
27952813
): void{
27962814
if(__DEV__&&enableAsyncDebugInfo){
2797-
// Add the currently resolving chunk's debug info representing the stream
2798-
// to the Promise that was waiting on the stream, or its underlying value.
2799-
constdebugInfo: ReactDebugInfo=[{awaited: streamState._debugInfo}];
2800-
if(chunk.status===PENDING||chunk.status===BLOCKED){
2801-
const boundAddDebugInfo =addDebugInfo.bind(null,chunk,debugInfo);
2802-
chunk.then(boundAddDebugInfo,boundAddDebugInfo);
2803-
}else{
2804-
addDebugInfo(chunk,debugInfo);
2815+
// Only include stream information after a macrotask. Any chunk processed
2816+
// before that is considered cached data.
2817+
if(response._debugIOStarted){
2818+
// Add the currently resolving chunk's debug info representing the stream
2819+
// to the Promise that was waiting on the stream, or its underlying value.
2820+
constasyncInfo: ReactAsyncInfo={awaited: streamState._debugInfo};
2821+
if(chunk.status===PENDING||chunk.status===BLOCKED){
2822+
constboundAddAsyncInfo=addAsyncInfo.bind(null,chunk,asyncInfo);
2823+
chunk.then(boundAddAsyncInfo,boundAddAsyncInfo);
2824+
}else{
2825+
addAsyncInfo(chunk,asyncInfo);
2826+
}
28052827
}
28062828
}
28072829
}
@@ -2837,12 +2859,12 @@ function resolveModel(
28372859
model,
28382860
);
28392861
if(__DEV__){
2840-
resolveChunkDebugInfo(streamState,newChunk);
2862+
resolveChunkDebugInfo(response,streamState,newChunk);
28412863
}
28422864
chunks.set(id,newChunk);
28432865
}else{
28442866
if(__DEV__){
2845-
resolveChunkDebugInfo(streamState,chunk);
2867+
resolveChunkDebugInfo(response,streamState,chunk);
28462868
}
28472869
resolveModelChunk(response,chunk,model);
28482870
}
@@ -2869,7 +2891,7 @@ function resolveText(
28692891
}
28702892
constnewChunk=createInitializedTextChunk(response,text);
28712893
if(__DEV__){
2872-
resolveChunkDebugInfo(streamState,newChunk);
2894+
resolveChunkDebugInfo(response,streamState,newChunk);
28732895
}
28742896
chunks.set(id,newChunk);
28752897
}
@@ -2895,7 +2917,7 @@ function resolveBuffer(
28952917
}
28962918
constnewChunk=createInitializedBufferChunk(response,buffer);
28972919
if(__DEV__){
2898-
resolveChunkDebugInfo(streamState,newChunk);
2920+
resolveChunkDebugInfo(response,streamState,newChunk);
28992921
}
29002922
chunks.set(id,newChunk);
29012923
}
@@ -2942,7 +2964,7 @@ function resolveModule(
29422964
blockedChunk.status=BLOCKED;
29432965
}
29442966
if(__DEV__){
2945-
resolveChunkDebugInfo(streamState,blockedChunk);
2967+
resolveChunkDebugInfo(response,streamState,blockedChunk);
29462968
}
29472969
promise.then(
29482970
()=>resolveModuleChunk(response,blockedChunk,clientReference),
@@ -2952,12 +2974,12 @@ function resolveModule(
29522974
if(!chunk){
29532975
constnewChunk=createResolvedModuleChunk(response,clientReference);
29542976
if(__DEV__){
2955-
resolveChunkDebugInfo(streamState,newChunk);
2977+
resolveChunkDebugInfo(response,streamState,newChunk);
29562978
}
29572979
chunks.set(id,newChunk);
29582980
}else{
29592981
if(__DEV__){
2960-
resolveChunkDebugInfo(streamState,chunk);
2982+
resolveChunkDebugInfo(response,streamState,chunk);
29612983
}
29622984
// This can't actually happen because we don't have any forward
29632985
// references to modules.
@@ -2978,13 +3000,13 @@ function resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(
29783000
if(!chunk){
29793001
constnewChunk=createInitializedStreamChunk(response,stream,controller);
29803002
if(__DEV__){
2981-
resolveChunkDebugInfo(streamState,newChunk);
3003+
resolveChunkDebugInfo(response,streamState,newChunk);
29823004
}
29833005
chunks.set(id,newChunk);
29843006
return;
29853007
}
29863008
if(__DEV__){
2987-
resolveChunkDebugInfo(streamState,chunk);
3009+
resolveChunkDebugInfo(response,streamState,chunk);
29883010
}
29893011
if(chunk.status!==PENDING){
29903012
// We already resolved. We didn't expect to see this.
@@ -3034,6 +3056,10 @@ function resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(
30343056
resolvedChunk.reason = controller;
30353057
if (resolveListeners !== null) {
30363058
wakeChunk(resolveListeners,chunk.value,(chunk: any));
3059+
} else {
3060+
if(__DEV__){
3061+
moveDebugInfoFromChunkToInnerValue(resolvedChunk,stream);
3062+
}
30373063
}
30383064
}
30393065

@@ -3433,12 +3459,12 @@ function resolvePostponeDev(
34333459
postponeInstance,
34343460
);
34353461
if(__DEV__){
3436-
resolveChunkDebugInfo(streamState,newChunk);
3462+
resolveChunkDebugInfo(response,streamState,newChunk);
34373463
}
34383464
chunks.set(id,newChunk);
34393465
}else{
34403466
if(__DEV__){
3441-
resolveChunkDebugInfo(streamState,chunk);
3467+
resolveChunkDebugInfo(response,streamState,chunk);
34423468
}
34433469
triggerErrorOnChunk(response,chunk,postponeInstance);
34443470
}
@@ -3467,12 +3493,12 @@ function resolveErrorModel(
34673493
errorWithDigest,
34683494
);
34693495
if (__DEV__) {
3470-
resolveChunkDebugInfo(streamState,newChunk);
3496+
resolveChunkDebugInfo(response,streamState,newChunk);
34713497
}
34723498
chunks.set(id, newChunk);
34733499
}else{
34743500
if(__DEV__){
3475-
resolveChunkDebugInfo(streamState,chunk);
3501+
resolveChunkDebugInfo(response,streamState,chunk);
34763502
}
34773503
triggerErrorOnChunk(response, chunk, errorWithDigest);
34783504
}

‎packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js‎

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3035,18 +3035,6 @@ describe('ReactFlightDOMBrowser', () => {
30353035
{
30363036
"time": 0,
30373037
},
3038-
{
3039-
"awaited": {
3040-
"byteSize": 0,
3041-
"end": 0,
3042-
"name": "RSC stream",
3043-
"owner": null,
3044-
"start": 0,
3045-
"value": {
3046-
"value": "stream",
3047-
},
3048-
},
3049-
},
30503038
]
30513039
`);
30523040
}

‎packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMEdge-test.js‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,11 +1248,6 @@ describe('ReactFlightDOMEdge', () => {
12481248
owner: greetInfo,
12491249
}),
12501250
{time: 14},
1251-
expect.objectContaining({
1252-
awaited: expect.objectContaining({
1253-
name: 'RSC stream',
1254-
}),
1255-
}),
12561251
]);
12571252
}
12581253
// The owner that created the span was the outer server component.

‎packages/react-server/src/ReactFlightServer.js‎

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2325,9 +2325,15 @@ function visitAsyncNode(
23252325
returnnull;
23262326
}
23272327
visited.add(node);
2328+
if (node.end >=0&&node.end<=request.timeOrigin){
2329+
// This was already resolved when we started this render. It must have been either something
2330+
// that's part of a start up sequence or externally cached data. We exclude that information.
2331+
// The technique for debugging the effects of uncached data on the render is to simply uncache it.
2332+
returnnull;
2333+
}
23282334
let previousIONode = null;
23292335
// First visit anything that blocked this sequence to start in the first place.
2330-
if (node.previous !== null&&node.end>request.timeOrigin){
2336+
if (node.previous !== null) {
23312337
previousIONode=visitAsyncNode(
23322338
request,
23332339
task,
@@ -2349,12 +2355,6 @@ function visitAsyncNode(
23492355
returnpreviousIONode;
23502356
}
23512357
case PROMISE_NODE: {
2352-
if(node.end<=request.timeOrigin){
2353-
// This was already resolved when we started this render. It must have been either something
2354-
// that's part of a start up sequence or externally cached data. We exclude that information.
2355-
// The technique for debugging the effects of uncached data on the render is to simply uncache it.
2356-
returnpreviousIONode;
2357-
}
23582358
constawaited=node.awaited;
23592359
letmatch: void|null|PromiseNode|IONode=previousIONode;
23602360
constpromise=node.promise.deref();
@@ -2437,11 +2437,7 @@ function visitAsyncNode(
24372437
}elseif(ioNode!==null){
24382438
conststartTime: number=node.start;
24392439
constendTime: number=node.end;
2440-
if(endTime<=request.timeOrigin){
2441-
// This was already resolved when we started this render. It must have been either something
2442-
// that's part of a start up sequence or externally cached data. We exclude that information.
2443-
return null;
2444-
}elseif(startTime<cutOff){
2440+
if(startTime<cutOff){
24452441
// We started awaiting this node before we started rendering this sequence.
24462442
// This means that this particular await was never part of the current sequence.
24472443
// If we have another await higher up in the chain it might have a more actionable stack

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' [Flight] Exclude RSC Stream if the stream resolves in a task (#34838) · react/react@56e8469 · GitHub
Skip to content

Commit 56e8469

Browse files
authored
[Flight] Exclude RSC Stream if the stream resolves in a task (#34838)
1 parent 19b7167 commit 56e8469

5 files changed

Lines changed: 236 additions & 267 deletions

File tree

‎packages/react-client/src/ReactFlightClient.js‎

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ type Response = {
367367
_debugRootStack?: null|Error,// DEV-only
368368
_debugRootTask?: null|ConsoleTask,// DEV-only
369369
_debugStartTime: number,// DEV-only
370+
_debugIOStarted: boolean,// DEV-only
370371
_debugFindSourceMapURL?: void|FindSourceMapURLCallback,// DEV-only
371372
_debugChannel?: void|DebugChannel,// DEV-only
372373
_blockedConsole?: null|SomeChunk<ConsoleEntry>,// DEV-only
@@ -500,7 +501,7 @@ function createErrorChunk<T>(
500501
}
501502

502503
function moveDebugInfoFromChunkToInnerValue<T>(
503-
chunk: InitializedChunk<T>,
504+
chunk: InitializedChunk<T> | InitializedStreamChunk<any>,
504505
value: T,
505506
): void {
506507
// Remove the debug info from the initialized chunk, and add it to the inner
@@ -1569,6 +1570,10 @@ function fulfillReference(
15691570
initializedChunk.reason=handler.reason;// Used by streaming chunks
15701571
if(resolveListeners!==null){
15711572
wakeChunk(resolveListeners,handler.value,initializedChunk);
1573+
}else{
1574+
if(__DEV__){
1575+
moveDebugInfoFromChunkToInnerValue(initializedChunk,handler.value);
1576+
}
15721577
}
15731578
}
15741579
}
@@ -1818,6 +1823,10 @@ function loadServerReference<A: Iterable<any>, T>(
18181823
initializedChunk.value=handler.value;
18191824
if(resolveListeners!==null){
18201825
wakeChunk(resolveListeners,handler.value,initializedChunk);
1826+
}else{
1827+
if(__DEV__){
1828+
moveDebugInfoFromChunkToInnerValue(initializedChunk,handler.value);
1829+
}
18211830
}
18221831
}
18231832
}
@@ -2536,6 +2545,10 @@ function missingCall() {
25362545
);
25372546
}
25382547

2548+
functionmarkIOStarted(this: Response){
2549+
this._debugIOStarted=true;
2550+
}
2551+
25392552
functionResponseInstance(
25402553
this: $FlowFixMe,
25412554
bundlerConfig: ServerConsumerModuleMap,
@@ -2609,6 +2622,10 @@ function ResponseInstance(
26092622
// where as if you use createFromReadableStream from the body of the fetch
26102623
// then the start time is when the headers resolved.
26112624
this._debugStartTime=performance.now();
2625+
this._debugIOStarted=false;
2626+
// We consider everything before the first setTimeout task to be cached data
2627+
// and is not considered I/O required to load the stream.
2628+
setTimeout(markIOStarted.bind(this),0);
26122629
}
26132630
this._debugFindSourceMapURL=findSourceMapURL;
26142631
this._debugChannel=debugChannel;
@@ -2762,7 +2779,7 @@ function incrementChunkDebugInfo(
27622779
}
27632780
}
27642781

2765-
functionaddDebugInfo(chunk: SomeChunk<any>,debugInfo: ReactDebugInfo): void{
2782+
functionaddAsyncInfo(chunk: SomeChunk<any>,asyncInfo: ReactAsyncInfo): void{
27662783
constvalue=resolveLazy(chunk.value);
27672784
if(
27682785
typeofvalue==='object'&&
@@ -2774,34 +2791,39 @@ function addDebugInfo(chunk: SomeChunk<any>, debugInfo: ReactDebugInfo): void {
27742791
){
27752792
if(isArray(value._debugInfo)){
27762793
// $FlowFixMe[method-unbinding]
2777-
value._debugInfo.push.apply(value._debugInfo,debugInfo);
2794+
value._debugInfo.push(asyncInfo);
27782795
}else{
27792796
Object.defineProperty((value: any),'_debugInfo',{
27802797
configurable: false,
27812798
enumerable: false,
27822799
writable: true,
2783-
value: debugInfo,
2800+
value: [asyncInfo],
27842801
});
27852802
}
27862803
}else{
27872804
// $FlowFixMe[method-unbinding]
2788-
chunk._debugInfo.push.apply(chunk._debugInfo,debugInfo);
2805+
chunk._debugInfo.push(asyncInfo);
27892806
}
27902807
}
27912808

27922809
functionresolveChunkDebugInfo(
2810+
response: Response,
27932811
streamState: StreamState,
27942812
chunk: SomeChunk<any>,
27952813
): void{
27962814
if(__DEV__&&enableAsyncDebugInfo){
2797-
// Add the currently resolving chunk's debug info representing the stream
2798-
// to the Promise that was waiting on the stream, or its underlying value.
2799-
constdebugInfo: ReactDebugInfo=[{awaited: streamState._debugInfo}];
2800-
if(chunk.status===PENDING||chunk.status===BLOCKED){
2801-
const boundAddDebugInfo =addDebugInfo.bind(null,chunk,debugInfo);
2802-
chunk.then(boundAddDebugInfo,boundAddDebugInfo);
2803-
}else{
2804-
addDebugInfo(chunk,debugInfo);
2815+
// Only include stream information after a macrotask. Any chunk processed
2816+
// before that is considered cached data.
2817+
if(response._debugIOStarted){
2818+
// Add the currently resolving chunk's debug info representing the stream
2819+
// to the Promise that was waiting on the stream, or its underlying value.
2820+
constasyncInfo: ReactAsyncInfo={awaited: streamState._debugInfo};
2821+
if(chunk.status===PENDING||chunk.status===BLOCKED){
2822+
constboundAddAsyncInfo=addAsyncInfo.bind(null,chunk,asyncInfo);
2823+
chunk.then(boundAddAsyncInfo,boundAddAsyncInfo);
2824+
}else{
2825+
addAsyncInfo(chunk,asyncInfo);
2826+
}
28052827
}
28062828
}
28072829
}
@@ -2837,12 +2859,12 @@ function resolveModel(
28372859
model,
28382860
);
28392861
if(__DEV__){
2840-
resolveChunkDebugInfo(streamState,newChunk);
2862+
resolveChunkDebugInfo(response,streamState,newChunk);
28412863
}
28422864
chunks.set(id,newChunk);
28432865
}else{
28442866
if(__DEV__){
2845-
resolveChunkDebugInfo(streamState,chunk);
2867+
resolveChunkDebugInfo(response,streamState,chunk);
28462868
}
28472869
resolveModelChunk(response,chunk,model);
28482870
}
@@ -2869,7 +2891,7 @@ function resolveText(
28692891
}
28702892
constnewChunk=createInitializedTextChunk(response,text);
28712893
if(__DEV__){
2872-
resolveChunkDebugInfo(streamState,newChunk);
2894+
resolveChunkDebugInfo(response,streamState,newChunk);
28732895
}
28742896
chunks.set(id,newChunk);
28752897
}
@@ -2895,7 +2917,7 @@ function resolveBuffer(
28952917
}
28962918
constnewChunk=createInitializedBufferChunk(response,buffer);
28972919
if(__DEV__){
2898-
resolveChunkDebugInfo(streamState,newChunk);
2920+
resolveChunkDebugInfo(response,streamState,newChunk);
28992921
}
29002922
chunks.set(id,newChunk);
29012923
}
@@ -2942,7 +2964,7 @@ function resolveModule(
29422964
blockedChunk.status=BLOCKED;
29432965
}
29442966
if(__DEV__){
2945-
resolveChunkDebugInfo(streamState,blockedChunk);
2967+
resolveChunkDebugInfo(response,streamState,blockedChunk);
29462968
}
29472969
promise.then(
29482970
()=>resolveModuleChunk(response,blockedChunk,clientReference),
@@ -2952,12 +2974,12 @@ function resolveModule(
29522974
if(!chunk){
29532975
constnewChunk=createResolvedModuleChunk(response,clientReference);
29542976
if(__DEV__){
2955-
resolveChunkDebugInfo(streamState,newChunk);
2977+
resolveChunkDebugInfo(response,streamState,newChunk);
29562978
}
29572979
chunks.set(id,newChunk);
29582980
}else{
29592981
if(__DEV__){
2960-
resolveChunkDebugInfo(streamState,chunk);
2982+
resolveChunkDebugInfo(response,streamState,chunk);
29612983
}
29622984
// This can't actually happen because we don't have any forward
29632985
// references to modules.
@@ -2978,13 +3000,13 @@ function resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(
29783000
if(!chunk){
29793001
constnewChunk=createInitializedStreamChunk(response,stream,controller);
29803002
if(__DEV__){
2981-
resolveChunkDebugInfo(streamState,newChunk);
3003+
resolveChunkDebugInfo(response,streamState,newChunk);
29823004
}
29833005
chunks.set(id,newChunk);
29843006
return;
29853007
}
29863008
if(__DEV__){
2987-
resolveChunkDebugInfo(streamState,chunk);
3009+
resolveChunkDebugInfo(response,streamState,chunk);
29883010
}
29893011
if(chunk.status!==PENDING){
29903012
// We already resolved. We didn't expect to see this.
@@ -3034,6 +3056,10 @@ function resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(
30343056
resolvedChunk.reason = controller;
30353057
if (resolveListeners !== null) {
30363058
wakeChunk(resolveListeners,chunk.value,(chunk: any));
3059+
} else {
3060+
if(__DEV__){
3061+
moveDebugInfoFromChunkToInnerValue(resolvedChunk,stream);
3062+
}
30373063
}
30383064
}
30393065

@@ -3433,12 +3459,12 @@ function resolvePostponeDev(
34333459
postponeInstance,
34343460
);
34353461
if(__DEV__){
3436-
resolveChunkDebugInfo(streamState,newChunk);
3462+
resolveChunkDebugInfo(response,streamState,newChunk);
34373463
}
34383464
chunks.set(id,newChunk);
34393465
}else{
34403466
if(__DEV__){
3441-
resolveChunkDebugInfo(streamState,chunk);
3467+
resolveChunkDebugInfo(response,streamState,chunk);
34423468
}
34433469
triggerErrorOnChunk(response,chunk,postponeInstance);
34443470
}
@@ -3467,12 +3493,12 @@ function resolveErrorModel(
34673493
errorWithDigest,
34683494
);
34693495
if (__DEV__) {
3470-
resolveChunkDebugInfo(streamState,newChunk);
3496+
resolveChunkDebugInfo(response,streamState,newChunk);
34713497
}
34723498
chunks.set(id, newChunk);
34733499
}else{
34743500
if(__DEV__){
3475-
resolveChunkDebugInfo(streamState,chunk);
3501+
resolveChunkDebugInfo(response,streamState,chunk);
34763502
}
34773503
triggerErrorOnChunk(response, chunk, errorWithDigest);
34783504
}

‎packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js‎

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3035,18 +3035,6 @@ describe('ReactFlightDOMBrowser', () => {
30353035
{
30363036
"time": 0,
30373037
},
3038-
{
3039-
"awaited": {
3040-
"byteSize": 0,
3041-
"end": 0,
3042-
"name": "RSC stream",
3043-
"owner": null,
3044-
"start": 0,
3045-
"value": {
3046-
"value": "stream",
3047-
},
3048-
},
3049-
},
30503038
]
30513039
`);
30523040
}

‎packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMEdge-test.js‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,11 +1248,6 @@ describe('ReactFlightDOMEdge', () => {
12481248
owner: greetInfo,
12491249
}),
12501250
{time: 14},
1251-
expect.objectContaining({
1252-
awaited: expect.objectContaining({
1253-
name: 'RSC stream',
1254-
}),
1255-
}),
12561251
]);
12571252
}
12581253
// The owner that created the span was the outer server component.

‎packages/react-server/src/ReactFlightServer.js‎

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2325,9 +2325,15 @@ function visitAsyncNode(
23252325
returnnull;
23262326
}
23272327
visited.add(node);
2328+
if (node.end >=0&&node.end<=request.timeOrigin){
2329+
// This was already resolved when we started this render. It must have been either something
2330+
// that's part of a start up sequence or externally cached data. We exclude that information.
2331+
// The technique for debugging the effects of uncached data on the render is to simply uncache it.
2332+
returnnull;
2333+
}
23282334
let previousIONode = null;
23292335
// First visit anything that blocked this sequence to start in the first place.
2330-
if (node.previous !== null&&node.end>request.timeOrigin){
2336+
if (node.previous !== null) {
23312337
previousIONode=visitAsyncNode(
23322338
request,
23332339
task,
@@ -2349,12 +2355,6 @@ function visitAsyncNode(
23492355
returnpreviousIONode;
23502356
}
23512357
case PROMISE_NODE: {
2352-
if(node.end<=request.timeOrigin){
2353-
// This was already resolved when we started this render. It must have been either something
2354-
// that's part of a start up sequence or externally cached data. We exclude that information.
2355-
// The technique for debugging the effects of uncached data on the render is to simply uncache it.
2356-
returnpreviousIONode;
2357-
}
23582358
constawaited=node.awaited;
23592359
letmatch: void|null|PromiseNode|IONode=previousIONode;
23602360
constpromise=node.promise.deref();
@@ -2437,11 +2437,7 @@ function visitAsyncNode(
24372437
}elseif(ioNode!==null){
24382438
conststartTime: number=node.start;
24392439
constendTime: number=node.end;
2440-
if(endTime<=request.timeOrigin){
2441-
// This was already resolved when we started this render. It must have been either something
2442-
// that's part of a start up sequence or externally cached data. We exclude that information.
2443-
return null;
2444-
}elseif(startTime<cutOff){
2440+
if(startTime<cutOff){
24452441
// We started awaiting this node before we started rendering this sequence.
24462442
// This means that this particular await was never part of the current sequence.
24472443
// If we have another await higher up in the chain it might have a more actionable stack

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' [Flight] Exclude RSC Stream if the stream resolves in a task (#34838) · react/react@56e8469 · GitHub
Skip to content

Commit 56e8469

Browse files
authored
[Flight] Exclude RSC Stream if the stream resolves in a task (#34838)
1 parent 19b7167 commit 56e8469

5 files changed

Lines changed: 236 additions & 267 deletions

File tree

‎packages/react-client/src/ReactFlightClient.js‎

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ type Response = {
367367
_debugRootStack?: null|Error,// DEV-only
368368
_debugRootTask?: null|ConsoleTask,// DEV-only
369369
_debugStartTime: number,// DEV-only
370+
_debugIOStarted: boolean,// DEV-only
370371
_debugFindSourceMapURL?: void|FindSourceMapURLCallback,// DEV-only
371372
_debugChannel?: void|DebugChannel,// DEV-only
372373
_blockedConsole?: null|SomeChunk<ConsoleEntry>,// DEV-only
@@ -500,7 +501,7 @@ function createErrorChunk<T>(
500501
}
501502

502503
function moveDebugInfoFromChunkToInnerValue<T>(
503-
chunk: InitializedChunk<T>,
504+
chunk: InitializedChunk<T> | InitializedStreamChunk<any>,
504505
value: T,
505506
): void {
506507
// Remove the debug info from the initialized chunk, and add it to the inner
@@ -1569,6 +1570,10 @@ function fulfillReference(
15691570
initializedChunk.reason=handler.reason;// Used by streaming chunks
15701571
if(resolveListeners!==null){
15711572
wakeChunk(resolveListeners,handler.value,initializedChunk);
1573+
}else{
1574+
if(__DEV__){
1575+
moveDebugInfoFromChunkToInnerValue(initializedChunk,handler.value);
1576+
}
15721577
}
15731578
}
15741579
}
@@ -1818,6 +1823,10 @@ function loadServerReference<A: Iterable<any>, T>(
18181823
initializedChunk.value=handler.value;
18191824
if(resolveListeners!==null){
18201825
wakeChunk(resolveListeners,handler.value,initializedChunk);
1826+
}else{
1827+
if(__DEV__){
1828+
moveDebugInfoFromChunkToInnerValue(initializedChunk,handler.value);
1829+
}
18211830
}
18221831
}
18231832
}
@@ -2536,6 +2545,10 @@ function missingCall() {
25362545
);
25372546
}
25382547

2548+
functionmarkIOStarted(this: Response){
2549+
this._debugIOStarted=true;
2550+
}
2551+
25392552
functionResponseInstance(
25402553
this: $FlowFixMe,
25412554
bundlerConfig: ServerConsumerModuleMap,
@@ -2609,6 +2622,10 @@ function ResponseInstance(
26092622
// where as if you use createFromReadableStream from the body of the fetch
26102623
// then the start time is when the headers resolved.
26112624
this._debugStartTime=performance.now();
2625+
this._debugIOStarted=false;
2626+
// We consider everything before the first setTimeout task to be cached data
2627+
// and is not considered I/O required to load the stream.
2628+
setTimeout(markIOStarted.bind(this),0);
26122629
}
26132630
this._debugFindSourceMapURL=findSourceMapURL;
26142631
this._debugChannel=debugChannel;
@@ -2762,7 +2779,7 @@ function incrementChunkDebugInfo(
27622779
}
27632780
}
27642781

2765-
functionaddDebugInfo(chunk: SomeChunk<any>,debugInfo: ReactDebugInfo): void{
2782+
functionaddAsyncInfo(chunk: SomeChunk<any>,asyncInfo: ReactAsyncInfo): void{
27662783
constvalue=resolveLazy(chunk.value);
27672784
if(
27682785
typeofvalue==='object'&&
@@ -2774,34 +2791,39 @@ function addDebugInfo(chunk: SomeChunk<any>, debugInfo: ReactDebugInfo): void {
27742791
){
27752792
if(isArray(value._debugInfo)){
27762793
// $FlowFixMe[method-unbinding]
2777-
value._debugInfo.push.apply(value._debugInfo,debugInfo);
2794+
value._debugInfo.push(asyncInfo);
27782795
}else{
27792796
Object.defineProperty((value: any),'_debugInfo',{
27802797
configurable: false,
27812798
enumerable: false,
27822799
writable: true,
2783-
value: debugInfo,
2800+
value: [asyncInfo],
27842801
});
27852802
}
27862803
}else{
27872804
// $FlowFixMe[method-unbinding]
2788-
chunk._debugInfo.push.apply(chunk._debugInfo,debugInfo);
2805+
chunk._debugInfo.push(asyncInfo);
27892806
}
27902807
}
27912808

27922809
functionresolveChunkDebugInfo(
2810+
response: Response,
27932811
streamState: StreamState,
27942812
chunk: SomeChunk<any>,
27952813
): void{
27962814
if(__DEV__&&enableAsyncDebugInfo){
2797-
// Add the currently resolving chunk's debug info representing the stream
2798-
// to the Promise that was waiting on the stream, or its underlying value.
2799-
constdebugInfo: ReactDebugInfo=[{awaited: streamState._debugInfo}];
2800-
if(chunk.status===PENDING||chunk.status===BLOCKED){
2801-
const boundAddDebugInfo =addDebugInfo.bind(null,chunk,debugInfo);
2802-
chunk.then(boundAddDebugInfo,boundAddDebugInfo);
2803-
}else{
2804-
addDebugInfo(chunk,debugInfo);
2815+
// Only include stream information after a macrotask. Any chunk processed
2816+
// before that is considered cached data.
2817+
if(response._debugIOStarted){
2818+
// Add the currently resolving chunk's debug info representing the stream
2819+
// to the Promise that was waiting on the stream, or its underlying value.
2820+
constasyncInfo: ReactAsyncInfo={awaited: streamState._debugInfo};
2821+
if(chunk.status===PENDING||chunk.status===BLOCKED){
2822+
constboundAddAsyncInfo=addAsyncInfo.bind(null,chunk,asyncInfo);
2823+
chunk.then(boundAddAsyncInfo,boundAddAsyncInfo);
2824+
}else{
2825+
addAsyncInfo(chunk,asyncInfo);
2826+
}
28052827
}
28062828
}
28072829
}
@@ -2837,12 +2859,12 @@ function resolveModel(
28372859
model,
28382860
);
28392861
if(__DEV__){
2840-
resolveChunkDebugInfo(streamState,newChunk);
2862+
resolveChunkDebugInfo(response,streamState,newChunk);
28412863
}
28422864
chunks.set(id,newChunk);
28432865
}else{
28442866
if(__DEV__){
2845-
resolveChunkDebugInfo(streamState,chunk);
2867+
resolveChunkDebugInfo(response,streamState,chunk);
28462868
}
28472869
resolveModelChunk(response,chunk,model);
28482870
}
@@ -2869,7 +2891,7 @@ function resolveText(
28692891
}
28702892
constnewChunk=createInitializedTextChunk(response,text);
28712893
if(__DEV__){
2872-
resolveChunkDebugInfo(streamState,newChunk);
2894+
resolveChunkDebugInfo(response,streamState,newChunk);
28732895
}
28742896
chunks.set(id,newChunk);
28752897
}
@@ -2895,7 +2917,7 @@ function resolveBuffer(
28952917
}
28962918
constnewChunk=createInitializedBufferChunk(response,buffer);
28972919
if(__DEV__){
2898-
resolveChunkDebugInfo(streamState,newChunk);
2920+
resolveChunkDebugInfo(response,streamState,newChunk);
28992921
}
29002922
chunks.set(id,newChunk);
29012923
}
@@ -2942,7 +2964,7 @@ function resolveModule(
29422964
blockedChunk.status=BLOCKED;
29432965
}
29442966
if(__DEV__){
2945-
resolveChunkDebugInfo(streamState,blockedChunk);
2967+
resolveChunkDebugInfo(response,streamState,blockedChunk);
29462968
}
29472969
promise.then(
29482970
()=>resolveModuleChunk(response,blockedChunk,clientReference),
@@ -2952,12 +2974,12 @@ function resolveModule(
29522974
if(!chunk){
29532975
constnewChunk=createResolvedModuleChunk(response,clientReference);
29542976
if(__DEV__){
2955-
resolveChunkDebugInfo(streamState,newChunk);
2977+
resolveChunkDebugInfo(response,streamState,newChunk);
29562978
}
29572979
chunks.set(id,newChunk);
29582980
}else{
29592981
if(__DEV__){
2960-
resolveChunkDebugInfo(streamState,chunk);
2982+
resolveChunkDebugInfo(response,streamState,chunk);
29612983
}
29622984
// This can't actually happen because we don't have any forward
29632985
// references to modules.
@@ -2978,13 +3000,13 @@ function resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(
29783000
if(!chunk){
29793001
constnewChunk=createInitializedStreamChunk(response,stream,controller);
29803002
if(__DEV__){
2981-
resolveChunkDebugInfo(streamState,newChunk);
3003+
resolveChunkDebugInfo(response,streamState,newChunk);
29823004
}
29833005
chunks.set(id,newChunk);
29843006
return;
29853007
}
29863008
if(__DEV__){
2987-
resolveChunkDebugInfo(streamState,chunk);
3009+
resolveChunkDebugInfo(response,streamState,chunk);
29883010
}
29893011
if(chunk.status!==PENDING){
29903012
// We already resolved. We didn't expect to see this.
@@ -3034,6 +3056,10 @@ function resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(
30343056
resolvedChunk.reason = controller;
30353057
if (resolveListeners !== null) {
30363058
wakeChunk(resolveListeners,chunk.value,(chunk: any));
3059+
} else {
3060+
if(__DEV__){
3061+
moveDebugInfoFromChunkToInnerValue(resolvedChunk,stream);
3062+
}
30373063
}
30383064
}
30393065

@@ -3433,12 +3459,12 @@ function resolvePostponeDev(
34333459
postponeInstance,
34343460
);
34353461
if(__DEV__){
3436-
resolveChunkDebugInfo(streamState,newChunk);
3462+
resolveChunkDebugInfo(response,streamState,newChunk);
34373463
}
34383464
chunks.set(id,newChunk);
34393465
}else{
34403466
if(__DEV__){
3441-
resolveChunkDebugInfo(streamState,chunk);
3467+
resolveChunkDebugInfo(response,streamState,chunk);
34423468
}
34433469
triggerErrorOnChunk(response,chunk,postponeInstance);
34443470
}
@@ -3467,12 +3493,12 @@ function resolveErrorModel(
34673493
errorWithDigest,
34683494
);
34693495
if (__DEV__) {
3470-
resolveChunkDebugInfo(streamState,newChunk);
3496+
resolveChunkDebugInfo(response,streamState,newChunk);
34713497
}
34723498
chunks.set(id, newChunk);
34733499
}else{
34743500
if(__DEV__){
3475-
resolveChunkDebugInfo(streamState,chunk);
3501+
resolveChunkDebugInfo(response,streamState,chunk);
34763502
}
34773503
triggerErrorOnChunk(response, chunk, errorWithDigest);
34783504
}

‎packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js‎

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3035,18 +3035,6 @@ describe('ReactFlightDOMBrowser', () => {
30353035
{
30363036
"time": 0,
30373037
},
3038-
{
3039-
"awaited": {
3040-
"byteSize": 0,
3041-
"end": 0,
3042-
"name": "RSC stream",
3043-
"owner": null,
3044-
"start": 0,
3045-
"value": {
3046-
"value": "stream",
3047-
},
3048-
},
3049-
},
30503038
]
30513039
`);
30523040
}

‎packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMEdge-test.js‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,11 +1248,6 @@ describe('ReactFlightDOMEdge', () => {
12481248
owner: greetInfo,
12491249
}),
12501250
{time: 14},
1251-
expect.objectContaining({
1252-
awaited: expect.objectContaining({
1253-
name: 'RSC stream',
1254-
}),
1255-
}),
12561251
]);
12571252
}
12581253
// The owner that created the span was the outer server component.

‎packages/react-server/src/ReactFlightServer.js‎

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2325,9 +2325,15 @@ function visitAsyncNode(
23252325
returnnull;
23262326
}
23272327
visited.add(node);
2328+
if (node.end >=0&&node.end<=request.timeOrigin){
2329+
// This was already resolved when we started this render. It must have been either something
2330+
// that's part of a start up sequence or externally cached data. We exclude that information.
2331+
// The technique for debugging the effects of uncached data on the render is to simply uncache it.
2332+
returnnull;
2333+
}
23282334
let previousIONode = null;
23292335
// First visit anything that blocked this sequence to start in the first place.
2330-
if (node.previous !== null&&node.end>request.timeOrigin){
2336+
if (node.previous !== null) {
23312337
previousIONode=visitAsyncNode(
23322338
request,
23332339
task,
@@ -2349,12 +2355,6 @@ function visitAsyncNode(
23492355
returnpreviousIONode;
23502356
}
23512357
case PROMISE_NODE: {
2352-
if(node.end<=request.timeOrigin){
2353-
// This was already resolved when we started this render. It must have been either something
2354-
// that's part of a start up sequence or externally cached data. We exclude that information.
2355-
// The technique for debugging the effects of uncached data on the render is to simply uncache it.
2356-
returnpreviousIONode;
2357-
}
23582358
constawaited=node.awaited;
23592359
letmatch: void|null|PromiseNode|IONode=previousIONode;
23602360
constpromise=node.promise.deref();
@@ -2437,11 +2437,7 @@ function visitAsyncNode(
24372437
}elseif(ioNode!==null){
24382438
conststartTime: number=node.start;
24392439
constendTime: number=node.end;
2440-
if(endTime<=request.timeOrigin){
2441-
// This was already resolved when we started this render. It must have been either something
2442-
// that's part of a start up sequence or externally cached data. We exclude that information.
2443-
return null;
2444-
}elseif(startTime<cutOff){
2440+
if(startTime<cutOff){
24452441
// We started awaiting this node before we started rendering this sequence.
24462442
// This means that this particular await was never part of the current sequence.
24472443
// If we have another await higher up in the chain it might have a more actionable stack

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' [Flight] Exclude RSC Stream if the stream resolves in a task (#34838) · react/react@56e8469 · GitHub
Skip to content

Commit 56e8469

Browse files
authored
[Flight] Exclude RSC Stream if the stream resolves in a task (#34838)
1 parent 19b7167 commit 56e8469

5 files changed

Lines changed: 236 additions & 267 deletions

File tree

‎packages/react-client/src/ReactFlightClient.js‎

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ type Response = {
367367
_debugRootStack?: null|Error,// DEV-only
368368
_debugRootTask?: null|ConsoleTask,// DEV-only
369369
_debugStartTime: number,// DEV-only
370+
_debugIOStarted: boolean,// DEV-only
370371
_debugFindSourceMapURL?: void|FindSourceMapURLCallback,// DEV-only
371372
_debugChannel?: void|DebugChannel,// DEV-only
372373
_blockedConsole?: null|SomeChunk<ConsoleEntry>,// DEV-only
@@ -500,7 +501,7 @@ function createErrorChunk<T>(
500501
}
501502

502503
function moveDebugInfoFromChunkToInnerValue<T>(
503-
chunk: InitializedChunk<T>,
504+
chunk: InitializedChunk<T> | InitializedStreamChunk<any>,
504505
value: T,
505506
): void {
506507
// Remove the debug info from the initialized chunk, and add it to the inner
@@ -1569,6 +1570,10 @@ function fulfillReference(
15691570
initializedChunk.reason=handler.reason;// Used by streaming chunks
15701571
if(resolveListeners!==null){
15711572
wakeChunk(resolveListeners,handler.value,initializedChunk);
1573+
}else{
1574+
if(__DEV__){
1575+
moveDebugInfoFromChunkToInnerValue(initializedChunk,handler.value);
1576+
}
15721577
}
15731578
}
15741579
}
@@ -1818,6 +1823,10 @@ function loadServerReference<A: Iterable<any>, T>(
18181823
initializedChunk.value=handler.value;
18191824
if(resolveListeners!==null){
18201825
wakeChunk(resolveListeners,handler.value,initializedChunk);
1826+
}else{
1827+
if(__DEV__){
1828+
moveDebugInfoFromChunkToInnerValue(initializedChunk,handler.value);
1829+
}
18211830
}
18221831
}
18231832
}
@@ -2536,6 +2545,10 @@ function missingCall() {
25362545
);
25372546
}
25382547

2548+
functionmarkIOStarted(this: Response){
2549+
this._debugIOStarted=true;
2550+
}
2551+
25392552
functionResponseInstance(
25402553
this: $FlowFixMe,
25412554
bundlerConfig: ServerConsumerModuleMap,
@@ -2609,6 +2622,10 @@ function ResponseInstance(
26092622
// where as if you use createFromReadableStream from the body of the fetch
26102623
// then the start time is when the headers resolved.
26112624
this._debugStartTime=performance.now();
2625+
this._debugIOStarted=false;
2626+
// We consider everything before the first setTimeout task to be cached data
2627+
// and is not considered I/O required to load the stream.
2628+
setTimeout(markIOStarted.bind(this),0);
26122629
}
26132630
this._debugFindSourceMapURL=findSourceMapURL;
26142631
this._debugChannel=debugChannel;
@@ -2762,7 +2779,7 @@ function incrementChunkDebugInfo(
27622779
}
27632780
}
27642781

2765-
functionaddDebugInfo(chunk: SomeChunk<any>,debugInfo: ReactDebugInfo): void{
2782+
functionaddAsyncInfo(chunk: SomeChunk<any>,asyncInfo: ReactAsyncInfo): void{
27662783
constvalue=resolveLazy(chunk.value);
27672784
if(
27682785
typeofvalue==='object'&&
@@ -2774,34 +2791,39 @@ function addDebugInfo(chunk: SomeChunk<any>, debugInfo: ReactDebugInfo): void {
27742791
){
27752792
if(isArray(value._debugInfo)){
27762793
// $FlowFixMe[method-unbinding]
2777-
value._debugInfo.push.apply(value._debugInfo,debugInfo);
2794+
value._debugInfo.push(asyncInfo);
27782795
}else{
27792796
Object.defineProperty((value: any),'_debugInfo',{
27802797
configurable: false,
27812798
enumerable: false,
27822799
writable: true,
2783-
value: debugInfo,
2800+
value: [asyncInfo],
27842801
});
27852802
}
27862803
}else{
27872804
// $FlowFixMe[method-unbinding]
2788-
chunk._debugInfo.push.apply(chunk._debugInfo,debugInfo);
2805+
chunk._debugInfo.push(asyncInfo);
27892806
}
27902807
}
27912808

27922809
functionresolveChunkDebugInfo(
2810+
response: Response,
27932811
streamState: StreamState,
27942812
chunk: SomeChunk<any>,
27952813
): void{
27962814
if(__DEV__&&enableAsyncDebugInfo){
2797-
// Add the currently resolving chunk's debug info representing the stream
2798-
// to the Promise that was waiting on the stream, or its underlying value.
2799-
constdebugInfo: ReactDebugInfo=[{awaited: streamState._debugInfo}];
2800-
if(chunk.status===PENDING||chunk.status===BLOCKED){
2801-
const boundAddDebugInfo =addDebugInfo.bind(null,chunk,debugInfo);
2802-
chunk.then(boundAddDebugInfo,boundAddDebugInfo);
2803-
}else{
2804-
addDebugInfo(chunk,debugInfo);
2815+
// Only include stream information after a macrotask. Any chunk processed
2816+
// before that is considered cached data.
2817+
if(response._debugIOStarted){
2818+
// Add the currently resolving chunk's debug info representing the stream
2819+
// to the Promise that was waiting on the stream, or its underlying value.
2820+
constasyncInfo: ReactAsyncInfo={awaited: streamState._debugInfo};
2821+
if(chunk.status===PENDING||chunk.status===BLOCKED){
2822+
constboundAddAsyncInfo=addAsyncInfo.bind(null,chunk,asyncInfo);
2823+
chunk.then(boundAddAsyncInfo,boundAddAsyncInfo);
2824+
}else{
2825+
addAsyncInfo(chunk,asyncInfo);
2826+
}
28052827
}
28062828
}
28072829
}
@@ -2837,12 +2859,12 @@ function resolveModel(
28372859
model,
28382860
);
28392861
if(__DEV__){
2840-
resolveChunkDebugInfo(streamState,newChunk);
2862+
resolveChunkDebugInfo(response,streamState,newChunk);
28412863
}
28422864
chunks.set(id,newChunk);
28432865
}else{
28442866
if(__DEV__){
2845-
resolveChunkDebugInfo(streamState,chunk);
2867+
resolveChunkDebugInfo(response,streamState,chunk);
28462868
}
28472869
resolveModelChunk(response,chunk,model);
28482870
}
@@ -2869,7 +2891,7 @@ function resolveText(
28692891
}
28702892
constnewChunk=createInitializedTextChunk(response,text);
28712893
if(__DEV__){
2872-
resolveChunkDebugInfo(streamState,newChunk);
2894+
resolveChunkDebugInfo(response,streamState,newChunk);
28732895
}
28742896
chunks.set(id,newChunk);
28752897
}
@@ -2895,7 +2917,7 @@ function resolveBuffer(
28952917
}
28962918
constnewChunk=createInitializedBufferChunk(response,buffer);
28972919
if(__DEV__){
2898-
resolveChunkDebugInfo(streamState,newChunk);
2920+
resolveChunkDebugInfo(response,streamState,newChunk);
28992921
}
29002922
chunks.set(id,newChunk);
29012923
}
@@ -2942,7 +2964,7 @@ function resolveModule(
29422964
blockedChunk.status=BLOCKED;
29432965
}
29442966
if(__DEV__){
2945-
resolveChunkDebugInfo(streamState,blockedChunk);
2967+
resolveChunkDebugInfo(response,streamState,blockedChunk);
29462968
}
29472969
promise.then(
29482970
()=>resolveModuleChunk(response,blockedChunk,clientReference),
@@ -2952,12 +2974,12 @@ function resolveModule(
29522974
if(!chunk){
29532975
constnewChunk=createResolvedModuleChunk(response,clientReference);
29542976
if(__DEV__){
2955-
resolveChunkDebugInfo(streamState,newChunk);
2977+
resolveChunkDebugInfo(response,streamState,newChunk);
29562978
}
29572979
chunks.set(id,newChunk);
29582980
}else{
29592981
if(__DEV__){
2960-
resolveChunkDebugInfo(streamState,chunk);
2982+
resolveChunkDebugInfo(response,streamState,chunk);
29612983
}
29622984
// This can't actually happen because we don't have any forward
29632985
// references to modules.
@@ -2978,13 +3000,13 @@ function resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(
29783000
if(!chunk){
29793001
constnewChunk=createInitializedStreamChunk(response,stream,controller);
29803002
if(__DEV__){
2981-
resolveChunkDebugInfo(streamState,newChunk);
3003+
resolveChunkDebugInfo(response,streamState,newChunk);
29823004
}
29833005
chunks.set(id,newChunk);
29843006
return;
29853007
}
29863008
if(__DEV__){
2987-
resolveChunkDebugInfo(streamState,chunk);
3009+
resolveChunkDebugInfo(response,streamState,chunk);
29883010
}
29893011
if(chunk.status!==PENDING){
29903012
// We already resolved. We didn't expect to see this.
@@ -3034,6 +3056,10 @@ function resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(
30343056
resolvedChunk.reason = controller;
30353057
if (resolveListeners !== null) {
30363058
wakeChunk(resolveListeners,chunk.value,(chunk: any));
3059+
} else {
3060+
if(__DEV__){
3061+
moveDebugInfoFromChunkToInnerValue(resolvedChunk,stream);
3062+
}
30373063
}
30383064
}
30393065

@@ -3433,12 +3459,12 @@ function resolvePostponeDev(
34333459
postponeInstance,
34343460
);
34353461
if(__DEV__){
3436-
resolveChunkDebugInfo(streamState,newChunk);
3462+
resolveChunkDebugInfo(response,streamState,newChunk);
34373463
}
34383464
chunks.set(id,newChunk);
34393465
}else{
34403466
if(__DEV__){
3441-
resolveChunkDebugInfo(streamState,chunk);
3467+
resolveChunkDebugInfo(response,streamState,chunk);
34423468
}
34433469
triggerErrorOnChunk(response,chunk,postponeInstance);
34443470
}
@@ -3467,12 +3493,12 @@ function resolveErrorModel(
34673493
errorWithDigest,
34683494
);
34693495
if (__DEV__) {
3470-
resolveChunkDebugInfo(streamState,newChunk);
3496+
resolveChunkDebugInfo(response,streamState,newChunk);
34713497
}
34723498
chunks.set(id, newChunk);
34733499
}else{
34743500
if(__DEV__){
3475-
resolveChunkDebugInfo(streamState,chunk);
3501+
resolveChunkDebugInfo(response,streamState,chunk);
34763502
}
34773503
triggerErrorOnChunk(response, chunk, errorWithDigest);
34783504
}

‎packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js‎

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3035,18 +3035,6 @@ describe('ReactFlightDOMBrowser', () => {
30353035
{
30363036
"time": 0,
30373037
},
3038-
{
3039-
"awaited": {
3040-
"byteSize": 0,
3041-
"end": 0,
3042-
"name": "RSC stream",
3043-
"owner": null,
3044-
"start": 0,
3045-
"value": {
3046-
"value": "stream",
3047-
},
3048-
},
3049-
},
30503038
]
30513039
`);
30523040
}

‎packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMEdge-test.js‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,11 +1248,6 @@ describe('ReactFlightDOMEdge', () => {
12481248
owner: greetInfo,
12491249
}),
12501250
{time: 14},
1251-
expect.objectContaining({
1252-
awaited: expect.objectContaining({
1253-
name: 'RSC stream',
1254-
}),
1255-
}),
12561251
]);
12571252
}
12581253
// The owner that created the span was the outer server component.

‎packages/react-server/src/ReactFlightServer.js‎

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2325,9 +2325,15 @@ function visitAsyncNode(
23252325
returnnull;
23262326
}
23272327
visited.add(node);
2328+
if (node.end >=0&&node.end<=request.timeOrigin){
2329+
// This was already resolved when we started this render. It must have been either something
2330+
// that's part of a start up sequence or externally cached data. We exclude that information.
2331+
// The technique for debugging the effects of uncached data on the render is to simply uncache it.
2332+
returnnull;
2333+
}
23282334
let previousIONode = null;
23292335
// First visit anything that blocked this sequence to start in the first place.
2330-
if (node.previous !== null&&node.end>request.timeOrigin){
2336+
if (node.previous !== null) {
23312337
previousIONode=visitAsyncNode(
23322338
request,
23332339
task,
@@ -2349,12 +2355,6 @@ function visitAsyncNode(
23492355
returnpreviousIONode;
23502356
}
23512357
case PROMISE_NODE: {
2352-
if(node.end<=request.timeOrigin){
2353-
// This was already resolved when we started this render. It must have been either something
2354-
// that's part of a start up sequence or externally cached data. We exclude that information.
2355-
// The technique for debugging the effects of uncached data on the render is to simply uncache it.
2356-
returnpreviousIONode;
2357-
}
23582358
constawaited=node.awaited;
23592359
letmatch: void|null|PromiseNode|IONode=previousIONode;
23602360
constpromise=node.promise.deref();
@@ -2437,11 +2437,7 @@ function visitAsyncNode(
24372437
}elseif(ioNode!==null){
24382438
conststartTime: number=node.start;
24392439
constendTime: number=node.end;
2440-
if(endTime<=request.timeOrigin){
2441-
// This was already resolved when we started this render. It must have been either something
2442-
// that's part of a start up sequence or externally cached data. We exclude that information.
2443-
return null;
2444-
}elseif(startTime<cutOff){
2440+
if(startTime<cutOff){
24452441
// We started awaiting this node before we started rendering this sequence.
24462442
// This means that this particular await was never part of the current sequence.
24472443
// If we have another await higher up in the chain it might have a more actionable stack

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' [Flight] Exclude RSC Stream if the stream resolves in a task (#34838) · react/react@56e8469 · GitHub
Skip to content

Commit 56e8469

Browse files
authored
[Flight] Exclude RSC Stream if the stream resolves in a task (#34838)
1 parent 19b7167 commit 56e8469

5 files changed

Lines changed: 236 additions & 267 deletions

File tree

‎packages/react-client/src/ReactFlightClient.js‎

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ type Response = {
367367
_debugRootStack?: null|Error,// DEV-only
368368
_debugRootTask?: null|ConsoleTask,// DEV-only
369369
_debugStartTime: number,// DEV-only
370+
_debugIOStarted: boolean,// DEV-only
370371
_debugFindSourceMapURL?: void|FindSourceMapURLCallback,// DEV-only
371372
_debugChannel?: void|DebugChannel,// DEV-only
372373
_blockedConsole?: null|SomeChunk<ConsoleEntry>,// DEV-only
@@ -500,7 +501,7 @@ function createErrorChunk<T>(
500501
}
501502

502503
function moveDebugInfoFromChunkToInnerValue<T>(
503-
chunk: InitializedChunk<T>,
504+
chunk: InitializedChunk<T> | InitializedStreamChunk<any>,
504505
value: T,
505506
): void {
506507
// Remove the debug info from the initialized chunk, and add it to the inner
@@ -1569,6 +1570,10 @@ function fulfillReference(
15691570
initializedChunk.reason=handler.reason;// Used by streaming chunks
15701571
if(resolveListeners!==null){
15711572
wakeChunk(resolveListeners,handler.value,initializedChunk);
1573+
}else{
1574+
if(__DEV__){
1575+
moveDebugInfoFromChunkToInnerValue(initializedChunk,handler.value);
1576+
}
15721577
}
15731578
}
15741579
}
@@ -1818,6 +1823,10 @@ function loadServerReference<A: Iterable<any>, T>(
18181823
initializedChunk.value=handler.value;
18191824
if(resolveListeners!==null){
18201825
wakeChunk(resolveListeners,handler.value,initializedChunk);
1826+
}else{
1827+
if(__DEV__){
1828+
moveDebugInfoFromChunkToInnerValue(initializedChunk,handler.value);
1829+
}
18211830
}
18221831
}
18231832
}
@@ -2536,6 +2545,10 @@ function missingCall() {
25362545
);
25372546
}
25382547

2548+
functionmarkIOStarted(this: Response){
2549+
this._debugIOStarted=true;
2550+
}
2551+
25392552
functionResponseInstance(
25402553
this: $FlowFixMe,
25412554
bundlerConfig: ServerConsumerModuleMap,
@@ -2609,6 +2622,10 @@ function ResponseInstance(
26092622
// where as if you use createFromReadableStream from the body of the fetch
26102623
// then the start time is when the headers resolved.
26112624
this._debugStartTime=performance.now();
2625+
this._debugIOStarted=false;
2626+
// We consider everything before the first setTimeout task to be cached data
2627+
// and is not considered I/O required to load the stream.
2628+
setTimeout(markIOStarted.bind(this),0);
26122629
}
26132630
this._debugFindSourceMapURL=findSourceMapURL;
26142631
this._debugChannel=debugChannel;
@@ -2762,7 +2779,7 @@ function incrementChunkDebugInfo(
27622779
}
27632780
}
27642781

2765-
functionaddDebugInfo(chunk: SomeChunk<any>,debugInfo: ReactDebugInfo): void{
2782+
functionaddAsyncInfo(chunk: SomeChunk<any>,asyncInfo: ReactAsyncInfo): void{
27662783
constvalue=resolveLazy(chunk.value);
27672784
if(
27682785
typeofvalue==='object'&&
@@ -2774,34 +2791,39 @@ function addDebugInfo(chunk: SomeChunk<any>, debugInfo: ReactDebugInfo): void {
27742791
){
27752792
if(isArray(value._debugInfo)){
27762793
// $FlowFixMe[method-unbinding]
2777-
value._debugInfo.push.apply(value._debugInfo,debugInfo);
2794+
value._debugInfo.push(asyncInfo);
27782795
}else{
27792796
Object.defineProperty((value: any),'_debugInfo',{
27802797
configurable: false,
27812798
enumerable: false,
27822799
writable: true,
2783-
value: debugInfo,
2800+
value: [asyncInfo],
27842801
});
27852802
}
27862803
}else{
27872804
// $FlowFixMe[method-unbinding]
2788-
chunk._debugInfo.push.apply(chunk._debugInfo,debugInfo);
2805+
chunk._debugInfo.push(asyncInfo);
27892806
}
27902807
}
27912808

27922809
functionresolveChunkDebugInfo(
2810+
response: Response,
27932811
streamState: StreamState,
27942812
chunk: SomeChunk<any>,
27952813
): void{
27962814
if(__DEV__&&enableAsyncDebugInfo){
2797-
// Add the currently resolving chunk's debug info representing the stream
2798-
// to the Promise that was waiting on the stream, or its underlying value.
2799-
constdebugInfo: ReactDebugInfo=[{awaited: streamState._debugInfo}];
2800-
if(chunk.status===PENDING||chunk.status===BLOCKED){
2801-
const boundAddDebugInfo =addDebugInfo.bind(null,chunk,debugInfo);
2802-
chunk.then(boundAddDebugInfo,boundAddDebugInfo);
2803-
}else{
2804-
addDebugInfo(chunk,debugInfo);
2815+
// Only include stream information after a macrotask. Any chunk processed
2816+
// before that is considered cached data.
2817+
if(response._debugIOStarted){
2818+
// Add the currently resolving chunk's debug info representing the stream
2819+
// to the Promise that was waiting on the stream, or its underlying value.
2820+
constasyncInfo: ReactAsyncInfo={awaited: streamState._debugInfo};
2821+
if(chunk.status===PENDING||chunk.status===BLOCKED){
2822+
constboundAddAsyncInfo=addAsyncInfo.bind(null,chunk,asyncInfo);
2823+
chunk.then(boundAddAsyncInfo,boundAddAsyncInfo);
2824+
}else{
2825+
addAsyncInfo(chunk,asyncInfo);
2826+
}
28052827
}
28062828
}
28072829
}
@@ -2837,12 +2859,12 @@ function resolveModel(
28372859
model,
28382860
);
28392861
if(__DEV__){
2840-
resolveChunkDebugInfo(streamState,newChunk);
2862+
resolveChunkDebugInfo(response,streamState,newChunk);
28412863
}
28422864
chunks.set(id,newChunk);
28432865
}else{
28442866
if(__DEV__){
2845-
resolveChunkDebugInfo(streamState,chunk);
2867+
resolveChunkDebugInfo(response,streamState,chunk);
28462868
}
28472869
resolveModelChunk(response,chunk,model);
28482870
}
@@ -2869,7 +2891,7 @@ function resolveText(
28692891
}
28702892
constnewChunk=createInitializedTextChunk(response,text);
28712893
if(__DEV__){
2872-
resolveChunkDebugInfo(streamState,newChunk);
2894+
resolveChunkDebugInfo(response,streamState,newChunk);
28732895
}
28742896
chunks.set(id,newChunk);
28752897
}
@@ -2895,7 +2917,7 @@ function resolveBuffer(
28952917
}
28962918
constnewChunk=createInitializedBufferChunk(response,buffer);
28972919
if(__DEV__){
2898-
resolveChunkDebugInfo(streamState,newChunk);
2920+
resolveChunkDebugInfo(response,streamState,newChunk);
28992921
}
29002922
chunks.set(id,newChunk);
29012923
}
@@ -2942,7 +2964,7 @@ function resolveModule(
29422964
blockedChunk.status=BLOCKED;
29432965
}
29442966
if(__DEV__){
2945-
resolveChunkDebugInfo(streamState,blockedChunk);
2967+
resolveChunkDebugInfo(response,streamState,blockedChunk);
29462968
}
29472969
promise.then(
29482970
()=>resolveModuleChunk(response,blockedChunk,clientReference),
@@ -2952,12 +2974,12 @@ function resolveModule(
29522974
if(!chunk){
29532975
constnewChunk=createResolvedModuleChunk(response,clientReference);
29542976
if(__DEV__){
2955-
resolveChunkDebugInfo(streamState,newChunk);
2977+
resolveChunkDebugInfo(response,streamState,newChunk);
29562978
}
29572979
chunks.set(id,newChunk);
29582980
}else{
29592981
if(__DEV__){
2960-
resolveChunkDebugInfo(streamState,chunk);
2982+
resolveChunkDebugInfo(response,streamState,chunk);
29612983
}
29622984
// This can't actually happen because we don't have any forward
29632985
// references to modules.
@@ -2978,13 +3000,13 @@ function resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(
29783000
if(!chunk){
29793001
constnewChunk=createInitializedStreamChunk(response,stream,controller);
29803002
if(__DEV__){
2981-
resolveChunkDebugInfo(streamState,newChunk);
3003+
resolveChunkDebugInfo(response,streamState,newChunk);
29823004
}
29833005
chunks.set(id,newChunk);
29843006
return;
29853007
}
29863008
if(__DEV__){
2987-
resolveChunkDebugInfo(streamState,chunk);
3009+
resolveChunkDebugInfo(response,streamState,chunk);
29883010
}
29893011
if(chunk.status!==PENDING){
29903012
// We already resolved. We didn't expect to see this.
@@ -3034,6 +3056,10 @@ function resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(
30343056
resolvedChunk.reason = controller;
30353057
if (resolveListeners !== null) {
30363058
wakeChunk(resolveListeners,chunk.value,(chunk: any));
3059+
} else {
3060+
if(__DEV__){
3061+
moveDebugInfoFromChunkToInnerValue(resolvedChunk,stream);
3062+
}
30373063
}
30383064
}
30393065

@@ -3433,12 +3459,12 @@ function resolvePostponeDev(
34333459
postponeInstance,
34343460
);
34353461
if(__DEV__){
3436-
resolveChunkDebugInfo(streamState,newChunk);
3462+
resolveChunkDebugInfo(response,streamState,newChunk);
34373463
}
34383464
chunks.set(id,newChunk);
34393465
}else{
34403466
if(__DEV__){
3441-
resolveChunkDebugInfo(streamState,chunk);
3467+
resolveChunkDebugInfo(response,streamState,chunk);
34423468
}
34433469
triggerErrorOnChunk(response,chunk,postponeInstance);
34443470
}
@@ -3467,12 +3493,12 @@ function resolveErrorModel(
34673493
errorWithDigest,
34683494
);
34693495
if (__DEV__) {
3470-
resolveChunkDebugInfo(streamState,newChunk);
3496+
resolveChunkDebugInfo(response,streamState,newChunk);
34713497
}
34723498
chunks.set(id, newChunk);
34733499
}else{
34743500
if(__DEV__){
3475-
resolveChunkDebugInfo(streamState,chunk);
3501+
resolveChunkDebugInfo(response,streamState,chunk);
34763502
}
34773503
triggerErrorOnChunk(response, chunk, errorWithDigest);
34783504
}

‎packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js‎

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3035,18 +3035,6 @@ describe('ReactFlightDOMBrowser', () => {
30353035
{
30363036
"time": 0,
30373037
},
3038-
{
3039-
"awaited": {
3040-
"byteSize": 0,
3041-
"end": 0,
3042-
"name": "RSC stream",
3043-
"owner": null,
3044-
"start": 0,
3045-
"value": {
3046-
"value": "stream",
3047-
},
3048-
},
3049-
},
30503038
]
30513039
`);
30523040
}

‎packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMEdge-test.js‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,11 +1248,6 @@ describe('ReactFlightDOMEdge', () => {
12481248
owner: greetInfo,
12491249
}),
12501250
{time: 14},
1251-
expect.objectContaining({
1252-
awaited: expect.objectContaining({
1253-
name: 'RSC stream',
1254-
}),
1255-
}),
12561251
]);
12571252
}
12581253
// The owner that created the span was the outer server component.

‎packages/react-server/src/ReactFlightServer.js‎

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2325,9 +2325,15 @@ function visitAsyncNode(
23252325
returnnull;
23262326
}
23272327
visited.add(node);
2328+
if (node.end >=0&&node.end<=request.timeOrigin){
2329+
// This was already resolved when we started this render. It must have been either something
2330+
// that's part of a start up sequence or externally cached data. We exclude that information.
2331+
// The technique for debugging the effects of uncached data on the render is to simply uncache it.
2332+
returnnull;
2333+
}
23282334
let previousIONode = null;
23292335
// First visit anything that blocked this sequence to start in the first place.
2330-
if (node.previous !== null&&node.end>request.timeOrigin){
2336+
if (node.previous !== null) {
23312337
previousIONode=visitAsyncNode(
23322338
request,
23332339
task,
@@ -2349,12 +2355,6 @@ function visitAsyncNode(
23492355
returnpreviousIONode;
23502356
}
23512357
case PROMISE_NODE: {
2352-
if(node.end<=request.timeOrigin){
2353-
// This was already resolved when we started this render. It must have been either something
2354-
// that's part of a start up sequence or externally cached data. We exclude that information.
2355-
// The technique for debugging the effects of uncached data on the render is to simply uncache it.
2356-
returnpreviousIONode;
2357-
}
23582358
constawaited=node.awaited;
23592359
letmatch: void|null|PromiseNode|IONode=previousIONode;
23602360
constpromise=node.promise.deref();
@@ -2437,11 +2437,7 @@ function visitAsyncNode(
24372437
}elseif(ioNode!==null){
24382438
conststartTime: number=node.start;
24392439
constendTime: number=node.end;
2440-
if(endTime<=request.timeOrigin){
2441-
// This was already resolved when we started this render. It must have been either something
2442-
// that's part of a start up sequence or externally cached data. We exclude that information.
2443-
return null;
2444-
}elseif(startTime<cutOff){
2440+
if(startTime<cutOff){
24452441
// We started awaiting this node before we started rendering this sequence.
24462442
// This means that this particular await was never part of the current sequence.
24472443
// If we have another await higher up in the chain it might have a more actionable stack

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); [Flight] Exclude RSC Stream if the stream resolves in a task (#34838) · react/react@56e8469 · GitHub
Skip to content

Commit 56e8469

Browse files
authored
[Flight] Exclude RSC Stream if the stream resolves in a task (#34838)
1 parent 19b7167 commit 56e8469

5 files changed

Lines changed: 236 additions & 267 deletions

File tree

‎packages/react-client/src/ReactFlightClient.js‎

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ type Response = {
367367
_debugRootStack?: null|Error,// DEV-only
368368
_debugRootTask?: null|ConsoleTask,// DEV-only
369369
_debugStartTime: number,// DEV-only
370+
_debugIOStarted: boolean,// DEV-only
370371
_debugFindSourceMapURL?: void|FindSourceMapURLCallback,// DEV-only
371372
_debugChannel?: void|DebugChannel,// DEV-only
372373
_blockedConsole?: null|SomeChunk<ConsoleEntry>,// DEV-only
@@ -500,7 +501,7 @@ function createErrorChunk<T>(
500501
}
501502

502503
function moveDebugInfoFromChunkToInnerValue<T>(
503-
chunk: InitializedChunk<T>,
504+
chunk: InitializedChunk<T> | InitializedStreamChunk<any>,
504505
value: T,
505506
): void {
506507
// Remove the debug info from the initialized chunk, and add it to the inner
@@ -1569,6 +1570,10 @@ function fulfillReference(
15691570
initializedChunk.reason=handler.reason;// Used by streaming chunks
15701571
if(resolveListeners!==null){
15711572
wakeChunk(resolveListeners,handler.value,initializedChunk);
1573+
}else{
1574+
if(__DEV__){
1575+
moveDebugInfoFromChunkToInnerValue(initializedChunk,handler.value);
1576+
}
15721577
}
15731578
}
15741579
}
@@ -1818,6 +1823,10 @@ function loadServerReference<A: Iterable<any>, T>(
18181823
initializedChunk.value=handler.value;
18191824
if(resolveListeners!==null){
18201825
wakeChunk(resolveListeners,handler.value,initializedChunk);
1826+
}else{
1827+
if(__DEV__){
1828+
moveDebugInfoFromChunkToInnerValue(initializedChunk,handler.value);
1829+
}
18211830
}
18221831
}
18231832
}
@@ -2536,6 +2545,10 @@ function missingCall() {
25362545
);
25372546
}
25382547

2548+
functionmarkIOStarted(this: Response){
2549+
this._debugIOStarted=true;
2550+
}
2551+
25392552
functionResponseInstance(
25402553
this: $FlowFixMe,
25412554
bundlerConfig: ServerConsumerModuleMap,
@@ -2609,6 +2622,10 @@ function ResponseInstance(
26092622
// where as if you use createFromReadableStream from the body of the fetch
26102623
// then the start time is when the headers resolved.
26112624
this._debugStartTime=performance.now();
2625+
this._debugIOStarted=false;
2626+
// We consider everything before the first setTimeout task to be cached data
2627+
// and is not considered I/O required to load the stream.
2628+
setTimeout(markIOStarted.bind(this),0);
26122629
}
26132630
this._debugFindSourceMapURL=findSourceMapURL;
26142631
this._debugChannel=debugChannel;
@@ -2762,7 +2779,7 @@ function incrementChunkDebugInfo(
27622779
}
27632780
}
27642781

2765-
functionaddDebugInfo(chunk: SomeChunk<any>,debugInfo: ReactDebugInfo): void{
2782+
functionaddAsyncInfo(chunk: SomeChunk<any>,asyncInfo: ReactAsyncInfo): void{
27662783
constvalue=resolveLazy(chunk.value);
27672784
if(
27682785
typeofvalue==='object'&&
@@ -2774,34 +2791,39 @@ function addDebugInfo(chunk: SomeChunk<any>, debugInfo: ReactDebugInfo): void {
27742791
){
27752792
if(isArray(value._debugInfo)){
27762793
// $FlowFixMe[method-unbinding]
2777-
value._debugInfo.push.apply(value._debugInfo,debugInfo);
2794+
value._debugInfo.push(asyncInfo);
27782795
}else{
27792796
Object.defineProperty((value: any),'_debugInfo',{
27802797
configurable: false,
27812798
enumerable: false,
27822799
writable: true,
2783-
value: debugInfo,
2800+
value: [asyncInfo],
27842801
});
27852802
}
27862803
}else{
27872804
// $FlowFixMe[method-unbinding]
2788-
chunk._debugInfo.push.apply(chunk._debugInfo,debugInfo);
2805+
chunk._debugInfo.push(asyncInfo);
27892806
}
27902807
}
27912808

27922809
functionresolveChunkDebugInfo(
2810+
response: Response,
27932811
streamState: StreamState,
27942812
chunk: SomeChunk<any>,
27952813
): void{
27962814
if(__DEV__&&enableAsyncDebugInfo){
2797-
// Add the currently resolving chunk's debug info representing the stream
2798-
// to the Promise that was waiting on the stream, or its underlying value.
2799-
constdebugInfo: ReactDebugInfo=[{awaited: streamState._debugInfo}];
2800-
if(chunk.status===PENDING||chunk.status===BLOCKED){
2801-
const boundAddDebugInfo =addDebugInfo.bind(null,chunk,debugInfo);
2802-
chunk.then(boundAddDebugInfo,boundAddDebugInfo);
2803-
}else{
2804-
addDebugInfo(chunk,debugInfo);
2815+
// Only include stream information after a macrotask. Any chunk processed
2816+
// before that is considered cached data.
2817+
if(response._debugIOStarted){
2818+
// Add the currently resolving chunk's debug info representing the stream
2819+
// to the Promise that was waiting on the stream, or its underlying value.
2820+
constasyncInfo: ReactAsyncInfo={awaited: streamState._debugInfo};
2821+
if(chunk.status===PENDING||chunk.status===BLOCKED){
2822+
constboundAddAsyncInfo=addAsyncInfo.bind(null,chunk,asyncInfo);
2823+
chunk.then(boundAddAsyncInfo,boundAddAsyncInfo);
2824+
}else{
2825+
addAsyncInfo(chunk,asyncInfo);
2826+
}
28052827
}
28062828
}
28072829
}
@@ -2837,12 +2859,12 @@ function resolveModel(
28372859
model,
28382860
);
28392861
if(__DEV__){
2840-
resolveChunkDebugInfo(streamState,newChunk);
2862+
resolveChunkDebugInfo(response,streamState,newChunk);
28412863
}
28422864
chunks.set(id,newChunk);
28432865
}else{
28442866
if(__DEV__){
2845-
resolveChunkDebugInfo(streamState,chunk);
2867+
resolveChunkDebugInfo(response,streamState,chunk);
28462868
}
28472869
resolveModelChunk(response,chunk,model);
28482870
}
@@ -2869,7 +2891,7 @@ function resolveText(
28692891
}
28702892
constnewChunk=createInitializedTextChunk(response,text);
28712893
if(__DEV__){
2872-
resolveChunkDebugInfo(streamState,newChunk);
2894+
resolveChunkDebugInfo(response,streamState,newChunk);
28732895
}
28742896
chunks.set(id,newChunk);
28752897
}
@@ -2895,7 +2917,7 @@ function resolveBuffer(
28952917
}
28962918
constnewChunk=createInitializedBufferChunk(response,buffer);
28972919
if(__DEV__){
2898-
resolveChunkDebugInfo(streamState,newChunk);
2920+
resolveChunkDebugInfo(response,streamState,newChunk);
28992921
}
29002922
chunks.set(id,newChunk);
29012923
}
@@ -2942,7 +2964,7 @@ function resolveModule(
29422964
blockedChunk.status=BLOCKED;
29432965
}
29442966
if(__DEV__){
2945-
resolveChunkDebugInfo(streamState,blockedChunk);
2967+
resolveChunkDebugInfo(response,streamState,blockedChunk);
29462968
}
29472969
promise.then(
29482970
()=>resolveModuleChunk(response,blockedChunk,clientReference),
@@ -2952,12 +2974,12 @@ function resolveModule(
29522974
if(!chunk){
29532975
constnewChunk=createResolvedModuleChunk(response,clientReference);
29542976
if(__DEV__){
2955-
resolveChunkDebugInfo(streamState,newChunk);
2977+
resolveChunkDebugInfo(response,streamState,newChunk);
29562978
}
29572979
chunks.set(id,newChunk);
29582980
}else{
29592981
if(__DEV__){
2960-
resolveChunkDebugInfo(streamState,chunk);
2982+
resolveChunkDebugInfo(response,streamState,chunk);
29612983
}
29622984
// This can't actually happen because we don't have any forward
29632985
// references to modules.
@@ -2978,13 +3000,13 @@ function resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(
29783000
if(!chunk){
29793001
constnewChunk=createInitializedStreamChunk(response,stream,controller);
29803002
if(__DEV__){
2981-
resolveChunkDebugInfo(streamState,newChunk);
3003+
resolveChunkDebugInfo(response,streamState,newChunk);
29823004
}
29833005
chunks.set(id,newChunk);
29843006
return;
29853007
}
29863008
if(__DEV__){
2987-
resolveChunkDebugInfo(streamState,chunk);
3009+
resolveChunkDebugInfo(response,streamState,chunk);
29883010
}
29893011
if(chunk.status!==PENDING){
29903012
// We already resolved. We didn't expect to see this.
@@ -3034,6 +3056,10 @@ function resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(
30343056
resolvedChunk.reason = controller;
30353057
if (resolveListeners !== null) {
30363058
wakeChunk(resolveListeners,chunk.value,(chunk: any));
3059+
} else {
3060+
if(__DEV__){
3061+
moveDebugInfoFromChunkToInnerValue(resolvedChunk,stream);
3062+
}
30373063
}
30383064
}
30393065

@@ -3433,12 +3459,12 @@ function resolvePostponeDev(
34333459
postponeInstance,
34343460
);
34353461
if(__DEV__){
3436-
resolveChunkDebugInfo(streamState,newChunk);
3462+
resolveChunkDebugInfo(response,streamState,newChunk);
34373463
}
34383464
chunks.set(id,newChunk);
34393465
}else{
34403466
if(__DEV__){
3441-
resolveChunkDebugInfo(streamState,chunk);
3467+
resolveChunkDebugInfo(response,streamState,chunk);
34423468
}
34433469
triggerErrorOnChunk(response,chunk,postponeInstance);
34443470
}
@@ -3467,12 +3493,12 @@ function resolveErrorModel(
34673493
errorWithDigest,
34683494
);
34693495
if (__DEV__) {
3470-
resolveChunkDebugInfo(streamState,newChunk);
3496+
resolveChunkDebugInfo(response,streamState,newChunk);
34713497
}
34723498
chunks.set(id, newChunk);
34733499
}else{
34743500
if(__DEV__){
3475-
resolveChunkDebugInfo(streamState,chunk);
3501+
resolveChunkDebugInfo(response,streamState,chunk);
34763502
}
34773503
triggerErrorOnChunk(response, chunk, errorWithDigest);
34783504
}

‎packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js‎

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3035,18 +3035,6 @@ describe('ReactFlightDOMBrowser', () => {
30353035
{
30363036
"time": 0,
30373037
},
3038-
{
3039-
"awaited": {
3040-
"byteSize": 0,
3041-
"end": 0,
3042-
"name": "RSC stream",
3043-
"owner": null,
3044-
"start": 0,
3045-
"value": {
3046-
"value": "stream",
3047-
},
3048-
},
3049-
},
30503038
]
30513039
`);
30523040
}

‎packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMEdge-test.js‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,11 +1248,6 @@ describe('ReactFlightDOMEdge', () => {
12481248
owner: greetInfo,
12491249
}),
12501250
{time: 14},
1251-
expect.objectContaining({
1252-
awaited: expect.objectContaining({
1253-
name: 'RSC stream',
1254-
}),
1255-
}),
12561251
]);
12571252
}
12581253
// The owner that created the span was the outer server component.

‎packages/react-server/src/ReactFlightServer.js‎

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2325,9 +2325,15 @@ function visitAsyncNode(
23252325
returnnull;
23262326
}
23272327
visited.add(node);
2328+
if (node.end >=0&&node.end<=request.timeOrigin){
2329+
// This was already resolved when we started this render. It must have been either something
2330+
// that's part of a start up sequence or externally cached data. We exclude that information.
2331+
// The technique for debugging the effects of uncached data on the render is to simply uncache it.
2332+
returnnull;
2333+
}
23282334
let previousIONode = null;
23292335
// First visit anything that blocked this sequence to start in the first place.
2330-
if (node.previous !== null&&node.end>request.timeOrigin){
2336+
if (node.previous !== null) {
23312337
previousIONode=visitAsyncNode(
23322338
request,
23332339
task,
@@ -2349,12 +2355,6 @@ function visitAsyncNode(
23492355
returnpreviousIONode;
23502356
}
23512357
case PROMISE_NODE: {
2352-
if(node.end<=request.timeOrigin){
2353-
// This was already resolved when we started this render. It must have been either something
2354-
// that's part of a start up sequence or externally cached data. We exclude that information.
2355-
// The technique for debugging the effects of uncached data on the render is to simply uncache it.
2356-
returnpreviousIONode;
2357-
}
23582358
constawaited=node.awaited;
23592359
letmatch: void|null|PromiseNode|IONode=previousIONode;
23602360
constpromise=node.promise.deref();
@@ -2437,11 +2437,7 @@ function visitAsyncNode(
24372437
}elseif(ioNode!==null){
24382438
conststartTime: number=node.start;
24392439
constendTime: number=node.end;
2440-
if(endTime<=request.timeOrigin){
2441-
// This was already resolved when we started this render. It must have been either something
2442-
// that's part of a start up sequence or externally cached data. We exclude that information.
2443-
return null;
2444-
}elseif(startTime<cutOff){
2440+
if(startTime<cutOff){
24452441
// We started awaiting this node before we started rendering this sequence.
24462442
// This means that this particular await was never part of the current sequence.
24472443
// If we have another await higher up in the chain it might have a more actionable stack

0 commit comments

Comments
 (0)