diff --git a/lighthouse-core/gather/computed/trace-of-tab.js b/lighthouse-core/gather/computed/trace-of-tab.js index 62b6ce86f3e4..dc381f57a6ab 100644 --- a/lighthouse-core/gather/computed/trace-of-tab.js +++ b/lighthouse-core/gather/computed/trace-of-tab.js @@ -42,21 +42,42 @@ class TraceOfTab extends ComputedArtifact { // *must* be stable to keep events correctly nested. /** @type Array */ const keyEvents = trace.traceEvents - .filter(e => { - return e.cat.includes('blink.user_timing') || + .filter(e => + e.cat.includes('blink.user_timing') || e.cat.includes('loading') || e.cat.includes('devtools.timeline') || - e.name === 'TracingStartedInPage'; - }) + e.cat === '__metadata') // @ts-ignore - stableSort added to Array by WebInspector. .stableSort((event0, event1) => event0.ts - event1.ts); - // The first TracingStartedInPage in the trace is definitely our renderer thread of interest - // Beware: the tracingStartedInPage event can appear slightly after a navigationStart - const startedInPageEvt = keyEvents.find(e => e.name === 'TracingStartedInPage'); + // Find out the inspected page frame. + /** @type {LH.TraceEvent|undefined} */ + let startedInPageEvt; + const startedInBrowserEvt = keyEvents.find(e => e.name === 'TracingStartedInBrowser'); + if (startedInBrowserEvt && startedInBrowserEvt.args.data && + startedInBrowserEvt.args.data.persistentIds) { + const mainFrame = (startedInBrowserEvt.args.data.frames || []).find(frame => !frame.parent); + const pid = mainFrame && mainFrame.processId; + const threadNameEvt = keyEvents.find(e => e.pid === pid && e.ph === 'M' && + e.cat === '__metadata' && e.name === 'thread_name' && + // @ts-ignore - property chain exists for 'thread_name' event. + e.args.name === 'CrRendererMain'); + startedInPageEvt = mainFrame && threadNameEvt ? + Object.assign({}, startedInBrowserEvt, { + pid, tid: threadNameEvt.tid, name: 'TracingStartedInPage', + args: {data: {page: mainFrame.frame}}}) : + undefined; + } + // Support legacy browser versions that do not emit TracingStartedInBrowser event. + if (!startedInPageEvt) { + // The first TracingStartedInPage in the trace is definitely our renderer thread of interest + // Beware: the tracingStartedInPage event can appear slightly after a navigationStart + startedInPageEvt = keyEvents.find(e => e.name === 'TracingStartedInPage'); + } if (!startedInPageEvt) throw new LHError(LHError.errors.NO_TRACING_STARTED); // @ts-ignore - property chain exists for 'TracingStartedInPage' event. const frameId = startedInPageEvt.args.data.page; + // Filter to just events matching the frame ID for sanity const frameEvents = keyEvents.filter(e => e.args.frame === frameId); @@ -106,12 +127,12 @@ class TraceOfTab extends ComputedArtifact { // stable-sort events to keep them correctly nested. /** @type Array */ const processEvents = trace.traceEvents - .filter(e => e.pid === startedInPageEvt.pid) + .filter(e => e.pid === /** @type {LH.TraceEvent} */ (startedInPageEvt).pid) // @ts-ignore - stableSort added to Array by WebInspector. .stableSort((event0, event1) => event0.ts - event1.ts); const mainThreadEvents = processEvents - .filter(e => e.tid === startedInPageEvt.tid); + .filter(e => e.tid === /** @type {LH.TraceEvent} */ (startedInPageEvt).tid); const traceEnd = trace.traceEvents.reduce((max, evt) => { return max.ts > evt.ts ? max : evt; diff --git a/lighthouse-core/test/fixtures/traces/threeframes-blank_content_more.json b/lighthouse-core/test/fixtures/traces/threeframes-blank_content_more.json index 38dfee3ca248..ab528381c16c 100644 --- a/lighthouse-core/test/fixtures/traces/threeframes-blank_content_more.json +++ b/lighthouse-core/test/fixtures/traces/threeframes-blank_content_more.json @@ -20,7 +20,7 @@ "tid": 1295, "ts": 900000000000, "ph": "X", - "cat": "toplevel", + "cat": "devtools.timeline", "name": "TracingStartedInPage", "args": { "data": { diff --git a/lighthouse-core/test/gather/computed/trace-of-tab-test.js b/lighthouse-core/test/gather/computed/trace-of-tab-test.js index cc0d281db0f1..77ca29474ca9 100644 --- a/lighthouse-core/test/gather/computed/trace-of-tab-test.js +++ b/lighthouse-core/test/gather/computed/trace-of-tab-test.js @@ -112,6 +112,56 @@ describe('Trace of Tab computed artifact:', () => { assert.equal(trace.firstMeaningfulPaintEvt, undefined, 'bad fmp'); }); + it('handles traces with TracingStartedInBrowser events', async () => { + const tracingStartedInBrowserTrace = { + 'traceEvents': [{ + 'pid': 69850, + 'tid': 69850, + 'ts': 2193564729582, + 'ph': 'I', + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'TracingStartedInBrowser', + 'args': {'data': { + 'frameTreeNodeId': 1, + 'persistentIds': true, + 'frames': [{ + 'frame': 'B192D1F3355A6F961EC8F0B01623C1FB', + 'url': 'http://www.example.com/', + 'name': '', + 'processId': 69920, + }], + }}, + 'tts': 1085165, + 's': 't', + }, { + 'pid': 69920, + 'tid': 1, + 'ts': 2193564790059, + 'ph': 'R', + 'cat': 'blink.user_timing', + 'name': 'navigationStart', + 'args': { + 'frame': 'B192D1F3355A6F961EC8F0B01623C1FB', + 'data': { + 'documentLoaderURL': 'http://www.example.com/', + 'isLoadingMainFrame': true, + }, + }, + 'tts': 141371, + }, { + 'pid': 69920, + 'tid': 1, + 'ts': 0, + 'ph': 'M', + 'cat': '__metadata', + 'name': 'thread_name', + 'args': {'name': 'CrRendererMain'}, + }]}; + const trace = await traceOfTab.compute_(tracingStartedInBrowserTrace); + assert.equal(trace.startedInPageEvt.ts, 2193564729582); + assert.equal(trace.navigationStartEvt.ts, 2193564790059); + }); + it('stably sorts events', async () => { const traceJson = fs.readFileSync(__dirname + '/../../fixtures/traces/tracingstarted-after-navstart.json', 'utf8'); diff --git a/typings/externs.d.ts b/typings/externs.d.ts index 1b6a67dc16b5..c6bd70afb923 100644 --- a/typings/externs.d.ts +++ b/typings/externs.d.ts @@ -137,6 +137,12 @@ declare global { cat: string; args: { data?: { + persistentIds?: boolean; + frames?: { + frame: string; + parent?: string; + processId?: number; + }[]; page?: string; readyState?: number; requestId?: string;