Skip to content
This repository has been archived by the owner on Apr 16, 2019. It is now read-only.

Make all event listeners passive where supported #4

Closed
wants to merge 3 commits into from

Conversation

RByers
Copy link

@RByers RByers commented Apr 7, 2016

See the passive event listener explainer. In practice we believe changing just this one script will have a measurable scroll performance improvement on the web. Fixes #3.

See [the passive event listener explainer](https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md).  In practice we believe changing just this one script will have a measurable scroll performance improvement on the web.
@RByers
Copy link
Author

RByers commented Apr 7, 2016

Note that I haven't made any attempt to test this PR, and may even have stupid typos. But hopefully it's still helpful as a start. Chrome 51 (current dev channel on desktop and Android) supports this feature.

@@ -85,9 +85,19 @@ limitations under the License.
root.focused = false;
});

var supportsPassive = false;
try {
addEventListener("test", null, Object.defineProperty({}, 'passive', {get: function () {
Copy link
Contributor

Choose a reason for hiding this comment

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

@RByers I'm having a hard time grokking this logic. I understand it's meant to determine whether the browser supports passive listeners, but I don't exactly see how it's doing that. Can you clarify?

Copy link
Author

Choose a reason for hiding this comment

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

Yeah it's a little ugly / confusing, sorry about that. Basically the canonical way (only way at the moment) to feature detect for dictionary members is to pass a custom object to an API that takes the dictionary and see if the getter is invoked for the property of interest. WebIDL Ecmascript bindings require that the getter for each supported property is invoked when the function is called.

So in this case we do a dummy call to addEventListener (passing null as the handler is defined to be a no-op). We pass into that a custom object whose passive getter function just records that it has been called. There are four possible behaviors:

  1. Browser doesn't support addEventListener or defineProperty at all - throws, supportsPassive remains false.
  2. addEventListener expects only a boolean in the 3rd position. The object gets coerced to the value true without invoking the getter. supportsPassive remains false.
  3. addEventListener supports taking a dictionary in the 3rd position, but not the passive member. In that case other getters may be invoked, but not the one we've defined for passive. supportsPassive remains false.
  4. addEventListener supports the passive option. In that case the getter function we've defined gets run as part of the JavaScript API binding and supportsPassive will be true.

For context see the original design discussion and this WebIDL issue where we're considering exposing something less ugly.

@emmettbutler
Copy link
Contributor

Thanks for the pull request @RByers. This repository is meant only as a public mirror of code that we use internally at Parse.ly. We don't actually import or use this repository in any way, so merging your pull request won't change anything.

However, this diff is very helpful as an example of how we can support passive listeners. I'll prioritize getting it into the tracker and testing it across different browsers.

@RByers
Copy link
Author

RByers commented Jul 5, 2016

Thanks for looking at this! I understand regarding the role of this repo - feel free to close the PR.

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.

2 participants