event-target-shim.mjs 23 KB

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