@aegisjsproject/callback-registry 1.0.1 → 1.0.3

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.
package/events.js CHANGED
@@ -1,121 +1,225 @@
1
1
  import { hasCallback, getCallback } from './callbacks.js';
2
2
 
3
- const EVENT_PREFIX = 'data-aegis-event-on-';
3
+ const PREFIX = 'data-aegis-event-';
4
+ const EVENT_PREFIX = PREFIX + 'on-';
4
5
  const EVENT_PREFIX_LENGTH = EVENT_PREFIX.length;
5
6
  const DATA_PREFIX = 'aegisEventOn';
6
7
  const DATA_PREFIX_LENGTH = DATA_PREFIX.length;
8
+ const signalSymbol = Symbol('aegis:signal');
9
+ const controllerSymbol = Symbol('aegis:controller');
10
+ const signalRegistry = new Map();
11
+ const controllerRegistry = new Map();
7
12
 
8
- const once = 'data-aegis-event-once',
9
- passive = 'data-aegis-event-passive',
10
- capture = 'data-aegis-event-capture';
11
-
12
- const eventAttrs = [
13
- EVENT_PREFIX + 'abort',
14
- EVENT_PREFIX + 'blur',
15
- EVENT_PREFIX + 'focus',
16
- EVENT_PREFIX + 'cancel',
17
- EVENT_PREFIX + 'auxclick',
18
- EVENT_PREFIX + 'beforeinput',
19
- EVENT_PREFIX + 'beforetoggle',
20
- EVENT_PREFIX + 'canplay',
21
- EVENT_PREFIX + 'canplaythrough',
22
- EVENT_PREFIX + 'change',
23
- EVENT_PREFIX + 'click',
24
- EVENT_PREFIX + 'close',
25
- EVENT_PREFIX + 'contextmenu',
26
- EVENT_PREFIX + 'copy',
27
- EVENT_PREFIX + 'cuechange',
28
- EVENT_PREFIX + 'cut',
29
- EVENT_PREFIX + 'dblclick',
30
- EVENT_PREFIX + 'drag',
31
- EVENT_PREFIX + 'dragend',
32
- EVENT_PREFIX + 'dragenter',
33
- EVENT_PREFIX + 'dragexit',
34
- EVENT_PREFIX + 'dragleave',
35
- EVENT_PREFIX + 'dragover',
36
- EVENT_PREFIX + 'dragstart',
37
- EVENT_PREFIX + 'drop',
38
- EVENT_PREFIX + 'durationchange',
39
- EVENT_PREFIX + 'emptied',
40
- EVENT_PREFIX + 'ended',
41
- EVENT_PREFIX + 'formdata',
42
- EVENT_PREFIX + 'input',
43
- EVENT_PREFIX + 'invalid',
44
- EVENT_PREFIX + 'keydown',
45
- EVENT_PREFIX + 'keypress',
46
- EVENT_PREFIX + 'keyup',
47
- EVENT_PREFIX + 'load',
48
- EVENT_PREFIX + 'loadeddata',
49
- EVENT_PREFIX + 'loadedmetadata',
50
- EVENT_PREFIX + 'loadstart',
51
- EVENT_PREFIX + 'mousedown',
52
- EVENT_PREFIX + 'mouseenter',
53
- EVENT_PREFIX + 'mouseleave',
54
- EVENT_PREFIX + 'mousemove',
55
- EVENT_PREFIX + 'mouseout',
56
- EVENT_PREFIX + 'mouseover',
57
- EVENT_PREFIX + 'mouseup',
58
- EVENT_PREFIX + 'wheel',
59
- EVENT_PREFIX + 'paste',
60
- EVENT_PREFIX + 'pause',
61
- EVENT_PREFIX + 'play',
62
- EVENT_PREFIX + 'playing',
63
- EVENT_PREFIX + 'progress',
64
- EVENT_PREFIX + 'ratechange',
65
- EVENT_PREFIX + 'reset',
66
- EVENT_PREFIX + 'resize',
67
- EVENT_PREFIX + 'scroll',
68
- EVENT_PREFIX + 'scrollend',
69
- EVENT_PREFIX + 'securitypolicyviolation',
70
- EVENT_PREFIX + 'seeked',
71
- EVENT_PREFIX + 'seeking',
72
- EVENT_PREFIX + 'select',
73
- EVENT_PREFIX + 'slotchange',
74
- EVENT_PREFIX + 'stalled',
75
- EVENT_PREFIX + 'submit',
76
- EVENT_PREFIX + 'suspend',
77
- EVENT_PREFIX + 'timeupdate',
78
- EVENT_PREFIX + 'volumechange',
79
- EVENT_PREFIX + 'waiting',
80
- EVENT_PREFIX + 'selectstart',
81
- EVENT_PREFIX + 'selectionchange',
82
- EVENT_PREFIX + 'toggle',
83
- EVENT_PREFIX + 'pointercancel',
84
- EVENT_PREFIX + 'pointerdown',
85
- EVENT_PREFIX + 'pointerup',
86
- EVENT_PREFIX + 'pointermove',
87
- EVENT_PREFIX + 'pointerout',
88
- EVENT_PREFIX + 'pointerover',
89
- EVENT_PREFIX + 'pointerenter',
90
- EVENT_PREFIX + 'pointerleave',
91
- EVENT_PREFIX + 'gotpointercapture',
92
- EVENT_PREFIX + 'lostpointercapture',
93
- EVENT_PREFIX + 'mozfullscreenchange',
94
- EVENT_PREFIX + 'mozfullscreenerror',
95
- EVENT_PREFIX + 'animationcancel',
96
- EVENT_PREFIX + 'animationend',
97
- EVENT_PREFIX + 'animationiteration',
98
- EVENT_PREFIX + 'animationstart',
99
- EVENT_PREFIX + 'transitioncancel',
100
- EVENT_PREFIX + 'transitionend',
101
- EVENT_PREFIX + 'transitionrun',
102
- EVENT_PREFIX + 'transitionstart',
103
- EVENT_PREFIX + 'webkitanimationend',
104
- EVENT_PREFIX + 'webkitanimationiteration',
105
- EVENT_PREFIX + 'webkitanimationstart',
106
- EVENT_PREFIX + 'webkittransitionend',
107
- EVENT_PREFIX + 'error',
13
+ export const once = PREFIX + 'once';
14
+ export const passive = PREFIX + 'passive';
15
+ export const capture = PREFIX + 'capture';
16
+ export const signal = PREFIX + 'signal';
17
+ export const controller = PREFIX + 'controller';
18
+ export const onAbort = EVENT_PREFIX + 'abort';
19
+ export const onBlur = EVENT_PREFIX + 'blur';
20
+ export const onFocus = EVENT_PREFIX + 'focus';
21
+ export const onCancel = EVENT_PREFIX + 'cancel';
22
+ export const onAuxclick = EVENT_PREFIX + 'auxclick';
23
+ export const onBeforeinput = EVENT_PREFIX + 'beforeinput';
24
+ export const onBeforetoggle = EVENT_PREFIX + 'beforetoggle';
25
+ export const onCanplay = EVENT_PREFIX + 'canplay';
26
+ export const onCanplaythrough = EVENT_PREFIX + 'canplaythrough';
27
+ export const onChange = EVENT_PREFIX + 'change';
28
+ export const onClick = EVENT_PREFIX + 'click';
29
+ export const onClose = EVENT_PREFIX + 'close';
30
+ export const onCommand = EVENT_PREFIX + 'command';
31
+ export const onContextmenu = EVENT_PREFIX + 'contextmenu';
32
+ export const onCopy = EVENT_PREFIX + 'copy';
33
+ export const onCuechange = EVENT_PREFIX + 'cuechange';
34
+ export const onCut = EVENT_PREFIX + 'cut';
35
+ export const onDblclick = EVENT_PREFIX + 'dblclick';
36
+ export const onDrag = EVENT_PREFIX + 'drag';
37
+ export const onDragend = EVENT_PREFIX + 'dragend';
38
+ export const onDragenter = EVENT_PREFIX + 'dragenter';
39
+ export const onDragexit = EVENT_PREFIX + 'dragexit';
40
+ export const onDragleave = EVENT_PREFIX + 'dragleave';
41
+ export const onDragover = EVENT_PREFIX + 'dragover';
42
+ export const onDragstart = EVENT_PREFIX + 'dragstart';
43
+ export const onDrop = EVENT_PREFIX + 'drop';
44
+ export const onDurationchange = EVENT_PREFIX + 'durationchange';
45
+ export const onEmptied = EVENT_PREFIX + 'emptied';
46
+ export const onEnded = EVENT_PREFIX + 'ended';
47
+ export const onFormdata = EVENT_PREFIX + 'formdata';
48
+ export const onInput = EVENT_PREFIX + 'input';
49
+ export const onInvalid = EVENT_PREFIX + 'invalid';
50
+ export const onKeydown = EVENT_PREFIX + 'keydown';
51
+ export const onKeypress = EVENT_PREFIX + 'keypress';
52
+ export const onKeyup = EVENT_PREFIX + 'keyup';
53
+ export const onLoad = EVENT_PREFIX + 'load';
54
+ export const onLoadeddata = EVENT_PREFIX + 'loadeddata';
55
+ export const onLoadedmetadata = EVENT_PREFIX + 'loadedmetadata';
56
+ export const onLoadstart = EVENT_PREFIX + 'loadstart';
57
+ export const onMousedown = EVENT_PREFIX + 'mousedown';
58
+ export const onMouseenter = EVENT_PREFIX + 'mouseenter';
59
+ export const onMouseleave = EVENT_PREFIX + 'mouseleave';
60
+ export const onMousemove = EVENT_PREFIX + 'mousemove';
61
+ export const onMouseout = EVENT_PREFIX + 'mouseout';
62
+ export const onMouseover = EVENT_PREFIX + 'mouseover';
63
+ export const onMouseup = EVENT_PREFIX + 'mouseup';
64
+ export const onWheel = EVENT_PREFIX + 'wheel';
65
+ export const onPaste = EVENT_PREFIX + 'paste';
66
+ export const onPause = EVENT_PREFIX + 'pause';
67
+ export const onPlay = EVENT_PREFIX + 'play';
68
+ export const onPlaying = EVENT_PREFIX + 'playing';
69
+ export const onProgress = EVENT_PREFIX + 'progress';
70
+ export const onRatechange = EVENT_PREFIX + 'ratechange';
71
+ export const onReset = EVENT_PREFIX + 'reset';
72
+ export const onResize = EVENT_PREFIX + 'resize';
73
+ export const onScroll = EVENT_PREFIX + 'scroll';
74
+ export const onScrollend = EVENT_PREFIX + 'scrollend';
75
+ export const onSecuritypolicyviolation = EVENT_PREFIX + 'securitypolicyviolation';
76
+ export const onSeeked = EVENT_PREFIX + 'seeked';
77
+ export const onSeeking = EVENT_PREFIX + 'seeking';
78
+ export const onSelect = EVENT_PREFIX + 'select';
79
+ export const onSlotchange = EVENT_PREFIX + 'slotchange';
80
+ export const onStalled = EVENT_PREFIX + 'stalled';
81
+ export const onSubmit = EVENT_PREFIX + 'submit';
82
+ export const onSuspend = EVENT_PREFIX + 'suspend';
83
+ export const onTimeupdate = EVENT_PREFIX + 'timeupdate';
84
+ export const onVolumechange = EVENT_PREFIX + 'volumechange';
85
+ export const onWaiting = EVENT_PREFIX + 'waiting';
86
+ export const onSelectstart = EVENT_PREFIX + 'selectstart';
87
+ export const onSelectionchange = EVENT_PREFIX + 'selectionchange';
88
+ export const onToggle = EVENT_PREFIX + 'toggle';
89
+ export const onPointercancel = EVENT_PREFIX + 'pointercancel';
90
+ export const onPointerdown = EVENT_PREFIX + 'pointerdown';
91
+ export const onPointerup = EVENT_PREFIX + 'pointerup';
92
+ export const onPointermove = EVENT_PREFIX + 'pointermove';
93
+ export const onPointerout = EVENT_PREFIX + 'pointerout';
94
+ export const onPointerover = EVENT_PREFIX + 'pointerover';
95
+ export const onPointerenter = EVENT_PREFIX + 'pointerenter';
96
+ export const onPointerleave = EVENT_PREFIX + 'pointerleave';
97
+ export const onGotpointercapture = EVENT_PREFIX + 'gotpointercapture';
98
+ export const onLostpointercapture = EVENT_PREFIX + 'lostpointercapture';
99
+ export const onMozfullscreenchange = EVENT_PREFIX + 'mozfullscreenchange';
100
+ export const onMozfullscreenerror = EVENT_PREFIX + 'mozfullscreenerror';
101
+ export const onAnimationcancel = EVENT_PREFIX + 'animationcancel';
102
+ export const onAnimationend = EVENT_PREFIX + 'animationend';
103
+ export const onAnimationiteration = EVENT_PREFIX + 'animationiteration';
104
+ export const onAnimationstart = EVENT_PREFIX + 'animationstart';
105
+ export const onTransitioncancel = EVENT_PREFIX + 'transitioncancel';
106
+ export const onTransitionend = EVENT_PREFIX + 'transitionend';
107
+ export const onTransitionrun = EVENT_PREFIX + 'transitionrun';
108
+ export const onTransitionstart = EVENT_PREFIX + 'transitionstart';
109
+ export const onWebkitanimationend = EVENT_PREFIX + 'webkitanimationend';
110
+ export const onWebkitanimationiteration = EVENT_PREFIX + 'webkitanimationiteration';
111
+ export const onWebkitanimationstart = EVENT_PREFIX + 'webkitanimationstart';
112
+ export const onWebkittransitionend = EVENT_PREFIX + 'webkittransitionend';
113
+ export const onError = EVENT_PREFIX + 'error';
114
+
115
+ export const eventAttrs = [
116
+ onAbort,
117
+ onBlur,
118
+ onFocus,
119
+ onCancel,
120
+ onAuxclick,
121
+ onBeforeinput,
122
+ onBeforetoggle,
123
+ onCanplay,
124
+ onCanplaythrough,
125
+ onChange,
126
+ onClick,
127
+ onClose,
128
+ onCommand,
129
+ onContextmenu,
130
+ onCopy,
131
+ onCuechange,
132
+ onCut,
133
+ onDblclick,
134
+ onDrag,
135
+ onDragend,
136
+ onDragenter,
137
+ onDragexit,
138
+ onDragleave,
139
+ onDragover,
140
+ onDragstart,
141
+ onDrop,
142
+ onDurationchange,
143
+ onEmptied,
144
+ onEnded,
145
+ onFormdata,
146
+ onInput,
147
+ onInvalid,
148
+ onKeydown,
149
+ onKeypress,
150
+ onKeyup,
151
+ onLoad,
152
+ onLoadeddata,
153
+ onLoadedmetadata,
154
+ onLoadstart,
155
+ onMousedown,
156
+ onMouseenter,
157
+ onMouseleave,
158
+ onMousemove,
159
+ onMouseout,
160
+ onMouseover,
161
+ onMouseup,
162
+ onWheel,
163
+ onPaste,
164
+ onPause,
165
+ onPlay,
166
+ onPlaying,
167
+ onProgress,
168
+ onRatechange,
169
+ onReset,
170
+ onResize,
171
+ onScroll,
172
+ onScrollend,
173
+ onSecuritypolicyviolation,
174
+ onSeeked,
175
+ onSeeking,
176
+ onSelect,
177
+ onSlotchange,
178
+ onStalled,
179
+ onSubmit,
180
+ onSuspend,
181
+ onTimeupdate,
182
+ onVolumechange,
183
+ onWaiting,
184
+ onSelectstart,
185
+ onSelectionchange,
186
+ onToggle,
187
+ onPointercancel,
188
+ onPointerdown,
189
+ onPointerup,
190
+ onPointermove,
191
+ onPointerout,
192
+ onPointerover,
193
+ onPointerenter,
194
+ onPointerleave,
195
+ onGotpointercapture,
196
+ onLostpointercapture,
197
+ onMozfullscreenchange,
198
+ onMozfullscreenerror,
199
+ onAnimationcancel,
200
+ onAnimationend,
201
+ onAnimationiteration,
202
+ onAnimationstart,
203
+ onTransitioncancel,
204
+ onTransitionend,
205
+ onTransitionrun,
206
+ onTransitionstart,
207
+ onWebkitanimationend,
208
+ onWebkitanimationiteration,
209
+ onWebkitanimationstart,
210
+ onWebkittransitionend,
211
+ onError,
108
212
  ];
109
213
 
110
214
  let selector = eventAttrs.map(attr => `[${CSS.escape(attr)}]`).join(', ');
111
215
 
112
216
  const attrToProp = attr => `on${attr[EVENT_PREFIX_LENGTH].toUpperCase()}${attr.substring(EVENT_PREFIX_LENGTH + 1)}`;
113
217
 
114
- const attrEntriesMap = attr => [attrToProp(attr), attr];
218
+ export const eventToProp = event => EVENT_PREFIX + event;
115
219
 
116
- const isEventDataAttr = ([name]) => name.startsWith(DATA_PREFIX);
220
+ export const hasEventAttribute = event => eventAttrs.includes(EVENT_PREFIX + event);
117
221
 
118
- const DATA_EVENTS = Object.fromEntries([...eventAttrs].map(attrEntriesMap));
222
+ const isEventDataAttr = ([name]) => name.startsWith(DATA_PREFIX);
119
223
 
120
224
  function _addListeners(el, { signal, attrFilter = EVENTS } = {}) {
121
225
  const dataset = el.dataset;
@@ -129,11 +233,11 @@ function _addListeners(el, { signal, attrFilter = EVENTS } = {}) {
129
233
  passive: dataset.hasOwnProperty('aegisEventPassive'),
130
234
  capture: dataset.hasOwnProperty('aegisEventCapture'),
131
235
  once: dataset.hasOwnProperty('aegisEventOnce'),
132
- signal,
236
+ signal: dataset.hasOwnProperty('aegisEventSignal') ? getSignal(dataset.aegisEventSignal) : signal,
133
237
  });
134
238
  }
