Skip to content

Commit da824b8

Browse files
jackfranklinDevtools-frontend LUCI CQ
authored andcommitted
TraceEngine: update render_blocking with preload status change
This CL fixes a bug where a blocking resource (e.g. stylesheet) is not marked as blocking in RPP because it is first preloaded. This was because we did not pay attention to the PreloadRenderBlockingStatusChange event which exists for this exact reason. With this CL when we construct the final synthetic network request for a resource, we will use the render blocking status from the last PreloadRenderBlockingStatusChange event (if we have any), before falling back to the render blocking status on the SendRequest event. [email protected] Fixed: 457323832 Change-Id: I996a3372a4ec8f9cbf8d1c387b2ec44a80aa9c14 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/7112841 Auto-Submit: Jack Franklin <[email protected]> Reviewed-by: Connor Clark <[email protected]> Commit-Queue: Connor Clark <[email protected]>
1 parent 5b4117d commit da824b8

File tree

6 files changed

+60
-3
lines changed

6 files changed

+60
-3
lines changed

front_end/models/trace/handlers/NetworkRequestsHandler.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,24 @@ describe('NetworkRequestsHandler', function() {
471471
assert.deepEqual(actualLinks, expectedLinks);
472472
});
473473
});
474+
475+
it('updates render blocking request statuses if they were updated with a preloadRenderBlockingStatusChange event',
476+
async function() {
477+
const traceEvents = await TraceLoader.rawEvents(this, 'render-blocking-preload.json.gz');
478+
for (const event of traceEvents) {
479+
Trace.Handlers.ModelHandlers.Meta.handleEvent(event);
480+
Trace.Handlers.ModelHandlers.NetworkRequests.handleEvent(event);
481+
}
482+
await Trace.Handlers.ModelHandlers.Meta.finalize();
483+
await Trace.Handlers.ModelHandlers.NetworkRequests.finalize();
484+
const url = 'https://andydavies.github.io/agent-tests/render-blocking/css/styles.css';
485+
const data = Trace.Handlers.ModelHandlers.NetworkRequests.data();
486+
487+
const request = data.byTime.find(e => e.args.data.url === url);
488+
assert.isOk(request);
489+
490+
assert.strictEqual(request.args.data.renderBlocking, 'blocking');
491+
});
474492
});
475493

