| <!DOCTYPE HTML> |
| <meta charset="utf-8"> |
| <title>EventListenerOptions.passive</title> |
| <link rel="author" title="Rick Byers" href="mailto:rbyers@chromium.org"> |
| <link rel="help" href="https://dom.spec.whatwg.org/#dom-addeventlisteneroptions-passive"> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <div id="log"></div> |
| |
| <script> |
| |
| test(function() { |
| var supportsPassive = false; |
| var query_options = { |
| get passive() { |
| supportsPassive = true; |
| return false; |
| }, |
| get dummy() { |
| assert_unreached("dummy value getter invoked"); |
| return false; |
| } |
| }; |
| |
| document.addEventListener('test_event', null, query_options); |
| assert_true(supportsPassive, "addEventListener doesn't support the passive option"); |
| |
| supportsPassive = false; |
| document.removeEventListener('test_event', null, query_options); |
| assert_false(supportsPassive, "removeEventListener supports the passive option when it should not"); |
| }, "Supports passive option on addEventListener only"); |
| |
| function testPassiveValue(optionsValue, expectedDefaultPrevented) { |
| var defaultPrevented = undefined; |
| var handler = function handler(e) { |
| assert_false(e.defaultPrevented, "Event prematurely marked defaultPrevented"); |
| e.preventDefault(); |
| defaultPrevented = e.defaultPrevented; |
| } |
| document.addEventListener('test', handler, optionsValue); |
| var uncanceled = document.body.dispatchEvent(new Event('test', {bubbles: true, cancelable: true})); |
| |
| assert_equals(defaultPrevented, expectedDefaultPrevented, "Incorrect defaultPrevented for options: " + JSON.stringify(optionsValue)); |
| assert_equals(uncanceled, !expectedDefaultPrevented, "Incorrect return value from dispatchEvent"); |
| |
| document.removeEventListener('test', handler, optionsValue); |
| } |
| |
| test(function() { |
| testPassiveValue(undefined, true); |
| testPassiveValue({}, true); |
| testPassiveValue({passive: false}, true); |
| testPassiveValue({passive: true}, false); |
| testPassiveValue({passive: 0}, true); |
| testPassiveValue({passive: 1}, false); |
| }, "preventDefault should be ignored if-and-only-if the passive option is true"); |
| |
| function testPassiveValueOnReturnValue(test, optionsValue, expectedDefaultPrevented) { |
| var defaultPrevented = undefined; |
| var handler = test.step_func(e => { |
| assert_false(e.defaultPrevented, "Event prematurely marked defaultPrevented"); |
| e.returnValue = false; |
| defaultPrevented = e.defaultPrevented; |
| }); |
| document.addEventListener('test', handler, optionsValue); |
| var uncanceled = document.body.dispatchEvent(new Event('test', {bubbles: true, cancelable: true})); |
| |
| assert_equals(defaultPrevented, expectedDefaultPrevented, "Incorrect defaultPrevented for options: " + JSON.stringify(optionsValue)); |
| assert_equals(uncanceled, !expectedDefaultPrevented, "Incorrect return value from dispatchEvent"); |
| |
| document.removeEventListener('test', handler, optionsValue); |
| } |
| |
| async_test(t => { |
| testPassiveValueOnReturnValue(t, undefined, true); |
| testPassiveValueOnReturnValue(t, {}, true); |
| testPassiveValueOnReturnValue(t, {passive: false}, true); |
| testPassiveValueOnReturnValue(t, {passive: true}, false); |
| testPassiveValueOnReturnValue(t, {passive: 0}, true); |
| testPassiveValueOnReturnValue(t, {passive: 1}, false); |
| t.done(); |
| }, "returnValue should be ignored if-and-only-if the passive option is true"); |
| |
| function testPassiveWithOtherHandlers(optionsValue, expectedDefaultPrevented) { |
| var handlerInvoked1 = false; |
| var dummyHandler1 = function() { |
| handlerInvoked1 = true; |
| }; |
| var handlerInvoked2 = false; |
| var dummyHandler2 = function() { |
| handlerInvoked2 = true; |
| }; |
| |
| document.addEventListener('test', dummyHandler1, {passive:true}); |
| document.addEventListener('test', dummyHandler2); |
| |
| testPassiveValue(optionsValue, expectedDefaultPrevented); |
| |
| assert_true(handlerInvoked1, "Extra passive handler not invoked"); |
| assert_true(handlerInvoked2, "Extra non-passive handler not invoked"); |
| |
| document.removeEventListener('test', dummyHandler1); |
| document.removeEventListener('test', dummyHandler2); |
| } |
| |
| test(function() { |
| testPassiveWithOtherHandlers({}, true); |
| testPassiveWithOtherHandlers({passive: false}, true); |
| testPassiveWithOtherHandlers({passive: true}, false); |
| }, "passive behavior of one listener should be unaffected by the presence of other listeners"); |
| |
| function testOptionEquivalence(optionValue1, optionValue2, expectedEquality) { |
| var invocationCount = 0; |
| var handler = function handler(e) { |
| invocationCount++; |
| } |
| document.addEventListener('test', handler, optionValue1); |
| document.addEventListener('test', handler, optionValue2); |
| document.body.dispatchEvent(new Event('test', {bubbles: true})); |
| assert_equals(invocationCount, expectedEquality ? 1 : 2, "equivalence of options " + |
| JSON.stringify(optionValue1) + " and " + JSON.stringify(optionValue2)); |
| document.removeEventListener('test', handler, optionValue1); |
| document.removeEventListener('test', handler, optionValue2); |
| } |
| |
| test(function() { |
| // Sanity check options that should be treated as distinct handlers |
| testOptionEquivalence({capture:true}, {capture:false, passive:false}, false); |
| testOptionEquivalence({capture:true}, {passive:true}, false); |
| |
| // Option values that should be treated as equivalent |
| testOptionEquivalence({}, {passive:false}, true); |
| testOptionEquivalence({passive:true}, {passive:false}, true); |
| testOptionEquivalence(undefined, {passive:true}, true); |
| testOptionEquivalence({capture: true, passive: false}, {capture: true, passive: true}, true); |
| |
| }, "Equivalence of option values"); |
| |
| </script> |