lighthouse 9.2.0-dev.20211217 → 9.2.0-dev.20211221

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/report/bundle.esm.js +6 -6
  2. package/dist/report/flow.js +5 -5
  3. package/dist/report/standalone.js +3 -3
  4. package/flow-report/src/common.tsx +1 -1
  5. package/flow-report/src/sidebar/flow.tsx +1 -1
  6. package/flow-report/src/util.ts +1 -2
  7. package/lighthouse-cli/run.js +1 -1
  8. package/lighthouse-cli/test/smokehouse/lighthouse-runners/cli.js +1 -1
  9. package/lighthouse-cli/test/smokehouse/report-assert.js +1 -1
  10. package/lighthouse-cli/test/smokehouse/smokehouse.js +4 -4
  11. package/lighthouse-core/audits/accessibility/axe-audit.js +4 -4
  12. package/lighthouse-core/audits/accessibility/object-alt.js +3 -3
  13. package/lighthouse-core/audits/audit.js +2 -2
  14. package/lighthouse-core/audits/byte-efficiency/byte-efficiency-audit.js +1 -1
  15. package/lighthouse-core/audits/byte-efficiency/duplicated-javascript.js +1 -1
  16. package/lighthouse-core/audits/dobetterweb/inspector-issues.js +3 -3
  17. package/lighthouse-core/audits/dobetterweb/uses-http2.js +1 -1
  18. package/lighthouse-core/audits/font-display.js +1 -1
  19. package/lighthouse-core/audits/installable-manifest.js +1 -1
  20. package/lighthouse-core/audits/maskable-icon.js +1 -1
  21. package/lighthouse-core/audits/multi-check-audit.js +1 -1
  22. package/lighthouse-core/audits/network-requests.js +4 -4
  23. package/lighthouse-core/audits/preload-lcp-image.js +1 -1
  24. package/lighthouse-core/audits/themed-omnibox.js +1 -1
  25. package/lighthouse-core/audits/valid-source-maps.js +2 -2
  26. package/lighthouse-core/computed/image-records.js +1 -1
  27. package/lighthouse-core/computed/js-bundles.js +1 -1
  28. package/lighthouse-core/computed/metrics/lantern-metric.js +1 -1
  29. package/lighthouse-core/computed/metrics/timing-summary.js +35 -35
  30. package/lighthouse-core/computed/page-dependency-graph.js +2 -2
  31. package/lighthouse-core/computed/resource-summary.js +1 -1
  32. package/lighthouse-core/config/config-helpers.js +2 -2
  33. package/lighthouse-core/config/config.js +1 -1
  34. package/lighthouse-core/fraggle-rock/config/filters.js +23 -1
  35. package/lighthouse-core/fraggle-rock/config/validation.js +2 -2
  36. package/lighthouse-core/fraggle-rock/gather/navigation-runner.js +2 -2
  37. package/lighthouse-core/fraggle-rock/user-flow.js +4 -4
  38. package/lighthouse-core/gather/connections/connection.js +1 -1
  39. package/lighthouse-core/gather/driver/execution-context.js +1 -1
  40. package/lighthouse-core/gather/driver/network-monitor.js +2 -2
  41. package/lighthouse-core/gather/driver/target-manager.js +1 -1
  42. package/lighthouse-core/gather/driver.js +1 -1
  43. package/lighthouse-core/gather/gatherers/console-messages.js +2 -2
  44. package/lighthouse-core/gather/gatherers/inspector-issues.js +3 -3
  45. package/lighthouse-core/gather/gatherers/js-usage.js +1 -1
  46. package/lighthouse-core/gather/gatherers/seo/font-size.js +1 -1
  47. package/lighthouse-core/gather/gatherers/trace-elements.js +8 -43
  48. package/lighthouse-core/lib/arbitrary-equality-map.js +1 -1
  49. package/lighthouse-core/lib/dependency-graph/simulator/connection-pool.js +1 -1
  50. package/lighthouse-core/lib/dependency-graph/simulator/network-analyzer.js +1 -1
  51. package/lighthouse-core/lib/emulation.js +1 -1
  52. package/lighthouse-core/lib/icons.js +1 -2
  53. package/lighthouse-core/lib/median-run.js +1 -2
  54. package/lighthouse-core/lib/network-recorder.js +2 -2
  55. package/lighthouse-core/lib/network-request.js +1 -1
  56. package/lighthouse-core/lib/tracehouse/cpu-profile-model.js +4 -6
  57. package/lighthouse-core/lib/tracehouse/main-thread-tasks.js +1 -1
  58. package/lighthouse-core/lib/tracehouse/trace-processor.js +14 -17
  59. package/lighthouse-core/runner.js +4 -4
  60. package/package.json +10 -10
  61. package/report/renderer/category-renderer.js +1 -1
  62. package/report/renderer/performance-category-renderer.js +4 -4
  63. package/report/renderer/report-renderer.js +1 -1
  64. package/report/test-assets/faux-psi.js +2 -3
  65. package/shared/localization/locales/en-US.json +3 -3
  66. package/shared/localization/locales/en-XL.json +3 -3
  67. package/third-party/snyk/snapshot.json +3 -1
