1 | /**
|
2 | * @author Toru Nagashima <https://github.com/mysticatea>
|
3 | * @copyright 2015 Toru Nagashima. All rights reserved.
|
4 | * See LICENSE file in root directory for full license.
|
5 | */
|
6 | ;
|
7 |
|
8 | Object.defineProperty(exports, '__esModule', { value: true });
|
9 |
|
10 | /**
|
11 | * @typedef {object} PrivateData
|
12 | * @property {EventTarget} eventTarget The event target.
|
13 | * @property {{type:string}} event The original event object.
|
14 | * @property {number} eventPhase The current event phase.
|
15 | * @property {EventTarget|null} currentTarget The current event target.
|
16 | * @property {boolean} canceled The flag to prevent default.
|
17 | * @property {boolean} stopped The flag to stop propagation immediately.
|
18 | * @property {Function|null} passiveListener The listener if the current listener is passive. Otherwise this is null.
|
19 | * @property {number} timeStamp The unix time.
|
20 | * @private
|
21 | */
|
22 |
|
23 | /**
|
24 | * Private data for event wrappers.
|
25 | * @type {WeakMap<Event, PrivateData>}
|
26 | * @private
|
27 | */
|
28 | const privateData = new WeakMap();
|
29 |
|
30 | /**
|
31 | * Cache for wrapper classes.
|
32 | * @type {WeakMap<Object, Function>}
|
33 | * @private
|
34 | */
|
35 | const wrappers = new WeakMap();
|
36 |
|
37 | /**
|
38 | * Get private data.
|
39 | * @param {Event} event The event object to get private data.
|
40 | * @returns {PrivateData} The private data of the event.
|
41 | * @private
|
42 | */
|
43 | function pd(event) {
|
44 | const retv = privateData.get(event);
|
45 | console.assert(retv != null, "'this' is expected an Event object, but got", event);
|
46 | return retv
|
47 | }
|
48 |
|
49 | /**
|
50 | * @see https://dom.spec.whatwg.org/#interface-event
|
51 | * @private
|
52 | */
|
53 | /**
|
54 | * The event wrapper.
|
55 | * @constructor
|
56 | * @param {EventTarget} eventTarget The event target of this dispatching.
|
57 | * @param {Event|{type:string}} event The original event to wrap.
|
58 | */
|
59 | function Event(eventTarget, event) {
|
60 | privateData.set(this, {
|
61 | eventTarget,
|
62 | event,
|
63 | eventPhase: 2,
|
64 | currentTarget: eventTarget,
|
65 | canceled: false,
|
66 | stopped: false,
|
67 | passiveListener: null,
|
68 | timeStamp: event.timeStamp || Date.now(),
|
69 | });
|
70 |
|
71 | // https://heycam.github.io/webidl/#Unforgeable
|
72 | Object.defineProperty(this, "isTrusted", { value: false, enumerable: true });
|
73 |
|
74 | // Define accessors
|
75 | const keys = Object.keys(event);
|
76 | for (let i = 0; i < keys.length; ++i) {
|
77 | const key = keys[i];
|
78 | if (!(key in this)) {
|
79 | Object.defineProperty(this, key, defineRedirectDescriptor(key));
|
80 | }
|
81 | }
|
82 | }
|
83 |
|
84 | // Should be enumerable, but class methods are not enumerable.
|
85 | Event.prototype = {
|
86 | /**
|
87 | * The type of this event.
|
88 | * @type {string}
|
89 | */
|
90 | get type() {
|
91 | return pd(this).event.type
|
92 | },
|
93 |
|
94 | /**
|
95 | * The target of this event.
|
96 | * @type {EventTarget}
|
97 | */
|
98 | get target() {
|
99 | return pd(this).eventTarget
|
100 | },
|
101 |
|
102 | /**
|
103 | * The target of this event.
|
104 | * @type {EventTarget}
|
105 | */
|
106 | get currentTarget() {
|
107 | return pd(this).currentTarget
|
108 | },
|
109 |
|
110 | /**
|
111 | * @returns {EventTarget[]} The composed path of this event.
|
112 | */
|
113 | composedPath() {
|
114 | const currentTarget = pd(this).currentTarget;
|
115 | if (currentTarget == null) {
|
116 | return []
|
117 | }
|
118 | return [currentTarget]
|
119 | },
|
120 |
|
121 | /**
|
122 | * Constant of NONE.
|
123 | * @type {number}
|
124 | */
|
125 | get NONE() {
|
126 | return 0
|
127 | },
|
128 |
|
129 | /**
|
130 | * Constant of CAPTURING_PHASE.
|
131 | * @type {number}
|
132 | */
|
133 | get CAPTURING_PHASE() {
|
134 | return 1
|
135 | },
|
136 |
|
137 | /**
|
138 | * Constant of AT_TARGET.
|
139 | * @type {number}
|
140 | */
|
141 | get AT_TARGET() {
|
142 | return 2
|
143 | },
|
144 |
|
145 | /**
|
146 | * Constant of BUBBLING_PHASE.
|
147 | * @type {number}
|
148 | */
|
149 | get BUBBLING_PHASE() {
|
150 | return 3
|
151 | },
|
152 |
|
153 | /**
|
154 | * The target of this event.
|
155 | * @type {number}
|
156 | */
|
157 | get eventPhase() {
|
158 | return pd(this).eventPhase
|
159 | },
|
160 |
|
161 | /**
|
162 | * Stop event bubbling.
|
163 | * @returns {void}
|
164 | */
|
165 | stopPropagation() {
|
166 | const data = pd(this);
|
167 | if (typeof data.event.stopPropagation === "function") {
|
168 | data.event.stopPropagation();
|
169 | }
|
170 | },
|
171 |
|
172 | /**
|
173 | * Stop event bubbling.
|
174 | * @returns {void}
|
175 | */
|
176 | stopImmediatePropagation() {
|
177 | const data = pd(this);
|
178 |
|
179 | data.stopped = true;
|
180 | if (typeof data.event.stopImmediatePropagation === "function") {
|
181 | data.event.stopImmediatePropagation();
|
182 | }
|
183 | },
|
184 |
|
185 | /**
|
186 | * The flag to be bubbling.
|
187 | * @type {boolean}
|
188 | */
|
189 | get bubbles() {
|
190 | return Boolean(pd(this).event.bubbles)
|
191 | },
|
192 |
|
193 | /**
|
194 | * The flag to be cancelable.
|
195 | * @type {boolean}
|
196 | */
|
197 | get cancelable() {
|
198 | return Boolean(pd(this).event.cancelable)
|
199 | },
|
200 |
|
201 | /**
|
202 | * Cancel this event.
|
203 | * @returns {void}
|
204 | */
|
205 | preventDefault() {
|
206 | const data = pd(this);
|
207 | if (data.passiveListener != null) {
|
208 | console.warn("Event#preventDefault() was called from a passive listener:", data.passiveListener);
|
209 | return
|
210 | }
|
211 | if (!data.event.cancelable) {
|
212 | return
|
213 | }
|
214 |
|
215 | data.canceled = true;
|
216 | if (typeof data.event.preventDefault === "function") {
|
217 | data.event.preventDefault();
|
218 | }
|
219 | },
|
220 |
|
221 | /**
|
222 | * The flag to indicate cancellation state.
|
223 | * @type {boolean}
|
224 | */
|
225 | get defaultPrevented() {
|
226 | return pd(this).canceled
|
227 | },
|
228 |
|
229 | /**
|
230 | * The flag to be composed.
|
231 | * @type {boolean}
|
232 | */
|
233 | get composed() {
|
234 | return Boolean(pd(this).event.composed)
|
235 | },
|
236 |
|
237 | /**
|
238 | * The unix time of this event.
|
239 | * @type {number}
|
240 | */
|
241 | get timeStamp() {
|
242 | return pd(this).timeStamp
|
243 | },
|
244 | };
|
245 |
|
246 | // `constructor` is not enumerable.
|
247 | Object.defineProperty(Event.prototype, "constructor", { value: Event, configurable: true, writable: true });
|
248 |
|
249 | // Ensure `event instanceof window.Event` is `true`.
|
250 | if (typeof window !== "undefined" && typeof window.Event !== "undefined") {
|
251 | Object.setPrototypeOf(Event.prototype, window.Event.prototype);
|
252 |
|
253 | // Make association for wrappers.
|
254 | wrappers.set(window.Event.prototype, Event);
|
255 | }
|
256 |
|
257 | /**
|
258 | * Get the property descriptor to redirect a given property.
|
259 | * @param {string} key Property name to define property descriptor.
|
260 | * @returns {PropertyDescriptor} The property descriptor to redirect the property.
|
261 | * @private
|
262 | */
|
263 | function defineRedirectDescriptor(key) {
|
264 | return {
|
265 | get() {
|
266 | return pd(this).event[key]
|
267 | },
|
268 | set(value) {
|
269 | pd(this).event[key] = value;
|
270 | },
|
271 | configurable: true,
|
272 | enumerable: true,
|
273 | }
|
274 | }
|
275 |
|
276 | /**
|
277 | * Get the property descriptor to call a given method property.
|
278 | * @param {string} key Property name to define property descriptor.
|
279 | * @returns {PropertyDescriptor} The property descriptor to call the method property.
|
280 | * @private
|
281 | */
|
282 | function defineCallDescriptor(key) {
|
283 | return {
|
284 | value() {
|
285 | const event = pd(this).event;
|
286 | return event[key].apply(event, arguments)
|
287 | },
|
288 | configurable: true,
|
289 | enumerable: true,
|
290 | }
|
291 | }
|
292 |
|
293 | /**
|
294 | * Define new wrapper class.
|
295 | * @param {Function} BaseEvent The base wrapper class.
|
296 | * @param {Object} proto The prototype of the original event.
|
297 | * @returns {Function} The defined wrapper class.
|
298 | * @private
|
299 | */
|
300 | function defineWrapper(BaseEvent, proto) {
|
301 | const keys = Object.keys(proto);
|
302 | if (keys.length === 0) {
|
303 | return BaseEvent
|
304 | }
|
305 |
|
306 | /** CustomEvent */
|
307 | function CustomEvent(eventTarget, event) {
|
308 | BaseEvent.call(this, eventTarget, event);
|
309 | }
|
310 |
|
311 | CustomEvent.prototype = Object.create(BaseEvent.prototype, {
|
312 | constructor: { value: CustomEvent, configurable: true, writable: true },
|
313 | });
|
314 |
|
315 | // Define accessors.
|
316 | for (let i = 0; i < keys.length; ++i) {
|
317 | const key = keys[i];
|
318 | if (!(key in BaseEvent.prototype)) {
|
319 | const descriptor = Object.getOwnPropertyDescriptor(proto, key);
|
320 | const isFunc = (typeof descriptor.value === "function");
|
321 | Object.defineProperty(
|
322 | CustomEvent.prototype,
|
323 | key,
|
324 | isFunc ? defineCallDescriptor(key) : defineRedirectDescriptor(key)
|
325 | );
|
326 | }
|
327 | }
|
328 |
|
329 | return CustomEvent
|
330 | }
|
331 |
|
332 | /**
|
333 | * Get the wrapper class of a given prototype.
|
334 | * @param {Object} proto The prototype of the original event to get its wrapper.
|
335 | * @returns {Function} The wrapper class.
|
336 | * @private
|
337 | */
|
338 | function getWrapper(proto) {
|
339 | if (proto == null || proto === Object.prototype) {
|
340 | return Event
|
341 | }
|
342 |
|
343 | let wrapper = wrappers.get(proto);
|
344 | if (wrapper == null) {
|
345 | wrapper = defineWrapper(getWrapper(Object.getPrototypeOf(proto)), proto);
|
346 | wrappers.set(proto, wrapper);
|
347 | }
|
348 | return wrapper
|
349 | }
|
350 |
|
351 | /**
|
352 | * Wrap a given event to management a dispatching.
|
353 | * @param {EventTarget} eventTarget The event target of this dispatching.
|
354 | * @param {Object} event The event to wrap.
|
355 | * @returns {Event} The wrapper instance.
|
356 | * @private
|
357 | */
|
358 | function wrapEvent(eventTarget, event) {
|
359 | const Wrapper = getWrapper(Object.getPrototypeOf(event));
|
360 | return new Wrapper(eventTarget, event)
|
361 | }
|
362 |
|
363 | /**
|
364 | * Get the stopped flag of a given event.
|
365 | * @param {Event} event The event to get.
|
366 | * @returns {boolean} The flag to stop propagation immediately.
|
367 | * @private
|
368 | */
|
369 | function isStopped(event) {
|
370 | return pd(event).stopped
|
371 | }
|
372 |
|
373 | /**
|
374 | * Set the current event phase of a given event.
|
375 | * @param {Event} event The event to set current target.
|
376 | * @param {number} eventPhase New event phase.
|
377 | * @returns {void}
|
378 | * @private
|
379 | */
|
380 | function setEventPhase(event, eventPhase) {
|
381 | pd(event).eventPhase = eventPhase;
|
382 | }
|
383 |
|
384 | /**
|
385 | * Set the current target of a given event.
|
386 | * @param {Event} event The event to set current target.
|
387 | * @param {EventTarget|null} currentTarget New current target.
|
388 | * @returns {void}
|
389 | * @private
|
390 | */
|
391 | function setCurrentTarget(event, currentTarget) {
|
392 | pd(event).currentTarget = currentTarget;
|
393 | }
|
394 |
|
395 | /**
|
396 | * Set a passive listener of a given event.
|
397 | * @param {Event} event The event to set current target.
|
398 | * @param {Function|null} passiveListener New passive listener.
|
399 | * @returns {void}
|
400 | * @private
|
401 | */
|
402 | function setPassiveListener(event, passiveListener) {
|
403 | pd(event).passiveListener = passiveListener;
|
404 | }
|
405 |
|
406 | /**
|
407 | * @typedef {object} ListenerNode
|
408 | * @property {Function} listener
|
409 | * @property {1|2|3} listenerType
|
410 | * @property {boolean} passive
|
411 | * @property {boolean} once
|
412 | * @property {ListenerNode|null} next
|
413 | * @private
|
414 | */
|
415 |
|
416 | /**
|
417 | * @type {WeakMap<object, Map<string, ListenerNode>>}
|
418 | * @private
|
419 | */
|
420 | const listenersMap = new WeakMap();
|
421 |
|
422 | // Listener types
|
423 | const CAPTURE = 1;
|
424 | const BUBBLE = 2;
|
425 | const ATTRIBUTE = 3;
|
426 |
|
427 | /**
|
428 | * Check whether a given value is an object or not.
|
429 | * @param {any} x The value to check.
|
430 | * @returns {boolean} `true` if the value is an object.
|
431 | */
|
432 | function isObject(x) {
|
433 | return x !== null && typeof x === "object" //eslint-disable-line no-restricted-syntax
|
434 | }
|
435 |
|
436 | /**
|
437 | * Get listeners.
|
438 | * @param {EventTarget} eventTarget The event target to get.
|
439 | * @returns {Map<string, ListenerNode>} The listeners.
|
440 | * @private
|
441 | */
|
442 | function getListeners(eventTarget) {
|
443 | const listeners = listenersMap.get(eventTarget);
|
444 | console.assert(listeners != null, "'this' is expected an EventTarget object, but got", eventTarget);
|
445 | return listeners || new Map()
|
446 | }
|
447 |
|
448 | /**
|
449 | * Get the property descriptor for the event attribute of a given event.
|
450 | * @param {string} eventName The event name to get property descriptor.
|
451 | * @returns {PropertyDescriptor} The property descriptor.
|
452 | * @private
|
453 | */
|
454 | function defineEventAttributeDescriptor(eventName) {
|
455 | return {
|
456 | get() {
|
457 | const listeners = getListeners(this);
|
458 | let node = listeners.get(eventName);
|
459 | while (node != null) {
|
460 | if (node.listenerType === ATTRIBUTE) {
|
461 | return node.listener
|
462 | }
|
463 | node = node.next;
|
464 | }
|
465 | return null
|
466 | },
|
467 |
|
468 | set(listener) {
|
469 | if (typeof listener !== "function" && !isObject(listener)) {
|
470 | listener = null; // eslint-disable-line no-param-reassign
|
471 | }
|
472 | const listeners = getListeners(this);
|
473 |
|
474 | // Traverse to the tail while removing old value.
|
475 | let prev = null;
|
476 | let node = listeners.get(eventName);
|
477 | while (node != null) {
|
478 | if (node.listenerType === ATTRIBUTE) {
|
479 | // Remove old value.
|
480 | if (prev !== null) {
|
481 | prev.next = node.next;
|
482 | }
|
483 | else if (node.next !== null) {
|
484 | listeners.set(eventName, node.next);
|
485 | }
|
486 | else {
|
487 | listeners.delete(eventName);
|
488 | }
|
489 | }
|
490 | else {
|
491 | prev = node;
|
492 | }
|
493 |
|
494 | node = node.next;
|
495 | }
|
496 |
|
497 | // Add new value.
|
498 | if (listener !== null) {
|
499 | const newNode = {
|
500 | listener,
|
501 | listenerType: ATTRIBUTE,
|
502 | passive: false,
|
503 | once: false,
|
504 | next: null,
|
505 | };
|
506 | if (prev === null) {
|
507 | listeners.set(eventName, newNode);
|
508 | }
|
509 | else {
|
510 | prev.next = newNode;
|
511 | }
|
512 | }
|
513 | },
|
514 | configurable: true,
|
515 | enumerable: true,
|
516 | }
|
517 | }
|
518 |
|
519 | /**
|
520 | * Define an event attribute (e.g. `eventTarget.onclick`).
|
521 | * @param {Object} eventTargetPrototype The event target prototype to define an event attrbite.
|
522 | * @param {string} eventName The event name to define.
|
523 | * @returns {void}
|
524 | */
|
525 | function defineEventAttribute(eventTargetPrototype, eventName) {
|
526 | Object.defineProperty(eventTargetPrototype, `on${eventName}`, defineEventAttributeDescriptor(eventName));
|
527 | }
|
528 |
|
529 | /**
|
530 | * Define a custom EventTarget with event attributes.
|
531 | * @param {string[]} eventNames Event names for event attributes.
|
532 | * @returns {EventTarget} The custom EventTarget.
|
533 | * @private
|
534 | */
|
535 | function defineCustomEventTarget(eventNames) {
|
536 | /** CustomEventTarget */
|
537 | function CustomEventTarget() {
|
538 | EventTarget.call(this);
|
539 | }
|
540 |
|
541 | CustomEventTarget.prototype = Object.create(EventTarget.prototype, {
|
542 | constructor: { value: CustomEventTarget, configurable: true, writable: true },
|
543 | });
|
544 |
|
545 | for (let i = 0; i < eventNames.length; ++i) {
|
546 | defineEventAttribute(CustomEventTarget.prototype, eventNames[i]);
|
547 | }
|
548 |
|
549 | return CustomEventTarget
|
550 | }
|
551 |
|
552 | /**
|
553 | * EventTarget.
|
554 | *
|
555 | * - This is constructor if no arguments.
|
556 | * - This is a function which returns a CustomEventTarget constructor if there are arguments.
|
557 | *
|
558 | * For example:
|
559 | *
|
560 | * class A extends EventTarget {}
|
561 | * class B extends EventTarget("message") {}
|
562 | * class C extends EventTarget("message", "error") {}
|
563 | * class D extends EventTarget(["message", "error"]) {}
|
564 | */
|
565 | function EventTarget() {
|
566 | /*eslint-disable consistent-return */
|
567 | if (this instanceof EventTarget) {
|
568 | listenersMap.set(this, new Map());
|
569 | return
|
570 | }
|
571 | if (arguments.length === 1 && Array.isArray(arguments[0])) {
|
572 | return defineCustomEventTarget(arguments[0])
|
573 | }
|
574 | if (arguments.length > 0) {
|
575 | const types = new Array(arguments.length);
|
576 | for (let i = 0; i < arguments.length; ++i) {
|
577 | types[i] = arguments[i];
|
578 | }
|
579 | return defineCustomEventTarget(types)
|
580 | }
|
581 | throw new TypeError("Cannot call a class as a function")
|
582 | /*eslint-enable consistent-return */
|
583 | }
|
584 |
|
585 | // Should be enumerable, but class methods are not enumerable.
|
586 | EventTarget.prototype = {
|
587 | /**
|
588 | * Add a given listener to this event target.
|
589 | * @param {string} eventName The event name to add.
|
590 | * @param {Function} listener The listener to add.
|
591 | * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener.
|
592 | * @returns {boolean} `true` if the listener was added actually.
|
593 | */
|
594 | addEventListener(eventName, listener, options) {
|
595 | if (listener == null) {
|
596 | return false
|
597 | }
|
598 | if (typeof listener !== "function" && !isObject(listener)) {
|
599 | throw new TypeError("'listener' should be a function or an object.")
|
600 | }
|
601 |
|
602 | const listeners = getListeners(this);
|
603 | const optionsIsObj = isObject(options);
|
604 | const capture = optionsIsObj ? Boolean(options.capture) : Boolean(options);
|
605 | const listenerType = (capture ? CAPTURE : BUBBLE);
|
606 | const newNode = {
|
607 | listener,
|
608 | listenerType,
|
609 | passive: optionsIsObj && Boolean(options.passive),
|
610 | once: optionsIsObj && Boolean(options.once),
|
611 | next: null,
|
612 | };
|
613 |
|
614 | // Set it as the first node if the first node is null.
|
615 | let node = listeners.get(eventName);
|
616 | if (node === undefined) {
|
617 | listeners.set(eventName, newNode);
|
618 | return true
|
619 | }
|
620 |
|
621 | // Traverse to the tail while checking duplication..
|
622 | let prev = null;
|
623 | while (node != null) {
|
624 | if (node.listener === listener && node.listenerType === listenerType) {
|
625 | // Should ignore duplication.
|
626 | return false
|
627 | }
|
628 | prev = node;
|
629 | node = node.next;
|
630 | }
|
631 |
|
632 | // Add it.
|
633 | prev.next = newNode;
|
634 | return true
|
635 | },
|
636 |
|
637 | /**
|
638 | * Remove a given listener from this event target.
|
639 | * @param {string} eventName The event name to remove.
|
640 | * @param {Function} listener The listener to remove.
|
641 | * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener.
|
642 | * @returns {boolean} `true` if the listener was removed actually.
|
643 | */
|
644 | removeEventListener(eventName, listener, options) {
|
645 | if (listener == null) {
|
646 | return false
|
647 | }
|
648 |
|
649 | const listeners = getListeners(this);
|
650 | const capture = isObject(options) ? Boolean(options.capture) : Boolean(options);
|
651 | const listenerType = (capture ? CAPTURE : BUBBLE);
|
652 |
|
653 | let prev = null;
|
654 | let node = listeners.get(eventName);
|
655 | while (node != null) {
|
656 | if (node.listener === listener && node.listenerType === listenerType) {
|
657 | if (prev !== null) {
|
658 | prev.next = node.next;
|
659 | }
|
660 | else if (node.next !== null) {
|
661 | listeners.set(eventName, node.next);
|
662 | }
|
663 | else {
|
664 | listeners.delete(eventName);
|
665 | }
|
666 | return true
|
667 | }
|
668 |
|
669 | prev = node;
|
670 | node = node.next;
|
671 | }
|
672 |
|
673 | return false
|
674 | },
|
675 |
|
676 | /**
|
677 | * Dispatch a given event.
|
678 | * @param {Event|{type:string}} event The event to dispatch.
|
679 | * @returns {boolean} `false` if canceled.
|
680 | */
|
681 | dispatchEvent(event) {
|
682 | if (event == null || typeof event.type !== "string") {
|
683 | throw new TypeError("\"event.type\" should be a string.")
|
684 | }
|
685 |
|
686 | // If listeners aren't registered, terminate.
|
687 | const listeners = getListeners(this);
|
688 | const eventName = event.type;
|
689 | let node = listeners.get(eventName);
|
690 | if (node == null) {
|
691 | return true
|
692 | }
|
693 |
|
694 | // Since we cannot rewrite several properties, so wrap object.
|
695 | const wrappedEvent = wrapEvent(this, event);
|
696 |
|
697 | // This doesn't process capturing phase and bubbling phase.
|
698 | // This isn't participating in a tree.
|
699 | let prev = null;
|
700 | while (node != null) {
|
701 | // Remove this listener if it's once
|
702 | if (node.once) {
|
703 | if (prev !== null) {
|
704 | prev.next = node.next;
|
705 | }
|
706 | else if (node.next !== null) {
|
707 | listeners.set(eventName, node.next);
|
708 | }
|
709 | else {
|
710 | listeners.delete(eventName);
|
711 | }
|
712 | }
|
713 | else {
|
714 | prev = node;
|
715 | }
|
716 |
|
717 | // Call this listener
|
718 | setPassiveListener(wrappedEvent, (node.passive ? node.listener : null));
|
719 | if (typeof node.listener === "function") {
|
720 | node.listener.call(this, wrappedEvent);
|
721 | }
|
722 | else if (node.listenerType !== ATTRIBUTE && typeof node.listener.handleEvent === "function") {
|
723 | node.listener.handleEvent(wrappedEvent);
|
724 | }
|
725 |
|
726 | // Break if `event.stopImmediatePropagation` was called.
|
727 | if (isStopped(wrappedEvent)) {
|
728 | break
|
729 | }
|
730 |
|
731 | node = node.next;
|
732 | }
|
733 | setPassiveListener(wrappedEvent, null);
|
734 | setEventPhase(wrappedEvent, 0);
|
735 | setCurrentTarget(wrappedEvent, null);
|
736 |
|
737 | return !wrappedEvent.defaultPrevented
|
738 | },
|
739 | };
|
740 |
|
741 | // `constructor` is not enumerable.
|
742 | Object.defineProperty(EventTarget.prototype, "constructor", { value: EventTarget, configurable: true, writable: true });
|
743 |
|
744 | // Ensure `eventTarget instanceof window.EventTarget` is `true`.
|
745 | if (typeof window !== "undefined" && typeof window.EventTarget !== "undefined") {
|
746 | Object.setPrototypeOf(EventTarget.prototype, window.EventTarget.prototype);
|
747 | }
|
748 |
|
749 | exports.defineEventAttribute = defineEventAttribute;
|
750 | exports.EventTarget = EventTarget;
|
751 | exports['default'] = EventTarget;
|
752 |
|
753 | module.exports = EventTarget
|
754 | module.exports.EventTarget = module.exports["default"] = EventTarget
|
755 | module.exports.defineEventAttribute = defineEventAttribute
|
756 | //# sourceMappingURL=event-target-shim.js.map
|