diff --git a/clients/extension/scripts/popup.js b/clients/extension/scripts/popup.js index a73d73759e1a..d790373e3c8d 100644 --- a/clients/extension/scripts/popup.js +++ b/clients/extension/scripts/popup.js @@ -26,12 +26,11 @@ const STRINGS = BROWSER_BRAND === 'chrome' ? CHROME_STRINGS : FIREFOX_STRINGS; /** * Guaranteed context.querySelector. Always returns an element or throws if * nothing matches query. - * @param {string} query + * @template {string} T + * @param {T} query * @param {ParentNode=} context - * @return {HTMLElement} */ function find(query, context = document) { - /** @type {?HTMLElement} */ const result = context.querySelector(query); if (result === null) { throw new Error(`query ${query} not found`); @@ -108,10 +107,9 @@ function fillDevToolsShortcut() { function readSettingsFromDomAndPersist() { const optionsEl = find('.section--options'); // Save settings when options page is closed. - const checkboxes = /** @type {NodeListOf} */ - (optionsEl.querySelectorAll('.options__categories input:checked')); + const checkboxes = optionsEl.querySelectorAll('.options__categories input:checked'); const selectedCategories = Array.from(checkboxes).map(input => input.value); - const device = /** @type {HTMLInputElement} */ (find('input[name="device"]:checked')).value; + const device = find('input[name="device"]:checked').value; const settings = { selectedCategories, @@ -155,8 +153,8 @@ async function initPopup() { const mainEl = find('main'); const optionsEl = find('.button--configure'); - const generateReportButton = /** @type {HTMLButtonElement} */ (find('.button--generate')); - const configureButton = /** @type {HTMLButtonElement} */ (find('.button--configure')); + const generateReportButton = find('button.button--generate'); + const configureButton = find('button.button--configure'); const psiDisclaimerEl = find('.psi-disclaimer'); const errorMessageEl = find('.errormsg'); const optionsFormEl = find('.options__form'); diff --git a/lighthouse-core/gather/fetcher.js b/lighthouse-core/gather/fetcher.js index cd13313e8873..94c2660e908f 100644 --- a/lighthouse-core/gather/fetcher.js +++ b/lighthouse-core/gather/fetcher.js @@ -143,7 +143,6 @@ class Fetcher { */ /* c8 ignore start */ function injectIframe(src) { - /** @type {HTMLIFrameElement} */ const iframe = document.createElement('iframe'); // Try really hard not to affect the page. iframe.style.display = 'none'; diff --git a/lighthouse-core/gather/gatherers/dobetterweb/tags-blocking-first-paint.js b/lighthouse-core/gather/gatherers/dobetterweb/tags-blocking-first-paint.js index 9fc13ea49202..8ef9d294f4e2 100644 --- a/lighthouse-core/gather/gatherers/dobetterweb/tags-blocking-first-paint.js +++ b/lighthouse-core/gather/gatherers/dobetterweb/tags-blocking-first-paint.js @@ -61,13 +61,10 @@ async function collectTagsThatBlockFirstPaint() { try { /** @type {Array} */ const linkTags = [...document.querySelectorAll('link')] - .filter(/** @return {tag is HTMLLinkElement} */ tag => { - if (tag.tagName !== 'LINK') return false; - + .filter(linkTag => { // Filter stylesheet/HTML imports that block rendering. // https://www.igvita.com/2012/06/14/debunking-responsive-css-performance-myths/ // https://www.w3.org/TR/html-imports/#dfn-import-async-attribute - const linkTag = /** @type {HTMLLinkElement} */ (tag); const blockingStylesheet = linkTag.rel === 'stylesheet' && window.matchMedia(linkTag.media).matches && !linkTag.disabled; const blockingImport = linkTag.rel === 'import' && !linkTag.hasAttribute('async'); @@ -87,10 +84,7 @@ async function collectTagsThatBlockFirstPaint() { /** @type {Array} */ const scriptTags = [...document.querySelectorAll('head script[src]')] - .filter(/** @return {tag is HTMLScriptElement} */ tag => { - if (tag.tagName !== 'SCRIPT') return false; - - const scriptTag = /** @type {HTMLScriptElement} */ (tag); + .filter(scriptTag => { return ( !scriptTag.hasAttribute('async') && !scriptTag.hasAttribute('defer') && diff --git a/lighthouse-core/report/html/renderer/category-renderer.js b/lighthouse-core/report/html/renderer/category-renderer.js index 58af7d068526..1fe8f5884113 100644 --- a/lighthouse-core/report/html/renderer/category-renderer.js +++ b/lighthouse-core/report/html/renderer/category-renderer.js @@ -170,7 +170,7 @@ class CategoryRenderer { /** * @param {LH.ReportResult.Category} category * @param {Record} groupDefinitions - * @return {Element} + * @return {DocumentFragment} */ renderCategoryHeader(category, groupDefinitions) { const tmpl = this.dom.cloneTemplate('#tmpl-lh-category-header', this.templateContext); @@ -184,7 +184,7 @@ class CategoryRenderer { this.dom.find('.lh-category-header__description', tmpl).appendChild(descEl); } - return /** @type {Element} */ (tmpl.firstElementChild); + return tmpl; } /** @@ -336,8 +336,7 @@ class CategoryRenderer { // Cast `null` to 0 const numericScore = Number(category.score); const gauge = this.dom.find('.lh-gauge', tmpl); - /** @type {?SVGCircleElement} */ - const gaugeArc = gauge.querySelector('.lh-gauge-arc'); + const gaugeArc = this.dom.find('circle.lh-gauge-arc', gauge); if (gaugeArc) this._setGaugeArc(gaugeArc, numericScore); diff --git a/lighthouse-core/report/html/renderer/dom.js b/lighthouse-core/report/html/renderer/dom.js index 8b564606772b..18f2db42b85b 100644 --- a/lighthouse-core/report/html/renderer/dom.js +++ b/lighthouse-core/report/html/renderer/dom.js @@ -218,7 +218,6 @@ class DOM { * @param {ParentNode} context */ find(query, context) { - /** @type {?import('typed-query-selector/parser').ParseSelector} */ const result = context.querySelector(query); if (result === null) { throw new Error(`query ${query} not found`); @@ -233,7 +232,6 @@ class DOM { * @param {ParentNode} context */ findAll(query, context) { - /** @type {Array>} */ const elements = Array.from(context.querySelectorAll(query)); return elements; } diff --git a/lighthouse-core/report/html/renderer/logger.js b/lighthouse-core/report/html/renderer/logger.js index 864c1b0ab87b..9044dac93586 100644 --- a/lighthouse-core/report/html/renderer/logger.js +++ b/lighthouse-core/report/html/renderer/logger.js @@ -24,7 +24,6 @@ class Logger { * @param {Element} element */ constructor(element) { - /** @type {Element} */ this.el = element; this._id = undefined; } diff --git a/lighthouse-core/report/html/renderer/report-renderer.js b/lighthouse-core/report/html/renderer/report-renderer.js index 002e567c9ceb..3f608125e607 100644 --- a/lighthouse-core/report/html/renderer/report-renderer.js +++ b/lighthouse-core/report/html/renderer/report-renderer.js @@ -83,7 +83,7 @@ class ReportRenderer { const el = this._dom.cloneTemplate('#tmpl-lh-heading', this._templateContext); const domFragment = this._dom.cloneTemplate('#tmpl-lh-scores-wrapper', this._templateContext); const placeholder = this._dom.find('.lh-scores-wrapper-placeholder', el); - /** @type {HTMLDivElement} */ (placeholder.parentNode).replaceChild(domFragment, placeholder); + placeholder.replaceWith(domFragment); return el; } diff --git a/lighthouse-core/report/html/renderer/report-ui-features.js b/lighthouse-core/report/html/renderer/report-ui-features.js index 15386ed3936c..db281706c667 100644 --- a/lighthouse-core/report/html/renderer/report-ui-features.js +++ b/lighthouse-core/report/html/renderer/report-ui-features.js @@ -238,8 +238,7 @@ class ReportUIFeatures { ]; // Get all tables with a text url column. - /** @type {Array} */ - const tables = Array.from(this._document.querySelectorAll('.lh-table')); + const tables = Array.from(this._document.querySelectorAll('table.lh-table')); const tablesWithUrls = tables .filter(el => el.querySelector('td.lh-table-column--url, td.lh-table-column--source-location')) @@ -335,8 +334,7 @@ class ReportUIFeatures { for (const rowEl of rowEls) { if (rowEl.classList.contains('lh-sub-item-row')) continue; - /** @type {HTMLElement|null} */ - const urlItem = rowEl.querySelector('.lh-text__url'); + const urlItem = rowEl.querySelector('div.lh-text__url'); if (!urlItem) continue; const datasetUrl = urlItem.dataset.url; @@ -834,11 +832,11 @@ class DropDown { /** * @param {Array} allNodes - * @param {?Node=} startNode - * @returns {Node} + * @param {?HTMLElement=} startNode + * @returns {HTMLElement} */ _getNextSelectableNode(allNodes, startNode) { - const nodes = allNodes.filter((node) => { + const nodes = allNodes.filter(/** @return {node is HTMLElement} */ (node) => { if (!(node instanceof HTMLElement)) { return false; } @@ -865,21 +863,21 @@ class DropDown { } /** - * @param {?Element=} startEl + * @param {?HTMLElement=} startEl * @returns {HTMLElement} */ _getNextMenuItem(startEl) { const nodes = Array.from(this._menuEl.childNodes); - return /** @type {HTMLElement} */ (this._getNextSelectableNode(nodes, startEl)); + return this._getNextSelectableNode(nodes, startEl); } /** - * @param {?Element=} startEl + * @param {?HTMLElement=} startEl * @returns {HTMLElement} */ _getPreviousMenuItem(startEl) { const nodes = Array.from(this._menuEl.childNodes).reverse(); - return /** @type {HTMLElement} */ (this._getNextSelectableNode(nodes, startEl)); + return this._getNextSelectableNode(nodes, startEl); } } diff --git a/lighthouse-treemap/app/src/util.js b/lighthouse-treemap/app/src/util.js index b5ceb79665d4..e80c9cd99f04 100644 --- a/lighthouse-treemap/app/src/util.js +++ b/lighthouse-treemap/app/src/util.js @@ -52,12 +52,11 @@ class TreemapUtil { /** * Guaranteed context.querySelector. Always returns an element or throws if * nothing matches query. - * @param {string} query + * @template {string} T + * @param {T} query * @param {ParentNode=} context - * @return {HTMLElement} */ static find(query, context = document) { - /** @type {?HTMLElement} */ const result = context.querySelector(query); if (result === null) { throw new Error(`query ${query} not found`); diff --git a/lighthouse-viewer/app/src/lighthouse-report-viewer.js b/lighthouse-viewer/app/src/lighthouse-report-viewer.js index 51b9265a9716..63dc87c0db03 100644 --- a/lighthouse-viewer/app/src/lighthouse-report-viewer.js +++ b/lighthouse-viewer/app/src/lighthouse-report-viewer.js @@ -12,12 +12,11 @@ /** * Guaranteed context.querySelector. Always returns an element or throws if * nothing matches query. - * @param {string} query + * @template {string} T + * @param {T} query * @param {ParentNode} context - * @return {HTMLElement} */ function find(query, context) { - /** @type {?HTMLElement} */ const result = context.querySelector(query); if (result === null) { throw new Error(`query ${query} not found`); @@ -67,7 +66,7 @@ class LighthouseReportViewer { gistUrlInput.addEventListener('change', this._onUrlInputChange); // Hidden file input to trigger manual file selector. - const fileInput = find('#hidden-file-input', document); + const fileInput = find('input#hidden-file-input', document); fileInput.addEventListener('change', e => { if (!e.target) { return; @@ -283,8 +282,7 @@ class LighthouseReportViewer { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = function(e) { - const readerTarget = /** @type {?FileReader} */ (e.target); - const result = /** @type {?string} */ (readerTarget && readerTarget.result); + const result = /** @type {?string} */ (e.target && e.target.result); if (!result) { reject('Could not read file'); return; diff --git a/types/externs.d.ts b/types/externs.d.ts index 9cdc87fe2258..3ceab1690d98 100644 --- a/types/externs.d.ts +++ b/types/externs.d.ts @@ -7,6 +7,9 @@ import _Crdp from 'devtools-protocol/types/protocol'; import _CrdpMappings from 'devtools-protocol/types/protocol-mapping' +// Import for side effects improving types of querySelector/querySelectorAll. +import 'typed-query-selector'; + declare global { // Augment Intl to include // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/getCanonicalLocales