@vanillaspa/event-bus 1.3.2 → 1.4.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.
Files changed (2) hide show
  1. package/index.js +41 -43
  2. package/package.json +2 -2
package/index.js CHANGED
@@ -1,58 +1,56 @@
1
1
  export const name = 'eventbus';
2
- const channel = new BroadcastChannel('eventbus');
3
- const contextListeners = new WeakMap(); // context - Map<type, listener[]>
4
2
 
5
- channel.onmessage = ({ data }) => {
6
- const { type, detail } = data;
7
- dispatchLocally(new CustomEvent(type, { detail }));
8
- }
3
+ const contextListeners = new WeakMap(); // context -> Map<type, listener[]>
4
+ const typeIndex = new Map(); // type -> Set<WeakRef<context>>
5
+
6
+ export function addEventListener(type, listener, context) {
7
+ if (!contextListeners.has(context)) { // first seen
8
+ contextListeners.set(context, new Map());
9
+ }
10
+ const byType = contextListeners.get(context);
11
+ if (!byType.has(type)) byType.set(type, []);
12
+ byType.get(type).push(listener);
9
13
 
10
- channel.onmessageerror = (e) => {
11
- console.error('eventbus deserialization error:', e);
14
+ if (!typeIndex.has(type)) typeIndex.set(type, new Set());
15
+ typeIndex.get(type).add(new WeakRef(context));
12
16
  }
13
17
 
14
- function dispatchLocally(event, context = undefined) {
15
- if (!context) context = event instanceof CustomEvent ? event.detail?.target : event.target;
18
+ export function removeEventListener(type, listener, context) {
19
+ const byType = contextListeners.get(context);
20
+ if (!byType?.has(type)) return;
16
21
 
17
- if (context && contextListeners.has(context)) {
18
- const byType = contextListeners.get(context);
19
- byType.get(event.type)?.forEach(handler => handler(event));
20
- } else {
21
- if (typeof window !== 'undefined') window.dispatchEvent(event);
22
- }
23
- }
22
+ const handlers = byType.get(type);
23
+ const index = handlers.indexOf(listener);
24
+ if (index > -1) handlers.splice(index, 1);
24
25
 
25
- export function addEventListener(type, listener, context = undefined) {
26
- if (context && typeof context === 'object') { // context is well defined, should be a WebComponent
27
- if (!contextListeners.has(context)) {
28
- contextListeners.set(context, new Map());
26
+ if (handlers.length === 0) {
27
+ byType.delete(type);
28
+ const refs = typeIndex.get(type);
29
+ if (refs) {
30
+ for (const ref of refs) {
31
+ if (ref.deref() === context) {
32
+ refs.delete(ref);
33
+ break;
34
+ }
35
+ }
29
36
  }
30
- const byType = contextListeners.get(context);
31
- if (!byType.has(type)) byType.set(type, []);
32
- byType.get(type).push(listener);
33
- } else {
34
- if (context) throw new Error('Syntax error: context must be an object.');
35
- if (typeof window !== 'undefined') window.addEventListener(type, listener);
36
37
  }
37
38
  }
38
39
 
39
- export function removeEventListener(type, listener, context = undefined) {
40
- if (context && typeof context === 'object') {
40
+ export function dispatchEvent(event, context = undefined) {
41
+ if (!context) context = event instanceof CustomEvent ? event.detail?.target : event.target;
42
+
43
+ if (context && contextListeners.has(context)) {
41
44
  const byType = contextListeners.get(context);
42
- if (!byType?.has(type)) return;
43
- const handlers = byType.get(type)
44
- const index = handlers.indexOf(listener);
45
- if (index > -1) handlers.splice(index, 1);
46
- if (handlers.length === 0) byType.delete(type);
45
+ byType.get(event.type)?.forEach(handler => handler(event));
47
46
  } else {
48
- if (typeof window !== 'undefined') window.removeEventListener(type, listener);
47
+ const refs = typeIndex.get(event.type);
48
+ if (refs) {
49
+ for (const ref of refs) {
50
+ const ctx = ref.deref();
51
+ if (!ctx) { refs.delete(ref); continue; }
52
+ contextListeners.get(ctx)?.get(event.type)?.forEach(handler => handler(event));
53
+ }
54
+ }
49
55
  }
50
56
  }
51
-
52
- export function dispatchEvent(event) {
53
- dispatchLocally(event, context);
54
- channel.postMessage({
55
- type: event.type,
56
- detail: event instanceof CustomEvent ? event.detail : {}
57
- });
58
- }
package/package.json CHANGED
@@ -6,7 +6,6 @@
6
6
  "description": "An event-bus for vanilla SPA. You can use it with web-components.",
7
7
  "homepage": "https://github.com/vanillaspa/event-bus#readme",
8
8
  "keywords": [
9
- "BroadcastChannel",
10
9
  "CustomElement",
11
10
  "EventBus",
12
11
  "JavaScript",
@@ -14,6 +13,7 @@
14
13
  "Vanilla",
15
14
  "SPA",
16
15
  "WeakMap",
16
+ "WeakRef",
17
17
  "WebComponents"
18
18
  ],
19
19
  "license": "Unlicense",
@@ -27,5 +27,5 @@
27
27
  "url": "git+https://github.com/vanillaspa/event-bus.git"
28
28
  },
29
29
  "type": "module",
30
- "version": "1.3.2"
30
+ "version": "1.4.0"
31
31
  }