135
239
  } catch(err) {
136
- console.error(err);
240
+ reportError(err);
137
241
  }
138
242
  }
139
243
  }
@@ -169,6 +273,7 @@ const observer = new MutationObserver(records => {
169
273
  once: record.target.hasAttribute(once),
170
274
  capture: record.target.hasAttribute(capture),
171
275
  passive: record.target.hasAttribute(passive),
276
+ signal: record.target.hasAttribute(signal) ? getSignal(record.target.getAttribute(signal)) : undefined,
172
277
  }
173
278
  );
174
279
  }
@@ -177,7 +282,107 @@ const observer = new MutationObserver(records => {
177
282
  });
178
283
  });
179
284
 
180
- export const EVENTS = { ...DATA_EVENTS, once, passive, capture };
285
+ export const EVENTS = {
286
+ onAbort,
287
+ onBlur,
288
+ onFocus,
289
+ onCancel,
290
+ onAuxclick,
291
+ onBeforeinput,
292
+ onBeforetoggle,
293
+ onCanplay,
294
+ onCanplaythrough,
295
+ onChange,
296
+ onClick,
297
+ onClose,
298
+ onCommand,
299
+ onContextmenu,
300
+ onCopy,
301
+ onCuechange,
302
+ onCut,
303
+ onDblclick,
304
+ onDrag,
305
+ onDragend,
306
+ onDragenter,
307
+ onDragexit,
308
+ onDragleave,
309
+ onDragover,
310
+ onDragstart,
311
+ onDrop,
312
+ onDurationchange,
313
+ onEmptied,
314
+ onEnded,
315
+ onFormdata,
316
+ onInput,
317
+ onInvalid,
318
+ onKeydown,
319
+ onKeypress,
320
+ onKeyup,
321
+ onLoad,
322
+ onLoadeddata,
323
+ onLoadedmetadata,
324
+ onLoadstart,
325
+ onMousedown,
326
+ onMouseenter,
327
+ onMouseleave,
328
+ onMousemove,
329
+ onMouseout,
330
+ onMouseover,
331
+ onMouseup,
332
+ onWheel,
333
+ onPaste,
334
+ onPause,
335
+ onPlay,
336
+ onPlaying,
337
+ onProgress,
338
+ onRatechange,
339
+ onReset,
340
+ onResize,
341
+ onScroll,
342
+ onScrollend,
343
+ onSecuritypolicyviolation,
344
+ onSeeked,
345
+ onSeeking,
346
+ onSelect,
347
+ onSlotchange,
348
+ onStalled,
349
+ onSubmit,
350
+ onSuspend,
351
+ onTimeupdate,
352
+ onVolumechange,
353
+ onWaiting,
354
+ onSelectstart,
355
+ onSelectionchange,
356
+ onToggle,
357
+ onPointercancel,
358
+ onPointerdown,
359
+ onPointerup,
360
+ onPointermove,
361
+ onPointerout,
362
+ onPointerover,
363
+ onPointerenter,
364
+ onPointerleave,
365
+ onGotpointercapture,
366
+ onLostpointercapture,
367
+ onMozfullscreenchange,
368
+ onMozfullscreenerror,
369
+ onAnimationcancel,
370
+ onAnimationend,
371
+ onAnimationiteration,
372
+ onAnimationstart,
373
+ onTransitioncancel,
374
+ onTransitionend,
375
+ onTransitionrun,
376
+ onTransitionstart,
377
+ onWebkitanimationend,
378
+ onWebkitanimationiteration,
379
+ onWebkitanimationstart,
380
+ onWebkittransitionend,
381
+ onError,
382
+ once,
383
+ passive,
384
+ capture,
385
+ };
181
386
 