@@ -47,7 +47,7 @@ class s{constructor(e,t){this._document=e,this._lighthouseChannel="unknown",this
47
47
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
48
48
  * See the License for the specific language governing permissions and
49
49
  * limitations under the License.
50
- */class c{constructor(e,t){this.dom=e,this.detailsRenderer=t}get _clumpTitles(){return{warning:l.i18n.strings.warningAuditsGroupTitle,manual:l.i18n.strings.manualAuditsGroupTitle,passed:l.i18n.strings.passedAuditsGroupTitle,notApplicable:l.i18n.strings.notApplicableAuditsGroupTitle}}renderAudit(e){const t=this.dom.createComponent("audit");return this.populateAuditValues(e,t)}populateAuditValues(e,t){const n=l.i18n.strings,r=this.dom.find(".lh-audit",t);r.id=e.result.id;const o=e.result.scoreDisplayMode;e.result.displayValue&&(this.dom.find(".lh-audit__display-text",r).textContent=e.result.displayValue);const i=this.dom.find(".lh-audit__title",r);i.appendChild(this.dom.convertMarkdownCodeSnippets(e.result.title));const a=this.dom.find(".lh-audit__description",r);a.appendChild(this.dom.convertMarkdownLinkSnippets(e.result.description));for(const t of e.relevantMetrics||[]){const e=this.dom.createChildOf(a,"span","lh-audit__adorn");e.title=`Relevant to ${t.result.title}`,e.textContent=t.acronym||t.id}e.stackPacks&&e.stackPacks.forEach((e=>{const t=this.dom.createElement("div");t.classList.add("lh-audit__stackpack");const n=this.dom.createElement("img");n.classList.add("lh-audit__stackpack__img"),n.src=e.iconDataURL,n.alt=e.title,t.appendChild(n),t.appendChild(this.dom.convertMarkdownLinkSnippets(e.description)),this.dom.find(".lh-audit__stackpacks",r).appendChild(t)}));const s=this.dom.find("details",r);if(e.result.details){const t=this.detailsRenderer.render(e.result.details);t&&(t.classList.add("lh-details"),s.appendChild(t))}if(this.dom.find(".lh-chevron-container",r).appendChild(this._createChevron()),this._setRatingClass(r,e.result.score,o),"error"===e.result.scoreDisplayMode){r.classList.add("lh-audit--error");const t=this.dom.find(".lh-audit__display-text",r);t.textContent=n.errorLabel,t.classList.add("lh-tooltip-boundary");this.dom.createChildOf(t,"div","lh-tooltip lh-tooltip--error").textContent=e.result.errorMessage||n.errorMissingAuditInfo}else if(e.result.explanation){this.dom.createChildOf(i,"div","lh-audit-explanation").textContent=e.result.explanation}const c=e.result.warnings;if(!c||0===c.length)return r;const d=this.dom.find("summary",s),h=this.dom.createChildOf(d,"div","lh-warnings");if(this.dom.createChildOf(h,"span").textContent=n.warningHeader,1===c.length)h.appendChild(this.dom.createTextNode(c.join("")));else{const e=this.dom.createChildOf(h,"ul");for(const t of c){this.dom.createChildOf(e,"li").textContent=t}}return r}injectFinalScreenshot(e,t,n){const r=t["final-screenshot"];if(!r||"error"===r.scoreDisplayMode)return null;if(!r.details||"screenshot"!==r.details.type)return null;const o=this.dom.createElement("img","lh-final-ss-image"),i=r.details.data;o.src=i,o.alt=r.title;const a=this.dom.find(".lh-category .lh-category-header",e),l=this.dom.createElement("div","lh-category-headercol"),s=this.dom.createElement("div","lh-category-headercol lh-category-headercol--separator"),c=this.dom.createElement("div","lh-category-headercol");l.append(...a.childNodes),l.append(n),c.append(o),a.append(l,s,c),a.classList.add("lh-category-header__finalscreenshot")}_createChevron(){const e=this.dom.createComponent("chevron");return this.dom.find("svg.lh-chevron",e)}_setRatingClass(e,t,n){const r=l.calculateRating(t,n);return e.classList.add(`lh-audit--${n.toLowerCase()}`),"informative"!==n&&e.classList.add(`lh-audit--${r}`),e}renderCategoryHeader(e,t,n){const r=this.dom.createComponent("categoryHeader"),o=this.dom.find(".lh-score__gauge",r),i=this.renderCategoryScore(e,t,n);if(o.appendChild(i),e.description){const t=this.dom.convertMarkdownLinkSnippets(e.description);this.dom.find(".lh-category-header__description",r).appendChild(t)}return r}renderAuditGroup(e){const t=this.dom.createElement("div","lh-audit-group"),n=this.dom.createElement("div","lh-audit-group__header");this.dom.createChildOf(n,"span","lh-audit-group__title").textContent=e.title,t.appendChild(n);let r=null;return e.description&&(r=this.dom.convertMarkdownLinkSnippets(e.description),r.classList.add("lh-audit-group__description","lh-audit-group__footer"),t.appendChild(r)),[t,r]}_renderGroupedAudits(e,t){const n=new Map,r="NotAGroup";n.set(r,[]);for(const t of e){const e=t.group||r,o=n.get(e)||[];o.push(t),n.set(e,o)}const o=[];for(const[e,i]of n){if(e===r){for(const e of i)o.push(this.renderAudit(e));continue}const n=t[e],[a,l]=this.renderAuditGroup(n);for(const e of i)a.insertBefore(this.renderAudit(e),l);a.classList.add(`lh-audit-group--${e}`),o.push(a)}return o}renderUnexpandableClump(e,t){const n=this.dom.createElement("div");return this._renderGroupedAudits(e,t).forEach((e=>n.appendChild(e))),n}renderClump(e,{auditRefs:t,description:n}){const r=this.dom.createComponent("clump"),o=this.dom.find(".lh-clump",r);"warning"===e&&o.setAttribute("open","");const i=this.dom.find(".lh-audit-group__header",o),a=this._clumpTitles[e];this.dom.find(".lh-audit-group__title",i).textContent=a;this.dom.find(".lh-audit-group__itemcount",o).textContent=`(${t.length})`;const s=t.map(this.renderAudit.bind(this));o.append(...s);const c=this.dom.find(".lh-audit-group",r);if(n){const e=this.dom.convertMarkdownLinkSnippets(n);e.classList.add("lh-audit-group__description","lh-audit-group__footer"),c.appendChild(e)}return this.dom.find(".lh-clump-toggletext--show",c).textContent=l.i18n.strings.show,this.dom.find(".lh-clump-toggletext--hide",c).textContent=l.i18n.strings.hide,o.classList.add(`lh-clump--${e.toLowerCase()}`),c}renderCategoryScore(e,t,n){let r;if(r=n&&l.shouldDisplayAsFraction(n.gatherMode)?this.renderCategoryFraction(e):this.renderScoreGauge(e,t),n?.omitLabel){this.dom.find(".lh-gauge__label,.lh-fraction__label",r).remove()}if(n?.onPageAnchorRendered){const e=this.dom.find("a",r);n.onPageAnchorRendered(e)}return r}renderScoreGauge(e,t){const n=this.dom.createComponent("gauge"),r=this.dom.find("a.lh-gauge__wrapper",n);l.isPluginCategory(e.id)&&r.classList.add("lh-gauge__wrapper--plugin");const o=Number(e.score),i=this.dom.find(".lh-gauge",n),a=this.dom.find("circle.lh-gauge-arc",i);a&&this._setGaugeArc(a,o);const s=Math.round(100*o),c=this.dom.find("div.lh-gauge__percentage",n);return c.textContent=s.toString(),null===e.score&&(c.textContent="?",c.title=l.i18n.strings.errorLabel),0===e.auditRefs.length||this.hasApplicableAudits(e)?r.classList.add(`lh-gauge__wrapper--${l.calculateRating(e.score)}`):(r.classList.add("lh-gauge__wrapper--not-applicable"),c.textContent="-",c.title=l.i18n.strings.notApplicableAuditsGroupTitle),this.dom.find(".lh-gauge__label",n).textContent=e.title,n}renderCategoryFraction(e){const t=this.dom.createComponent("fraction"),n=this.dom.find("a.lh-fraction__wrapper",t),{numPassed:r,numPassableAudits:o,totalWeight:i}=l.calculateCategoryFraction(e),a=r/o,s=this.dom.find(".lh-fraction__content",t),c=this.dom.createElement("span");c.textContent=`${r}/${o}`,s.appendChild(c);let d=l.calculateRating(a);return 0===i&&(d="null"),n.classList.add(`lh-fraction__wrapper--${d}`),this.dom.find(".lh-fraction__label",t).textContent=e.title,t}hasApplicableAudits(e){return e.auditRefs.some((e=>"notApplicable"!==e.result.scoreDisplayMode))}_setGaugeArc(e,t){const n=2*Math.PI*Number(e.getAttribute("r")),r=Number(e.getAttribute("stroke-width")),o=.25*r/n;e.style.transform=`rotate(${360*o-90}deg)`;let i=t*n-r/2;0===t&&(e.style.opacity="0"),1===t&&(i=n),e.style.strokeDasharray=`${Math.max(i,0)} ${n}`}_auditHasWarning(e){return Boolean(e.result.warnings&&e.result.warnings.length)}_getClumpIdForAuditRef(e){const t=e.result.scoreDisplayMode;return"manual"===t||"notApplicable"===t?t:l.showAsPassed(e.result)?this._auditHasWarning(e)?"warning":"passed":"failed"}render(e,t={},n){const r=this.dom.createElement("div","lh-category");r.id=e.id,r.appendChild(this.renderCategoryHeader(e,t,n));const o=new Map;o.set("failed",[]),o.set("warning",[]),o.set("manual",[]),o.set("passed",[]),o.set("notApplicable",[]);for(const t of e.auditRefs){const e=this._getClumpIdForAuditRef(t),n=o.get(e);n.push(t),o.set(e,n)}for(const e of o.values())e.sort(((e,t)=>t.weight-e.weight));for(const[n,i]of o){if(0===i.length)continue;if("failed"===n){const e=this.renderUnexpandableClump(i,t);e.classList.add("lh-clump--failed"),r.appendChild(e);continue}const o="manual"===n?e.manualDescription:void 0,a=this.renderClump(n,{auditRefs:i,description:o});r.appendChild(a)}return r}}
50
+ */class c{constructor(e,t){this.dom=e,this.detailsRenderer=t}get _clumpTitles(){return{warning:l.i18n.strings.warningAuditsGroupTitle,manual:l.i18n.strings.manualAuditsGroupTitle,passed:l.i18n.strings.passedAuditsGroupTitle,notApplicable:l.i18n.strings.notApplicableAuditsGroupTitle}}renderAudit(e){const t=this.dom.createComponent("audit");return this.populateAuditValues(e,t)}populateAuditValues(e,t){const n=l.i18n.strings,r=this.dom.find(".lh-audit",t);r.id=e.result.id;const o=e.result.scoreDisplayMode;e.result.displayValue&&(this.dom.find(".lh-audit__display-text",r).textContent=e.result.displayValue);const i=this.dom.find(".lh-audit__title",r);i.appendChild(this.dom.convertMarkdownCodeSnippets(e.result.title));const a=this.dom.find(".lh-audit__description",r);a.appendChild(this.dom.convertMarkdownLinkSnippets(e.result.description));for(const t of e.relevantMetrics||[]){const e=this.dom.createChildOf(a,"span","lh-audit__adorn");e.title=`Relevant to ${t.result.title}`,e.textContent=t.acronym||t.id}e.stackPacks&&e.stackPacks.forEach((e=>{const t=this.dom.createElement("div");t.classList.add("lh-audit__stackpack");const n=this.dom.createElement("img");n.classList.add("lh-audit__stackpack__img"),n.src=e.iconDataURL,n.alt=e.title,t.appendChild(n),t.appendChild(this.dom.convertMarkdownLinkSnippets(e.description)),this.dom.find(".lh-audit__stackpacks",r).appendChild(t)}));const s=this.dom.find("details",r);if(e.result.details){const t=this.detailsRenderer.render(e.result.details);t&&(t.classList.add("lh-details"),s.appendChild(t))}if(this.dom.find(".lh-chevron-container",r).appendChild(this._createChevron()),this._setRatingClass(r,e.result.score,o),"error"===e.result.scoreDisplayMode){r.classList.add("lh-audit--error");const t=this.dom.find(".lh-audit__display-text",r);t.textContent=n.errorLabel,t.classList.add("lh-tooltip-boundary");this.dom.createChildOf(t,"div","lh-tooltip lh-tooltip--error").textContent=e.result.errorMessage||n.errorMissingAuditInfo}else if(e.result.explanation){this.dom.createChildOf(i,"div","lh-audit-explanation").textContent=e.result.explanation}const c=e.result.warnings;if(!c||0===c.length)return r;const d=this.dom.find("summary",s),h=this.dom.createChildOf(d,"div","lh-warnings");if(this.dom.createChildOf(h,"span").textContent=n.warningHeader,1===c.length)h.appendChild(this.dom.createTextNode(c.join("")));else{const e=this.dom.createChildOf(h,"ul");for(const t of c){this.dom.createChildOf(e,"li").textContent=t}}return r}injectFinalScreenshot(e,t,n){const r=t["final-screenshot"];if(!r||"error"===r.scoreDisplayMode)return null;if(!r.details||"screenshot"!==r.details.type)return null;const o=this.dom.createElement("img","lh-final-ss-image"),i=r.details.data;o.src=i,o.alt=r.title;const a=this.dom.find(".lh-category .lh-category-header",e),l=this.dom.createElement("div","lh-category-headercol"),s=this.dom.createElement("div","lh-category-headercol lh-category-headercol--separator"),c=this.dom.createElement("div","lh-category-headercol");l.append(...a.childNodes),l.append(n),c.append(o),a.append(l,s,c),a.classList.add("lh-category-header__finalscreenshot")}_createChevron(){const e=this.dom.createComponent("chevron");return this.dom.find("svg.lh-chevron",e)}_setRatingClass(e,t,n){const r=l.calculateRating(t,n);return e.classList.add(`lh-audit--${n.toLowerCase()}`),"informative"!==n&&e.classList.add(`lh-audit--${r}`),e}renderCategoryHeader(e,t,n){const r=this.dom.createComponent("categoryHeader"),o=this.dom.find(".lh-score__gauge",r),i=this.renderCategoryScore(e,t,n);if(o.appendChild(i),e.description){const t=this.dom.convertMarkdownLinkSnippets(e.description);this.dom.find(".lh-category-header__description",r).appendChild(t)}return r}renderAuditGroup(e){const t=this.dom.createElement("div","lh-audit-group"),n=this.dom.createElement("div","lh-audit-group__header");this.dom.createChildOf(n,"span","lh-audit-group__title").textContent=e.title,t.appendChild(n);let r=null;return e.description&&(r=this.dom.convertMarkdownLinkSnippets(e.description),r.classList.add("lh-audit-group__description","lh-audit-group__footer"),t.appendChild(r)),[t,r]}_renderGroupedAudits(e,t){const n=new Map,r="NotAGroup";n.set(r,[]);for(const t of e){const e=t.group||r,o=n.get(e)||[];o.push(t),n.set(e,o)}const o=[];for(const[e,i]of n){if(e===r){for(const e of i)o.push(this.renderAudit(e));continue}const n=t[e],[a,l]=this.renderAuditGroup(n);for(const e of i)a.insertBefore(this.renderAudit(e),l);a.classList.add(`lh-audit-group--${e}`),o.push(a)}return o}renderUnexpandableClump(e,t){const n=this.dom.createElement("div");return this._renderGroupedAudits(e,t).forEach((e=>n.appendChild(e))),n}renderClump(e,{auditRefs:t,description:n}){const r=this.dom.createComponent("clump"),o=this.dom.find(".lh-clump",r);"warning"===e&&o.setAttribute("open","");const i=this.dom.find(".lh-audit-group__header",o),a=this._clumpTitles[e];this.dom.find(".lh-audit-group__title",i).textContent=a;this.dom.find(".lh-audit-group__itemcount",o).textContent=`(${t.length})`;const s=t.map(this.renderAudit.bind(this));o.append(...s);const c=this.dom.find(".lh-audit-group",r);if(n){const e=this.dom.convertMarkdownLinkSnippets(n);e.classList.add("lh-audit-group__description","lh-audit-group__footer"),c.appendChild(e)}return this.dom.find(".lh-clump-toggletext--show",c).textContent=l.i18n.strings.show,this.dom.find(".lh-clump-toggletext--hide",c).textContent=l.i18n.strings.hide,o.classList.add(`lh-clump--${e.toLowerCase()}`),c}renderCategoryScore(e,t,n){let r;if(r=n&&l.shouldDisplayAsFraction(n.gatherMode)?this.renderCategoryFraction(e):this.renderScoreGauge(e,t),n?.omitLabel){this.dom.find(".lh-gauge__label,.lh-fraction__label",r).remove()}if(n?.onPageAnchorRendered){const e=this.dom.find("a",r);n.onPageAnchorRendered(e)}return r}renderScoreGauge(e,t){const n=this.dom.createComponent("gauge"),r=this.dom.find("a.lh-gauge__wrapper",n);l.isPluginCategory(e.id)&&r.classList.add("lh-gauge__wrapper--plugin");const o=Number(e.score),i=this.dom.find(".lh-gauge",n),a=this.dom.find("circle.lh-gauge-arc",i);a&&this._setGaugeArc(a,o);const s=Math.round(100*o),c=this.dom.find("div.lh-gauge__percentage",n);return c.textContent=s.toString(),null===e.score&&(c.textContent="?",c.title=l.i18n.strings.errorLabel),0===e.auditRefs.length||this.hasApplicableAudits(e)?r.classList.add(`lh-gauge__wrapper--${l.calculateRating(e.score)}`):(r.classList.add("lh-gauge__wrapper--not-applicable"),c.textContent="-",c.title=l.i18n.strings.notApplicableAuditsGroupTitle),this.dom.find(".lh-gauge__label",n).textContent=e.title,n}renderCategoryFraction(e){const t=this.dom.createComponent("fraction"),n=this.dom.find("a.lh-fraction__wrapper",t),{numPassed:r,numPassableAudits:o,totalWeight:i}=l.calculateCategoryFraction(e),a=r/o,s=this.dom.find(".lh-fraction__content",t),c=this.dom.createElement("span");c.textContent=`${r}/${o}`,s.appendChild(c);let d=l.calculateRating(a);return 0===i&&(d="null"),n.classList.add(`lh-fraction__wrapper--${d}`),this.dom.find(".lh-fraction__label",t).textContent=e.title,t}hasApplicableAudits(e){return e.auditRefs.some((e=>"notApplicable"!==e.result.scoreDisplayMode))}_setGaugeArc(e,t){const n=2*Math.PI*Number(e.getAttribute("r")),r=Number(e.getAttribute("stroke-width")),o=.25*r/n;e.style.transform=`rotate(${360*o-90}deg)`;let i=t*n-r/2;0===t&&(e.style.opacity="0"),1===t&&(i=n),e.style.strokeDasharray=`${Math.max(i,0)} ${n}`}_auditHasWarning(e){return Boolean(e.result.warnings?.length)}_getClumpIdForAuditRef(e){const t=e.result.scoreDisplayMode;return"manual"===t||"notApplicable"===t?t:l.showAsPassed(e.result)?this._auditHasWarning(e)?"warning":"passed":"failed"}render(e,t={},n){const r=this.dom.createElement("div","lh-category");r.id=e.id,r.appendChild(this.renderCategoryHeader(e,t,n));const o=new Map;o.set("failed",[]),o.set("warning",[]),o.set("manual",[]),o.set("passed",[]),o.set("notApplicable",[]);for(const t of e.auditRefs){const e=this._getClumpIdForAuditRef(t),n=o.get(e);n.push(t),o.set(e,n)}for(const e of o.values())e.sort(((e,t)=>t.weight-e.weight));for(const[n,i]of o){if(0===i.length)continue;if("failed"===n){const e=this.renderUnexpandableClump(i,t);e.classList.add("lh-clump--failed"),r.appendChild(e);continue}const o="manual"===n?e.manualDescription:void 0,a=this.renderClump(n,{auditRefs:i,description:o});r.appendChild(a)}return r}}
51
51
  /**
52
52
  * @license
53
53
  * Copyright 2017 The Lighthouse Authors. All Rights Reserved.
@@ -110,7 +110,7 @@ class s{constructor(e,t){this._document=e,this._lighthouseChannel="unknown",this
110
110
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
111
111
  * See the License for the specific language governing permissions and
112
112
  * limitations under the License.
113
- */class M extends c{_renderMetric(e){const t=this.dom.createComponent("metric"),n=this.dom.find(".lh-metric",t);n.id=e.result.id;const r=l.calculateRating(e.result.score,e.result.scoreDisplayMode);n.classList.add(`lh-metric--${r}`);this.dom.find(".lh-metric__title",t).textContent=e.result.title;const o=this.dom.find(".lh-metric__value",t);o.textContent=e.result.displayValue||"";const i=this.dom.find(".lh-metric__description",t);if(i.appendChild(this.dom.convertMarkdownLinkSnippets(e.result.description)),"error"===e.result.scoreDisplayMode){i.textContent="",o.textContent="Error!";this.dom.createChildOf(i,"span").textContent=e.result.errorMessage||"Report error: no metric information"}return n}_renderOpportunity(e,t){const n=this.dom.createComponent("opportunity"),r=this.populateAuditValues(e,n);if(r.id=e.result.id,!e.result.details||"error"===e.result.scoreDisplayMode)return r;const o=e.result.details;if("opportunity"!==o.type)return r;const i=this.dom.find("span.lh-audit__display-text, div.lh-audit__display-text",r),a=o.overallSavingsMs/t*100+"%";if(this.dom.find("div.lh-sparkline__bar",r).style.width=a,i.textContent=l.i18n.formatSeconds(o.overallSavingsMs,.01),e.result.displayValue){const t=e.result.displayValue;this.dom.find("div.lh-load-opportunity__sparkline",r).title=t,i.title=t}return r}_getWastedMs(e){if(e.result.details&&"opportunity"===e.result.details.type){const t=e.result.details;if("number"!=typeof t.overallSavingsMs)throw new Error("non-opportunity details passed to _getWastedMs");return t.overallSavingsMs}return Number.MIN_VALUE}_getScoringCalculatorHref(e){const t=e.filter((e=>"metrics"===e.group)),n=e.find((e=>"first-cpu-idle"===e.id)),r=e.find((e=>"first-meaningful-paint"===e.id));n&&t.push(n),r&&t.push(r);const o=[...t.map((e=>{let t;var n;return"number"==typeof e.result.numericValue?(t="cumulative-layout-shift"===e.id?(n=e.result.numericValue,Math.round(100*n)/100):Math.round(e.result.numericValue),t=t.toString()):t="null",[e.acronym||e.id,t]}))];l.reportJson&&(o.push(["device",l.reportJson.configSettings.formFactor]),o.push(["version",l.reportJson.lighthouseVersion]));const i=new URLSearchParams(o),a=new URL("https://googlechrome.github.io/lighthouse/scorecalc/");return a.hash=i.toString(),a.href}_classifyPerformanceAudit(e){return e.group?null:e.result.details&&"opportunity"===e.result.details.type?"load-opportunity":"diagnostic"}render(e,t,n){const r=l.i18n.strings,o=this.dom.createElement("div","lh-category");o.id=e.id,o.appendChild(this.renderCategoryHeader(e,t,n));const i=e.auditRefs.filter((e=>"metrics"===e.group));if(i.length){const[n,a]=this.renderAuditGroup(t.metrics),s=this.dom.createElement("input","lh-metrics-toggle__input"),c=`lh-metrics-toggle${l.getUniqueSuffix()}`;s.setAttribute("aria-label","Toggle the display of metric descriptions"),s.type="checkbox",s.id=c,n.prepend(s);const d=this.dom.find(".lh-audit-group__header",n),h=this.dom.createChildOf(d,"label","lh-metrics-toggle__label");h.htmlFor=c;const p=this.dom.createChildOf(h,"span","lh-metrics-toggle__labeltext--show"),u=this.dom.createChildOf(h,"span","lh-metrics-toggle__labeltext--hide");p.textContent=l.i18n.strings.expandView,u.textContent=l.i18n.strings.collapseView;const g=this.dom.createElement("div","lh-metrics-container");n.insertBefore(g,a),i.forEach((e=>{g.appendChild(this._renderMetric(e))}));const m=this.dom.find(".lh-category-header__description",o),f=this.dom.createChildOf(m,"div","lh-metrics__disclaimer"),v=this.dom.convertMarkdownLinkSnippets(r.varianceDisclaimer);f.appendChild(v);const b=this.dom.createChildOf(f,"a","lh-calclink");b.target="_blank",b.textContent=r.calculatorLink,this.dom.safelySetHref(b,this._getScoringCalculatorHref(e.auditRefs)),n.classList.add("lh-audit-group--metrics"),o.appendChild(n)}const a=this.dom.createChildOf(o,"div","lh-filmstrip-container"),s=e.auditRefs.find((e=>"screenshot-thumbnails"===e.id)),c=s&&s.result;if(c&&c.details){a.id=c.id;const e=this.detailsRenderer.render(c.details);e&&a.appendChild(e)}const d=e.auditRefs.filter((e=>"load-opportunity"===this._classifyPerformanceAudit(e))).filter((e=>!l.showAsPassed(e.result))).sort(((e,t)=>this._getWastedMs(t)-this._getWastedMs(e))),h=i.filter((e=>!!e.relevantAudits));if(h.length&&this.renderMetricAuditFilter(h,o),d.length){const e=2e3,n=d.map((e=>this._getWastedMs(e))),i=Math.max(...n),a=Math.max(1e3*Math.ceil(i/1e3),e),[l,s]=this.renderAuditGroup(t["load-opportunities"]),c=this.dom.createComponent("opportunityHeader");this.dom.find(".lh-load-opportunity__col--one",c).textContent=r.opportunityResourceColumnLabel,this.dom.find(".lh-load-opportunity__col--two",c).textContent=r.opportunitySavingsColumnLabel;const h=this.dom.find(".lh-load-opportunity__header",c);l.insertBefore(h,s),d.forEach((e=>l.insertBefore(this._renderOpportunity(e,a),s))),l.classList.add("lh-audit-group--load-opportunities"),o.appendChild(l)}const p=e.auditRefs.filter((e=>"diagnostic"===this._classifyPerformanceAudit(e))).filter((e=>!l.showAsPassed(e.result))).sort(((e,t)=>("informative"===e.result.scoreDisplayMode?100:Number(e.result.score))-("informative"===t.result.scoreDisplayMode?100:Number(t.result.score))));if(p.length){const[e,n]=this.renderAuditGroup(t.diagnostics);p.forEach((t=>e.insertBefore(this.renderAudit(t),n))),e.classList.add("lh-audit-group--diagnostics"),o.appendChild(e)}const u=e.auditRefs.filter((e=>this._classifyPerformanceAudit(e)&&l.showAsPassed(e.result)));if(!u.length)return o;const g={auditRefs:u,groupDefinitions:t},m=this.renderClump("passed",g);o.appendChild(m);const f=[];if(["performance-budget","timing-budget"].forEach((t=>{const n=e.auditRefs.find((e=>e.id===t));if(n&&n.result.details){const e=this.detailsRenderer.render(n.result.details);e&&(e.id=t,e.classList.add("lh-details","lh-details--budget","lh-audit"),f.push(e))}})),f.length>0){const[e,n]=this.renderAuditGroup(t.budgets);f.forEach((t=>e.insertBefore(t,n))),e.classList.add("lh-audit-group--budgets"),o.appendChild(e)}return o}renderMetricAuditFilter(e,t){const n=this.dom.createElement("div","lh-metricfilter");this.dom.createChildOf(n,"span","lh-metricfilter__text").textContent=l.i18n.strings.showRelevantAudits;const r=[{acronym:"All"},...e],o=l.getUniqueSuffix();for(const e of r){const r=`metric-${e.acronym}-${o}`,i=this.dom.createChildOf(n,"input","lh-metricfilter__radio");i.type="radio",i.name=`metricsfilter-${o}`,i.id=r;const a=this.dom.createChildOf(n,"label","lh-metricfilter__label");a.htmlFor=r,a.title=e.result&&e.result.title,a.textContent=e.acronym||e.id,"All"===e.acronym&&(i.checked=!0,a.classList.add("lh-metricfilter__label--active")),t.append(n),i.addEventListener("input",(n=>{for(const e of t.querySelectorAll("label.lh-metricfilter__label"))e.classList.toggle("lh-metricfilter__label--active",e.htmlFor===r);t.classList.toggle("lh-category--filtered","All"!==e.acronym);for(const n of t.querySelectorAll("div.lh-audit"))"All"!==e.acronym?(n.hidden=!0,e.relevantAudits&&e.relevantAudits.includes(n.id)&&(n.hidden=!1)):n.hidden=!1;const o=t.querySelectorAll("div.lh-audit-group, details.lh-audit-group");for(const e of o){e.hidden=!1;const t=Array.from(e.querySelectorAll("div.lh-audit")),n=!!t.length&&t.every((e=>e.hidden));e.hidden=n}}))}}}
113
+ */class M extends c{_renderMetric(e){const t=this.dom.createComponent("metric"),n=this.dom.find(".lh-metric",t);n.id=e.result.id;const r=l.calculateRating(e.result.score,e.result.scoreDisplayMode);n.classList.add(`lh-metric--${r}`);this.dom.find(".lh-metric__title",t).textContent=e.result.title;const o=this.dom.find(".lh-metric__value",t);o.textContent=e.result.displayValue||"";const i=this.dom.find(".lh-metric__description",t);if(i.appendChild(this.dom.convertMarkdownLinkSnippets(e.result.description)),"error"===e.result.scoreDisplayMode){i.textContent="",o.textContent="Error!";this.dom.createChildOf(i,"span").textContent=e.result.errorMessage||"Report error: no metric information"}return n}_renderOpportunity(e,t){const n=this.dom.createComponent("opportunity"),r=this.populateAuditValues(e,n);if(r.id=e.result.id,!e.result.details||"error"===e.result.scoreDisplayMode)return r;const o=e.result.details;if("opportunity"!==o.type)return r;const i=this.dom.find("span.lh-audit__display-text, div.lh-audit__display-text",r),a=o.overallSavingsMs/t*100+"%";if(this.dom.find("div.lh-sparkline__bar",r).style.width=a,i.textContent=l.i18n.formatSeconds(o.overallSavingsMs,.01),e.result.displayValue){const t=e.result.displayValue;this.dom.find("div.lh-load-opportunity__sparkline",r).title=t,i.title=t}return r}_getWastedMs(e){if(e.result.details&&"opportunity"===e.result.details.type){const t=e.result.details;if("number"!=typeof t.overallSavingsMs)throw new Error("non-opportunity details passed to _getWastedMs");return t.overallSavingsMs}return Number.MIN_VALUE}_getScoringCalculatorHref(e){const t=e.filter((e=>"metrics"===e.group)),n=e.find((e=>"first-cpu-idle"===e.id)),r=e.find((e=>"first-meaningful-paint"===e.id));n&&t.push(n),r&&t.push(r);const o=[...t.map((e=>{let t;var n;return"number"==typeof e.result.numericValue?(t="cumulative-layout-shift"===e.id?(n=e.result.numericValue,Math.round(100*n)/100):Math.round(e.result.numericValue),t=t.toString()):t="null",[e.acronym||e.id,t]}))];l.reportJson&&(o.push(["device",l.reportJson.configSettings.formFactor]),o.push(["version",l.reportJson.lighthouseVersion]));const i=new URLSearchParams(o),a=new URL("https://googlechrome.github.io/lighthouse/scorecalc/");return a.hash=i.toString(),a.href}_classifyPerformanceAudit(e){return e.group?null:e.result.details&&"opportunity"===e.result.details.type?"load-opportunity":"diagnostic"}render(e,t,n){const r=l.i18n.strings,o=this.dom.createElement("div","lh-category");o.id=e.id,o.appendChild(this.renderCategoryHeader(e,t,n));const i=e.auditRefs.filter((e=>"metrics"===e.group));if(i.length){const[n,a]=this.renderAuditGroup(t.metrics),s=this.dom.createElement("input","lh-metrics-toggle__input"),c=`lh-metrics-toggle${l.getUniqueSuffix()}`;s.setAttribute("aria-label","Toggle the display of metric descriptions"),s.type="checkbox",s.id=c,n.prepend(s);const d=this.dom.find(".lh-audit-group__header",n),h=this.dom.createChildOf(d,"label","lh-metrics-toggle__label");h.htmlFor=c;const p=this.dom.createChildOf(h,"span","lh-metrics-toggle__labeltext--show"),u=this.dom.createChildOf(h,"span","lh-metrics-toggle__labeltext--hide");p.textContent=l.i18n.strings.expandView,u.textContent=l.i18n.strings.collapseView;const g=this.dom.createElement("div","lh-metrics-container");n.insertBefore(g,a),i.forEach((e=>{g.appendChild(this._renderMetric(e))}));const m=this.dom.find(".lh-category-header__description",o),f=this.dom.createChildOf(m,"div","lh-metrics__disclaimer"),v=this.dom.convertMarkdownLinkSnippets(r.varianceDisclaimer);f.appendChild(v);const b=this.dom.createChildOf(f,"a","lh-calclink");b.target="_blank",b.textContent=r.calculatorLink,this.dom.safelySetHref(b,this._getScoringCalculatorHref(e.auditRefs)),n.classList.add("lh-audit-group--metrics"),o.appendChild(n)}const a=this.dom.createChildOf(o,"div","lh-filmstrip-container"),s=e.auditRefs.find((e=>"screenshot-thumbnails"===e.id))?.result;if(s?.details){a.id=s.id;const e=this.detailsRenderer.render(s.details);e&&a.appendChild(e)}const c=e.auditRefs.filter((e=>"load-opportunity"===this._classifyPerformanceAudit(e))).filter((e=>!l.showAsPassed(e.result))).sort(((e,t)=>this._getWastedMs(t)-this._getWastedMs(e))),d=i.filter((e=>!!e.relevantAudits));if(d.length&&this.renderMetricAuditFilter(d,o),c.length){const e=2e3,n=c.map((e=>this._getWastedMs(e))),i=Math.max(...n),a=Math.max(1e3*Math.ceil(i/1e3),e),[l,s]=this.renderAuditGroup(t["load-opportunities"]),d=this.dom.createComponent("opportunityHeader");this.dom.find(".lh-load-opportunity__col--one",d).textContent=r.opportunityResourceColumnLabel,this.dom.find(".lh-load-opportunity__col--two",d).textContent=r.opportunitySavingsColumnLabel;const h=this.dom.find(".lh-load-opportunity__header",d);l.insertBefore(h,s),c.forEach((e=>l.insertBefore(this._renderOpportunity(e,a),s))),l.classList.add("lh-audit-group--load-opportunities"),o.appendChild(l)}const h=e.auditRefs.filter((e=>"diagnostic"===this._classifyPerformanceAudit(e))).filter((e=>!l.showAsPassed(e.result))).sort(((e,t)=>("informative"===e.result.scoreDisplayMode?100:Number(e.result.score))-("informative"===t.result.scoreDisplayMode?100:Number(t.result.score))));if(h.length){const[e,n]=this.renderAuditGroup(t.diagnostics);h.forEach((t=>e.insertBefore(this.renderAudit(t),n))),e.classList.add("lh-audit-group--diagnostics"),o.appendChild(e)}const p=e.auditRefs.filter((e=>this._classifyPerformanceAudit(e)&&l.showAsPassed(e.result)));if(!p.length)return o;const u={auditRefs:p,groupDefinitions:t},g=this.renderClump("passed",u);o.appendChild(g);const m=[];if(["performance-budget","timing-budget"].forEach((t=>{const n=e.auditRefs.find((e=>e.id===t));if(n?.result.details){const e=this.detailsRenderer.render(n.result.details);e&&(e.id=t,e.classList.add("lh-details","lh-details--budget","lh-audit"),m.push(e))}})),m.length>0){const[e,n]=this.renderAuditGroup(t.budgets);m.forEach((t=>e.insertBefore(t,n))),e.classList.add("lh-audit-group--budgets"),o.appendChild(e)}return o}renderMetricAuditFilter(e,t){const n=this.dom.createElement("div","lh-metricfilter");this.dom.createChildOf(n,"span","lh-metricfilter__text").textContent=l.i18n.strings.showRelevantAudits;const r=[{acronym:"All"},...e],o=l.getUniqueSuffix();for(const e of r){const r=`metric-${e.acronym}-${o}`,i=this.dom.createChildOf(n,"input","lh-metricfilter__radio");i.type="radio",i.name=`metricsfilter-${o}`,i.id=r;const a=this.dom.createChildOf(n,"label","lh-metricfilter__label");a.htmlFor=r,a.title=e.result?.title,a.textContent=e.acronym||e.id,"All"===e.acronym&&(i.checked=!0,a.classList.add("lh-metricfilter__label--active")),t.append(n),i.addEventListener("input",(n=>{for(const e of t.querySelectorAll("label.lh-metricfilter__label"))e.classList.toggle("lh-metricfilter__label--active",e.htmlFor===r);t.classList.toggle("lh-category--filtered","All"!==e.acronym);for(const n of t.querySelectorAll("div.lh-audit"))"All"!==e.acronym?(n.hidden=!0,e.relevantAudits&&e.relevantAudits.includes(n.id)&&(n.hidden=!1)):n.hidden=!1;const o=t.querySelectorAll("div.lh-audit-group, details.lh-audit-group");for(const e of o){e.hidden=!1;const t=Array.from(e.querySelectorAll("div.lh-audit")),n=!!t.length&&t.every((e=>e.hidden));e.hidden=n}}))}}}
114
114
  /**
115
115
  * @license
116
116
  * Copyright 2018 The Lighthouse Authors. All Rights Reserved.
@@ -145,7 +145,7 @@ class s{constructor(e,t){this._document=e,this._lighthouseChannel="unknown",this
145
145
  *
146
146
  * Dummy text for ensuring report robustness: <\/script> pre$`post %%LIGHTHOUSE_JSON%%
147
147
  * (this is handled by terser)
148
- */class N{constructor(e){this._dom=e,this._opts={}}renderReport(e,t,n){if(!this._dom.rootEl&&t){console.warn("Please adopt the new report API in renderer/api.js.");const e=t.closest(".lh-root");e?this._dom.rootEl=e:(t.classList.add("lh-root","lh-vars"),this._dom.rootEl=t)}else this._dom.rootEl&&t&&(this._dom.rootEl=t);n&&(this._opts=n),this._dom.setLighthouseChannel(e.configSettings.channel||"unknown");const r=l.prepareReportResult(e);return this._dom.rootEl.textContent="",this._dom.rootEl.appendChild(this._renderReport(r)),this._dom.rootEl}_renderReportTopbar(e){const t=this._dom.createComponent("topbar"),n=this._dom.find("a.lh-topbar__url",t);return n.textContent=e.finalUrl,n.title=e.finalUrl,this._dom.safelySetHref(n,e.finalUrl),t}_renderReportHeader(){const e=this._dom.createComponent("heading"),t=this._dom.createComponent("scoresWrapper");return this._dom.find(".lh-scores-wrapper-placeholder",e).replaceWith(t),e}_renderReportFooter(e){const t=this._dom.createComponent("footer");return this._renderMetaBlock(e,t),this._dom.find(".lh-footer__version_issue",t).textContent=l.i18n.strings.footerIssue,this._dom.find(".lh-footer__version",t).textContent=e.lighthouseVersion,t}_renderMetaBlock(e,t){const n=l.getEmulationDescriptions(e.configSettings||{}),r=e.userAgent.match(/(\w*Chrome\/[\d.]+)/),o=Array.isArray(r)?r[1].replace("/"," ").replace("Chrome","Chromium"):"Chromium",i=e.configSettings.channel,a=e.environment.benchmarkIndex.toFixed(0),s=e.environment.credits?.["axe-core"],c=[["date",`Captured at ${l.i18n.formatDateTime(e.fetchTime)}`],["devices",`${n.deviceEmulation} with Lighthouse ${e.lighthouseVersion}`,`${l.i18n.strings.runtimeSettingsBenchmark}: ${a}\n${l.i18n.strings.runtimeSettingsCPUThrottling}: ${n.cpuThrottling}`+(s?`\n${l.i18n.strings.runtimeSettingsAxeVersion}: ${s}`:"")],["samples-one",l.i18n.strings.runtimeSingleLoad,l.i18n.strings.runtimeSingleLoadTooltip],["stopwatch",l.i18n.strings.runtimeAnalysisWindow],["networkspeed",`${n.summary}`,`${l.i18n.strings.runtimeSettingsNetworkThrottling}: ${n.networkThrottling}`],["chrome",`Using ${o}`+(i?` with ${i}`:""),`${l.i18n.strings.runtimeSettingsUANetwork}: "${e.environment.networkUserAgent}"`]],d=this._dom.find(".lh-meta__items",t);for(const[e,t,n]of c){const r=this._dom.createChildOf(d,"li","lh-meta__item");if(r.textContent=t,n){r.classList.add("lh-tooltip-boundary");this._dom.createChildOf(r,"div","lh-tooltip").textContent=n}r.classList.add("lh-report-icon",`lh-report-icon--${e}`)}}_renderReportWarnings(e){if(!e.runWarnings||0===e.runWarnings.length)return this._dom.createElement("div");const t=this._dom.createComponent("warningsToplevel");this._dom.find(".lh-warnings__msg",t).textContent=l.i18n.strings.toplevelWarningsMessage;const n=this._dom.find("ul",t);for(const t of e.runWarnings){n.appendChild(this._dom.createElement("li")).appendChild(this._dom.convertMarkdownLinkSnippets(t))}return t}_renderScoreGauges(e,t,n){const r=[],o=[],i=[];for(const a of Object.values(e.categories)){const s=n[a.id]||t,c=s.renderCategoryScore(a,e.categoryGroups||{},{gatherMode:e.gatherMode}),d=this._dom.find("a.lh-gauge__wrapper, a.lh-fraction__wrapper",c);d&&(this._dom.safelySetHref(d,`#${a.id}`),d.addEventListener("click",(e=>{if(!d.matches('[href^="#"]'))return;const t=d.getAttribute("href"),n=this._dom.rootEl;if(!t||!n)return;const r=this._dom.find(t,n);e.preventDefault(),r.scrollIntoView()})),this._opts.onPageAnchorRendered?.(d)),l.isPluginCategory(a.id)?i.push(c):s.renderCategoryScore===t.renderCategoryScore?r.push(c):o.push(c)}return[...r,...o,...i]}_renderReport(e){const t=new L(e.configSettings.locale,{...l.UIStrings,...e.i18n.rendererFormattedStrings});l.i18n=t,l.reportJson=e;const n=e.audits["full-page-screenshot"]&&e.audits["full-page-screenshot"].details&&"full-page-screenshot"===e.audits["full-page-screenshot"].details.type?e.audits["full-page-screenshot"].details:void 0,r=new z(this._dom,{fullPageScreenshot:n}),o=new c(this._dom,r),i={performance:new M(this._dom,r),pwa:new F(this._dom,r)},a=this._dom.createElement("div");a.appendChild(this._renderReportHeader());const s=this._dom.createElement("div","lh-container"),d=this._dom.createElement("div","lh-report");let h;d.appendChild(this._renderReportWarnings(e));1===Object.keys(e.categories).length?a.classList.add("lh-header--solo-category"):h=this._dom.createElement("div","lh-scores-header");const p=this._dom.createElement("div");if(p.classList.add("lh-scorescale-wrap"),p.append(this._dom.createComponent("scorescale")),h){const t=this._dom.find(".lh-scores-container",a);h.append(...this._renderScoreGauges(e,o,i)),t.appendChild(h),t.appendChild(p);const n=this._dom.createElement("div","lh-sticky-header");n.append(...this._renderScoreGauges(e,o,i)),s.appendChild(n)}const u=d.appendChild(this._dom.createElement("div","lh-categories")),g={gatherMode:e.gatherMode};for(const t of Object.values(e.categories)){const n=i[t.id]||o;n.dom.createChildOf(u,"div","lh-category-wrapper").appendChild(n.render(t,e.categoryGroups,g))}o.injectFinalScreenshot(u,e.audits,p);const m=this._dom.createFragment();return this._opts.omitGlobalStyles||m.append(this._dom.createComponent("styles")),this._opts.omitTopbar||m.appendChild(this._renderReportTopbar(e)),m.appendChild(s),s.appendChild(a),s.appendChild(d),d.appendChild(this._renderReportFooter(e)),n&&A.installFullPageScreenshot(this._dom.rootEl,n.screenshot),m}}
148
+ */class N{constructor(e){this._dom=e,this._opts={}}renderReport(e,t,n){if(!this._dom.rootEl&&t){console.warn("Please adopt the new report API in renderer/api.js.");const e=t.closest(".lh-root");e?this._dom.rootEl=e:(t.classList.add("lh-root","lh-vars"),this._dom.rootEl=t)}else this._dom.rootEl&&t&&(this._dom.rootEl=t);n&&(this._opts=n),this._dom.setLighthouseChannel(e.configSettings.channel||"unknown");const r=l.prepareReportResult(e);return this._dom.rootEl.textContent="",this._dom.rootEl.appendChild(this._renderReport(r)),this._dom.rootEl}_renderReportTopbar(e){const t=this._dom.createComponent("topbar"),n=this._dom.find("a.lh-topbar__url",t);return n.textContent=e.finalUrl,n.title=e.finalUrl,this._dom.safelySetHref(n,e.finalUrl),t}_renderReportHeader(){const e=this._dom.createComponent("heading"),t=this._dom.createComponent("scoresWrapper");return this._dom.find(".lh-scores-wrapper-placeholder",e).replaceWith(t),e}_renderReportFooter(e){const t=this._dom.createComponent("footer");return this._renderMetaBlock(e,t),this._dom.find(".lh-footer__version_issue",t).textContent=l.i18n.strings.footerIssue,this._dom.find(".lh-footer__version",t).textContent=e.lighthouseVersion,t}_renderMetaBlock(e,t){const n=l.getEmulationDescriptions(e.configSettings||{}),r=e.userAgent.match(/(\w*Chrome\/[\d.]+)/),o=Array.isArray(r)?r[1].replace("/"," ").replace("Chrome","Chromium"):"Chromium",i=e.configSettings.channel,a=e.environment.benchmarkIndex.toFixed(0),s=e.environment.credits?.["axe-core"],c=[["date",`Captured at ${l.i18n.formatDateTime(e.fetchTime)}`],["devices",`${n.deviceEmulation} with Lighthouse ${e.lighthouseVersion}`,`${l.i18n.strings.runtimeSettingsBenchmark}: ${a}\n${l.i18n.strings.runtimeSettingsCPUThrottling}: ${n.cpuThrottling}`+(s?`\n${l.i18n.strings.runtimeSettingsAxeVersion}: ${s}`:"")],["samples-one",l.i18n.strings.runtimeSingleLoad,l.i18n.strings.runtimeSingleLoadTooltip],["stopwatch",l.i18n.strings.runtimeAnalysisWindow],["networkspeed",`${n.summary}`,`${l.i18n.strings.runtimeSettingsNetworkThrottling}: ${n.networkThrottling}`],["chrome",`Using ${o}`+(i?` with ${i}`:""),`${l.i18n.strings.runtimeSettingsUANetwork}: "${e.environment.networkUserAgent}"`]],d=this._dom.find(".lh-meta__items",t);for(const[e,t,n]of c){const r=this._dom.createChildOf(d,"li","lh-meta__item");if(r.textContent=t,n){r.classList.add("lh-tooltip-boundary");this._dom.createChildOf(r,"div","lh-tooltip").textContent=n}r.classList.add("lh-report-icon",`lh-report-icon--${e}`)}}_renderReportWarnings(e){if(!e.runWarnings||0===e.runWarnings.length)return this._dom.createElement("div");const t=this._dom.createComponent("warningsToplevel");this._dom.find(".lh-warnings__msg",t).textContent=l.i18n.strings.toplevelWarningsMessage;const n=this._dom.find("ul",t);for(const t of e.runWarnings){n.appendChild(this._dom.createElement("li")).appendChild(this._dom.convertMarkdownLinkSnippets(t))}return t}_renderScoreGauges(e,t,n){const r=[],o=[],i=[];for(const a of Object.values(e.categories)){const s=n[a.id]||t,c=s.renderCategoryScore(a,e.categoryGroups||{},{gatherMode:e.gatherMode}),d=this._dom.find("a.lh-gauge__wrapper, a.lh-fraction__wrapper",c);d&&(this._dom.safelySetHref(d,`#${a.id}`),d.addEventListener("click",(e=>{if(!d.matches('[href^="#"]'))return;const t=d.getAttribute("href"),n=this._dom.rootEl;if(!t||!n)return;const r=this._dom.find(t,n);e.preventDefault(),r.scrollIntoView()})),this._opts.onPageAnchorRendered?.(d)),l.isPluginCategory(a.id)?i.push(c):s.renderCategoryScore===t.renderCategoryScore?r.push(c):o.push(c)}return[...r,...o,...i]}_renderReport(e){const t=new L(e.configSettings.locale,{...l.UIStrings,...e.i18n.rendererFormattedStrings});l.i18n=t,l.reportJson=e;const n=e.audits["full-page-screenshot"]?.details&&"full-page-screenshot"===e.audits["full-page-screenshot"].details.type?e.audits["full-page-screenshot"].details:void 0,r=new z(this._dom,{fullPageScreenshot:n}),o=new c(this._dom,r),i={performance:new M(this._dom,r),pwa:new F(this._dom,r)},a=this._dom.createElement("div");a.appendChild(this._renderReportHeader());const s=this._dom.createElement("div","lh-container"),d=this._dom.createElement("div","lh-report");let h;d.appendChild(this._renderReportWarnings(e));1===Object.keys(e.categories).length?a.classList.add("lh-header--solo-category"):h=this._dom.createElement("div","lh-scores-header");const p=this._dom.createElement("div");if(p.classList.add("lh-scorescale-wrap"),p.append(this._dom.createComponent("scorescale")),h){const t=this._dom.find(".lh-scores-container",a);h.append(...this._renderScoreGauges(e,o,i)),t.appendChild(h),t.appendChild(p);const n=this._dom.createElement("div","lh-sticky-header");n.append(...this._renderScoreGauges(e,o,i)),s.appendChild(n)}const u=d.appendChild(this._dom.createElement("div","lh-categories")),g={gatherMode:e.gatherMode};for(const t of Object.values(e.categories)){const n=i[t.id]||o;n.dom.createChildOf(u,"div","lh-category-wrapper").appendChild(n.render(t,e.categoryGroups,g))}o.injectFinalScreenshot(u,e.audits,p);const m=this._dom.createFragment();return this._opts.omitGlobalStyles||m.append(this._dom.createComponent("styles")),this._opts.omitTopbar||m.appendChild(this._renderReportTopbar(e)),m.appendChild(s),s.appendChild(a),s.appendChild(d),d.appendChild(this._renderReportFooter(e)),n&&A.installFullPageScreenshot(this._dom.rootEl,n.screenshot),m}}
149
149
  /**
150
150
  * @license Copyright 2021 The Lighthouse Authors. All Rights Reserved.
151
151
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
@@ -93,7 +93,7 @@ const FlowStepThumbnail: FunctionComponent<{
93
93
  }
94
94
 
95
95
  let thumbnail;
96
- if (frames && frames.length) {
96
+ if (frames?.length) {
97
97
  thumbnail = frames[frames.length - 1].data;
98
98
  if (lhr.gatherMode === 'timespan') {
99
99
  return <FlowStepAnimatedThumbnail frames={frames} width={width} height={height} />;
@@ -59,7 +59,7 @@ export const SidebarFlow: FunctionComponent = () => {
59
59
  mode={lhr.gatherMode}
60
60
  href={`#index=${index}`}
61
61
  label={name}
62
- isCurrent={index === (hashState && hashState.index)}
62
+ isCurrent={index === hashState?.index}
63
63
  />
64
64
  </>;
65
65
  })
@@ -44,8 +44,7 @@ function getScreenDimensions(reportResult: LH.Result) {
44
44
  function getFullPageScreenshot(reportResult: LH.Result) {
45
45
  const fullPageScreenshotAudit = reportResult.audits['full-page-screenshot'];
46
46
  const fullPageScreenshot =
47
- fullPageScreenshotAudit &&
48
- fullPageScreenshotAudit.details &&
47
+ fullPageScreenshotAudit?.details &&
49
48
  fullPageScreenshotAudit.details.type === 'full-page-screenshot' &&
50
49
  fullPageScreenshotAudit.details;
51
50
 
@@ -254,7 +254,7 @@ async function runLighthouse(url, flags, config) {
254
254
  // Runtime errors indicate something was *very* wrong with the page result.
255
255
  // We don't want the user to have to parse the report to figure it out, so we'll still exit
256
256
  // with an error code after we saved the results.
257
- if (runnerResult && runnerResult.lhr.runtimeError) {
257
+ if (runnerResult?.lhr.runtimeError) {
258
258
  const {runtimeError} = runnerResult.lhr;
259
259
  return printErrorAndExit({
260
260
  name: 'LHError',
@@ -133,7 +133,7 @@ async function internalRun(url, tmpPath, configJson, options) {
133
133
 
134
134
  // There should either be both an error exitCode and a lhr.runtimeError or neither.
135
135
  if (Boolean(exitCode) !== Boolean(lhr.runtimeError)) {
136
- const runtimeErrorCode = lhr.runtimeError && lhr.runtimeError.code;
136
+ const runtimeErrorCode = lhr.runtimeError?.code;
137
137
  throw new ChildProcessError(`Lighthouse did not exit with an error correctly, exiting with ${exitCode} but with runtimeError '${runtimeErrorCode}'`, // eslint-disable-line max-len
138
138
  localConsole.getLog());
139
139
  }
@@ -162,7 +162,7 @@ function makeComparison(name, actualResult, expectedResult) {
162
162
  */
163
163
  function pruneExpectations(localConsole, lhr, expected, reportOptions) {
164
164
  const isFraggleRock = lhr.configSettings.channel === 'fraggle-rock-cli';
165
- const isBundled = reportOptions && reportOptions.isBundled;
165
+ const isBundled = reportOptions?.isBundled;
166
166
 
167
167
  /**
168
168
  * Lazily compute the Chrome version because some reports are explicitly asserting error conditions.
@@ -32,7 +32,7 @@
32
32
  * @property {Run[]} runs
33
33
  */
34
34
 
35
- import {strict as assert} from 'assert';
35
+ import assert from 'assert';
36
36
 
37
37
  import log from 'lighthouse-logger';
38
38
 
@@ -244,7 +244,7 @@ function getShardedDefinitions(testDefns, shardArg) {
244
244
  // eslint-disable-next-line max-len
245
245
  const errorMessage = `'shard' must be of the form 'n/d' and n and d must be positive integers with 1 ≤ n ≤ d. Got '${shardArg}'`;
246
246
  const match = /^(?<shardNumber>\d+)\/(?<shardTotal>\d+)$/.exec(shardArg);
247
- assert(match && match.groups, errorMessage);
247
+ assert(match?.groups, errorMessage);
248
248
  const shardNumber = Number(match.groups.shardNumber);
249
249
  const shardTotal = Number(match.groups.shardTotal);
250
250
  assert(shardNumber > 0 && Number.isInteger(shardNumber), errorMessage);
@@ -267,8 +267,8 @@ function getShardedDefinitions(testDefns, shardArg) {
267
267
  shards.push(testDefns.slice(index, index + shardSize));
268
268
  index += shardSize;
269
269
  }
270
- assert.equal(shards.length, shardTotal);
271
- assert.deepEqual(shards.flat(), testDefns);
270
+ assert.strictEqual(shards.length, shardTotal);
271
+ assert.deepStrictEqual(shards.flat(), testDefns);
272
272
 
273
273
  const shardDefns = shards[shardNumber - 1];
274
274
  console.log(`In this shard (${shardArg}), running: ${shardDefns.map(d => d.id).join(' ')}\n`);
@@ -47,7 +47,7 @@ class AxeAudit extends Audit {
47
47
  // If aXe reports an error, then bubble it up to the caller
48
48
  const incomplete = artifacts.Accessibility.incomplete || [];
49
49
  const incompleteResult = incomplete.find(result => result.id === this.meta.id);
50
- if (incompleteResult && incompleteResult.error) {
50
+ if (incompleteResult?.error) {
51
51
  return {
52
52
  score: null,
53
53
  errorMessage: `axe-core Error: ${incompleteResult.error.message || 'Unknown error'}`,
@@ -58,8 +58,8 @@ class AxeAudit extends Audit {
58
58
  const violations = artifacts.Accessibility.violations || [];
59
59
  const failureCases = isInformative ? violations.concat(incomplete) : violations;
60
60
  const rule = failureCases.find(result => result.id === this.meta.id);
61
- const impact = rule && rule.impact;
62
- const tags = rule && rule.tags;
61
+ const impact = rule?.impact;
62
+ const tags = rule?.tags;
63
63
 
64
64
  // Handle absence of aXe failure results for informative rules as 'not applicable'
65
65
  // This scenario indicates that no action is required by the web property owner
@@ -73,7 +73,7 @@ class AxeAudit extends Audit {
73
73
 
74
74
  /** @type {LH.Audit.Details.Table['items']}>} */
75
75
  let items = [];
76
- if (rule && rule.nodes) {
76
+ if (rule?.nodes) {
77
77
  items = rule.nodes.map(axeNode => ({
78
78
  node: {
79
79
  ...Audit.makeNodeItem(axeNode.node),
@@ -15,11 +15,11 @@ const i18n = require('../../lib/i18n/i18n.js');
15
15
 
16
16
  const UIStrings = {
17
17
  /** Title of an accesibility audit that evaluates if all object elements have an alt HTML attribute that describes their contents. This title is descriptive of the successful state and is shown to users when no user action is required. */
18
- title: '`<object>` elements have `[alt]` text',
18
+ title: '`<object>` elements have alternate text',
19
19
  /** Title of an accesibility audit that evaluates if all object elements have an alt HTML attribute that describes their contents. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed. */
20
- failureTitle: '`<object>` elements do not have `[alt]` text',
20
+ failureTitle: '`<object>` elements do not have alternate text',
21
21
  /** Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. */
22
- description: 'Screen readers cannot translate non-text content. Adding alt text to ' +
22
+ description: 'Screen readers cannot translate non-text content. Adding alternate text to ' +
23
23
  '`<object>` elements helps screen readers convey meaning to users. ' +
24
24
  '[Learn more](https://web.dev/object-alt/).',
25
25
  };
@@ -360,8 +360,8 @@ class Audit {
360
360
 
361
361
  score,
362
362
  scoreDisplayMode,
363
- numericValue: numericProduct && numericProduct.numericValue,
364
- numericUnit: numericProduct && numericProduct.numericUnit,
363
+ numericValue: numericProduct?.numericValue,
364
+ numericUnit: numericProduct?.numericUnit,
365
365
 
366
366
  displayValue: product.displayValue,
367
367
  explanation: product.explanation,
@@ -109,7 +109,7 @@ class UnusedBytes extends Audit {
109
109
  const gatherContext = artifacts.GatherContext;
110
110
  const trace = artifacts.traces[Audit.DEFAULT_PASS];
111
111
  const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
112
- const settings = context && context.settings || {};
112
+ const settings = context?.settings || {};
113
113
  const simulatorOptions = {
114
114
  devtoolsLog,
115
115
  settings,
@@ -127,7 +127,7 @@ class DuplicatedJavascript extends ByteEfficiencyAudit {
127
127
  */
128
128
  static async audit_(artifacts, networkRecords, context) {
129
129
  const ignoreThresholdInBytes =
130
- context.options && context.options.ignoreThresholdInBytes || IGNORE_THRESHOLD_IN_BYTES;
130
+ context.options?.ignoreThresholdInBytes || IGNORE_THRESHOLD_IN_BYTES;
131
131
  const duplication =
132
132
  await DuplicatedJavascript._getDuplicationGroupedByNodeModules(artifacts, context);
133
133
  const mainDocumentRecord = NetworkAnalyzer.findOptionalMainDocument(networkRecords);
@@ -58,7 +58,7 @@ class IssuesPanelEntries extends Audit {
58
58
  static getMixedContentRow(mixedContentIssues) {
59
59
  const requestUrls = new Set();
60
60
  for (const issue of mixedContentIssues) {
61
- const requestUrl = (issue.request && issue.request.url) || issue.mainResourceURL;
61
+ const requestUrl = issue.request?.url || issue.mainResourceURL;
62
62
  requestUrls.add(requestUrl);
63
63
  }
64
64
  return {
@@ -77,7 +77,7 @@ class IssuesPanelEntries extends Audit {
77
77
  static getSameSiteCookieRow(sameSiteCookieIssues) {
78
78
  const requestUrls = new Set();
79
79
  for (const issue of sameSiteCookieIssues) {
80
- const requestUrl = (issue.request && issue.request.url) || issue.cookieUrl;
80
+ const requestUrl = (issue.request?.url) || issue.cookieUrl;
81
81
  if (requestUrl) {
82
82
  requestUrls.add(requestUrl);
83
83
  }
@@ -102,7 +102,7 @@ class IssuesPanelEntries extends Audit {
102
102
  static getBlockedByResponseRow(blockedByResponseIssues) {
103
103
  const requestUrls = new Set();
104
104
  for (const issue of blockedByResponseIssues) {
105
- const requestUrl = issue.request && issue.request.url;
105
+ const requestUrl = issue.request?.url;
106
106
  if (requestUrl) {
107
107
  requestUrls.add(requestUrl);
108
108
  }
@@ -227,7 +227,7 @@ class UsesHTTP2Audit extends Audit {
227
227
  };
228
228
  }
229
229
 
230
- const settings = context && context.settings || {};
230
+ const settings = context?.settings || {};
231
231
  const simulatorOptions = {
232
232
  devtoolsLog,
233
233
  settings,
@@ -79,7 +79,7 @@ class FontDisplay extends Audit {
79
79
  // Find the font-display value by matching a single token, optionally surrounded by whitespace,
80
80
  // followed either by a semicolon or the end of a block.
81
81
  const fontDisplayMatch = declaration.match(/font-display\s*:\s*(\w+)\s*(;|\})/);
82
- const rawFontDisplay = (fontDisplayMatch && fontDisplayMatch[1]) || '';
82
+ const rawFontDisplay = fontDisplayMatch?.[1] || '';
83
83
  const hasPassingFontDisplay = passingFontDisplayRegex.test(rawFontDisplay);
84
84
  const targetURLSet = hasPassingFontDisplay ? passingURLs : failingURLs;
85
85
 
@@ -169,7 +169,7 @@ class InstallableManifest extends Audit {
169
169
  * If there is an argument value, get it.
170
170
  * We only expect a `minimum-icon-size-in-pixels` errorArg[0] for two errorIds, currently.
171
171
  */
172
- const value0 = err.errorArguments && err.errorArguments.length && err.errorArguments[0].value;
172
+ const value0 = err.errorArguments?.length && err.errorArguments[0].value;
173
173
 
174
174
  if (matchingString && err.errorArguments.length !== UIStringArguments.length) {
175
175
  // Matching string, but have the incorrect number of arguments for the message.
@@ -62,7 +62,7 @@ class MaskableIcon extends Audit {
62
62
  }
63
63
  const maskableIconCheck = manifestValues.allChecks.find(i => i.id === 'hasMaskableIcon');
64
64
  return {
65
- score: (maskableIconCheck && maskableIconCheck.passing) ? 1 : 0,
65
+ score: maskableIconCheck?.passing ? 1 : 0,
66
66
  };
67
67
  }
68
68
  }
@@ -35,7 +35,7 @@ class MultiCheckAudit extends Audit {
35
35
  allChecks: undefined,
36
36
  };
37
37
 
38
- if (result.manifestValues && result.manifestValues.allChecks) {
38
+ if (result.manifestValues?.allChecks) {
39
39
  result.manifestValues.allChecks.forEach(check => {
40
40
  detailsItem[check.id] = check.passing;
41
41
  });
@@ -41,10 +41,10 @@ class NetworkRequests extends Audit {
41
41
  undefined : (time - earliestStartTime) * 1000;
42
42
 
43
43
  const results = records.map(record => {
44
- const endTimeDeltaMs = record.lrStatistics && record.lrStatistics.endTimeDeltaMs;
45
- const TCPMs = record.lrStatistics && record.lrStatistics.TCPMs;
46
- const requestMs = record.lrStatistics && record.lrStatistics.requestMs;
47
- const responseMs = record.lrStatistics && record.lrStatistics.responseMs;
44
+ const endTimeDeltaMs = record.lrStatistics?.endTimeDeltaMs;
45
+ const TCPMs = record.lrStatistics?.TCPMs;
46
+ const requestMs = record.lrStatistics?.requestMs;
47
+ const responseMs = record.lrStatistics?.responseMs;
48
48
 
49
49
  return {
50
50
  url: URL.elideDataURI(record.url),
@@ -176,7 +176,7 @@ class PreloadLCPImageAudit extends Audit {
176
176
  const node = modifiedNodesById.get(nodeId);
177
177
  if (!node) throw new Error('Impossible - node should never be undefined');
178
178
  const timings = simulationAfterChanges.nodeTimings.get(node);
179
- const endTime = timings && timings.endTime || 0;
179
+ const endTime = timings?.endTime || 0;
180
180
  maxDependencyEndTime = Math.max(maxDependencyEndTime, endTime);
181
181
  }
182
182
 
@@ -101,7 +101,7 @@ class ThemedOmnibox extends MultiCheckAudit {
101
101
  return {
102
102
  failures,
103
103
  manifestValues,
104
- themeColor: (themeColorMeta && themeColorMeta.content) || null,
104
+ themeColor: themeColorMeta?.content || null,
105
105
  };
106
106
  }
107
107
  }
@@ -93,7 +93,7 @@ class ValidSourceMaps extends Audit {
93
93
  }
94
94
 
95
95
  // Sources content errors.
96
- if (sourceMap && sourceMap.map) {
96
+ if (sourceMap?.map) {
97
97
  const sourcesContent = sourceMap.map.sourcesContent || [];
98
98
  let missingSourcesContentCount = 0;
99
99
  for (let i = 0; i < sourceMap.map.sources.length; i++) {
@@ -108,7 +108,7 @@ class ValidSourceMaps extends Audit {
108
108
  if (sourceMap || errors.length) {
109
109
  results.push({
110
110
  scriptUrl: scriptElement.src,
111
- sourceMapUrl: sourceMap && sourceMap.sourceMapUrl,
111
+ sourceMapUrl: sourceMap?.sourceMapUrl,
112
112
  subItems: {
113
113
  type: /** @type {const} */ ('subitems'),
114
114
  items: errors,
@@ -39,7 +39,7 @@ class ImageRecords {
39
39
 
40
40
  for (const element of data.ImageElements) {
41
41
  const networkRecord = indexedNetworkRecords[element.src];
42
- const mimeType = networkRecord && networkRecord.mimeType;
42
+ const mimeType = networkRecord?.mimeType;
43
43
 
44
44
  // Don't change the guessed mime type if no mime type was found.
45
45
  imageRecords.push({
@@ -100,7 +100,7 @@ class JSBundles {
100
100
  const mapUrl = SourceMap.sourceMapUrl || 'compiled.js.map';
101
101
  const map = new SDK.TextSourceMap(compiledUrl, mapUrl, rawMap);
102
102
 
103
- const content = scriptElement && scriptElement.content ? scriptElement.content : '';
103
+ const content = scriptElement?.content ? scriptElement.content : '';
104
104
  const sizes = computeGeneratedFileSizes(map, content);
105
105
 
106
106
  const bundle = {
@@ -111,7 +111,7 @@ class LanternMetricArtifact {
111
111
  const processedTrace = await ProcessedTrace.request(trace, context);
112
112
  const processedNavigation = await ProcessedNavigation.request(processedTrace, context);
113
113
  const simulator = data.simulator ||
114
- await LoadSimulator.request({devtoolsLog, settings}, context);
114
+ (await LoadSimulator.request({devtoolsLog, settings}, context));
115
115
 
116
116
  const optimisticGraph = this.getOptimisticGraph(graph, processedNavigation);
117
117
  const pessimisticGraph = this.getPessimisticGraph(graph, processedNavigation);
@@ -67,22 +67,22 @@ class TimingSummary {
67
67
  /** @type {LH.Artifacts.TimingSummary} */
68
68
  const metrics = {
69
69
  // Include the simulated/observed performance metrics
70
- firstContentfulPaint: firstContentfulPaint && firstContentfulPaint.timing,
71
- firstContentfulPaintTs: firstContentfulPaint && firstContentfulPaint.timestamp,
72
- firstContentfulPaintAllFrames: firstContentfulPaintAllFrames && firstContentfulPaintAllFrames.timing,
73
- firstContentfulPaintAllFramesTs: firstContentfulPaintAllFrames && firstContentfulPaintAllFrames.timestamp,
74
- firstMeaningfulPaint: firstMeaningfulPaint && firstMeaningfulPaint.timing,
75
- firstMeaningfulPaintTs: firstMeaningfulPaint && firstMeaningfulPaint.timestamp,
76
- largestContentfulPaint: largestContentfulPaint && largestContentfulPaint.timing,
77
- largestContentfulPaintTs: largestContentfulPaint && largestContentfulPaint.timestamp,
78
- largestContentfulPaintAllFrames: largestContentfulPaintAllFrames && largestContentfulPaintAllFrames.timing,
79
- largestContentfulPaintAllFramesTs: largestContentfulPaintAllFrames && largestContentfulPaintAllFrames.timestamp,
80
- interactive: interactive && interactive.timing,
81
- interactiveTs: interactive && interactive.timestamp,
82
- speedIndex: speedIndex && speedIndex.timing,
83
- speedIndexTs: speedIndex && speedIndex.timestamp,
84
- totalBlockingTime: totalBlockingTime && totalBlockingTime.timing,
85
- maxPotentialFID: maxPotentialFID && maxPotentialFID.timing,
70
+ firstContentfulPaint: firstContentfulPaint?.timing,
71
+ firstContentfulPaintTs: firstContentfulPaint?.timestamp,
72
+ firstContentfulPaintAllFrames: firstContentfulPaintAllFrames?.timing,
73
+ firstContentfulPaintAllFramesTs: firstContentfulPaintAllFrames?.timestamp,
74
+ firstMeaningfulPaint: firstMeaningfulPaint?.timing,
75
+ firstMeaningfulPaintTs: firstMeaningfulPaint?.timestamp,
76
+ largestContentfulPaint: largestContentfulPaint?.timing,
77
+ largestContentfulPaintTs: largestContentfulPaint?.timestamp,
78
+ largestContentfulPaintAllFrames: largestContentfulPaintAllFrames?.timing,
79
+ largestContentfulPaintAllFramesTs: largestContentfulPaintAllFrames?.timestamp,
80
+ interactive: interactive?.timing,
81
+ interactiveTs: interactive?.timestamp,
82
+ speedIndex: speedIndex?.timing,
83
+ speedIndexTs: speedIndex?.timestamp,
84
+ totalBlockingTime: totalBlockingTime?.timing,
85
+ maxPotentialFID: maxPotentialFID?.timing,
86
86
  cumulativeLayoutShift,
87
87
  cumulativeLayoutShiftMainFrame,
88
88
  totalCumulativeLayoutShift,
@@ -91,26 +91,26 @@ class TimingSummary {
91
91
  observedTimeOrigin: processedTrace.timings.timeOrigin,
92
92
  observedTimeOriginTs: processedTrace.timestamps.timeOrigin,
93
93
  // For now, navigationStart is always timeOrigin.
94
- observedNavigationStart: processedNavigation && processedNavigation.timings.timeOrigin,
95
- observedNavigationStartTs: processedNavigation && processedNavigation.timestamps.timeOrigin,
96
- observedFirstPaint: processedNavigation && processedNavigation.timings.firstPaint,
97
- observedFirstPaintTs: processedNavigation && processedNavigation.timestamps.firstPaint,
98
- observedFirstContentfulPaint: processedNavigation && processedNavigation.timings.firstContentfulPaint,
99
- observedFirstContentfulPaintTs: processedNavigation && processedNavigation.timestamps.firstContentfulPaint,
100
- observedFirstContentfulPaintAllFrames: processedNavigation && processedNavigation.timings.firstContentfulPaintAllFrames,
101
- observedFirstContentfulPaintAllFramesTs: processedNavigation && processedNavigation.timestamps.firstContentfulPaintAllFrames,
102
- observedFirstMeaningfulPaint: processedNavigation && processedNavigation.timings.firstMeaningfulPaint,
103
- observedFirstMeaningfulPaintTs: processedNavigation && processedNavigation.timestamps.firstMeaningfulPaint,
104
- observedLargestContentfulPaint: processedNavigation && processedNavigation.timings.largestContentfulPaint,
105
- observedLargestContentfulPaintTs: processedNavigation && processedNavigation.timestamps.largestContentfulPaint,
106
- observedLargestContentfulPaintAllFrames: processedNavigation && processedNavigation.timings.largestContentfulPaintAllFrames,
107
- observedLargestContentfulPaintAllFramesTs: processedNavigation && processedNavigation.timestamps.largestContentfulPaintAllFrames,
94
+ observedNavigationStart: processedNavigation?.timings.timeOrigin,
95
+ observedNavigationStartTs: processedNavigation?.timestamps.timeOrigin,
96
+ observedFirstPaint: processedNavigation?.timings.firstPaint,
97
+ observedFirstPaintTs: processedNavigation?.timestamps.firstPaint,
98
+ observedFirstContentfulPaint: processedNavigation?.timings.firstContentfulPaint,
99
+ observedFirstContentfulPaintTs: processedNavigation?.timestamps.firstContentfulPaint,
100
+ observedFirstContentfulPaintAllFrames: processedNavigation?.timings.firstContentfulPaintAllFrames,
101
+ observedFirstContentfulPaintAllFramesTs: processedNavigation?.timestamps.firstContentfulPaintAllFrames,
102
+ observedFirstMeaningfulPaint: processedNavigation?.timings.firstMeaningfulPaint,
103
+ observedFirstMeaningfulPaintTs: processedNavigation?.timestamps.firstMeaningfulPaint,
104
+ observedLargestContentfulPaint: processedNavigation?.timings.largestContentfulPaint,
105
+ observedLargestContentfulPaintTs: processedNavigation?.timestamps.largestContentfulPaint,
106
+ observedLargestContentfulPaintAllFrames: processedNavigation?.timings.largestContentfulPaintAllFrames,
107
+ observedLargestContentfulPaintAllFramesTs: processedNavigation?.timestamps.largestContentfulPaintAllFrames,
108
108
  observedTraceEnd: processedTrace.timings.traceEnd,
109
109
  observedTraceEndTs: processedTrace.timestamps.traceEnd,
110
- observedLoad: processedNavigation && processedNavigation.timings.load,
111
- observedLoadTs: processedNavigation && processedNavigation.timestamps.load,
112
- observedDomContentLoaded: processedNavigation && processedNavigation.timings.domContentLoaded,
113
- observedDomContentLoadedTs: processedNavigation && processedNavigation.timestamps.domContentLoaded,
110
+ observedLoad: processedNavigation?.timings.load,
111
+ observedLoadTs: processedNavigation?.timestamps.load,
112
+ observedDomContentLoaded: processedNavigation?.timings.domContentLoaded,
113
+ observedDomContentLoadedTs: processedNavigation?.timestamps.domContentLoaded,
114
114
  observedCumulativeLayoutShift: cumulativeLayoutShift,
115
115
  observedCumulativeLayoutShiftMainFrame: cumulativeLayoutShiftMainFrame,
116
116
  observedTotalCumulativeLayoutShift: totalCumulativeLayoutShift,
@@ -128,7 +128,7 @@ class TimingSummary {
128
128
 
129
129
  /** @type {Record<string,boolean>} */
130
130
  const debugInfo = {
131
- lcpInvalidated: !!(processedNavigation && processedNavigation.lcpInvalidated),
131
+ lcpInvalidated: !!processedNavigation?.lcpInvalidated,
132
132
  };
133
133
 
134
134
  return {metrics, debugInfo};
@@ -205,7 +205,7 @@ class PageDependencyGraph {
205
205
  networkNode.startTime <= cpuNode.startTime) return;
206
206
  const {record} = networkNode;
207
207
  const resourceType = record.resourceType ||
208
- record.redirectDestination && record.redirectDestination.resourceType;
208
+ record.redirectDestination?.resourceType;
209
209
  if (!linkableResourceTypes.has(resourceType)) {
210
210
  // We only link some resources to CPU nodes because we observe LCP simulation
211
211
  // regressions when including images, etc.
@@ -405,7 +405,7 @@ class PageDependencyGraph {
405
405
 
406
406
  // The root request is the earliest request in the main document redirect chain.
407
407
  // Will be undefined if there were no redirects.
408
- const rootRequest = mainDocumentNode.record.redirects && mainDocumentNode.record.redirects[0];
408
+ const rootRequest = mainDocumentNode.record.redirects?.[0];
409
409
 
410
410
  let rootNode;
411
411
  if (rootRequest) {
@@ -55,7 +55,7 @@ class ResourceSummary {
55
55
  const budget = Budget.getMatchingBudget(budgets, mainResourceURL);
56
56
  /** @type {ReadonlyArray<string>} */
57
57
  let firstPartyHosts = [];
58
- if (budget && budget.options && budget.options.firstPartyHostnames) {
58
+ if (budget?.options?.firstPartyHostnames) {
59
59
  firstPartyHosts = budget.options.firstPartyHostnames;
60
60
  } else {
61
61
  const rootDomain = Util.getRootDomain(mainResourceURL);
@@ -295,7 +295,7 @@ function resolveSettings(settingsJson = {}, overrides = undefined) {
295
295
  // however `lookupLocale` will always determine which of our supported locales to use (falling
296
296
  // back if necessary).
297
297
  // TODO: could do more work to sniff out the user's locale
298
- const locale = i18n.lookupLocale((overrides && overrides.locale) || settingsJson.locale);
298
+ const locale = i18n.lookupLocale(overrides?.locale || settingsJson.locale);
299
299
 
300
300
  // Fill in missing settings with defaults
301
301
  const {defaultSettings} = constants;
@@ -332,7 +332,7 @@ function resolveSettings(settingsJson = {}, overrides = undefined) {
332
332
  */
333
333
  function mergePlugins(configJSON, configDir, flags) {
334
334
  const configPlugins = configJSON.plugins || [];
335
- const flagPlugins = (flags && flags.plugins) || [];
335
+ const flagPlugins = flags?.plugins || [];
336
336
  const pluginNames = new Set([...configPlugins, ...flagPlugins]);
337
337
 
338
338
  for (const pluginName of pluginNames) {