happy-dom 8.5.0 → 8.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of happy-dom might be problematic. Click here for more details.

@@ -1,6 +1,7 @@
1
1
  import IEventListener from './IEventListener';
2
2
  import Event from './Event';
3
3
  import IEventTarget from './IEventTarget';
4
+ import IEventListenerOptions from './IEventListenerOptions';
4
5
  /**
5
6
  * Handles events.
6
7
  */
@@ -8,13 +9,18 @@ export default abstract class EventTarget implements IEventTarget {
8
9
  readonly _listeners: {
9
10
  [k: string]: (((event: Event) => void) | IEventListener)[];
10
11
  };
12
+ readonly _listenerOptions: {
13
+ [k: string]: (IEventListenerOptions | null)[];
14
+ };
11
15
  /**
12
16
  * Adds an event listener.
13
17
  *
14
18
  * @param type Event type.
15
19
  * @param listener Listener.
20
+ * @param options An object that specifies characteristics about the event listener.(currently only once)
21
+ * @param options.once
16
22
  */
17
- addEventListener(type: string, listener: ((event: Event) => void) | IEventListener): void;
23
+ addEventListener(type: string, listener: ((event: Event) => void) | IEventListener, options?: IEventListenerOptions): void;
18
24
  /**
19
25
  * Adds an event listener.
20
26
  *
@@ -6,16 +6,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  class EventTarget {
7
7
  constructor() {
8
8
  this._listeners = {};
9
+ this._listenerOptions = {};
9
10
  }
10
11
  /**
11
12
  * Adds an event listener.
12
13
  *
13
14
  * @param type Event type.
14
15
  * @param listener Listener.
16
+ * @param options An object that specifies characteristics about the event listener.(currently only once)
17
+ * @param options.once
15
18
  */
16
- addEventListener(type, listener) {
19
+ addEventListener(type, listener, options) {
17
20
  this._listeners[type] = this._listeners[type] || [];
21
+ this._listenerOptions[type] = this._listenerOptions[type] || [];
18
22
  this._listeners[type].push(listener);
23
+ this._listenerOptions[type].push(options || null);
19
24
  }
20
25
  /**
21
26
  * Adds an event listener.
@@ -28,6 +33,7 @@ class EventTarget {
28
33
  const index = this._listeners[type].indexOf(listener);
29
34
  if (index !== -1) {
30
35
  this._listeners[type].splice(index, 1);
36
+ this._listenerOptions[type].splice(index, 1);
31
37
  }
32
38
  }
33
39
  }
@@ -47,13 +53,18 @@ class EventTarget {
47
53
  this[onEventName].call(this, event);
48
54
  }
49
55
  if (this._listeners[event.type]) {
50
- for (const listener of this._listeners[event.type]) {
56
+ for (let i = 0, max = this._listeners[event.type].length; i < max; i++) {
57
+ const listener = this._listeners[event.type][i];
58
+ const options = this._listenerOptions[event.type][i];
51
59
  if (listener.handleEvent) {
52
60
  listener.handleEvent(event);
53
61
  }
54
62
  else {
55
63
  listener.call(this, event);
56
64
  }
65
+ if (options?.once) {
66
+ this.removeEventListener(event.type, listener);
67
+ }
57
68
  if (event._immediatePropagationStopped) {
58
69
  return !(event.cancelable && event.defaultPrevented);
59
70
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EventTarget.js","sourceRoot":"","sources":["../../src/event/EventTarget.ts"],"names":[],"mappings":";;AAIA;;GAEG;AACH,MAA8B,WAAW;IAAzC;QACiB,eAAU,GAEtB,EAAE,CAAC;IA6FR,CAAC;IA3FA;;;;;OAKG;IACI,gBAAgB,CAAC,IAAY,EAAE,QAAmD;QACxF,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACpD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;IAED;;;;;OAKG;IACI,mBAAmB,CACzB,IAAY,EACZ,QAAmD;QAEnD,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE;YAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YACtD,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE;gBACjB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;aACvC;SACD;IACF,CAAC;IAED;;;;;OAKG;IACI,aAAa,CAAC,KAAY;QAChC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE;YACnB,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;SACrB;QAED,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC;QAE5B,MAAM,WAAW,GAAG,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QAEpD,IAAI,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,UAAU,EAAE;YAC5C,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;SACpC;QAED,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;YAChC,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;gBACnD,IAAqB,QAAS,CAAC,WAAW,EAAE;oBAC1B,QAAS,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;iBAC9C;qBAAM;oBACmB,QAAS,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;iBACrD;gBACD,IAAI,KAAK,CAAC,4BAA4B,EAAE;oBACvC,OAAO,CAAC,CAAC,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;iBACrD;aACD;SACD;QAED,OAAO,CAAC,CAAC,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACtD,CAAC;IAED;;;;;;;;;OASG;IACI,WAAW,CAAC,IAAY,EAAE,QAAmD;QACnF,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;IACzD,CAAC;IAED;;;;;;;;;OASG;IACI,WAAW,CAAC,IAAY,EAAE,QAAmD;QACnF,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC5D,CAAC;CACD;AAhGD,8BAgGC"}
1
+ {"version":3,"file":"EventTarget.js","sourceRoot":"","sources":["../../src/event/EventTarget.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export default interface IEventListenerOptions {
2
+ once?: boolean;
3
+ capture?: boolean;
4
+ passive?: boolean;
5
+ signal?: unknown;
6
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=IEventListenerOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IEventListenerOptions.js","sourceRoot":"","sources":["../../src/event/IEventListenerOptions.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "happy-dom",
3
- "version": "8.5.0",
3
+ "version": "8.6.0",
4
4
  "license": "MIT",
5
5
  "homepage": "https://github.com/capricorn86/happy-dom",
6
6
  "repository": "https://github.com/capricorn86/happy-dom",
@@ -1,6 +1,7 @@
1
1
  import IEventListener from './IEventListener';
2
2
  import Event from './Event';
3
3
  import IEventTarget from './IEventTarget';
4
+ import IEventListenerOptions from './IEventListenerOptions';
4
5
 
5
6
  /**
6
7
  * Handles events.
@@ -9,16 +10,28 @@ export default abstract class EventTarget implements IEventTarget {
9
10
  public readonly _listeners: {
10
11
  [k: string]: (((event: Event) => void) | IEventListener)[];
11
12
  } = {};
13
+ public readonly _listenerOptions: {
14
+ [k: string]: (IEventListenerOptions | null)[];
15
+ } = {};
12
16
 
13
17
  /**
14
18
  * Adds an event listener.
15
19
  *
16
20
  * @param type Event type.
17
21
  * @param listener Listener.
22
+ * @param options An object that specifies characteristics about the event listener.(currently only once)
23
+ * @param options.once
18
24
  */
19
- public addEventListener(type: string, listener: ((event: Event) => void) | IEventListener): void {
25
+ public addEventListener(
26
+ type: string,
27
+ listener: ((event: Event) => void) | IEventListener,
28
+ options?: IEventListenerOptions
29
+ ): void {
20
30
  this._listeners[type] = this._listeners[type] || [];
31
+ this._listenerOptions[type] = this._listenerOptions[type] || [];
32
+
21
33
  this._listeners[type].push(listener);
34
+ this._listenerOptions[type].push(options || null);
22
35
  }
23
36
 
24
37
  /**
@@ -35,6 +48,7 @@ export default abstract class EventTarget implements IEventTarget {
35
48
  const index = this._listeners[type].indexOf(listener);
36
49
  if (index !== -1) {
37
50
  this._listeners[type].splice(index, 1);
51
+ this._listenerOptions[type].splice(index, 1);
38
52
  }
39
53
  }
40
54
  }
@@ -59,12 +73,20 @@ export default abstract class EventTarget implements IEventTarget {
59
73
  }
60
74
 
61
75
  if (this._listeners[event.type]) {
62
- for (const listener of this._listeners[event.type]) {
76
+ for (let i = 0, max = this._listeners[event.type].length; i < max; i++) {
77
+ const listener = this._listeners[event.type][i];
78
+ const options = this._listenerOptions[event.type][i];
79
+
63
80
  if ((<IEventListener>listener).handleEvent) {
64
81
  (<IEventListener>listener).handleEvent(event);
65
82
  } else {
66
83
  (<(event: Event) => void>listener).call(this, event);
67
84
  }
85
+
86
+ if (options?.once) {
87
+ this.removeEventListener(event.type, listener);
88
+ }
89
+
68
90
  if (event._immediatePropagationStopped) {
69
91
  return !(event.cancelable && event.defaultPrevented);
70
92
  }
@@ -0,0 +1,8 @@
1
+ export default interface IEventListenerOptions {
2
+ once?: boolean;
3
+
4
+ // TODO: Not implemented yet.
5
+ capture?: boolean;
6
+ passive?: boolean;
7
+ signal?: unknown;
8
+ }