182
387
  /**
183
388
  * Register an attribute to observe for adding/removing event listeners
@@ -214,6 +419,134 @@ export function registerEventAttribute(attr, {
214
419
  return fullAttr;
215
420
  }
216
421
 
422
+ /**
423
+ * Registers an `AbortController` in the controller registry and returns the key for it
424
+ *
425
+ * @param {AbortController} controller
426
+ * @returns {string} The randomly generated key with which the controller is registered
427
+ * @throws {TypeError} If controller is not an `AbortController`
428
+ * @throws {Error} Any `reason` if controller is already aborted
429
+ */
430
+ export function registerController(controller) {
431
+ if (! (controller instanceof AbortController)) {
432
+ throw new TypeError('Controller is not an `AbortSignal.');
433
+ } else if (controller.signal.aborted) {
434
+ throw controller.signal.reason;
435
+ } else if (typeof controller.signal[controllerSymbol] === 'string') {
436
+ return controller.signal[controllerSymbol];
437
+ } else {
438
+ const key = 'aegis:event:controller:' + crypto.randomUUID();
439
+ Object.defineProperty(controller.signal, controllerSymbol, { value: key, writable: false, enumerable: false });
440
+ controllerRegistry.set(key, controller);
441
+
442
+ controller.signal.addEventListener('abort', unregisterController, { once: true });
443
+
444
+ return key;
445
+ }
446
+ }
447
+
448
+ /**
449
+ * Removes a controller from the registry
450
+ *
451
+ * @param {AbortController|AbortSignal|string} key The registed key or the controller or signal it corresponds to
452
+ * @returns {boolean} Whether or not the controller was successfully unregistered
453
+ */
454
+ export function unregisterController(key) {
455
+ if (key instanceof AbortController) {
456
+ return controllerRegistry.delete(key.signal[controllerSymbol]);
457
+ } else if (key instanceof AbortSignal) {
458
+ return controllerRegistry.delete(key[controllerSymbol]);
459
+ } else {
460
+ return controllerRegistry.delete(key);
461
+ }
462
+ }
463
+
464
+ /**
465
+ * Creates and registers an `AbortController` in the controller registry and returns the key for it
466
+ *
467
+ * @param {object} options
468
+ * @param {AbortSignal} [options.signal] An optional `AbortSignal` to externally abort the controller with
469
+ * @returns {string} The randomly generated key with which the controller is registered
470
+ */
471
+ export function createController({ signal } = {}) {
472
+ const controller = new AbortController();
473
+
474
+ if (signal instanceof AbortSignal) {
475
+ signal.addEventListener('abort', ({ target }) => controller.abort(target.reason), { signal: controller.signal});
476
+ }
477
+
478
+ return registerController(controller);
479
+ }
480
+
481
+ /**
482
+ * Get a registetd controller from the registry
483
+ *
484
+ * @param {string} key Generated key with which the controller was registered
485
+ * @returns {AbortController|void} Any registered controller, if any
486
+ */
487
+ export const getController = key => controllerRegistry.get(key);
488
+
489
+ export function abortController(key, reason) {
490
+ const controller = getController(key);
491
+
492
+ if (! (controller instanceof AbortController)) {
493
+ return false;
494
+ } else if (typeof reason === 'string') {
495
+ controller.abort(new Error(reason));
496
+ return true;
497
+ } else {
498
+ controller.abort(reason);
499
+ return true;
500
+ }
501
+ }
502
+
503
+ /**
504
+ * Register an `AbortSignal` to be used in declarative HTML as a value for `data-aegis-event-signal`
505
+ *
506
+ * @param {AbortSignal} signal The signal to register
507
+ * @returns {string} The registered key
508
+ * @throws {TypeError} Thrown if not an `AbortSignal`
509
+ */
510
+ export function registerSignal(signal) {
511
+ if (! (signal instanceof AbortSignal)) {
512
+ throw new TypeError('Signal must be an `AbortSignal`.');
513
+ } else if (typeof signal[signalSymbol] === 'string') {
514
+ return signal[signalSymbol];
515
+ } else {
516
+ const key = 'aegis:event:signal:' + crypto.randomUUID();
517
+ Object.defineProperty(signal, signalSymbol, { value: key, writable: false, enumerable: false });
518
+ signalRegistry.set(key, signal);
519
+ signal.addEventListener('abort', ({ target }) => unregisterSignal(target[signalSymbol]), { once: true });
520
+
521
+ return key;
522
+ }
523
+ }
524
+
525
+ /**
526
+ * Gets and `AbortSignal` from the registry
527
+ *
528
+ * @param {string} key The registered key for the signal
529
+ * @returns {AbortSignal|void} The corresponding `AbortSignal`, if any
530
+ */
531
+ export const getSignal = key => signalRegistry.get(key);
532
+
533
+ /**
534
+ * Removes an `AbortSignal` from the registry
535
+ *
536
+ * @param {AbortSignal|string} signal An `AbortSignal` or the registered key for one
537
+ * @returns {boolean} Whether or not the signal was sucessfully unregistered
538
+ * @throws {TypeError} Throws if `signal` is not an `AbortSignal` or the key for a registered signal
539
+ */
540
+ export function unregisterSignal(signal) {
541
+ if (signal instanceof AbortSignal) {
542
+ return signalRegistry.delete(signal[signalSymbol]);
543
+ } else if (typeof signal === 'string') {
544
+ return signalRegistry.delete(signal);
545
+ } else {
546
+ throw new TypeError('Signal must be an `AbortSignal` or registered key/attribute.');
547
+ }
548
+ }
549
+
217
550
  /**
218
551
  * Add listeners to an element and its children, matching a generated query based on registered attributes
219
552
  *
@@ -231,6 +564,7 @@ export function attachListeners(target, { signal } = {}) {
231
564
 
232
565
  return target;
233
566
  }
567
+
234
568
  /**
235
569
  * Add a node to the `MutationObserver` to observe attributes and add/remove event listeners
236
570
  *
@@ -238,6 +572,7 @@ export function attachListeners(target, { signal } = {}) {
238
572
  */
