Skip to content

Commit 2e50e01

Browse files
Only lint JavaScript belonging to the tested page
A browsertime HAR can contain more than one page, for example when a concurrent browsertime run on the same host races for the same Chrome DevTools port and its crossed CDP session records another website's page load into this run's recording (see Webperf-se/webperf_core#1557). This analyzer linted every JavaScript response body and every inline script in the whole HAR, so a crossed-in recording could attribute another website's JavaScript issues to the tested website. Filter entries to the ones belonging to the first page in the HAR's pages array, and verify that the recording's first request matches the tested URL's hostname (the URL API normalizes IDN hostnames to punycode on both sides). On mismatch nothing is analyzed. HARs without a pages array and entries without pageref behave as before.
1 parent 9360a63 commit 2e50e01

1 file changed

Lines changed: 42 additions & 5 deletions

File tree

lib/harAnalyzer.js

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,47 @@ export class HarAnalyzer {
2929
this.dependencies = this.package.dependencies;
3030
this.version = this.package.version;
3131
}
32+
getFirstPageEntries(url, harData) {
33+
if ('log' in harData) {
34+
harData = harData['log'];
35+
}
36+
37+
const entries = harData.entries;
38+
if (!Array.isArray(entries)) {
39+
return [];
40+
}
41+
42+
// A HAR can contain more than one page, for example when a concurrent
43+
// browsertime run ends up in the same browser session (crossed DevTools
44+
// port) and navigates to another website mid-recording. Requests made
45+
// by other pages must not be attributed to the tested website, and if
46+
// the recording doesn't even start with the tested website nothing in
47+
// it can be trusted.
48+
if (url && entries.length > 0) {
49+
const firstUrl = entries[0].request && entries[0].request.url;
50+
if (firstUrl) {
51+
try {
52+
if (new URL(firstUrl).hostname !== new URL(url).hostname) {
53+
return [];
54+
}
55+
} catch {
56+
// Unparsable URLs are handled by the entry loops as before
57+
}
58+
}
59+
}
60+
61+
const pages = harData.pages;
62+
if (!Array.isArray(pages) || pages.length === 0) {
63+
return entries;
64+
}
65+
const firstPageId = pages[0].id;
66+
if (firstPageId === undefined) {
67+
return entries;
68+
}
69+
return entries.filter(entry =>
70+
entry.pageref === undefined || entry.pageref === firstPageId);
71+
}
72+
3273
transform2SimplifiedData(harData, url) {
3374
const data = {
3475
'url': url,
@@ -41,13 +82,9 @@ export class HarAnalyzer {
4182
'script-files': []
4283
};
4384

44-
if ('log' in harData) {
45-
harData = harData['log'];
46-
}
47-
4885
let reqIndex = 1;
4986

50-
for (const entry of harData.entries) {
87+
for (const entry of this.getFirstPageEntries(url, harData)) {
5188
const req = entry.request;
5289
const res = entry.response;
5390
const reqUrl = req.url;

0 commit comments

Comments
 (0)