UNPKG

3.95 kBJavaScriptView Raw
1const root =
2 (typeof globalThis !== "undefined" && globalThis) ||
3 (typeof self !== "undefined" && self) ||
4 (typeof global !== "undefined" && global);
5
6if (typeof root.Event === "undefined") {
7 root.Event = (function () {
8 function Event(type, options) {
9 if (options) {
10 for (let key of options) {
11 if (options.hasOwnProperty(key)) {
12 this[key] = options[key];
13 }
14 }
15 }
16 this.type = type;
17 }
18
19 return Event;
20 })();
21}
22
23if (typeof root.EventTarget === "undefined" || !(function () { try { return new EventTarget() } catch { return 0 } }())) {
24 root.EventTarget = (function () {
25 function EventTarget() {
26 this.__listeners = new Map();
27 }
28
29 EventTarget.prototype = Object.create(Object.prototype);
30
31 EventTarget.prototype.addEventListener = function (
32 type,
33 listener,
34 options
35 ) {
36 if (arguments.length < 2) {
37 throw new TypeError(
38 `TypeError: Failed to execute 'addEventListener' on 'EventTarget': 2 arguments required, but only ${arguments.length} present.`
39 );
40 }
41 const __listeners = this.__listeners;
42 const actualType = type.toString();
43 if (!__listeners.has(actualType)) {
44 __listeners.set(actualType, new Map());
45 }
46 const listenersForType = __listeners.get(actualType);
47 if (!listenersForType.has(listener)) {
48 // Any given listener is only registered once
49 listenersForType.set(listener, options);
50 }
51 };
52
53 EventTarget.prototype.removeEventListener = function (
54 type,
55 listener,
56 _options
57 ) {
58 if (arguments.length < 2) {
59 throw new TypeError(
60 `TypeError: Failed to execute 'addEventListener' on 'EventTarget': 2 arguments required, but only ${arguments.length} present.`
61 );
62 }
63 const __listeners = this.__listeners;
64 const actualType = type.toString();
65 if (__listeners.has(actualType)) {
66 const listenersForType = __listeners.get(actualType);
67 if (listenersForType.has(listener)) {
68 listenersForType.delete(listener);
69 }
70 }
71 };
72
73 EventTarget.prototype.dispatchEvent = function (event) {
74 if (!(event instanceof Event)) {
75 throw new TypeError(
76 `Failed to execute 'dispatchEvent' on 'EventTarget': parameter 1 is not of type 'Event'.`
77 );
78 }
79 const type = event.type;
80 const __listeners = this.__listeners;
81 const listenersForType = __listeners.get(type);
82 if (listenersForType) {
83 for (const [listener, options] of listenersForType.entries()) {
84 try {
85 if (typeof listener === "function") {
86 // Listener functions must be executed with the EventTarget as the `this` context.
87 listener.call(this, event);
88 } else if (listener && typeof listener.handleEvent === "function") {
89 // Listener objects have their handleEvent method called, if they have one
90 listener.handleEvent(event);
91 }
92 } catch (err) {
93 // We need to report the error to the global error handling event,
94 // but we do not want to break the loop that is executing the events.
95 // Unfortunately, this is the best we can do, which isn't great, because the
96 // native EventTarget will actually do this synchronously before moving to the next
97 // event in the loop.
98 setTimeout(() => {
99 throw err;
100 });
101 }
102 if (options && options.once) {
103 // If this was registered with { once: true }, we need
104 // to remove it now.
105 listenersForType.delete(listener);
106 }
107 }
108 }
109 // Since there are no cancellable events on a base EventTarget,
110 // this should always return true.
111 return true;
112 };
113
114 return EventTarget;
115 })();
116}