239
573
  export function observeEvents(root = document) {
240
574
  attachListeners(root);
575
+
241
576
  observer.observe(root, {
242
577
  subtree: true,
243
578
  childList:true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aegisjsproject/callback-registry",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": " A callback registry for AegisJSProject",
5
5
  "keywords": [
6
6
  "aegis",
@@ -40,12 +40,13 @@
40
40
  "private": false,
41
41
  "scripts": {
42
42
  "test": "npm run lint:js && npm run run:tests",
43
+ "start": "http-server ./ -c-1 --port 8080 --gzip true --brotli true -a localhost -o /test/",
43
44
  "preversion": "npm test && npm run build",
44
45
  "prepare": "npm test && npm run build",
45
46
  "lint:js": "eslint .",
46
47
  "fix:js": "eslint . --fix",
47
48
  "build": "npm run build:js",
48
- "run:tests": "node --test",
49
+ "run:tests": "node --test *.test.js",
49
50
  "clean": "rm -f ./*.cjs",
50
51
  "build:js": "npm run clean && rollup -c rollup.config.js",
51
52
  "create:lock": "npm i --package-lock-only --ignore-scripts --no-audit --no-fund",
@@ -77,7 +78,9 @@
77
78
  "devDependencies": {
78
79
  "@rollup/plugin-terser": "^0.4.4",
79
80
  "@shgysk8zer0/eslint-config": "^1.0.1",
81
+ "@shgysk8zer0/polyfills": "^0.4.13",
80
82
  "eslint": "^9.15.0",
83
+ "http-server": "^14.1.1",
81
84
  "rollup": "^4.27.2"
82
85
  }
83
86
  }