| Index: third_party/WebKit/Source/devtools/front_end/audits2/lighthouse/renderer/dom.js
|
| diff --git a/third_party/WebKit/Source/devtools/front_end/audits2/lighthouse/renderer/dom.js b/third_party/WebKit/Source/devtools/front_end/audits2/lighthouse/renderer/dom.js
|
| index 698985602b2037a349cfd23c1b32dd1628d04e63..412087a94d5e4e59f4deffb4faadd020f5c54e1e 100644
|
| --- a/third_party/WebKit/Source/devtools/front_end/audits2/lighthouse/renderer/dom.js
|
| +++ b/third_party/WebKit/Source/devtools/front_end/audits2/lighthouse/renderer/dom.js
|
| @@ -15,13 +15,14 @@
|
| */
|
| 'use strict';
|
|
|
| -/* globals URL */
|
| +/* globals URL self */
|
|
|
| class DOM {
|
| /**
|
| * @param {!Document} document
|
| */
|
| constructor(document) {
|
| + /** @private {!Document} */
|
| this._document = document;
|
| }
|
|
|
| @@ -33,9 +34,7 @@ class DOM {
|
| * set the attribute on the node.
|
| * @return {!Element}
|
| */
|
| - createElement(name, className, attrs) {
|
| - // TODO(all): adopt `attrs` default arg when https://codereview.chromium.org/2821773002/ lands
|
| - attrs = attrs || {};
|
| + createElement(name, className, attrs = {}) {
|
| const element = this._document.createElement(name);
|
| if (className) {
|
| element.className = className;
|
| @@ -51,16 +50,36 @@ class DOM {
|
|
|
| /**
|
| * @param {string} selector
|
| - * @param {!Document|!Element} context
|
| + * @param {!Node} context
|
| * @return {!DocumentFragment} A clone of the template content.
|
| * @throws {Error}
|
| */
|
| cloneTemplate(selector, context) {
|
| - const template = context.querySelector(selector);
|
| + const template = /** @type {?HTMLTemplateElement} */ (context.querySelector(selector));
|
| if (!template) {
|
| throw new Error(`Template not found: template${selector}`);
|
| }
|
| - return /** @type {!DocumentFragment} */ (this._document.importNode(template.content, true));
|
| +
|
| + const clone = /** @type {!DocumentFragment} */ (
|
| + this._document.importNode(template.content, true));
|
| +
|
| + // Prevent duplicate styles in the DOM. After a template has been stamped
|
| + // for the first time, remove the clone's styles so they're not re-added.
|
| + if (template.hasAttribute('data-stamped')) {
|
| + this.findAll('style', clone).forEach(style => style.remove());
|
| + }
|
| + template.setAttribute('data-stamped', true);
|
| +
|
| + return clone;
|
| + }
|
| +
|
| + /**
|
| + * Resets the "stamped" state of the templates.
|
| + */
|
| + resetTemplates() {
|
| + this.findAll('template[data-stamped]', this._document).forEach(t => {
|
| + t.removeAttribute('data-stamped');
|
| + });
|
| }
|
|
|
| /**
|
| @@ -80,7 +99,7 @@ class DOM {
|
|
|
| // Append link if there are any.
|
| if (linkText && linkHref) {
|
| - const a = this.createElement('a');
|
| + const a = /** @type {!HTMLAnchorElement} */ (this.createElement('a'));
|
| a.rel = 'noopener';
|
| a.target = '_blank';
|
| a.textContent = linkText;
|
| @@ -98,8 +117,35 @@ class DOM {
|
| document() {
|
| return this._document;
|
| }
|
| +
|
| + /**
|
| + * Guaranteed context.querySelector. Always returns an element or throws if
|
| + * nothing matches query.
|
| + * @param {string} query
|
| + * @param {!Node} context
|
| + * @return {!Element}
|
| + */
|
| + find(query, context) {
|
| + const result = context.querySelector(query);
|
| + if (result === null) {
|
| + throw new Error(`query ${query} not found`);
|
| + }
|
| + return result;
|
| + }
|
| +
|
| + /**
|
| + * Helper for context.querySelectorAll. Returns an Array instead of a NodeList.
|
| + * @param {string} query
|
| + * @param {!Node} context
|
| + * @return {!Array<!Element>}
|
| + */
|
| + findAll(query, context) {
|
| + return Array.from(context.querySelectorAll(query));
|
| + }
|
| }
|
|
|
| if (typeof module !== 'undefined' && module.exports) {
|
| module.exports = DOM;
|
| +} else {
|
| + self.DOM = DOM;
|
| }
|
|
|