summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/dom/events/AddEventListenerOptions-passive.any.js
blob: 8e59cf5b379f2e806fa52b82d87dd09f90c212d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// META: title=AddEventListenerOptions.passive

test(function() {
  var supportsPassive = false;
  var query_options = {
    get passive() {
      supportsPassive = true;
      return false;
    },
    get dummy() {
      assert_unreached("dummy value getter invoked");
      return false;
    }
  };

  const et = new EventTarget();
  et.addEventListener('test_event', null, query_options);
  assert_true(supportsPassive, "addEventListener doesn't support the passive option");

  supportsPassive = false;
  et.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, existingEventTarget) {
  var defaultPrevented = undefined;
  var handler = function handler(e) {
    assert_false(e.defaultPrevented, "Event prematurely marked defaultPrevented");
    e.preventDefault();
    defaultPrevented = e.defaultPrevented;
  }
  const et = existingEventTarget || new EventTarget();
  et.addEventListener('test', handler, optionsValue);
  var uncanceled = et.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");

  et.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;
  });
  const et = new EventTarget();
  et.addEventListener('test', handler, optionsValue);
  var uncanceled = et.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");

  et.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;
  };

  const et = new EventTarget();
  et.addEventListener('test', dummyHandler1, {passive:true});
  et.addEventListener('test', dummyHandler2);

  testPassiveValue(optionsValue, expectedDefaultPrevented, et);

  assert_true(handlerInvoked1, "Extra passive handler not invoked");
  assert_true(handlerInvoked2, "Extra non-passive handler not invoked");

  et.removeEventListener('test', dummyHandler1);
  et.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++;
  }
  const et = new EventTarget();
  et.addEventListener('test', handler, optionValue1);
  et.addEventListener('test', handler, optionValue2);
  et.dispatchEvent(new Event('test', {bubbles: true}));
  assert_equals(invocationCount, expectedEquality ? 1 : 2, "equivalence of options " +
    JSON.stringify(optionValue1) + " and " + JSON.stringify(optionValue2));
  et.removeEventListener('test', handler, optionValue1);
  et.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");