Skip to content
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

DBW: Add audit for passive event listeners #830

Merged
merged 6 commits into from
Oct 29, 2016
Merged

DBW: Add audit for passive event listeners #830

merged 6 commits into from
Oct 29, 2016

Conversation

ebidel
Copy link
Contributor

@ebidel ebidel commented Oct 26, 2016

R: @paulirish @brendankenny @GoogleChrome/lighthouse

This audit adds:

  1. a gatherer for document-level event listeners (e.g. on window, document, document.body)
  2. an audit that uses the gatherer to check for scroll blocking listeners (touchstart, touchmove, wheel) that are not {passive: true} and which do not call preventDefault().

The gatherer results:

1

Report:
screen shot 2016-10-25 at 10 02 14 pm

@ebidel
Copy link
Contributor Author

ebidel commented Oct 27, 2016

@RByers for the FYI

Copy link
Member

@paulirish paulirish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels really nice so far. Nothing stood out in the review; nice stuff.

return PassiveEventsAudit.generateAuditResult({
rawValue: results.length === 0,
extendedInfo: {
formatter: Formatter.SUPPORTED_FORMATS.URLLIST,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to handle the text wrapping?
image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

const Audit = require('../audit');
const Formatter = require('../../formatters/formatter');

const SCROLL_BLOCKING_EVENTS = [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a comment pointing to something in the Blink source that confirms this list?
I think this is probably the best link: https://cs.chromium.org/search/?q=f:webinputevent.h+blocking&sq=package:chromium&type=cs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// not call preventDefault() are scroll blocking events.
const results = listeners.filter(loc => {
const isScrollBlocking = SCROLL_BLOCKING_EVENTS.indexOf(loc.type) !== -1;
const callsPreventDefault = loc.handler.description.match(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe call this mentionsPreventDefault?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

class PageLevelEventListeners extends Gatherer {

listenForScriptParsedEvents() {
return this.driver.sendCommand('Debugger.enable').then(_ => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we're mostly good, but let's make sure this domain is off when we dont need it.

can you add Debugger.disable, DOM.disable, and CSS.disable to beginTrace()? That's what devtools does:
image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

const matchedListeners = [];

return this._listEventListeners(location).then(results => {
const parsedScriptIds = this._parsedScripts.map(script => script.scriptId);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wanna store _parsedScripts as a map object instead (by scriptId), so you dont have to do this .map() each time?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need all the goodies in each parsed script later when creating combo

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clarified offline what I meant. Not a huge deal, though.

Copy link
Contributor Author

@ebidel ebidel Oct 29, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since multiple parsed scripts can share the same scriptId, I'm not sure the Map approach would work. I'd be able to look things up by scriptId, but it wouldn't (necessarily) be the correct value. I might be dumb.

..wait....

const Formatter = require('../../formatters/formatter');

const SCROLL_BLOCKING_EVENTS = [
'wheel', 'mousewheel', 'touchstart', 'touchmove'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wanna move these to a getBlockingEvents method on the audit so you dont have to duplicate in the test?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


// Note: line/col numbers are zero-index. Add one to each so we have
// actual file line/col numbers.
combo.line = combo.lineNumber + 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you want to check that handler, url exist before assuming the line/col are correct and exist?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was getting line/col numbers even before setting objectGroup: 'page-listeners-gatherer'. If handler doesn't exist, it might be good to handle that instead in the audit extendedInfo.code. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗺 'd so hard

@ebidel
Copy link
Contributor Author

ebidel commented Oct 29, 2016

PTAL

Copy link
Member

@paulirish paulirish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feels good.

Can't think of other audits that could reuse this gatherer, but it's the right shape for it.

The other area of concern is flipping on Debugger domain in beforePass. I don't think this raises any particular concerns right now, but it's something for us to keep in mind.

lgtm

@ebidel
Copy link
Contributor Author

ebidel commented Oct 29, 2016

We'll rock the gatherer in #786

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants