Skip to content
This repository has been archived by the owner on Jan 4, 2023. It is now read-only.

Create has_shadow_root.js #159

Merged
merged 4 commits into from
May 28, 2019
Merged

Create has_shadow_root.js #159

merged 4 commits into from
May 28, 2019

Conversation

bkardell
Copy link
Contributor

per HTTPArchive/httparchive.org#141 - this is slightly complicated by the fact that I think we don't want to include native elements that have a shadow root like inputs and video in this, so... someone should probably review this to see if it makes sense.

per HTTPArchive/httparchive.org#141 - this is slightly complicated by the fact that I think we don't want to include native elements that have a shadow root like inputs and video in this, so... someone should probably review this to see if it makes sense.
@rviscomi
Copy link
Member

rviscomi commented Apr 27, 2019

Do you know of a page that has a shadow root? We can plug the custom metric into WPT and see if the results are expected.

FWIW I tested it on facebook.com and got null. Search "has_shadow_root" in the JSON results.

To reproduce, on the WPT home page go to the "Custom" tab of Advanced Settings and enter this under Custom Metrics:

[has_shadow_root]
/* 
  What we're looking for here is elements with non-native, 
  author-created shadow roots.

  ShadowRoots can be author-created on either 
  
  * the elements specifically in the allowed list 
  
  * on things parsed with valid custom element name productions. 
  
  (see https://dom.spec.whatwg.org/#dom-element-attachshadow)
  Since we are using the parsed DOM, we can simplify the second part a little 
  by simply checking for a dash and then whether it parsed as HTMLUnknownElement 
  or not. 
*/

var allowed = /^(article|aside|blockquote|body|div|footer|h1|h2|h3|h4|h5|h6|header||main|nav|p|section|span)$/i

function isValidCustomElementName(el) {
    return (el.tagName.indexOf('-') !== -1 && !(el instanceof HTMLUnknownElement))
}

function hasAuthorShadowRoot(el) {
    return (
        (
            isValidCustomElementName(el) 
            || 
            allowed.test(el.tagName)
        ) 
        && 
        el.shadowRoot
    )
}

return Array.from(document.querySelectorAll('*'))
            .some(hasAuthorShadowRoot)

@bkardell
Copy link
Contributor Author

bkardell commented Apr 27, 2019

There's something funny going on there I guess with returning a boolean? If I run it on facebook.com it is empty in the details table, if I run it on https://uncovered-mask.glitch.me/ then it is 1. IF I prefix a ""+ before the return to cast is as a string I get fb false and the glitch true (but, I assume as a string?)...

So, at least for these two tests I think it is working 'correctly' it's just a matter of what we want there I guess? I guess if it had to be returning a string, giving back "true" or "false" explicitly would make more sense?

I'd like like someone to review the actual logic there too though. Maybe @zcorpan can?

@rviscomi
Copy link
Member

rviscomi commented Apr 27, 2019

Oh, I had a rogue comma at the end of the return statement. Returning false now for FB and 1 for glitch. Close enough?

@zcorpan
Copy link
Contributor

zcorpan commented Apr 28, 2019

var allowed = /^(article|aside|blockquote|body|div|footer|h1|h2|h3|h4|h5|h6|header||main|nav|p|section|span)$/i

This has two consecutive ||. I guess tagName won't ever be the empty string, but still.

@zcorpan
Copy link
Contributor

zcorpan commented Apr 28, 2019

This code would include SVG elements, but I don't know if any SVG elements have a shadowRoot by default.

Fix double || in regexp and stringify response for consistency
@bkardell
Copy link
Contributor Author

This code would include SVG elements, but I don't know if any SVG elements have a shadowRoot by default.

Hmm yeah... There are a very few svg elements with a dash, right? It looks like most of them are deprecated and looking through a few I can't imagine how they could have a shadow.... Also, now that you mention it, I'm not entirely sure what I was thinking looking at the 'shortcut' I was trying to take to that using !HTMLUnknownElement because they wouldn't be anyway. Do you think it would make more sense to include another regexp there instead (from the spec) @zcorpan ?

Kind of makes me wish we had a allowsDefiningShadowRoot(element) or something in retrospect because lists of tags and logic that need to be applied that live in multiple places is very meh.

I think this is very close, it may still need a tweak I'm just not sure what yet... I guess the challenge here is that it just says "does" or "doesn't" and if we match something we shouldn't that would make the data very misleading. Maybe let's leave it open and think on it some for a few days?

@bkardell
Copy link
Contributor Author

Ah... now I think I remember what I was thinking, though, this seems backward -- I guess realistically we could check instanceof HTMLElement instead of the !HTMLUnknownElement and that should cover it?

@zcorpan
Copy link
Contributor

zcorpan commented Apr 30, 2019

HTMLUnknownElement inherits from HTMLElement, so you still would need to check both if you want to limit to "known" HTML elements.

@bkardell
Copy link
Contributor Author

HTMLUnknownElement inherits from HTMLElement, so you still would need to check both if you want to limit to "known" HTML elements.

Yeah, so... something like this expanded out with comments form?

function isValidCustomElementName(el) {
    // it's got to have a dash
    if ((el.tagName.indexOf('-') !== -1) {
         // it has to be both an HTMLElement this prevents us from getting
         // any dasherized elements that could exist in 'other embdedded'
        if (el instanceof HTMLElement) {

             // finally, it actually has to be defined as a custom element
             return !(el instanceof HTMLUnknownElement)
        }
    }
    return false
}

@zcorpan
Copy link
Contributor

zcorpan commented May 2, 2019

Yes

Update the way we check for valid custom element name after some discussion in order to avoid potential false positives.
@rviscomi
Copy link
Member

@bkardell have you had a chance to test this on WPT?

Fixed broken paren.  Tested on Web Page Test via custom metrics - returns explicit true or false. Assuming links hold up, these should illustrate successful runs..

https://www.webpagetest.org/custom_metrics.php?test=190514_AV_0cdf6cffade2c8b54dc205d6b3ac596a&run=1&cached=0
https://www.webpagetest.org/custom_metrics.php?test=190514_X3_773a477c083e5705cd680858be91f31e&run=1&cached=0
@bkardell
Copy link
Contributor Author

Sorry, no I hadn't. Have now, updated the pull including links to (I hope, assuming the links hold) the result runs.

@rviscomi
Copy link
Member

Ok great, thanks. Where can I find those links?

FWIW I tested this on facebook and the glitch URLs from earlier and I'm getting false/true respectively.

Let me know if you're happy with the results and I'll merge the PR. We should get initial data in the June crawl, available in early July.

@rviscomi
Copy link
Member

@bkardell closing the loop, is this PR ready to merge?

@bkardell
Copy link
Contributor Author

Yes, I'm happy with it. The links are in the pull request comments, sorry I was traveling all last week

@rviscomi rviscomi merged commit e5d3242 into HTTPArchive:master May 28, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants