Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
static async audit(artifacts, context) {
const trace = artifacts.traces[Audit.DEFAULT_PASS];
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
const networkRecords = await NetworkRecords.request(devtoolsLog, context);
/** @type {LH.Artifacts.TaskNode[]} */ let mainThreadTasks = [];
try {
mainThreadTasks = await MainThreadTasks.request(trace, context);
} catch (e) {
// Ignore tracing errors.
}
const {timings} = await TraceOfTab.request(trace, context);
const timerEvents =
trace.traceEvents.filter((t) => t.name.startsWith('Timer'));
const pageStartTime = getPageStartTime(networkRecords);
const blockingRequests =
await computeAdRequestWaterfall(trace, devtoolsLog, context);
if (!blockingRequests.length) {
return auditNotApplicable.NoAdRelatedReq;
static async audit(artifacts, context) {
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
const trace = artifacts.traces[Audit.DEFAULT_PASS];
const unfilteredNetworkRecords =
await NetworkRecords.request(devtoolsLog, context);
if (!unfilteredNetworkRecords.length) {
return auditNotApplicable.NoRecords;
}
const mainResource =
await MainResource.request({URL: artifacts.URL, devtoolsLog}, context);
// Filter out requests without responses, image responses, and responses
// taking less than 50ms.
const networkRecords = unfilteredNetworkRecords
.filter(isPossibleBid)
.filter((r) => r.frameId == mainResource.frameId);
// We filter for URLs that are related to header bidding.
// Then we create shallow copies of each record. This is because the records
// by default have circular structure, which causes an error to be thrown
static async audit(artifacts, context) {
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
const trace = artifacts.traces[Audit.DEFAULT_PASS];
const networkRecords = await NetworkRecords.request(devtoolsLog, context);
const tag = networkRecords.find((req) => isAdTag(new URL(req.url)));
if (!tag) {
return auditNotApplicable.NoTag;
}
/** @type {Map} */
const timingsByRecord =
await getTimingsByRecord(trace, devtoolsLog, context);
// NOTE(warrengm): Ideally we would key be requestId here but LinkElements
// don't have request IDs.
/** @type {Set} */
const blockingElementUrls = new Set();
for (const link of artifacts.LinkElements) {
// TODO(warrengm): Check for media queries? Or is the network filter below
// sufficient?
static async audit(artifacts, context) {
const trace = artifacts.traces[Audit.DEFAULT_PASS];
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
const networkRecords = await NetworkRecords.request(devtoolsLog, context);
const {timings, processEvents} = await TraceOfTab.request(trace, context);
/** @type {Map} */
const timingsByRecord =
await getTimingsByRecord(trace, devtoolsLog, context);
const criticalRequests =
(await computeAdRequestWaterfall(trace, devtoolsLog, context))
// Sort by start time so we process the earliest requests first.
.sort((a, b) => a.startTime - b.startTime);
if (!criticalRequests.length) {
return auditNotApplicable.NoAdRelatedReq;
}
const eventTimes = [
...findEventIntervals('domContentLoaded', processEvents),
async function getTimingsByRecord(trace, devtoolsLog, context) {
/** @type {Map} */
const timingsByRecord = new Map();
const networkRecords = await NetworkRecords.request(devtoolsLog, context);
if (context.settings.throttlingMethod == 'simulate') {
/** @type {NetworkNode} */
const documentNode =
// @ts-ignore Property 'request' does not appear on PageDependencyGraph
await PageDependencyGraph.request({trace, devtoolsLog}, context);
const releventGraph = AdLanternMetric.getOptimisticGraph(documentNode);
const simulator = await LoadSimulator.request(
{devtoolsLog, settings: context.settings}, context);
const {nodeTimings} = simulator.simulate(releventGraph, {});
for (const [{record}, timing] of nodeTimings.entries()) {
if (!record) continue;
timingsByRecord.set(record, timing);
}
} else {
const pageStartTime = getPageStartTime(networkRecords);
for (const record of networkRecords) {
static async audit(artifacts, context) {
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
const networkRecords = await NetworkRecords.request(devtoolsLog, context);
const mainResource =
await MainResource.request({URL: artifacts.URL, devtoolsLog}, context);
const tagReqs = networkRecords
.filter((req) => isAdTag(new URL(req.url)))
.filter((req) => req.frameId === mainResource.frameId);
if (!tagReqs.length) {
return auditNotApplicable.NoTag;
}
const numSync = array.count(tagReqs, isAsync) - tagReqs.length;
const passed = (numSync === 0);
return {
score: Number(passed),
numericValue: numSync,
};
static async audit(artifacts, context) {
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
const networkRecords = await NetworkRecords.request(devtoolsLog, context);
const gptUrl = networkRecords.map((r) => new URL(r.url)).find(isGptTag);
if (!gptUrl) {
return auditNotApplicable.NoGpt;
}
const passed = (gptUrl.host === 'securepubads.g.doubleclick.net');
return {
score: Number(passed),
numericValue: Number(!passed),
};
}
}
static async audit(artifacts, context) {
const devtoolsLogs = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
const networkRecords = await NetworkRecords.request(devtoolsLogs, context);
const tagReqs = networkRecords
.filter((req) => isGptTag(new URL(req.url)));
if (!tagReqs.length) {
return auditNotApplicable.NoTag;
}
const numStatic = array.count(tagReqs, isStaticRequest);
const numTags = tagReqs.length;
const dynamicReq = tagReqs.find((r) => !isStaticRequest(r));
const table = dynamicReq ? getDetailsTable(dynamicReq) : [];
const failed = numStatic < numTags;
let displayValue = '';
if (failed) {
static async audit(artifacts, context) {
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
const trace = artifacts.traces[Audit.DEFAULT_PASS];
const network = await NetworkRecords.request(devtoolsLog, context);
const pubadsImpl = network.find((r) => isGptImplTag(r.url));
if (!pubadsImpl) {
return auditNotApplicable.NoGpt;
}
const bids = network.filter(isBidRequest)
.filter((b) => b.frameId == pubadsImpl.frameId);
if (!bids.length) {
return auditNotApplicable.NoBids;
}
/** @type {Map} */
const timingsByRecord = await getTimingsByRecord(
trace, devtoolsLog, context);
const tableView = [];
static async audit(artifacts, context) {
const devtoolsLogs = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
const networkRecords = await NetworkRecords.request(devtoolsLogs, context);
const pageReq = networkRecords.find((record) => record.statusCode == 200);
if (!pageReq) {
return auditNotApplicable.NoRecords;
}
const adRequests = networkRecords
.filter((record) => isAdTag(new URL(record.url)));
const secureAdRequests = adRequests.filter((request) => request.isSecure);
/** @type {LH.Audit.Details.DebugData} */
const details = {
type: 'debugdata',
numAdTagHttpReqs: adRequests.length - secureAdRequests.length,
numAdTagHttpsReqs: secureAdRequests.length,