476494
function assertDataArgsStats<D extends keyof DataArgs>(

front_end/models/trace/handlers/NetworkRequestsHandler.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export interface TraceEventsForNetworkRequest {
3232
resourceFinish?: Types.Events.ResourceFinish;
3333
receivedData?: Types.Events.ResourceReceivedData[];
3434
resourceMarkAsCached?: Types.Events.ResourceMarkAsCached;
35+
preloadRenderBlockingStatusChange?: Types.Events.PreloadRenderBlockingStatusChangeEvent[];
3536
}
3637

3738
export interface WebSocketTraceDataForFrame {
@@ -164,6 +165,10 @@ export function handleEvent(event: Types.Events.Event): void {
164165
return;
165166
}
166167

168+
if (Types.Events.isPreloadRenderBlockingStatusChangeEvent(event)) {
169+
storeTraceEventWithRequestId(event.args.data.requestId, 'preloadRenderBlockingStatusChange', [event]);
170+
}
171+
167172
if (Types.Events.isWebSocketCreate(event) || Types.Events.isWebSocketInfo(event) ||
168173
Types.Events.isWebSocketTransfer(event)) {
169174
const identifier = event.args.data.identifier;
@@ -487,13 +492,24 @@ export async function finalize(): Promise<void> {
487492
Types.Timing.Micro(0);
488493

489494
// Finally get some of the general data from the trace events.
490-
const {frame, url, renderBlocking} = finalSendRequest.args.data;
495+
const {frame, url, renderBlocking: sendRequestIsRenderBlocking} = finalSendRequest.args.data;
491496
const {encodedDataLength, decodedBodyLength} =
492497
request.resourceFinish ? request.resourceFinish.args.data : {encodedDataLength: 0, decodedBodyLength: 0};
493498
const parsedUrl = new URL(url);
494499
const isHttps = parsedUrl.protocol === 'https:';
495500
const requestingFrameUrl =
496501
Helpers.Trace.activeURLForFrameAtTime(frame, finalSendRequest.ts, rendererProcessesByFrame) || '';
502+
503+
// A resource that is preloaded (and not marked as render blocking) can
504+
// become render blocked later via a PreloadRenderBlockingStatusChange. In
505+
// this case, we take the render blocking value of the last
506+
// PreloadRenderBlockingStatusChange for this request.
507+
const preloadRenderBlockingStatusChange =
508+
request.preloadRenderBlockingStatusChange?.at(-1)?.args.data.renderBlocking;
509+
510+
// In the event the property isn't set, assume non-blocking.
511+
const isRenderBlocking = preloadRenderBlockingStatusChange ?? sendRequestIsRenderBlocking ?? 'non_blocking';
512+
497513
// Construct a synthetic trace event for this network request.
498514
const networkEvent =
499515
Helpers.SyntheticEvents.SyntheticEventsManager.registerSyntheticEvent<Types.Events.SyntheticNetworkRequest>({
@@ -535,8 +551,7 @@ export async function finalize(): Promise<void> {
535551
initialPriority,
536552
protocol: request.receiveResponse?.args.data.protocol ?? 'unknown',
537553
redirects,
538-
// In the event the property isn't set, assume non-blocking.
539-
renderBlocking: renderBlocking ?? 'non_blocking',
554+
renderBlocking: isRenderBlocking,
540555
requestId,
541556
requestingFrameUrl,
542557
requestMethod: finalSendRequest.args.data.requestMethod,

front_end/models/trace/types/TraceEvents.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3142,6 +3142,8 @@ export const enum Name {
31423142
USER_TIMING_MEASURE = 'UserTiming::Measure',
31433143

31443144
LINK_PRECONNECT = 'LinkPreconnect',
3145+
3146+
PRELOAD_RENDER_BLOCKING_STATUS_CHANGE = 'PreloadRenderBlockingStatusChange',
31453147
}
31463148

31473149
/**
@@ -3275,3 +3277,20 @@ export function isAnyScriptSourceEvent(event: Event): event is RundownScriptSour
32753277
RundownScriptStub {
32763278
return event.cat === 'disabled-by-default-devtools.v8-source-rundown-sources';
32773279
}
3280+
3281+
export interface PreloadRenderBlockingStatusChangeEvent extends Instant {
3282+
name: Name.PRELOAD_RENDER_BLOCKING_STATUS_CHANGE;
3283+
cat: 'devtools.timeline';
3284+
args: Args&{
3285+
data: {
3286+
requestId: string,
3287+
url: string,
3288+
renderBlocking?: RenderBlocking,
3289+
},
3290+
};
3291+
}
3292+
3293+
export function isPreloadRenderBlockingStatusChangeEvent(event: Event):
3294+
event is PreloadRenderBlockingStatusChangeEvent {
3295+
return event.name === Name.PRELOAD_RENDER_BLOCKING_STATUS_CHANGE;
3296+
}

front_end/panels/timeline/fixtures/traces/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ copy_to_gen("traces") {
110110
"reload-no-tti.json.gz",
111111
"render-blocking-body.json.gz",
112112
"render-blocking-in-iframe.json.gz",
113+
"render-blocking-preload.json.gz",
113114
"render-blocking-requests.json.gz",
114115
"scheduler-post-task.json.gz",
115116
"scripts/coursehero-bundle-1.js.gz",

front_end/panels/timeline/fixtures/traces/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,3 +365,7 @@ A trace that has a layout shift with a root cause that is a non-composited anima
365365
### cls-with-iframes
366366

367367
A trace of https://astro-news-1026410574114.us-central1.run.app/ used to test CLS + iframes and what our AI output looks like.
368+
369+
### render-blocking-preload
370+
371+
A trace of https://andydavies.github.io/agent-tests/render-blocking/css-preload.html that highlighted a bug where we do not update render blocking status based on PreloadRenderBlockingStatus events (crbug.com/457323832).
Binary file not shown.

0 commit comments

Comments
 (0)