| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -13,6 +13,7 @@ Last update: | |||
| 13 | 13 | - common: https://github.com/web-platform-tests/wpt/tree/03c5072aff/common | |
| 14 | 14 | - console: https://github.com/web-platform-tests/wpt/tree/3b1f72e99a/console | |
| 15 | 15 | - dom/abort: https://github.com/web-platform-tests/wpt/tree/c49cafb491/dom/abort | |
| 16 | + - dom/events: https://github.com/web-platform-tests/wpt/tree/f8821adb28/dom/events | ||
| 16 | 17 | - encoding: https://github.com/web-platform-tests/wpt/tree/35f70910d3/encoding | |
| 17 | 18 | - FileAPI: https://github.com/web-platform-tests/wpt/tree/3b279420d4/FileAPI | |
| 18 | 19 | - hr-time: https://github.com/web-platform-tests/wpt/tree/9910784394/hr-time | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,96 @@ | |||
| 1 | + // META: title=AddEventListenerOptions.once | ||
| 2 | + | ||
| 3 | + "use strict"; | ||
| 4 | + | ||
| 5 | + test(function() { | ||
| 6 | + var invoked_once = false; | ||
| 7 | + var invoked_normal = false; | ||
| 8 | + function handler_once() { | ||
| 9 | + invoked_once = true; | ||
| 10 | + } | ||
| 11 | + function handler_normal() { | ||
| 12 | + invoked_normal = true; | ||
| 13 | + } | ||
| 14 | + | ||
| 15 | + const et = new EventTarget(); | ||
| 16 | + et.addEventListener('test', handler_once, {once: true}); | ||
| 17 | + et.addEventListener('test', handler_normal); | ||
| 18 | + et.dispatchEvent(new Event('test')); | ||
| 19 | + assert_equals(invoked_once, true, "Once handler should be invoked"); | ||
| 20 | + assert_equals(invoked_normal, true, "Normal handler should be invoked"); | ||
| 21 | + | ||
| 22 | + invoked_once = false; | ||
| 23 | + invoked_normal = false; | ||
| 24 | + et.dispatchEvent(new Event('test')); | ||
| 25 | + assert_equals(invoked_once, false, "Once handler shouldn't be invoked again"); | ||
| 26 | + assert_equals(invoked_normal, true, "Normal handler should be invoked again"); | ||
| 27 | + et.removeEventListener('test', handler_normal); | ||
| 28 | + }, "Once listener should be invoked only once"); | ||
| 29 | + | ||
| 30 | + test(function() { | ||
| 31 | + const et = new EventTarget(); | ||
| 32 | + var invoked_count = 0; | ||
| 33 | + function handler() { | ||
| 34 | + invoked_count++; | ||
| 35 | + if (invoked_count == 1) | ||
| 36 | + et.dispatchEvent(new Event('test')); | ||
| 37 | + } | ||
| 38 | + et.addEventListener('test', handler, {once: true}); | ||
| 39 | + et.dispatchEvent(new Event('test')); | ||
| 40 | + assert_equals(invoked_count, 1, "Once handler should only be invoked once"); | ||
| 41 | + | ||
| 42 | + invoked_count = 0; | ||
| 43 | + function handler2() { | ||
| 44 | + invoked_count++; | ||
| 45 | + if (invoked_count == 1) | ||
| 46 | + et.addEventListener('test', handler2, {once: true}); | ||
| 47 | + if (invoked_count <= 2) | ||
| 48 | + et.dispatchEvent(new Event('test')); | ||
| 49 | + } | ||
| 50 | + et.addEventListener('test', handler2, {once: true}); | ||
| 51 | + et.dispatchEvent(new Event('test')); | ||
| 52 | + assert_equals(invoked_count, 2, "Once handler should only be invoked once after each adding"); | ||
| 53 | + }, "Once listener should be invoked only once even if the event is nested"); | ||
| 54 | + | ||
| 55 | + test(function() { | ||
| 56 | + var invoked_count = 0; | ||
| 57 | + function handler() { | ||
| 58 | + invoked_count++; | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + const et = new EventTarget(); | ||
| 62 | + | ||
| 63 | + et.addEventListener('test', handler, {once: true}); | ||
| 64 | + et.addEventListener('test', handler); | ||
| 65 | + et.dispatchEvent(new Event('test')); | ||
| 66 | + assert_equals(invoked_count, 1, "The handler should only be added once"); | ||
| 67 | + | ||
| 68 | + invoked_count = 0; | ||
| 69 | + et.dispatchEvent(new Event('test')); | ||
| 70 | + assert_equals(invoked_count, 0, "The handler was added as a once listener"); | ||
| 71 | + | ||
| 72 | + invoked_count = 0; | ||
| 73 | + et.addEventListener('test', handler, {once: true}); | ||
| 74 | + et.removeEventListener('test', handler); | ||
| 75 | + et.dispatchEvent(new Event('test')); | ||
| 76 | + assert_equals(invoked_count, 0, "The handler should have been removed"); | ||
| 77 | + }, "Once listener should be added / removed like normal listeners"); | ||
| 78 | + | ||
| 79 | + test(function() { | ||
| 80 | + const et = new EventTarget(); | ||
| 81 | + | ||
| 82 | + var invoked_count = 0; | ||
| 83 | + | ||
| 84 | + for (let n = 4; n > 0; n--) { | ||
| 85 | + et.addEventListener('test', (e) => { | ||
| 86 | + invoked_count++; | ||
| 87 | + e.stopImmediatePropagation(); | ||
| 88 | + }, {once: true}); | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + for (let n = 4; n > 0; n--) { | ||
| 92 | + et.dispatchEvent(new Event('test')); | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + assert_equals(invoked_count, 4, "The listeners should be invoked"); | ||
| 96 | + }, "Multiple once listeners should be invoked even if the stopImmediatePropagation is set"); | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,134 @@ | |||
| 1 | + // META: title=AddEventListenerOptions.passive | ||
| 2 | + | ||
| 3 | + test(function() { | ||
| 4 | + var supportsPassive = false; | ||
| 5 | + var query_options = { | ||
| 6 | + get passive() { | ||
| 7 | + supportsPassive = true; | ||
| 8 | + return false; | ||
| 9 | + }, | ||
| 10 | + get dummy() { | ||
| 11 | + assert_unreached("dummy value getter invoked"); | ||
| 12 | + return false; | ||
| 13 | + } | ||
| 14 | + }; | ||
| 15 | + | ||
| 16 | + const et = new EventTarget(); | ||
| 17 | + et.addEventListener('test_event', null, query_options); | ||
| 18 | + assert_true(supportsPassive, "addEventListener doesn't support the passive option"); | ||
| 19 | + | ||
| 20 | + supportsPassive = false; | ||
| 21 | + et.removeEventListener('test_event', null, query_options); | ||
| 22 | + assert_false(supportsPassive, "removeEventListener supports the passive option when it should not"); | ||
| 23 | + }, "Supports passive option on addEventListener only"); | ||
| 24 | + | ||
| 25 | + function testPassiveValue(optionsValue, expectedDefaultPrevented, existingEventTarget) { | ||
| 26 | + var defaultPrevented = undefined; | ||
| 27 | + var handler = function handler(e) { | ||
| 28 | + assert_false(e.defaultPrevented, "Event prematurely marked defaultPrevented"); | ||
| 29 | + e.preventDefault(); | ||
| 30 | + defaultPrevented = e.defaultPrevented; | ||
| 31 | + } | ||
| 32 | + const et = existingEventTarget || new EventTarget(); | ||
| 33 | + et.addEventListener('test', handler, optionsValue); | ||
| 34 | + var uncanceled = et.dispatchEvent(new Event('test', {bubbles: true, cancelable: true})); | ||
| 35 | + | ||
| 36 | + assert_equals(defaultPrevented, expectedDefaultPrevented, "Incorrect defaultPrevented for options: " + JSON.stringify(optionsValue)); | ||
| 37 | + assert_equals(uncanceled, !expectedDefaultPrevented, "Incorrect return value from dispatchEvent"); | ||
| 38 | + | ||
| 39 | + et.removeEventListener('test', handler, optionsValue); | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + test(function() { | ||
| 43 | + testPassiveValue(undefined, true); | ||
| 44 | + testPassiveValue({}, true); | ||
| 45 | + testPassiveValue({passive: false}, true); | ||
| 46 | + testPassiveValue({passive: true}, false); | ||
| 47 | + testPassiveValue({passive: 0}, true); | ||
| 48 | + testPassiveValue({passive: 1}, false); | ||
| 49 | + }, "preventDefault should be ignored if-and-only-if the passive option is true"); | ||
| 50 | + | ||
| 51 | + function testPassiveValueOnReturnValue(test, optionsValue, expectedDefaultPrevented) { | ||
| 52 | + var defaultPrevented = undefined; | ||
| 53 | + var handler = test.step_func(e => { | ||
| 54 | + assert_false(e.defaultPrevented, "Event prematurely marked defaultPrevented"); | ||
| 55 | + e.returnValue = false; | ||
| 56 | + defaultPrevented = e.defaultPrevented; | ||
| 57 | + }); | ||
| 58 | + const et = new EventTarget(); | ||
| 59 | + et.addEventListener('test', handler, optionsValue); | ||
| 60 | + var uncanceled = et.dispatchEvent(new Event('test', {bubbles: true, cancelable: true})); | ||
| 61 | + | ||
| 62 | + assert_equals(defaultPrevented, expectedDefaultPrevented, "Incorrect defaultPrevented for options: " + JSON.stringify(optionsValue)); | ||
| 63 | + assert_equals(uncanceled, !expectedDefaultPrevented, "Incorrect return value from dispatchEvent"); | ||
| 64 | + | ||
| 65 | + et.removeEventListener('test', handler, optionsValue); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + async_test(t => { | ||
| 69 | + testPassiveValueOnReturnValue(t, undefined, true); | ||
| 70 | + testPassiveValueOnReturnValue(t, {}, true); | ||
| 71 | + testPassiveValueOnReturnValue(t, {passive: false}, true); | ||
| 72 | + testPassiveValueOnReturnValue(t, {passive: true}, false); | ||
| 73 | + testPassiveValueOnReturnValue(t, {passive: 0}, true); | ||
| 74 | + testPassiveValueOnReturnValue(t, {passive: 1}, false); | ||
| 75 | + t.done(); | ||
| 76 | + }, "returnValue should be ignored if-and-only-if the passive option is true"); | ||
| 77 | + | ||
| 78 | + function testPassiveWithOtherHandlers(optionsValue, expectedDefaultPrevented) { | ||
| 79 | + var handlerInvoked1 = false; | ||
| 80 | + var dummyHandler1 = function() { | ||
| 81 | + handlerInvoked1 = true; | ||
| 82 | + }; | ||
| 83 | + var handlerInvoked2 = false; | ||
| 84 | + var dummyHandler2 = function() { | ||
| 85 | + handlerInvoked2 = true; | ||
| 86 | + }; | ||
| 87 | + | ||
| 88 | + const et = new EventTarget(); | ||
| 89 | + et.addEventListener('test', dummyHandler1, {passive:true}); | ||
| 90 | + et.addEventListener('test', dummyHandler2); | ||
| 91 | + | ||
| 92 | + testPassiveValue(optionsValue, expectedDefaultPrevented, et); | ||
| 93 | + | ||
| 94 | + assert_true(handlerInvoked1, "Extra passive handler not invoked"); | ||
| 95 | + assert_true(handlerInvoked2, "Extra non-passive handler not invoked"); | ||
| 96 | + | ||
| 97 | + et.removeEventListener('test', dummyHandler1); | ||
| 98 | + et.removeEventListener('test', dummyHandler2); | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + test(function() { | ||
| 102 | + testPassiveWithOtherHandlers({}, true); | ||
| 103 | + testPassiveWithOtherHandlers({passive: false}, true); | ||
| 104 | + testPassiveWithOtherHandlers({passive: true}, false); | ||
| 105 | + }, "passive behavior of one listener should be unaffected by the presence of other listeners"); | ||
| 106 | + | ||
| 107 | + function testOptionEquivalence(optionValue1, optionValue2, expectedEquality) { | ||
| 108 | + var invocationCount = 0; | ||
| 109 | + var handler = function handler(e) { | ||
| 110 | + invocationCount++; | ||
| 111 | + } | ||
| 112 | + const et = new EventTarget(); | ||
| 113 | + et.addEventListener('test', handler, optionValue1); | ||
| 114 | + et.addEventListener('test', handler, optionValue2); | ||
| 115 | + et.dispatchEvent(new Event('test', {bubbles: true})); | ||
| 116 | + assert_equals(invocationCount, expectedEquality ? 1 : 2, "equivalence of options " + | ||
| 117 | + JSON.stringify(optionValue1) + " and " + JSON.stringify(optionValue2)); | ||
| 118 | + et.removeEventListener('test', handler, optionValue1); | ||
| 119 | + et.removeEventListener('test', handler, optionValue2); | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + test(function() { | ||
| 123 | + // Sanity check options that should be treated as distinct handlers | ||
| 124 | + testOptionEquivalence({capture:true}, {capture:false, passive:false}, false); | ||
| 125 | + testOptionEquivalence({capture:true}, {passive:true}, false); | ||
| 126 | + | ||
| 127 | + // Option values that should be treated as equivalent | ||
| 128 | + testOptionEquivalence({}, {passive:false}, true); | ||
| 129 | + testOptionEquivalence({passive:true}, {passive:false}, true); | ||
| 130 | + testOptionEquivalence(undefined, {passive:true}, true); | ||
| 131 | + testOptionEquivalence({capture: true, passive: false}, {capture: true, passive: true}, true); | ||
| 132 | + | ||
| 133 | + }, "Equivalence of option values"); | ||
| 134 | + | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,143 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + test(function() { | ||
| 4 | + let count = 0; | ||
| 5 | + function handler() { | ||
| 6 | + count++; | ||
| 7 | + } | ||
| 8 | + const et = new EventTarget(); | ||
| 9 | + const controller = new AbortController(); | ||
| 10 | + et.addEventListener('test', handler, { signal: controller.signal }); | ||
| 11 | + et.dispatchEvent(new Event('test')); | ||
| 12 | + assert_equals(count, 1, "Adding a signal still adds a listener"); | ||
| 13 | + et.dispatchEvent(new Event('test')); | ||
| 14 | + assert_equals(count, 2, "The listener was not added with the once flag"); | ||
| 15 | + controller.abort(); | ||
| 16 | + et.dispatchEvent(new Event('test')); | ||
| 17 | + assert_equals(count, 2, "Aborting on the controller removes the listener"); | ||
| 18 | + et.addEventListener('test', handler, { signal: controller.signal }); | ||
| 19 | + et.dispatchEvent(new Event('test')); | ||
| 20 | + assert_equals(count, 2, "Passing an aborted signal never adds the handler"); | ||
| 21 | + }, "Passing an AbortSignal to addEventListener options should allow removing a listener"); | ||
| 22 | + | ||
| 23 | + test(function() { | ||
| 24 | + let count = 0; | ||
| 25 | + function handler() { | ||
| 26 | + count++; | ||
| 27 | + } | ||
| 28 | + const et = new EventTarget(); | ||
| 29 | + const controller = new AbortController(); | ||
| 30 | + et.addEventListener('test', handler, { signal: controller.signal }); | ||
| 31 | + et.removeEventListener('test', handler); | ||
| 32 | + et.dispatchEvent(new Event('test')); | ||
| 33 | + assert_equals(count, 0, "The listener was still removed"); | ||
| 34 | + }, "Passing an AbortSignal to addEventListener does not prevent removeEventListener"); | ||
| 35 | + | ||
| 36 | + test(function() { | ||
| 37 | + let count = 0; | ||
| 38 | + function handler() { | ||
| 39 | + count++; | ||
| 40 | + } | ||
| 41 | + const et = new EventTarget(); | ||
| 42 | + const controller = new AbortController(); | ||
| 43 | + et.addEventListener('test', handler, { signal: controller.signal, once: true }); | ||
| 44 | + controller.abort(); | ||
| 45 | + et.dispatchEvent(new Event('test')); | ||
| 46 | + assert_equals(count, 0, "The listener was still removed"); | ||
| 47 | + }, "Passing an AbortSignal to addEventListener works with the once flag"); | ||
| 48 | + | ||
| 49 | + test(function() { | ||
| 50 | + let count = 0; | ||
| 51 | + function handler() { | ||
| 52 | + count++; | ||
| 53 | + } | ||
| 54 | + const et = new EventTarget(); | ||
| 55 | + const controller = new AbortController(); | ||
| 56 | + et.addEventListener('test', handler, { signal: controller.signal, once: true }); | ||
| 57 | + et.removeEventListener('test', handler); | ||
| 58 | + et.dispatchEvent(new Event('test')); | ||
| 59 | + assert_equals(count, 0, "The listener was still removed"); | ||
| 60 | + }, "Removing a once listener works with a passed signal"); | ||
| 61 | + | ||
| 62 | + test(function() { | ||
| 63 | + let count = 0; | ||
| 64 | + function handler() { | ||
| 65 | + count++; | ||
| 66 | + } | ||
| 67 | + const et = new EventTarget(); | ||
| 68 | + const controller = new AbortController(); | ||
| 69 | + et.addEventListener('first', handler, { signal: controller.signal, once: true }); | ||
| 70 | + et.addEventListener('second', handler, { signal: controller.signal, once: true }); | ||
| 71 | + controller.abort(); | ||
| 72 | + et.dispatchEvent(new Event('first')); | ||
| 73 | + et.dispatchEvent(new Event('second')); | ||
| 74 | + assert_equals(count, 0, "The listener was still removed"); | ||
| 75 | + }, "Passing an AbortSignal to multiple listeners"); | ||
| 76 | + | ||
| 77 | + test(function() { | ||
| 78 | + let count = 0; | ||
| 79 | + function handler() { | ||
| 80 | + count++; | ||
| 81 | + } | ||
| 82 | + const et = new EventTarget(); | ||
| 83 | + const controller = new AbortController(); | ||
| 84 | + et.addEventListener('test', handler, { signal: controller.signal, capture: true }); | ||
| 85 | + controller.abort(); | ||
| 86 | + et.dispatchEvent(new Event('test')); | ||
| 87 | + assert_equals(count, 0, "The listener was still removed"); | ||
| 88 | + }, "Passing an AbortSignal to addEventListener works with the capture flag"); | ||
| 89 | + | ||
| 90 | + test(function() { | ||
| 91 | + let count = 0; | ||
| 92 | + function handler() { | ||
| 93 | + count++; | ||
| 94 | + } | ||
| 95 | + const et = new EventTarget(); | ||
| 96 | + const controller = new AbortController(); | ||
| 97 | + et.addEventListener('test', () => { | ||
| 98 | + controller.abort(); | ||
| 99 | + }, { signal: controller.signal }); | ||
| 100 | + et.addEventListener('test', handler, { signal: controller.signal }); | ||
| 101 | + et.dispatchEvent(new Event('test')); | ||
| 102 | + assert_equals(count, 0, "The listener was still removed"); | ||
| 103 | + }, "Aborting from a listener does not call future listeners"); | ||
| 104 | + | ||
| 105 | + test(function() { | ||
| 106 | + let count = 0; | ||
| 107 | + function handler() { | ||
| 108 | + count++; | ||
| 109 | + } | ||
| 110 | + const et = new EventTarget(); | ||
| 111 | + const controller = new AbortController(); | ||
| 112 | + et.addEventListener('test', () => { | ||
| 113 | + et.addEventListener('test', handler, { signal: controller.signal }); | ||
| 114 | + controller.abort(); | ||
| 115 | + }, { signal: controller.signal }); | ||
| 116 | + et.dispatchEvent(new Event('test')); | ||
| 117 | + assert_equals(count, 0, "The listener was still removed"); | ||
| 118 | + }, "Adding then aborting a listener in another listener does not call it"); | ||
| 119 | + | ||
| 120 | + test(function() { | ||
| 121 | + const et = new EventTarget(); | ||
| 122 | + const ac = new AbortController(); | ||
| 123 | + let count = 0; | ||
| 124 | + et.addEventListener('foo', () => { | ||
| 125 | + et.addEventListener('foo', () => { | ||
| 126 | + count++; | ||
| 127 | + if (count > 5) ac.abort(); | ||
| 128 | + et.dispatchEvent(new Event('foo')); | ||
| 129 | + }, { signal: ac.signal }); | ||
| 130 | + et.dispatchEvent(new Event('foo')); | ||
| 131 | + }, { once: true }); | ||
| 132 | + et.dispatchEvent(new Event('foo')); | ||
| 133 | + }, "Aborting from a nested listener should remove it"); | ||
| 134 | + | ||
| 135 | + test(function() { | ||
| 136 | + const et = new EventTarget(); | ||
| 137 | + assert_throws_js(TypeError, () => { et.addEventListener("foo", () => {}, { signal: null }); }); | ||
| 138 | + }, "Passing null as the signal should throw"); | ||
| 139 | + | ||
| 140 | + test(function() { | ||
| 141 | + const et = new EventTarget(); | ||
| 142 | + assert_throws_js(TypeError, () => { et.addEventListener("foo", null, { signal: null }); }); | ||
| 143 | + }, "Passing null as the signal should throw (listener is also null)"); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments