-
Notifications
You must be signed in to change notification settings - Fork 9.6k
core: add type checking to page functions #11958
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| async cacheNatives() { | ||
| await this.evaluateScriptOnNewDocument(` | ||
| window.__nativePromise = Promise; | ||
| window.__nativeError = Error; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAICT this hasn't been used since #5509
| if (!err || typeof err === 'string') { | ||
| err = new Error(err); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the research for what can end up in here was so long ago that I didn't want to break anything, so this is just a cleaned up version of what already existed. Also added tests to make sure all the cases are handled.
| // FIXME COMPAT: This hack isn't neccessary as of Chrome 62.0.3176.0 | ||
| // https://bugs.chromium.org/p/chromium/issues/detail?id=742530#c7 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fix shipped to stable Chrome in 2017
| if (element instanceof ShadowRoot) { | ||
| element = element.host; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the catch block below relies on element not being a ShadowRoot anymore, so this needs to be outside of the try block. From the PR that added it, it seems like the concern was the clone throwing, not this step anyways
| /** @type {Element} */ | ||
| // @ts-expect-error - clone will be same type as element - see https://github.com/microsoft/TypeScript/issues/283 | ||
| const clone = element.cloneNode(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clone is an Element since element is an Element, but the tsc dom types don't reflect this. When the mentioned issue (microsoft/TypeScript#283) is fixed (a fix was tried last year but backed out when it broke some stuff), this @ts-expect-error will start erroring and can be removed
| node = prevNode; | ||
| // skip empty text nodes | ||
| if (node.nodeType === Node.TEXT_NODE && node.nodeValue.trim().length === 0) continue; | ||
| if (node.nodeType === Node.TEXT_NODE && (node.nodeValue || '').trim().length === 0) continue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nodeValue technically can be null*, so, fine
*(though this code shouldn't ever end up on a node where it is)
| * - nodeSelector: section > img | ||
| */ | ||
| function getNodeSelector(node) { | ||
| function getNodeSelector(element) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we require this to be an Element (in the existing type, but also because we access classList and parentElement), so changed the param name, but it seemed like too much to rename the function to getElementSelector...
| /** | ||
| * @param {HTMLElement} element | ||
| * @param {string} attr | ||
| * @param {'overflowY'|'position'} attr |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was just easier since CSSStyleDeclaration doesn't have a string index, and CSSStyleDeclaration[keyof CSSStyleDeclaration] includes numbers and null. getStyleAttrValue is an inner convenience function, and it's unlikely to ever see any more values here (but more could always be added, of course) so this seems fine
| // html and body content is too broad to be useful, since they contain all page content | ||
| if (tagName !== 'html' && tagName !== 'body') { | ||
| const nodeLabel = node.innerText || node.getAttribute('alt') || node.getAttribute('aria-label'); | ||
| const nodeLabel = element instanceof HTMLElement && element.innerText || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
innerText is only on HTMLElement (though innerHTML is on Element 🤷)
|
|
||
| /** | ||
| * @param {HTMLElement} element | ||
| * @param {Element|ShadowRoot} element |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
made the HTMLElement -> Element change for two reasons:
- if
elementis aShadowRoot,element.hostis anElementnot anHTMLElement, so would really have needed a second test below to make sure it was still anHTMLElement - buuut, there doesn't appear to be any reason to limit
getNodeDetailstoHTMLElement...it seems reasonable for a gatherer to want to getnodeDetailsof an SVG element, for instance
There aren't any significant effects from this change, just some type ones (like __lighthouseNodesDontTouchOrAllVarianceGoesAway becomes a Map<Element, string>)
| const gl = canvas.getContext('webgl'); | ||
| if (!gl) throw new Error('no webgl'); | ||
| const maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE); | ||
| canvas = gl = undefined; // Cleanup for GC |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't understand why this was necessary at the time because I thought escape analysis is the same either way and the memory leak potential is in the side-effects of creating a webgl canvas creating a reference (in which case canvas = gl = undefined does nothing to help that, right?), but supposedly there was still a reason for this.
Given how fresh it is though, maybe @paulirish can clarify where #11847 (comment) ended up from his perspective :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it started from this offhand comment, not a detected problem #11847 (comment)
But yeah, they're references to DOM objects. Unsetting the locals isn't going to affect their lifecycle after the function is done.
|
|
||
| /** Used by FullPageScreenshot gatherer. */ | ||
| __lighthouseNodesDontTouchOrAllVarianceGoesAway: Map<HTMLElement, string>; | ||
| __lighthouseNodesDontTouchOrAllVarianceGoesAway: Map<Element, string>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hey wait a second how did this name end up staying like this 😆 I thought we had like 3 👎 comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hey wait a second how did this name end up staying like this 😆 I thought we had like 3 👎 comments
ha, yes, I would have also preferred a different name there :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lol I only recall @brendankenny downvoting. seems I snuck some personality in the code without any approval, sry.
to be clear this is referencing React's __SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED. but it's also a tounge-in-cheek response to some user expectations (the classic "I ran LH twice and got 91 and 92, which is it?!" that Patrick likes to reference)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haha I loved the concept I just didn't understand why it was backwards!! I'm so onboard for __lighthouseNodesDontTouchOrAllVarianceGoesThroughTheRoof :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose I'm hoping someone finds it and suggests removing it to fix our variance problem..
The file was actually in pretty good shape, and only needed three
// @ts-expect-errors, two of which could be worked around instead (but which approach to take is arguable) and the other error will hopefully be fixed in future tsc updates.This should give a lot more confidence when making changes to e.g.
nodeDetailsand the like in the future.