Skip to content

Commit 67f7d47

Browse files
authored
[Flight] Fix debug info filtering to include later resolved I/O (#35036)
In #35019, we excluded debug I/O info from being considered for enhancing the owner stack if it resolved after the defined `endTime` option that can be passed to the Flight client. However, we should include any I/O that was awaited before that end time, even if it resolved later.
1 parent 561ee24 commit 67f7d47

2 files changed

Lines changed: 45 additions & 58 deletions

File tree

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,9 @@ function filterDebugInfo(
510510
return;
511511
}
512512

513-
// Remove any debug info entries that arrived after the defined end time.
513+
// Remove any debug info entries after the defined end time. For async info
514+
// that means we're including anything that was awaited before the end time,
515+
// but it doesn't need to be resolved before the end time.
514516
const relativeEndTime =
515517
response._debugEndTime -
516518
// $FlowFixMe[prop-missing]
@@ -521,9 +523,6 @@ function filterDebugInfo(
521523
if(typeofinfo.time==='number'&&info.time>relativeEndTime){
522524
break;
523525
}
524-
if(info.awaited!=null&&info.awaited.end> relativeEndTime) {
525-
break;
526-
}
527526
debugInfo.push(info);
528527
}
529528
value._debugInfo=debugInfo;

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

Lines changed: 42 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,35 +1197,28 @@ describe('ReactFlightDOMNode', () => {
11971197
});
11981198

11991199
it('should use late-arriving I/O debug info to enhance component and owner stacks when aborting a prerender',async()=>{
1200-
// This test is constructing a scenario where a framework might separate
1201-
// I/O into different phases, e.g. runtime I/O and dynamic I/O. The
1202-
// framework might choose to define an end time for the Flight client,
1203-
// indicating that all I/O info (or any debug info for that matter) that
1204-
// arrives after that time should be ignored. When rendering in Fizz is
1205-
// then aborted, the late-arriving debug info that's used to enhance the
1206-
// owner stack only includes I/O info up to that end time.
1207-
letresolveRuntimeData;
1208-
letresolveDynamicData;
1209-
1210-
asyncfunctiongetRuntimeData(){
1200+
letresolveDynamicData1;
1201+
letresolveDynamicData2;
1202+
1203+
asyncfunctiongetDynamicData1(){
12111204
returnnewPromise(resolve=>{
1212-
resolveRuntimeData=resolve;
1205+
resolveDynamicData1=resolve;
12131206
});
12141207
}
12151208

1216-
asyncfunctiongetDynamicData(){
1209+
asyncfunctiongetDynamicData2(){
12171210
returnnewPromise(resolve=>{
1218-
resolveDynamicData=resolve;
1211+
resolveDynamicData2=resolve;
12191212
});
12201213
}
12211214

12221215
asyncfunctionDynamic(){
1223-
construntimeData=awaitgetRuntimeData();
1224-
constdynamicData=awaitgetDynamicData();
1216+
constdata1=awaitgetDynamicData1();
1217+
constdata2=awaitgetDynamicData2();
12251218

12261219
return(
12271220
<p>
1228-
{runtimeData}{dynamicData}
1221+
{data1}{data2}
12291222
</p>
12301223
);
12311224
}
@@ -1242,45 +1235,40 @@ describe('ReactFlightDOMNode', () => {
12421235
);
12431236
}
12441237

1245-
conststream=awaitReactServerDOMServer.renderToPipeableStream(
1246-
ReactServer.createElement(App),
1247-
webpackMap,
1248-
{filterStackFrame},
1249-
);
1250-
1238+
letstaticEndTime=-1;
12511239
constinitialChunks=[];
12521240
constdynamicChunks=[];
1253-
letisDynamic=false;
12541241

1255-
constpassThrough=newStream.PassThrough(streamOptions);
1256-
stream.pipe(passThrough);
1242+
awaitnewPromise(resolve=>{
1243+
setTimeout(async()=>{
1244+
conststream=ReactServerDOMServer.renderToPipeableStream(
1245+
ReactServer.createElement(App),
1246+
webpackMap,
1247+
{filterStackFrame},
1248+
);
12571249

1258-
passThrough.on('data',chunk=>{
1259-
if(isDynamic){
1260-
dynamicChunks.push(chunk);
1261-
}else{
1262-
initialChunks.push(chunk);
1263-
}
1264-
});
1250+
constpassThrough=newStream.PassThrough(streamOptions);
1251+
stream.pipe(passThrough);
12651252

1266-
letendTime;
1253+
passThrough.on('data',chunk=>{
1254+
if(staticEndTime<0){
1255+
initialChunks.push(chunk);
1256+
}else{
1257+
dynamicChunks.push(chunk);
1258+
}
1259+
});
12671260

1268-
awaitnewPromise(resolve=>{
1269-
setTimeout(()=>{
1270-
resolveRuntimeData('Hi');
1261+
passThrough.on('end',resolve);
12711262
});
12721263
setTimeout(()=>{
1273-
isDynamic=true;
1274-
endTime=performance.now()+performance.timeOrigin;
1275-
resolveDynamicData('Josh');
1276-
resolve();
1264+
staticEndTime=performance.now()+performance.timeOrigin;
1265+
resolveDynamicData1('Hi');
1266+
setTimeout(()=>{
1267+
resolveDynamicData2('Josh');
1268+
});
12771269
});
12781270
});
12791271

1280-
awaitnewPromise(resolve=>{
1281-
passThrough.on('end',resolve);
1282-
});
1283-
12841272
// Create a new Readable and push all initial chunks immediately.
12851273
constreadable=newStream.Readable({...streamOptions,read(){}});
12861274
for(leti=0;i<initialChunks.length;i++){
@@ -1311,8 +1299,8 @@ describe('ReactFlightDOMNode', () => {
13111299
},
13121300
{
13131301
// Debug info arriving after this end time will be ignored, e.g. the
1314-
// I/O info for the dynamic data.
1315-
endTime,
1302+
// I/O info for the second dynamic data.
1303+
endTime: staticEndTime,
13161304
},
13171305
);
13181306

@@ -1358,12 +1346,12 @@ describe('ReactFlightDOMNode', () => {
13581346
'\n'+
13591347
' in Dynamic'+
13601348
(gate(flags=>flags.enableAsyncDebugInfo)
1361-
? ' (file://ReactFlightDOMNode-test.js:1223:33)\n'
1349+
? ' (file://ReactFlightDOMNode-test.js:1216:27)\n'
13621350
: '\n')+
13631351
' in body\n'+
13641352
' in html\n'+
1365-
' in App (file://ReactFlightDOMNode-test.js:1240:25)\n'+
1366-
' in ClientRoot (ReactFlightDOMNode-test.js:1320:16)',
1353+
' in App (file://ReactFlightDOMNode-test.js:1233:25)\n'+
1354+
' in ClientRoot (ReactFlightDOMNode-test.js:1308:16)',
13671355
);
13681356
}else{
13691357
expect(
@@ -1372,7 +1360,7 @@ describe('ReactFlightDOMNode', () => {
13721360
'\n'+
13731361
' in body\n'+
13741362
' in html\n'+
1375-
' in ClientRoot (ReactFlightDOMNode-test.js:1320:16)',
1363+
' in ClientRoot (ReactFlightDOMNode-test.js:1308:16)',
13761364
);
13771365
}
13781366

@@ -1382,16 +1370,16 @@ describe('ReactFlightDOMNode', () => {
13821370
normalizeCodeLocInfo(ownerStack,{preserveLocation: true}),
13831371
).toBe(
13841372
'\n'+
1385-
' in Dynamic (file://ReactFlightDOMNode-test.js:1223:33)\n'+
1386-
' in App (file://ReactFlightDOMNode-test.js:1240:25)',
1373+
' in Dynamic (file://ReactFlightDOMNode-test.js:1216:27)\n'+
1374+
' in App (file://ReactFlightDOMNode-test.js:1233:25)',
13871375
);
13881376
}else{
13891377
expect(
13901378
normalizeCodeLocInfo(ownerStack,{preserveLocation: true}),
13911379
).toBe(
13921380
''+
13931381
'\n'+
1394-
' in App (file://ReactFlightDOMNode-test.js:1240:25)',
1382+
' in App (file://ReactFlightDOMNode-test.js:1233:25)',
13951383
);
13961384
}
13971385
}else{

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] Fix debug info filtering to include later resolved I/O (#35036) · react/react@67f7d47 · GitHub
Skip to content

Commit 67f7d47

Browse files
authored
[Flight] Fix debug info filtering to include later resolved I/O (#35036)
In #35019, we excluded debug I/O info from being considered for enhancing the owner stack if it resolved after the defined `endTime` option that can be passed to the Flight client. However, we should include any I/O that was awaited before that end time, even if it resolved later.
1 parent 561ee24 commit 67f7d47

2 files changed

Lines changed: 45 additions & 58 deletions

File tree

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,9 @@ function filterDebugInfo(
510510
return;
511511
}
512512

513-
// Remove any debug info entries that arrived after the defined end time.
513+
// Remove any debug info entries after the defined end time. For async info
514+
// that means we're including anything that was awaited before the end time,
515+
// but it doesn't need to be resolved before the end time.
514516
const relativeEndTime =
515517
response._debugEndTime -
516518
// $FlowFixMe[prop-missing]
@@ -521,9 +523,6 @@ function filterDebugInfo(
521523
if(typeofinfo.time==='number'&&info.time>relativeEndTime){
522524
break;
523525
}
524-
if(info.awaited!=null&&info.awaited.end> relativeEndTime) {
525-
break;
526-
}
527526
debugInfo.push(info);
528527
}
529528
value._debugInfo=debugInfo;

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

Lines changed: 42 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,35 +1197,28 @@ describe('ReactFlightDOMNode', () => {
11971197
});
11981198

11991199
it('should use late-arriving I/O debug info to enhance component and owner stacks when aborting a prerender',async()=>{
1200-
// This test is constructing a scenario where a framework might separate
1201-
// I/O into different phases, e.g. runtime I/O and dynamic I/O. The
1202-
// framework might choose to define an end time for the Flight client,
1203-
// indicating that all I/O info (or any debug info for that matter) that
1204-
// arrives after that time should be ignored. When rendering in Fizz is
1205-
// then aborted, the late-arriving debug info that's used to enhance the
1206-
// owner stack only includes I/O info up to that end time.
1207-
letresolveRuntimeData;
1208-
letresolveDynamicData;
1209-
1210-
asyncfunctiongetRuntimeData(){
1200+
letresolveDynamicData1;
1201+
letresolveDynamicData2;
1202+
1203+
asyncfunctiongetDynamicData1(){
12111204
returnnewPromise(resolve=>{
1212-
resolveRuntimeData=resolve;
1205+
resolveDynamicData1=resolve;
12131206
});
12141207
}
12151208

1216-
asyncfunctiongetDynamicData(){
1209+
asyncfunctiongetDynamicData2(){
12171210
returnnewPromise(resolve=>{
1218-
resolveDynamicData=resolve;
1211+
resolveDynamicData2=resolve;
12191212
});
12201213
}
12211214

12221215
asyncfunctionDynamic(){
1223-
construntimeData=awaitgetRuntimeData();
1224-
constdynamicData=awaitgetDynamicData();
1216+
constdata1=awaitgetDynamicData1();
1217+
constdata2=awaitgetDynamicData2();
12251218

12261219
return(
12271220
<p>
1228-
{runtimeData}{dynamicData}
1221+
{data1}{data2}
12291222
</p>
12301223
);
12311224
}
@@ -1242,45 +1235,40 @@ describe('ReactFlightDOMNode', () => {
12421235
);
12431236
}
12441237

1245-
conststream=awaitReactServerDOMServer.renderToPipeableStream(
1246-
ReactServer.createElement(App),
1247-
webpackMap,
1248-
{filterStackFrame},
1249-
);
1250-
1238+
letstaticEndTime=-1;
12511239
constinitialChunks=[];
12521240
constdynamicChunks=[];
1253-
letisDynamic=false;
12541241

1255-
constpassThrough=newStream.PassThrough(streamOptions);
1256-
stream.pipe(passThrough);
1242+
awaitnewPromise(resolve=>{
1243+
setTimeout(async()=>{
1244+
conststream=ReactServerDOMServer.renderToPipeableStream(
1245+
ReactServer.createElement(App),
1246+
webpackMap,
1247+
{filterStackFrame},
1248+
);
12571249

1258-
passThrough.on('data',chunk=>{
1259-
if(isDynamic){
1260-
dynamicChunks.push(chunk);
1261-
}else{
1262-
initialChunks.push(chunk);
1263-
}
1264-
});
1250+
constpassThrough=newStream.PassThrough(streamOptions);
1251+
stream.pipe(passThrough);
12651252

1266-
letendTime;
1253+
passThrough.on('data',chunk=>{
1254+
if(staticEndTime<0){
1255+
initialChunks.push(chunk);
1256+
}else{
1257+
dynamicChunks.push(chunk);
1258+
}
1259+
});
12671260

1268-
awaitnewPromise(resolve=>{
1269-
setTimeout(()=>{
1270-
resolveRuntimeData('Hi');
1261+
passThrough.on('end',resolve);
12711262
});
12721263
setTimeout(()=>{
1273-
isDynamic=true;
1274-
endTime=performance.now()+performance.timeOrigin;
1275-
resolveDynamicData('Josh');
1276-
resolve();
1264+
staticEndTime=performance.now()+performance.timeOrigin;
1265+
resolveDynamicData1('Hi');
1266+
setTimeout(()=>{
1267+
resolveDynamicData2('Josh');
1268+
});
12771269
});
12781270
});
12791271

1280-
awaitnewPromise(resolve=>{
1281-
passThrough.on('end',resolve);
1282-
});
1283-
12841272
// Create a new Readable and push all initial chunks immediately.
12851273
constreadable=newStream.Readable({...streamOptions,read(){}});
12861274
for(leti=0;i<initialChunks.length;i++){
@@ -1311,8 +1299,8 @@ describe('ReactFlightDOMNode', () => {
13111299
},
13121300
{
13131301
// Debug info arriving after this end time will be ignored, e.g. the
1314-
// I/O info for the dynamic data.
1315-
endTime,
1302+
// I/O info for the second dynamic data.
1303+
endTime: staticEndTime,
13161304
},
13171305
);
13181306

@@ -1358,12 +1346,12 @@ describe('ReactFlightDOMNode', () => {
13581346
'\n'+
13591347
' in Dynamic'+
13601348
(gate(flags=>flags.enableAsyncDebugInfo)
1361-
? ' (file://ReactFlightDOMNode-test.js:1223:33)\n'
1349+
? ' (file://ReactFlightDOMNode-test.js:1216:27)\n'
13621350
: '\n')+
13631351
' in body\n'+
13641352
' in html\n'+
1365-
' in App (file://ReactFlightDOMNode-test.js:1240:25)\n'+
1366-
' in ClientRoot (ReactFlightDOMNode-test.js:1320:16)',
1353+
' in App (file://ReactFlightDOMNode-test.js:1233:25)\n'+
1354+
' in ClientRoot (ReactFlightDOMNode-test.js:1308:16)',
13671355
);
13681356
}else{
13691357
expect(
@@ -1372,7 +1360,7 @@ describe('ReactFlightDOMNode', () => {
13721360
'\n'+
13731361
' in body\n'+
13741362
' in html\n'+
1375-
' in ClientRoot (ReactFlightDOMNode-test.js:1320:16)',
1363+
' in ClientRoot (ReactFlightDOMNode-test.js:1308:16)',
13761364
);
13771365
}
13781366

@@ -1382,16 +1370,16 @@ describe('ReactFlightDOMNode', () => {
13821370
normalizeCodeLocInfo(ownerStack,{preserveLocation: true}),
13831371
).toBe(
13841372
'\n'+
1385-
' in Dynamic (file://ReactFlightDOMNode-test.js:1223:33)\n'+
1386-
' in App (file://ReactFlightDOMNode-test.js:1240:25)',
1373+
' in Dynamic (file://ReactFlightDOMNode-test.js:1216:27)\n'+
1374+
' in App (file://ReactFlightDOMNode-test.js:1233:25)',
13871375
);
13881376
}else{
13891377
expect(
13901378
normalizeCodeLocInfo(ownerStack,{preserveLocation: true}),
13911379
).toBe(
13921380
''+
13931381
'\n'+
1394-
' in App (file://ReactFlightDOMNode-test.js:1240:25)',
1382+
' in App (file://ReactFlightDOMNode-test.js:1233:25)',
13951383
);
13961384
}
13971385
}else{

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] Fix debug info filtering to include later resolved I/O (#35036) · react/react@67f7d47 · GitHub
Skip to content

Commit 67f7d47

Browse files
authored
[Flight] Fix debug info filtering to include later resolved I/O (#35036)
In #35019, we excluded debug I/O info from being considered for enhancing the owner stack if it resolved after the defined `endTime` option that can be passed to the Flight client. However, we should include any I/O that was awaited before that end time, even if it resolved later.
1 parent 561ee24 commit 67f7d47

2 files changed

Lines changed: 45 additions & 58 deletions

File tree

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,9 @@ function filterDebugInfo(
510510
return;
511511
}
512512

513-
// Remove any debug info entries that arrived after the defined end time.
513+
// Remove any debug info entries after the defined end time. For async info
514+
// that means we're including anything that was awaited before the end time,
515+
// but it doesn't need to be resolved before the end time.
514516
const relativeEndTime =
515517
response._debugEndTime -
516518
// $FlowFixMe[prop-missing]
@@ -521,9 +523,6 @@ function filterDebugInfo(
521523
if(typeofinfo.time==='number'&&info.time>relativeEndTime){
522524
break;
523525
}
524-
if(info.awaited!=null&&info.awaited.end> relativeEndTime) {
525-
break;
526-
}
527526
debugInfo.push(info);
528527
}
529528
value._debugInfo=debugInfo;

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

Lines changed: 42 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,35 +1197,28 @@ describe('ReactFlightDOMNode', () => {
11971197
});
11981198

11991199
it('should use late-arriving I/O debug info to enhance component and owner stacks when aborting a prerender',async()=>{
1200-
// This test is constructing a scenario where a framework might separate
1201-
// I/O into different phases, e.g. runtime I/O and dynamic I/O. The
1202-
// framework might choose to define an end time for the Flight client,
1203-
// indicating that all I/O info (or any debug info for that matter) that
1204-
// arrives after that time should be ignored. When rendering in Fizz is
1205-
// then aborted, the late-arriving debug info that's used to enhance the
1206-
// owner stack only includes I/O info up to that end time.
1207-
letresolveRuntimeData;
1208-
letresolveDynamicData;
1209-
1210-
asyncfunctiongetRuntimeData(){
1200+
letresolveDynamicData1;
1201+
letresolveDynamicData2;
1202+
1203+
asyncfunctiongetDynamicData1(){
12111204
returnnewPromise(resolve=>{
1212-
resolveRuntimeData=resolve;
1205+
resolveDynamicData1=resolve;
12131206
});
12141207
}
12151208

1216-
asyncfunctiongetDynamicData(){
1209+
asyncfunctiongetDynamicData2(){
12171210
returnnewPromise(resolve=>{
1218-
resolveDynamicData=resolve;
1211+
resolveDynamicData2=resolve;
12191212
});
12201213
}
12211214

12221215
asyncfunctionDynamic(){
1223-
construntimeData=awaitgetRuntimeData();
1224-
constdynamicData=awaitgetDynamicData();
1216+
constdata1=awaitgetDynamicData1();
1217+
constdata2=awaitgetDynamicData2();
12251218

12261219
return(
12271220
<p>
1228-
{runtimeData}{dynamicData}
1221+
{data1}{data2}
12291222
</p>
12301223
);
12311224
}
@@ -1242,45 +1235,40 @@ describe('ReactFlightDOMNode', () => {
12421235
);
12431236
}
12441237

1245-
conststream=awaitReactServerDOMServer.renderToPipeableStream(
1246-
ReactServer.createElement(App),
1247-
webpackMap,
1248-
{filterStackFrame},
1249-
);
1250-
1238+
letstaticEndTime=-1;
12511239
constinitialChunks=[];
12521240
constdynamicChunks=[];
1253-
letisDynamic=false;
12541241

1255-
constpassThrough=newStream.PassThrough(streamOptions);
1256-
stream.pipe(passThrough);
1242+
awaitnewPromise(resolve=>{
1243+
setTimeout(async()=>{
1244+
conststream=ReactServerDOMServer.renderToPipeableStream(
1245+
ReactServer.createElement(App),
1246+
webpackMap,
1247+
{filterStackFrame},
1248+
);
12571249

1258-
passThrough.on('data',chunk=>{
1259-
if(isDynamic){
1260-
dynamicChunks.push(chunk);
1261-
}else{
1262-
initialChunks.push(chunk);
1263-
}
1264-
});
1250+
constpassThrough=newStream.PassThrough(streamOptions);
1251+
stream.pipe(passThrough);
12651252

1266-
letendTime;
1253+
passThrough.on('data',chunk=>{
1254+
if(staticEndTime<0){
1255+
initialChunks.push(chunk);
1256+
}else{
1257+
dynamicChunks.push(chunk);
1258+
}
1259+
});
12671260

1268-
awaitnewPromise(resolve=>{
1269-
setTimeout(()=>{
1270-
resolveRuntimeData('Hi');
1261+
passThrough.on('end',resolve);
12711262
});
12721263
setTimeout(()=>{
1273-
isDynamic=true;
1274-
endTime=performance.now()+performance.timeOrigin;
1275-
resolveDynamicData('Josh');
1276-
resolve();
1264+
staticEndTime=performance.now()+performance.timeOrigin;
1265+
resolveDynamicData1('Hi');
1266+
setTimeout(()=>{
1267+
resolveDynamicData2('Josh');
1268+
});
12771269
});
12781270
});
12791271

1280-
awaitnewPromise(resolve=>{
1281-
passThrough.on('end',resolve);
1282-
});
1283-
12841272
// Create a new Readable and push all initial chunks immediately.
12851273
constreadable=newStream.Readable({...streamOptions,read(){}});
12861274
for(leti=0;i<initialChunks.length;i++){
@@ -1311,8 +1299,8 @@ describe('ReactFlightDOMNode', () => {
13111299
},
13121300
{
13131301
// Debug info arriving after this end time will be ignored, e.g. the
1314-
// I/O info for the dynamic data.
1315-
endTime,
1302+
// I/O info for the second dynamic data.
1303+
endTime: staticEndTime,
13161304
},
13171305
);
13181306

@@ -1358,12 +1346,12 @@ describe('ReactFlightDOMNode', () => {
13581346
'\n'+
13591347
' in Dynamic'+
13601348
(gate(flags=>flags.enableAsyncDebugInfo)
1361-
? ' (file://ReactFlightDOMNode-test.js:1223:33)\n'
1349+
? ' (file://ReactFlightDOMNode-test.js:1216:27)\n'
13621350
: '\n')+
13631351
' in body\n'+
13641352
' in html\n'+
1365-
' in App (file://ReactFlightDOMNode-test.js:1240:25)\n'+
1366-
' in ClientRoot (ReactFlightDOMNode-test.js:1320:16)',
1353+
' in App (file://ReactFlightDOMNode-test.js:1233:25)\n'+
1354+
' in ClientRoot (ReactFlightDOMNode-test.js:1308:16)',
13671355
);
13681356
}else{
13691357
expect(
@@ -1372,7 +1360,7 @@ describe('ReactFlightDOMNode', () => {
13721360
'\n'+
13731361
' in body\n'+
13741362
' in html\n'+
1375-
' in ClientRoot (ReactFlightDOMNode-test.js:1320:16)',
1363+
' in ClientRoot (ReactFlightDOMNode-test.js:1308:16)',
13761364
);
13771365
}
13781366

@@ -1382,16 +1370,16 @@ describe('ReactFlightDOMNode', () => {
13821370
normalizeCodeLocInfo(ownerStack,{preserveLocation: true}),
13831371
).toBe(
13841372
'\n'+
1385-
' in Dynamic (file://ReactFlightDOMNode-test.js:1223:33)\n'+
1386-
' in App (file://ReactFlightDOMNode-test.js:1240:25)',
1373+
' in Dynamic (file://ReactFlightDOMNode-test.js:1216:27)\n'+
1374+
' in App (file://ReactFlightDOMNode-test.js:1233:25)',
13871375
);
13881376
}else{
13891377
expect(
13901378
normalizeCodeLocInfo(ownerStack,{preserveLocation: true}),
13911379
).toBe(
13921380
''+
13931381
'\n'+
1394-
' in App (file://ReactFlightDOMNode-test.js:1240:25)',
1382+
' in App (file://ReactFlightDOMNode-test.js:1233:25)',
13951383
);
13961384
}
13971385
}else{

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] Fix debug info filtering to include later resolved I/O (#35036) · react/react@67f7d47 · GitHub
Skip to content

Commit 67f7d47

Browse files
authored
[Flight] Fix debug info filtering to include later resolved I/O (#35036)
In #35019, we excluded debug I/O info from being considered for enhancing the owner stack if it resolved after the defined `endTime` option that can be passed to the Flight client. However, we should include any I/O that was awaited before that end time, even if it resolved later.
1 parent 561ee24 commit 67f7d47

2 files changed

Lines changed: 45 additions & 58 deletions

File tree

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,9 @@ function filterDebugInfo(
510510
return;
511511
}
512512

513-
// Remove any debug info entries that arrived after the defined end time.
513+
// Remove any debug info entries after the defined end time. For async info
514+
// that means we're including anything that was awaited before the end time,
515+
// but it doesn't need to be resolved before the end time.
514516
const relativeEndTime =
515517
response._debugEndTime -
516518
// $FlowFixMe[prop-missing]
@@ -521,9 +523,6 @@ function filterDebugInfo(
521523
if(typeofinfo.time==='number'&&info.time>relativeEndTime){
522524
break;
523525
}
524-
if(info.awaited!=null&&info.awaited.end> relativeEndTime) {
525-
break;
526-
}
527526
debugInfo.push(info);
528527
}
529528
value._debugInfo=debugInfo;

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

Lines changed: 42 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,35 +1197,28 @@ describe('ReactFlightDOMNode', () => {
11971197
});
11981198

11991199
it('should use late-arriving I/O debug info to enhance component and owner stacks when aborting a prerender',async()=>{
1200-
// This test is constructing a scenario where a framework might separate
1201-
// I/O into different phases, e.g. runtime I/O and dynamic I/O. The
1202-
// framework might choose to define an end time for the Flight client,
1203-
// indicating that all I/O info (or any debug info for that matter) that
1204-
// arrives after that time should be ignored. When rendering in Fizz is
1205-
// then aborted, the late-arriving debug info that's used to enhance the
1206-
// owner stack only includes I/O info up to that end time.
1207-
letresolveRuntimeData;
1208-
letresolveDynamicData;
1209-
1210-
asyncfunctiongetRuntimeData(){
1200+
letresolveDynamicData1;
1201+
letresolveDynamicData2;
1202+
1203+
asyncfunctiongetDynamicData1(){
12111204
returnnewPromise(resolve=>{
1212-
resolveRuntimeData=resolve;
1205+
resolveDynamicData1=resolve;
12131206
});
12141207
}
12151208

1216-
asyncfunctiongetDynamicData(){
1209+
asyncfunctiongetDynamicData2(){
12171210
returnnewPromise(resolve=>{
1218-
resolveDynamicData=resolve;
1211+
resolveDynamicData2=resolve;
12191212
});
12201213
}
12211214

12221215
asyncfunctionDynamic(){
1223-
construntimeData=awaitgetRuntimeData();
1224-
constdynamicData=awaitgetDynamicData();
1216+
constdata1=awaitgetDynamicData1();
1217+
constdata2=awaitgetDynamicData2();
12251218

12261219
return(
12271220
<p>
1228-
{runtimeData}{dynamicData}
1221+
{data1}{data2}
12291222
</p>
12301223
);
12311224
}
@@ -1242,45 +1235,40 @@ describe('ReactFlightDOMNode', () => {
12421235
);
12431236
}
12441237

1245-
conststream=awaitReactServerDOMServer.renderToPipeableStream(
1246-
ReactServer.createElement(App),
1247-
webpackMap,
1248-
{filterStackFrame},
1249-
);
1250-
1238+
letstaticEndTime=-1;
12511239
constinitialChunks=[];
12521240
constdynamicChunks=[];
1253-
letisDynamic=false;
12541241

1255-
constpassThrough=newStream.PassThrough(streamOptions);
1256-
stream.pipe(passThrough);
1242+
awaitnewPromise(resolve=>{
1243+
setTimeout(async()=>{
1244+
conststream=ReactServerDOMServer.renderToPipeableStream(
1245+
ReactServer.createElement(App),
1246+
webpackMap,
1247+
{filterStackFrame},
1248+
);
12571249

1258-
passThrough.on('data',chunk=>{
1259-
if(isDynamic){
1260-
dynamicChunks.push(chunk);
1261-
}else{
1262-
initialChunks.push(chunk);
1263-
}
1264-
});
1250+
constpassThrough=newStream.PassThrough(streamOptions);
1251+
stream.pipe(passThrough);
12651252

1266-
letendTime;
1253+
passThrough.on('data',chunk=>{
1254+
if(staticEndTime<0){
1255+
initialChunks.push(chunk);
1256+
}else{
1257+
dynamicChunks.push(chunk);
1258+
}
1259+
});
12671260

1268-
awaitnewPromise(resolve=>{
1269-
setTimeout(()=>{
1270-
resolveRuntimeData('Hi');
1261+
passThrough.on('end',resolve);
12711262
});
12721263
setTimeout(()=>{
1273-
isDynamic=true;
1274-
endTime=performance.now()+performance.timeOrigin;
1275-
resolveDynamicData('Josh');
1276-
resolve();
1264+
staticEndTime=performance.now()+performance.timeOrigin;
1265+
resolveDynamicData1('Hi');
1266+
setTimeout(()=>{
1267+
resolveDynamicData2('Josh');
1268+
});
12771269
});
12781270
});
12791271

1280-
awaitnewPromise(resolve=>{
1281-
passThrough.on('end',resolve);
1282-
});
1283-
12841272
// Create a new Readable and push all initial chunks immediately.
12851273
constreadable=newStream.Readable({...streamOptions,read(){}});
12861274
for(leti=0;i<initialChunks.length;i++){
@@ -1311,8 +1299,8 @@ describe('ReactFlightDOMNode', () => {
13111299
},
13121300
{
13131301
// Debug info arriving after this end time will be ignored, e.g. the
1314-
// I/O info for the dynamic data.
1315-
endTime,
1302+
// I/O info for the second dynamic data.
1303+
endTime: staticEndTime,
13161304
},
13171305
);
13181306

@@ -1358,12 +1346,12 @@ describe('ReactFlightDOMNode', () => {
13581346
'\n'+
13591347
' in Dynamic'+
13601348
(gate(flags=>flags.enableAsyncDebugInfo)
1361-
? ' (file://ReactFlightDOMNode-test.js:1223:33)\n'
1349+
? ' (file://ReactFlightDOMNode-test.js:1216:27)\n'
13621350
: '\n')+
13631351
' in body\n'+
13641352
' in html\n'+
1365-
' in App (file://ReactFlightDOMNode-test.js:1240:25)\n'+
1366-
' in ClientRoot (ReactFlightDOMNode-test.js:1320:16)',
1353+
' in App (file://ReactFlightDOMNode-test.js:1233:25)\n'+
1354+
' in ClientRoot (ReactFlightDOMNode-test.js:1308:16)',
13671355
);
13681356
}else{
13691357
expect(
@@ -1372,7 +1360,7 @@ describe('ReactFlightDOMNode', () => {
13721360
'\n'+
13731361
' in body\n'+
13741362
' in html\n'+
1375-
' in ClientRoot (ReactFlightDOMNode-test.js:1320:16)',
1363+
' in ClientRoot (ReactFlightDOMNode-test.js:1308:16)',
13761364
);
13771365
}
13781366

@@ -1382,16 +1370,16 @@ describe('ReactFlightDOMNode', () => {
13821370
normalizeCodeLocInfo(ownerStack,{preserveLocation: true}),
13831371
).toBe(
13841372
'\n'+
1385-
' in Dynamic (file://ReactFlightDOMNode-test.js:1223:33)\n'+
1386-
' in App (file://ReactFlightDOMNode-test.js:1240:25)',
1373+
' in Dynamic (file://ReactFlightDOMNode-test.js:1216:27)\n'+
1374+
' in App (file://ReactFlightDOMNode-test.js:1233:25)',
13871375
);
13881376
}else{
13891377
expect(
13901378
normalizeCodeLocInfo(ownerStack,{preserveLocation: true}),
13911379
).toBe(
13921380
''+
13931381
'\n'+
1394-
' in App (file://ReactFlightDOMNode-test.js:1240:25)',
1382+
' in App (file://ReactFlightDOMNode-test.js:1233:25)',
13951383
);
13961384
}
13971385
}else{

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] Fix debug info filtering to include later resolved I/O (#35036) · react/react@67f7d47 · GitHub
Skip to content

Commit 67f7d47

Browse files
authored
[Flight] Fix debug info filtering to include later resolved I/O (#35036)
In #35019, we excluded debug I/O info from being considered for enhancing the owner stack if it resolved after the defined `endTime` option that can be passed to the Flight client. However, we should include any I/O that was awaited before that end time, even if it resolved later.
1 parent 561ee24 commit 67f7d47

2 files changed

Lines changed: 45 additions & 58 deletions

File tree

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,9 @@ function filterDebugInfo(
510510
return;
511511
}
512512

513-
// Remove any debug info entries that arrived after the defined end time.
513+
// Remove any debug info entries after the defined end time. For async info
514+
// that means we're including anything that was awaited before the end time,
515+
// but it doesn't need to be resolved before the end time.
514516
const relativeEndTime =
515517
response._debugEndTime -
516518
// $FlowFixMe[prop-missing]
@@ -521,9 +523,6 @@ function filterDebugInfo(
521523
if(typeofinfo.time==='number'&&info.time>relativeEndTime){
522524
break;
523525
}
524-
if(info.awaited!=null&&info.awaited.end> relativeEndTime) {
525-
break;
526-
}
527526
debugInfo.push(info);
528527
}
529528
value._debugInfo=debugInfo;

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

Lines changed: 42 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,35 +1197,28 @@ describe('ReactFlightDOMNode', () => {
11971197
});
11981198

11991199
it('should use late-arriving I/O debug info to enhance component and owner stacks when aborting a prerender',async()=>{
1200-
// This test is constructing a scenario where a framework might separate
1201-
// I/O into different phases, e.g. runtime I/O and dynamic I/O. The
1202-
// framework might choose to define an end time for the Flight client,
1203-
// indicating that all I/O info (or any debug info for that matter) that
1204-
// arrives after that time should be ignored. When rendering in Fizz is
1205-
// then aborted, the late-arriving debug info that's used to enhance the
1206-
// owner stack only includes I/O info up to that end time.
1207-
letresolveRuntimeData;
1208-
letresolveDynamicData;
1209-
1210-
asyncfunctiongetRuntimeData(){
1200+
letresolveDynamicData1;
1201+
letresolveDynamicData2;
1202+
1203+
asyncfunctiongetDynamicData1(){
12111204
returnnewPromise(resolve=>{
1212-
resolveRuntimeData=resolve;
1205+
resolveDynamicData1=resolve;
12131206
});
12141207
}
12151208

1216-
asyncfunctiongetDynamicData(){
1209+
asyncfunctiongetDynamicData2(){
12171210
returnnewPromise(resolve=>{
1218-
resolveDynamicData=resolve;
1211+
resolveDynamicData2=resolve;
12191212
});
12201213
}
12211214

12221215
asyncfunctionDynamic(){
1223-
construntimeData=awaitgetRuntimeData();
1224-
constdynamicData=awaitgetDynamicData();
1216+
constdata1=awaitgetDynamicData1();
1217+
constdata2=awaitgetDynamicData2();
12251218

12261219
return(
12271220
<p>
1228-
{runtimeData}{dynamicData}
1221+
{data1}{data2}
12291222
</p>
12301223
);
12311224
}
@@ -1242,45 +1235,40 @@ describe('ReactFlightDOMNode', () => {
12421235
);
12431236
}
12441237

1245-
conststream=awaitReactServerDOMServer.renderToPipeableStream(
1246-
ReactServer.createElement(App),
1247-
webpackMap,
1248-
{filterStackFrame},
1249-
);
1250-
1238+
letstaticEndTime=-1;
12511239
constinitialChunks=[];
12521240
constdynamicChunks=[];
1253-
letisDynamic=false;
12541241

1255-
constpassThrough=newStream.PassThrough(streamOptions);
1256-
stream.pipe(passThrough);
1242+
awaitnewPromise(resolve=>{
1243+
setTimeout(async()=>{
1244+
conststream=ReactServerDOMServer.renderToPipeableStream(
1245+
ReactServer.createElement(App),
1246+
webpackMap,
1247+
{filterStackFrame},
1248+
);
12571249

1258-
passThrough.on('data',chunk=>{
1259-
if(isDynamic){
1260-
dynamicChunks.push(chunk);
1261-
}else{
1262-
initialChunks.push(chunk);
1263-
}
1264-
});
1250+
constpassThrough=newStream.PassThrough(streamOptions);
1251+
stream.pipe(passThrough);
12651252

1266-
letendTime;
1253+
passThrough.on('data',chunk=>{
1254+
if(staticEndTime<0){
1255+
initialChunks.push(chunk);
1256+
}else{
1257+
dynamicChunks.push(chunk);
1258+
}
1259+
});
12671260

1268-
awaitnewPromise(resolve=>{
1269-
setTimeout(()=>{
1270-
resolveRuntimeData('Hi');
1261+
passThrough.on('end',resolve);
12711262
});
12721263
setTimeout(()=>{
1273-
isDynamic=true;
1274-
endTime=performance.now()+performance.timeOrigin;
1275-
resolveDynamicData('Josh');
1276-
resolve();
1264+
staticEndTime=performance.now()+performance.timeOrigin;
1265+
resolveDynamicData1('Hi');
1266+
setTimeout(()=>{
1267+
resolveDynamicData2('Josh');
1268+
});
12771269
});
12781270
});
12791271

1280-
awaitnewPromise(resolve=>{
1281-
passThrough.on('end',resolve);
1282-
});
1283-
12841272
// Create a new Readable and push all initial chunks immediately.
12851273
constreadable=newStream.Readable({...streamOptions,read(){}});
12861274
for(leti=0;i<initialChunks.length;i++){
@@ -1311,8 +1299,8 @@ describe('ReactFlightDOMNode', () => {
13111299
},
13121300
{
13131301
// Debug info arriving after this end time will be ignored, e.g. the
1314-
// I/O info for the dynamic data.
1315-
endTime,
1302+
// I/O info for the second dynamic data.
1303+
endTime: staticEndTime,
13161304
},
13171305
);
13181306

@@ -1358,12 +1346,12 @@ describe('ReactFlightDOMNode', () => {
13581346
'\n'+
13591347
' in Dynamic'+
13601348
(gate(flags=>flags.enableAsyncDebugInfo)
1361-
? ' (file://ReactFlightDOMNode-test.js:1223:33)\n'
1349+
? ' (file://ReactFlightDOMNode-test.js:1216:27)\n'
13621350
: '\n')+
13631351
' in body\n'+
13641352
' in html\n'+
1365-
' in App (file://ReactFlightDOMNode-test.js:1240:25)\n'+
1366-
' in ClientRoot (ReactFlightDOMNode-test.js:1320:16)',
1353+
' in App (file://ReactFlightDOMNode-test.js:1233:25)\n'+
1354+
' in ClientRoot (ReactFlightDOMNode-test.js:1308:16)',
13671355
);
13681356
}else{
13691357
expect(
@@ -1372,7 +1360,7 @@ describe('ReactFlightDOMNode', () => {
13721360
'\n'+
13731361
' in body\n'+
13741362
' in html\n'+
1375-
' in ClientRoot (ReactFlightDOMNode-test.js:1320:16)',
1363+
' in ClientRoot (ReactFlightDOMNode-test.js:1308:16)',
13761364
);
13771365
}
13781366

@@ -1382,16 +1370,16 @@ describe('ReactFlightDOMNode', () => {
13821370
normalizeCodeLocInfo(ownerStack,{preserveLocation: true}),
13831371
).toBe(
13841372
'\n'+
1385-
' in Dynamic (file://ReactFlightDOMNode-test.js:1223:33)\n'+
1386-
' in App (file://ReactFlightDOMNode-test.js:1240:25)',
1373+
' in Dynamic (file://ReactFlightDOMNode-test.js:1216:27)\n'+
1374+
' in App (file://ReactFlightDOMNode-test.js:1233:25)',
13871375
);
13881376
}else{
13891377
expect(
13901378
normalizeCodeLocInfo(ownerStack,{preserveLocation: true}),
13911379
).toBe(
13921380
''+
13931381
'\n'+
1394-
' in App (file://ReactFlightDOMNode-test.js:1240:25)',
1382+
' in App (file://ReactFlightDOMNode-test.js:1233:25)',
13951383
);
13961384
}
13971385
}else{

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] Fix debug info filtering to include later resolved I/O (#35036) · react/react@67f7d47 · GitHub
Skip to content

Commit 67f7d47

Browse files
authored
[Flight] Fix debug info filtering to include later resolved I/O (#35036)
In #35019, we excluded debug I/O info from being considered for enhancing the owner stack if it resolved after the defined `endTime` option that can be passed to the Flight client. However, we should include any I/O that was awaited before that end time, even if it resolved later.
1 parent 561ee24 commit 67f7d47

2 files changed

Lines changed: 45 additions & 58 deletions

File tree

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,9 @@ function filterDebugInfo(
510510
return;
511511
}
512512

513-
// Remove any debug info entries that arrived after the defined end time.
513+
// Remove any debug info entries after the defined end time. For async info
514+
// that means we're including anything that was awaited before the end time,
515+
// but it doesn't need to be resolved before the end time.
514516
const relativeEndTime =
515517
response._debugEndTime -
516518
// $FlowFixMe[prop-missing]
@@ -521,9 +523,6 @@ function filterDebugInfo(
521523
if(typeofinfo.time==='number'&&info.time>relativeEndTime){
522524
break;
523525
}
524-
if(info.awaited!=null&&info.awaited.end> relativeEndTime) {
525-
break;
526-
}
527526
debugInfo.push(info);
528527
}
529528
value._debugInfo=debugInfo;

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

Lines changed: 42 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,35 +1197,28 @@ describe('ReactFlightDOMNode', () => {
11971197
});
11981198

11991199
it('should use late-arriving I/O debug info to enhance component and owner stacks when aborting a prerender',async()=>{
1200-
// This test is constructing a scenario where a framework might separate
1201-
// I/O into different phases, e.g. runtime I/O and dynamic I/O. The
1202-
// framework might choose to define an end time for the Flight client,
1203-
// indicating that all I/O info (or any debug info for that matter) that
1204-
// arrives after that time should be ignored. When rendering in Fizz is
1205-
// then aborted, the late-arriving debug info that's used to enhance the
1206-
// owner stack only includes I/O info up to that end time.
1207-
letresolveRuntimeData;
1208-
letresolveDynamicData;
1209-
1210-
asyncfunctiongetRuntimeData(){
1200+
letresolveDynamicData1;
1201+
letresolveDynamicData2;
1202+
1203+
asyncfunctiongetDynamicData1(){
12111204
returnnewPromise(resolve=>{
1212-
resolveRuntimeData=resolve;
1205+
resolveDynamicData1=resolve;
12131206
});
12141207
}
12151208

1216-
asyncfunctiongetDynamicData(){
1209+
asyncfunctiongetDynamicData2(){
12171210
returnnewPromise(resolve=>{
1218-
resolveDynamicData=resolve;
1211+
resolveDynamicData2=resolve;
12191212
});
12201213
}
12211214

12221215
asyncfunctionDynamic(){
1223-
construntimeData=awaitgetRuntimeData();
1224-
constdynamicData=awaitgetDynamicData();
1216+
constdata1=awaitgetDynamicData1();
1217+
constdata2=awaitgetDynamicData2();
12251218

12261219
return(
12271220
<p>
1228-
{runtimeData}{dynamicData}
1221+
{data1}{data2}
12291222
</p>
12301223
);
12311224
}
@@ -1242,45 +1235,40 @@ describe('ReactFlightDOMNode', () => {
12421235
);
12431236
}
12441237

1245-
conststream=awaitReactServerDOMServer.renderToPipeableStream(
1246-
ReactServer.createElement(App),
1247-
webpackMap,
1248-
{filterStackFrame},
1249-
);
1250-
1238+
letstaticEndTime=-1;
12511239
constinitialChunks=[];
12521240
constdynamicChunks=[];
1253-
letisDynamic=false;
12541241

1255-
constpassThrough=newStream.PassThrough(streamOptions);
1256-
stream.pipe(passThrough);
1242+
awaitnewPromise(resolve=>{
1243+
setTimeout(async()=>{
1244+
conststream=ReactServerDOMServer.renderToPipeableStream(
1245+
ReactServer.createElement(App),
1246+
webpackMap,
1247+
{filterStackFrame},
1248+
);
12571249

1258-
passThrough.on('data',chunk=>{
1259-
if(isDynamic){
1260-
dynamicChunks.push(chunk);
1261-
}else{
1262-
initialChunks.push(chunk);
1263-
}
1264-
});
1250+
constpassThrough=newStream.PassThrough(streamOptions);
1251+
stream.pipe(passThrough);
12651252

1266-
letendTime;
1253+
passThrough.on('data',chunk=>{
1254+
if(staticEndTime<0){
1255+
initialChunks.push(chunk);
1256+
}else{
1257+
dynamicChunks.push(chunk);
1258+
}
1259+
});
12671260

1268-
awaitnewPromise(resolve=>{
1269-
setTimeout(()=>{
1270-
resolveRuntimeData('Hi');
1261+
passThrough.on('end',resolve);
12711262
});
12721263
setTimeout(()=>{
1273-
isDynamic=true;
1274-
endTime=performance.now()+performance.timeOrigin;
1275-
resolveDynamicData('Josh');
1276-
resolve();
1264+
staticEndTime=performance.now()+performance.timeOrigin;
1265+
resolveDynamicData1('Hi');
1266+
setTimeout(()=>{
1267+
resolveDynamicData2('Josh');
1268+
});
12771269
});
12781270
});
12791271

1280-
awaitnewPromise(resolve=>{
1281-
passThrough.on('end',resolve);
1282-
});
1283-
12841272
// Create a new Readable and push all initial chunks immediately.
12851273
constreadable=newStream.Readable({...streamOptions,read(){}});
12861274
for(leti=0;i<initialChunks.length;i++){
@@ -1311,8 +1299,8 @@ describe('ReactFlightDOMNode', () => {
13111299
},
13121300
{
13131301
// Debug info arriving after this end time will be ignored, e.g. the
1314-
// I/O info for the dynamic data.
1315-
endTime,
1302+
// I/O info for the second dynamic data.
1303+
endTime: staticEndTime,
13161304
},
13171305
);
13181306

@@ -1358,12 +1346,12 @@ describe('ReactFlightDOMNode', () => {
13581346
'\n'+
13591347
' in Dynamic'+
13601348
(gate(flags=>flags.enableAsyncDebugInfo)
1361-
? ' (file://ReactFlightDOMNode-test.js:1223:33)\n'
1349+
? ' (file://ReactFlightDOMNode-test.js:1216:27)\n'
13621350
: '\n')+
13631351
' in body\n'+
13641352
' in html\n'+
1365-
' in App (file://ReactFlightDOMNode-test.js:1240:25)\n'+
1366-
' in ClientRoot (ReactFlightDOMNode-test.js:1320:16)',
1353+
' in App (file://ReactFlightDOMNode-test.js:1233:25)\n'+
1354+
' in ClientRoot (ReactFlightDOMNode-test.js:1308:16)',
13671355
);
13681356
}else{
13691357
expect(
@@ -1372,7 +1360,7 @@ describe('ReactFlightDOMNode', () => {
13721360
'\n'+
13731361
' in body\n'+
13741362
' in html\n'+
1375-
' in ClientRoot (ReactFlightDOMNode-test.js:1320:16)',
1363+
' in ClientRoot (ReactFlightDOMNode-test.js:1308:16)',
13761364
);
13771365
}
13781366

@@ -1382,16 +1370,16 @@ describe('ReactFlightDOMNode', () => {
13821370
normalizeCodeLocInfo(ownerStack,{preserveLocation: true}),
13831371
).toBe(
13841372
'\n'+
1385-
' in Dynamic (file://ReactFlightDOMNode-test.js:1223:33)\n'+
1386-
' in App (file://ReactFlightDOMNode-test.js:1240:25)',
1373+
' in Dynamic (file://ReactFlightDOMNode-test.js:1216:27)\n'+
1374+
' in App (file://ReactFlightDOMNode-test.js:1233:25)',
13871375
);
13881376
}else{
13891377
expect(
13901378
normalizeCodeLocInfo(ownerStack,{preserveLocation: true}),
13911379
).toBe(
13921380
''+
13931381
'\n'+
1394-
' in App (file://ReactFlightDOMNode-test.js:1240:25)',
1382+
' in App (file://ReactFlightDOMNode-test.js:1233:25)',
13951383
);
13961384
}
13971385
}else{

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] Fix debug info filtering to include later resolved I/O (#35036) · react/react@67f7d47 · GitHub
Skip to content

Commit 67f7d47

Browse files
authored
[Flight] Fix debug info filtering to include later resolved I/O (#35036)
In #35019, we excluded debug I/O info from being considered for enhancing the owner stack if it resolved after the defined `endTime` option that can be passed to the Flight client. However, we should include any I/O that was awaited before that end time, even if it resolved later.
1 parent 561ee24 commit 67f7d47

2 files changed

Lines changed: 45 additions & 58 deletions

File tree

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,9 @@ function filterDebugInfo(
510510
return;
511511
}
512512

513-
// Remove any debug info entries that arrived after the defined end time.
513+
// Remove any debug info entries after the defined end time. For async info
514+
// that means we're including anything that was awaited before the end time,
515+
// but it doesn't need to be resolved before the end time.
514516
const relativeEndTime =
515517
response._debugEndTime -
516518
// $FlowFixMe[prop-missing]
@@ -521,9 +523,6 @@ function filterDebugInfo(
521523
if(typeofinfo.time==='number'&&info.time>relativeEndTime){
522524
break;
523525
}
524-
if(info.awaited!=null&&info.awaited.end> relativeEndTime) {
525-
break;
526-
}
527526
debugInfo.push(info);
528527
}
529528
value._debugInfo=debugInfo;

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

Lines changed: 42 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,35 +1197,28 @@ describe('ReactFlightDOMNode', () => {
11971197
});
11981198

11991199
it('should use late-arriving I/O debug info to enhance component and owner stacks when aborting a prerender',async()=>{
1200-
// This test is constructing a scenario where a framework might separate
1201-
// I/O into different phases, e.g. runtime I/O and dynamic I/O. The
1202-
// framework might choose to define an end time for the Flight client,
1203-
// indicating that all I/O info (or any debug info for that matter) that
1204-
// arrives after that time should be ignored. When rendering in Fizz is
1205-
// then aborted, the late-arriving debug info that's used to enhance the
1206-
// owner stack only includes I/O info up to that end time.
1207-
letresolveRuntimeData;
1208-
letresolveDynamicData;
1209-
1210-
asyncfunctiongetRuntimeData(){
1200+
letresolveDynamicData1;
1201+
letresolveDynamicData2;
1202+
1203+
asyncfunctiongetDynamicData1(){
12111204
returnnewPromise(resolve=>{
1212-
resolveRuntimeData=resolve;
1205+
resolveDynamicData1=resolve;
12131206
});
12141207
}
12151208

1216-
asyncfunctiongetDynamicData(){
1209+
asyncfunctiongetDynamicData2(){
12171210
returnnewPromise(resolve=>{
1218-
resolveDynamicData=resolve;
1211+
resolveDynamicData2=resolve;
12191212
});
12201213
}
12211214

12221215
asyncfunctionDynamic(){
1223-
construntimeData=awaitgetRuntimeData();
1224-
constdynamicData=awaitgetDynamicData();
1216+
constdata1=awaitgetDynamicData1();
1217+
constdata2=awaitgetDynamicData2();
12251218

12261219
return(
12271220
<p>
1228-
{runtimeData}{dynamicData}
1221+
{data1}{data2}
12291222
</p>
12301223
);
12311224
}
@@ -1242,45 +1235,40 @@ describe('ReactFlightDOMNode', () => {
12421235
);
12431236
}
12441237

1245-
conststream=awaitReactServerDOMServer.renderToPipeableStream(
1246-
ReactServer.createElement(App),
1247-
webpackMap,
1248-
{filterStackFrame},
1249-
);
1250-
1238+
letstaticEndTime=-1;
12511239
constinitialChunks=[];
12521240
constdynamicChunks=[];
1253-
letisDynamic=false;
12541241

1255-
constpassThrough=newStream.PassThrough(streamOptions);
1256-
stream.pipe(passThrough);
1242+
awaitnewPromise(resolve=>{
1243+
setTimeout(async()=>{
1244+
conststream=ReactServerDOMServer.renderToPipeableStream(
1245+
ReactServer.createElement(App),
1246+
webpackMap,
1247+
{filterStackFrame},
1248+
);
12571249

1258-
passThrough.on('data',chunk=>{
1259-
if(isDynamic){
1260-
dynamicChunks.push(chunk);
1261-
}else{
1262-
initialChunks.push(chunk);
1263-
}
1264-
});
1250+
constpassThrough=newStream.PassThrough(streamOptions);
1251+
stream.pipe(passThrough);
12651252

1266-
letendTime;
1253+
passThrough.on('data',chunk=>{
1254+
if(staticEndTime<0){
1255+
initialChunks.push(chunk);
1256+
}else{
1257+
dynamicChunks.push(chunk);
1258+
}
1259+
});
12671260

1268-
awaitnewPromise(resolve=>{
1269-
setTimeout(()=>{
1270-
resolveRuntimeData('Hi');
1261+
passThrough.on('end',resolve);
12711262
});
12721263
setTimeout(()=>{
1273-
isDynamic=true;
1274-
endTime=performance.now()+performance.timeOrigin;
1275-
resolveDynamicData('Josh');
1276-
resolve();
1264+
staticEndTime=performance.now()+performance.timeOrigin;
1265+
resolveDynamicData1('Hi');
1266+
setTimeout(()=>{
1267+
resolveDynamicData2('Josh');
1268+
});
12771269
});
12781270
});
12791271

1280-
awaitnewPromise(resolve=>{
1281-
passThrough.on('end',resolve);
1282-
});
1283-
12841272
// Create a new Readable and push all initial chunks immediately.
12851273
constreadable=newStream.Readable({...streamOptions,read(){}});
12861274
for(leti=0;i<initialChunks.length;i++){
@@ -1311,8 +1299,8 @@ describe('ReactFlightDOMNode', () => {
13111299
},
13121300
{
13131301
// Debug info arriving after this end time will be ignored, e.g. the
1314-
// I/O info for the dynamic data.
1315-
endTime,
1302+
// I/O info for the second dynamic data.
1303+
endTime: staticEndTime,
13161304
},
13171305
);
13181306

@@ -1358,12 +1346,12 @@ describe('ReactFlightDOMNode', () => {
13581346
'\n'+
13591347
' in Dynamic'+
13601348
(gate(flags=>flags.enableAsyncDebugInfo)
1361-
? ' (file://ReactFlightDOMNode-test.js:1223:33)\n'
1349+
? ' (file://ReactFlightDOMNode-test.js:1216:27)\n'
13621350
: '\n')+
13631351
' in body\n'+
13641352
' in html\n'+
1365-
' in App (file://ReactFlightDOMNode-test.js:1240:25)\n'+
1366-
' in ClientRoot (ReactFlightDOMNode-test.js:1320:16)',
1353+
' in App (file://ReactFlightDOMNode-test.js:1233:25)\n'+
1354+
' in ClientRoot (ReactFlightDOMNode-test.js:1308:16)',
13671355
);
13681356
}else{
13691357
expect(
@@ -1372,7 +1360,7 @@ describe('ReactFlightDOMNode', () => {
13721360
'\n'+
13731361
' in body\n'+
13741362
' in html\n'+
1375-
' in ClientRoot (ReactFlightDOMNode-test.js:1320:16)',
1363+
' in ClientRoot (ReactFlightDOMNode-test.js:1308:16)',
13761364
);
13771365
}
13781366

@@ -1382,16 +1370,16 @@ describe('ReactFlightDOMNode', () => {
13821370
normalizeCodeLocInfo(ownerStack,{preserveLocation: true}),
13831371
).toBe(
13841372
'\n'+
1385-
' in Dynamic (file://ReactFlightDOMNode-test.js:1223:33)\n'+
1386-
' in App (file://ReactFlightDOMNode-test.js:1240:25)',
1373+
' in Dynamic (file://ReactFlightDOMNode-test.js:1216:27)\n'+
1374+
' in App (file://ReactFlightDOMNode-test.js:1233:25)',
13871375
);
13881376
}else{
13891377
expect(
13901378
normalizeCodeLocInfo(ownerStack,{preserveLocation: true}),
13911379
).toBe(
13921380
''+
13931381
'\n'+
1394-
' in App (file://ReactFlightDOMNode-test.js:1240:25)',
1382+
' in App (file://ReactFlightDOMNode-test.js:1233:25)',
13951383
);
13961384
}
13971385
}else{

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] Fix debug info filtering to include later resolved I/O (#35036) · react/react@67f7d47 · GitHub
Skip to content

Commit 67f7d47

Browse files
authored
[Flight] Fix debug info filtering to include later resolved I/O (#35036)
In #35019, we excluded debug I/O info from being considered for enhancing the owner stack if it resolved after the defined `endTime` option that can be passed to the Flight client. However, we should include any I/O that was awaited before that end time, even if it resolved later.
1 parent 561ee24 commit 67f7d47

2 files changed

Lines changed: 45 additions & 58 deletions

File tree

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,9 @@ function filterDebugInfo(
510510
return;
511511
}
512512

513-
// Remove any debug info entries that arrived after the defined end time.
513+
// Remove any debug info entries after the defined end time. For async info
514+
// that means we're including anything that was awaited before the end time,
515+
// but it doesn't need to be resolved before the end time.
514516
const relativeEndTime =
515517
response._debugEndTime -
516518
// $FlowFixMe[prop-missing]
@@ -521,9 +523,6 @@ function filterDebugInfo(
521523
if(typeofinfo.time==='number'&&info.time>relativeEndTime){
522524
break;
523525
}
524-
if(info.awaited!=null&&info.awaited.end> relativeEndTime) {
525-
break;
526-
}
527526
debugInfo.push(info);
528527
}
529528
value._debugInfo=debugInfo;

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

Lines changed: 42 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,35 +1197,28 @@ describe('ReactFlightDOMNode', () => {
11971197
});
11981198

11991199
it('should use late-arriving I/O debug info to enhance component and owner stacks when aborting a prerender',async()=>{
1200-
// This test is constructing a scenario where a framework might separate
1201-
// I/O into different phases, e.g. runtime I/O and dynamic I/O. The
1202-
// framework might choose to define an end time for the Flight client,
1203-
// indicating that all I/O info (or any debug info for that matter) that
1204-
// arrives after that time should be ignored. When rendering in Fizz is
1205-
// then aborted, the late-arriving debug info that's used to enhance the
1206-
// owner stack only includes I/O info up to that end time.
1207-
letresolveRuntimeData;
1208-
letresolveDynamicData;
1209-
1210-
asyncfunctiongetRuntimeData(){
1200+
letresolveDynamicData1;
1201+
letresolveDynamicData2;
1202+
1203+
asyncfunctiongetDynamicData1(){
12111204
returnnewPromise(resolve=>{
1212-
resolveRuntimeData=resolve;
1205+
resolveDynamicData1=resolve;
12131206
});
12141207
}
12151208

1216-
asyncfunctiongetDynamicData(){
1209+
asyncfunctiongetDynamicData2(){
12171210
returnnewPromise(resolve=>{
1218-
resolveDynamicData=resolve;
1211+
resolveDynamicData2=resolve;
12191212
});
12201213
}
12211214

12221215
asyncfunctionDynamic(){
1223-
construntimeData=awaitgetRuntimeData();
1224-
constdynamicData=awaitgetDynamicData();
1216+
constdata1=awaitgetDynamicData1();
1217+
constdata2=awaitgetDynamicData2();
12251218

12261219
return(
12271220
<p>
1228-
{runtimeData}{dynamicData}
1221+
{data1}{data2}
12291222
</p>
12301223
);
12311224
}
@@ -1242,45 +1235,40 @@ describe('ReactFlightDOMNode', () => {
12421235
);
12431236
}
12441237

1245-
conststream=awaitReactServerDOMServer.renderToPipeableStream(
1246-
ReactServer.createElement(App),
1247-
webpackMap,
1248-
{filterStackFrame},
1249-
);
1250-
1238+
letstaticEndTime=-1;
12511239
constinitialChunks=[];
12521240
constdynamicChunks=[];
1253-
letisDynamic=false;
12541241

1255-
constpassThrough=newStream.PassThrough(streamOptions);
1256-
stream.pipe(passThrough);
1242+
awaitnewPromise(resolve=>{
1243+
setTimeout(async()=>{
1244+
conststream=ReactServerDOMServer.renderToPipeableStream(
1245+
ReactServer.createElement(App),
1246+
webpackMap,
1247+
{filterStackFrame},
1248+
);
12571249

1258-
passThrough.on('data',chunk=>{
1259-
if(isDynamic){
1260-
dynamicChunks.push(chunk);
1261-
}else{
1262-
initialChunks.push(chunk);
1263-
}
1264-
});
1250+
constpassThrough=newStream.PassThrough(streamOptions);
1251+
stream.pipe(passThrough);
12651252

1266-
letendTime;
1253+
passThrough.on('data',chunk=>{
1254+
if(staticEndTime<0){
1255+
initialChunks.push(chunk);
1256+
}else{
1257+
dynamicChunks.push(chunk);
1258+
}
1259+
});
12671260

1268-
awaitnewPromise(resolve=>{
1269-
setTimeout(()=>{
1270-
resolveRuntimeData('Hi');
1261+
passThrough.on('end',resolve);
12711262
});
12721263
setTimeout(()=>{
1273-
isDynamic=true;
1274-
endTime=performance.now()+performance.timeOrigin;
1275-
resolveDynamicData('Josh');
1276-
resolve();
1264+
staticEndTime=performance.now()+performance.timeOrigin;
1265+
resolveDynamicData1('Hi');
1266+
setTimeout(()=>{
1267+
resolveDynamicData2('Josh');
1268+
});
12771269
});
12781270
});
12791271

1280-
awaitnewPromise(resolve=>{
1281-
passThrough.on('end',resolve);
1282-
});
1283-
12841272
// Create a new Readable and push all initial chunks immediately.
12851273
constreadable=newStream.Readable({...streamOptions,read(){}});
12861274
for(leti=0;i<initialChunks.length;i++){
@@ -1311,8 +1299,8 @@ describe('ReactFlightDOMNode', () => {
13111299
},
13121300
{
13131301
// Debug info arriving after this end time will be ignored, e.g. the
1314-
// I/O info for the dynamic data.
1315-
endTime,
1302+
// I/O info for the second dynamic data.
1303+
endTime: staticEndTime,
13161304
},
13171305
);
13181306

@@ -1358,12 +1346,12 @@ describe('ReactFlightDOMNode', () => {
13581346
'\n'+
13591347
' in Dynamic'+
13601348
(gate(flags=>flags.enableAsyncDebugInfo)
1361-
? ' (file://ReactFlightDOMNode-test.js:1223:33)\n'
1349+
? ' (file://ReactFlightDOMNode-test.js:1216:27)\n'
13621350
: '\n')+
13631351
' in body\n'+
13641352
' in html\n'+
1365-
' in App (file://ReactFlightDOMNode-test.js:1240:25)\n'+
1366-
' in ClientRoot (ReactFlightDOMNode-test.js:1320:16)',
1353+
' in App (file://ReactFlightDOMNode-test.js:1233:25)\n'+
1354+
' in ClientRoot (ReactFlightDOMNode-test.js:1308:16)',
13671355
);
13681356
}else{
13691357
expect(
@@ -1372,7 +1360,7 @@ describe('ReactFlightDOMNode', () => {
13721360
'\n'+
13731361
' in body\n'+
13741362
' in html\n'+
1375-
' in ClientRoot (ReactFlightDOMNode-test.js:1320:16)',
1363+
' in ClientRoot (ReactFlightDOMNode-test.js:1308:16)',
13761364
);
13771365
}
13781366

@@ -1382,16 +1370,16 @@ describe('ReactFlightDOMNode', () => {
13821370
normalizeCodeLocInfo(ownerStack,{preserveLocation: true}),
13831371
).toBe(
13841372
'\n'+
1385-
' in Dynamic (file://ReactFlightDOMNode-test.js:1223:33)\n'+
1386-
' in App (file://ReactFlightDOMNode-test.js:1240:25)',
1373+
' in Dynamic (file://ReactFlightDOMNode-test.js:1216:27)\n'+
1374+
' in App (file://ReactFlightDOMNode-test.js:1233:25)',
13871375
);
13881376
}else{
13891377
expect(
13901378
normalizeCodeLocInfo(ownerStack,{preserveLocation: true}),
13911379
).toBe(
13921380
''+
13931381
'\n'+
1394-
' in App (file://ReactFlightDOMNode-test.js:1240:25)',
1382+
' in App (file://ReactFlightDOMNode-test.js:1233:25)',
13951383
);
13961384
}
13971385
}else{

0 commit comments

Comments
 (0)