Skip to content

Commit

Permalink
core: refactor out entity-classification lookup tables (#14744)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexnj committed Feb 2, 2023
1 parent b245ca3 commit bdbc91b
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 177 deletions.
29 changes: 9 additions & 20 deletions core/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,37 +154,26 @@ class Runner {

/** @type {Array<LH.Result.LhrEntity>} */
const entities = [];
/** @type {Record<string, number>} */
const entityIndexByOrigin = {};
/** @type {Record<string, number>} */
const entityIndexByName = {};

for (const [entity, entityUrls] of classifiedEntities.urlsByEntity) {
const uniqueOrigins = new Set();
for (const url of entityUrls) {
const origin = UrlUtils.getOrigin(url);
if (origin) uniqueOrigins.add(origin);
}

/** @type {LH.Result.LhrEntity} */
const shortEntity = {
name: entity.name,
homepage: entity.homepage,
origins: [...uniqueOrigins],
};

// Reduce payload size in LHR JSON by omitting whats falsy.
if (entity === classifiedEntities.firstParty) shortEntity.isFirstParty = true;
if (entity.isUnrecognized) shortEntity.isUnrecognized = true;

const id = entities.push(shortEntity) - 1;
for (const url of entityUrls) {
const origin = UrlUtils.getOrigin(url);
if (!origin) continue;
entityIndexByOrigin[origin] = id;
}
entityIndexByName[shortEntity.name] = id;
entities.push(shortEntity);
}

return {
list: entities,
firstParty: classifiedEntities.firstParty?.name,
entityIndexByOrigin,
entityIndexByName,
};
return entities;
}

/**
Expand Down
121 changes: 53 additions & 68 deletions core/test/fixtures/fraggle-rock/reports/sample-flow-result.json

Large diffs are not rendered by default.

37 changes: 16 additions & 21 deletions core/test/results/sample_v2.json

Large diffs are not rendered by default.

22 changes: 5 additions & 17 deletions proto/lighthouse-result.proto
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ message LighthouseResult {
google.protobuf.Value full_page_screenshot = 19;

// Entity classification data.
Entities entities = 20;
repeated LhrEntity entities = 20;
}

// Message containing a category
Expand Down Expand Up @@ -614,26 +614,11 @@ message StackPack {
map<string, string> descriptions = 4;
}

// Message containing Entity Classification.
message Entities {
// List of entities.
repeated LhrEntity list = 1;

// Name of the first-party entity.
string firstParty = 2;

// Lookup table that maps URL origins to corresponding index in entities.
map<string, uint32> entityIndexByOrigin = 3;

// Lookup table that maps entity names to corresponding index in entities.
map<string, uint32> entityIndexByName = 4;
}

// Message containing an Entity.
message LhrEntity {
// Name of the entity.
string name = 1;

// An optional homepage URL of the entity.
optional string homepage = 2;

Expand All @@ -645,4 +630,7 @@ message LhrEntity {

// An optional flag indicating if the entity is not recognized.
optional bool isUnrecognized = 5;

// A list of URL origin strings that belong to this entity.
repeated string origins = 6;
}
2 changes: 1 addition & 1 deletion report/renderer/report-ui-features.js
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ export class ReportUIFeatures {
*/
_getThirdPartyRows(rowEls, finalDisplayedUrl) {
const finalDisplayedUrlRootDomain = Util.getRootDomain(finalDisplayedUrl);
const firstPartyEntityName = this.json.entities?.firstParty;
const firstPartyEntityName = this.json.entities?.find(e => e.isFirstParty === true)?.name;

/** @type {Array<HTMLElement>} */
const thirdPartyRowEls = [];
Expand Down
14 changes: 6 additions & 8 deletions report/renderer/report-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,11 @@ class ReportUtils {

/**
* Mark TableItems/OpportunityItems with entity names.
* @param {LH.Result.Entities|undefined} entityClassification
* @param {LH.Result.Entities|undefined} entities
* @param {import('../../types/lhr/audit-result').Result} audit
*/
static classifyEntities(entityClassification, audit) {
if (!entityClassification) return;
static classifyEntities(entities, audit) {
if (!entities) return;
if (audit.details?.type !== 'opportunity' && audit.details?.type !== 'table') {
return;
}
Expand All @@ -130,17 +130,15 @@ class ReportUtils {
const url = urlLocatorFn(item);
if (!url) continue;

let origin;
let origin = '';
try {
// Non-URLs can appear in valueType: url columns, like 'Unattributable'
origin = Util.parseURL(url).origin;
} catch {}
if (!origin) continue;

const entityIndex = entityClassification.entityIndexByOrigin[origin];
if (entityIndex === undefined) return;
const entity = entityClassification.list[entityIndex];
item.entity = entity.name;
const entity = entities.find(e => e.origins.includes(origin));
if (entity) item.entity = entity.name;
}
}

Expand Down
51 changes: 20 additions & 31 deletions report/test/renderer/report-ui-features-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,39 +240,28 @@ describe('ReportUIFeatures', () => {

before(() => {
// Setup entity-classification with recognized entities first.
lhrJson.entities = {
firstParty: 'example.com',
list: [
{
name: 'example.com',
isFirstParty: true,
isUnrecognized: true,
},
{
name: 'cdn.com',
isUnrecognized: true,
},
{
name: 'notexample.com',
isUnrecognized: true,
},
{
name: 'google.com',
},
],
entityIndexByOrigin: {
'http://www.example.com': 0,
'http://www.cdn.com': 1,
'http://www.notexample.com': 2,
'http://www.google.com': 3,
lhrJson.entities = [
{
name: 'example.com',
isFirstParty: true,
isUnrecognized: true,
origins: ['http://www.example.com'],
},
entityIndexByName: {
'example.com': 0,
'cdn.com': 1,
'notexample.com': 2,
'google.com': 3,
{
name: 'cdn.com',
isUnrecognized: true,
origins: ['http://www.cdn.com'],
},
};
{
name: 'notexample.com',
isUnrecognized: true,
origins: ['http://www.notexample.com'],
},
{
name: 'google.com',
origins: ['http://www.google.com'],
},
];

// Entity resolution is done during prepareReportResult
const result = ReportUtils.prepareReportResult(lhrJson);
Expand Down
14 changes: 3 additions & 11 deletions types/lhr/lhr.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,18 +155,8 @@ declare module Result {

/**
* Entity classification for the run, for resolving URLs/items to entities in report.
* The two lookup tables (LUT) below provide space-optimized, O(1) index lookup into entities.list.
*/
interface Entities {
/** All entities (1st and 3rd party) discovered during the run */
list: Array<LhrEntity>;
/** Name of the first-party entity */
firstParty?: string;
/** Entity-name to entity index lookup table */
entityIndexByName: Record<string, number>;
/** URL origin to entity index lookup table */
entityIndexByOrigin: Record<string, number>;
}
interface Entities extends Array<LhrEntity> {}

/**
* An entity that's either recognized by third-party-web or made up by Lighthouse.
Expand All @@ -182,6 +172,8 @@ declare module Result {
isFirstParty?: boolean;
/** Is this entity recognized by third-party-web? */
isUnrecognized?: boolean;
/** List of origin strings that belong to this entity found in network records. */
origins: Array<string>;
}

/**
Expand Down

0 comments on commit bdbc91b

Please sign in to comment.