event-emission 0.2.0 → 0.2.1

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 (43) hide show
  1. package/README.md +80 -24
  2. package/dist/event-emission.d.ts +13 -14
  3. package/dist/event-emission.d.ts.map +1 -1
  4. package/dist/factory.d.ts +1 -1
  5. package/dist/factory.d.ts.map +1 -1
  6. package/dist/index.cjs +474 -285
  7. package/dist/index.cjs.map +8 -9
  8. package/dist/index.d.ts +1 -7
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +449 -278
  11. package/dist/index.js.map +8 -9
  12. package/dist/interoperability.cjs +1605 -0
  13. package/dist/interoperability.cjs.map +15 -0
  14. package/dist/{interop.d.ts → interoperability.d.ts} +2 -1
  15. package/dist/interoperability.d.ts.map +1 -0
  16. package/dist/interoperability.js +1555 -0
  17. package/dist/interoperability.js.map +15 -0
  18. package/dist/observable.cjs +286 -0
  19. package/dist/observable.cjs.map +11 -0
  20. package/dist/observable.js +253 -0
  21. package/dist/observable.js.map +11 -0
  22. package/dist/observe.cjs +344 -0
  23. package/dist/observe.cjs.map +10 -0
  24. package/dist/observe.d.ts +6 -1
  25. package/dist/observe.d.ts.map +1 -1
  26. package/dist/observe.js +313 -0
  27. package/dist/observe.js.map +10 -0
  28. package/dist/symbols.d.ts +1 -1
  29. package/dist/types.cjs +35 -0
  30. package/dist/types.cjs.map +9 -0
  31. package/dist/types.d.ts +60 -25
  32. package/dist/types.d.ts.map +1 -1
  33. package/dist/types.js +3 -0
  34. package/dist/types.js.map +9 -0
  35. package/package.json +25 -1
  36. package/src/event-emission.ts +26 -20
  37. package/src/factory.ts +538 -218
  38. package/src/index.ts +4 -33
  39. package/src/{interop.ts → interoperability.ts} +24 -6
  40. package/src/observe.ts +54 -17
  41. package/src/symbols.ts +1 -1
  42. package/src/types.ts +75 -30
  43. package/dist/interop.d.ts.map +0 -1
package/dist/index.cjs CHANGED
@@ -27,37 +27,19 @@ var __export = (target, all) => {
27
27
  });
28
28
  };
29
29
 
30
- // src/index.ts
31
- var exports_src = {};
32
- __export(exports_src, {
33
- setupEventForwarding: () => setupEventForwarding,
34
- pipe: () => pipe,
35
- isObserved: () => isObserved,
36
- getOriginal: () => getOriginal,
37
- fromEventTarget: () => fromEventTarget,
38
- forwardToEventTarget: () => forwardToEventTarget,
39
- createEventTarget: () => createEventTarget,
40
- SymbolObservable: () => SymbolObservable,
41
- PROXY_MARKER: () => PROXY_MARKER,
42
- Observable: () => Observable,
43
- ORIGINAL_TARGET: () => ORIGINAL_TARGET,
44
- EventEmission: () => EventEmission,
45
- BufferOverflowError: () => BufferOverflowError
30
+ // src/observable.ts
31
+ var exports_observable = {};
32
+ __export(exports_observable, {
33
+ Observable: () => Observable
46
34
  });
47
- module.exports = __toCommonJS(exports_src);
35
+ module.exports = __toCommonJS(exports_observable);
48
36
 
49
37
  // src/symbols.ts
50
38
  var SymbolObservable = typeof Symbol === "function" && Symbol.observable || Symbol.for("@@observable");
51
39
  if (typeof Symbol === "function") {
52
40
  Symbol.observable = SymbolObservable;
53
41
  }
54
- // src/errors.ts
55
- class BufferOverflowError extends Error {
56
- constructor(eventType, bufferSize) {
57
- super(`Buffer overflow for event type "${eventType}" (max: ${bufferSize})`);
58
- this.name = "BufferOverflowError";
59
- }
60
- }
42
+
61
43
  // src/observable.ts
62
44
  function getMethod(obj, key) {
63
45
  if (obj === null || obj === undefined)
@@ -301,6 +283,16 @@ class Observable {
301
283
  }
302
284
 
303
285
  // src/observe.ts
286
+ var exports_observe = {};
287
+ __export(exports_observe, {
288
+ setupEventForwarding: () => setupEventForwarding,
289
+ isObserved: () => isObserved,
290
+ getOriginal: () => getOriginal,
291
+ createObservableProxy: () => createObservableProxy,
292
+ PROXY_MARKER: () => PROXY_MARKER,
293
+ ORIGINAL_TARGET: () => ORIGINAL_TARGET
294
+ });
295
+ module.exports = __toCommonJS(exports_observe);
304
296
  var PROXY_MARKER = Symbol.for("@lasercat/event-emission/proxy");
305
297
  var ORIGINAL_TARGET = Symbol.for("@lasercat/event-emission/original");
306
298
  var ARRAY_MUTATORS = new Set([
@@ -324,17 +316,13 @@ function isArrayMutator(prop) {
324
316
  return typeof prop === "string" && ARRAY_MUTATORS.has(prop);
325
317
  }
326
318
  function cloneAlongPath(obj, path) {
327
- if (obj === null || typeof obj !== "object") {
328
- return obj;
329
- }
330
- if (!path) {
331
- return Array.isArray(obj) ? [...obj] : { ...obj };
319
+ const isArray = Array.isArray(obj);
320
+ const rootClone = isArray ? [...obj] : { ...obj };
321
+ if (!path || isArray) {
322
+ return rootClone;
332
323
  }
333
324
  const parts = path.split(".");
334
- if (Array.isArray(obj)) {
335
- return [...obj];
336
- }
337
- const result = { ...obj };
325
+ const result = rootClone;
338
326
  let current = result;
339
327
  for (let i = 0;i < parts.length; i++) {
340
328
  const key = parts[i];
@@ -350,13 +338,19 @@ function cloneAlongPath(obj, path) {
350
338
  }
351
339
  return result;
352
340
  }
353
- function cloneForComparison(obj, strategy, changedPath) {
341
+ function cloneForComparison(obj, strategy, changedPath, deepClone) {
354
342
  if (obj === null || typeof obj !== "object")
355
343
  return obj;
356
344
  switch (strategy) {
357
345
  case "shallow":
358
346
  return Array.isArray(obj) ? [...obj] : { ...obj };
359
347
  case "deep":
348
+ if (deepClone) {
349
+ return deepClone(obj);
350
+ }
351
+ if (typeof structuredClone !== "function") {
352
+ throw new Error("structuredClone is not available in this runtime; provide observe.deepClone, or use cloneStrategy 'path' or 'shallow'.");
353
+ }
360
354
  return structuredClone(obj);
361
355
  case "path":
362
356
  return cloneAlongPath(obj, changedPath);
@@ -404,7 +398,7 @@ function getContextRegistry(target) {
404
398
  function createArrayMethodInterceptor(array, method, path, context) {
405
399
  const original = array[method];
406
400
  return function(...args) {
407
- const previousState = cloneForComparison(context.originalRoot, context.options.cloneStrategy, path);
401
+ const previousState = cloneForComparison(context.originalRoot, context.options.cloneStrategy, path, context.options.deepClone);
408
402
  const previousItems = [...array];
409
403
  const result = original.apply(this, args);
410
404
  const { added, removed } = computeArrayDiff(method, previousItems, array, args);
@@ -476,7 +470,7 @@ function createObservableProxyInternal(target, path, context) {
476
470
  return true;
477
471
  }
478
472
  const propPath = path ? `${path}.${prop}` : prop;
479
- const previousState = cloneForComparison(context.originalRoot, context.options.cloneStrategy, propPath);
473
+ const previousState = cloneForComparison(context.originalRoot, context.options.cloneStrategy, propPath, context.options.deepClone);
480
474
  const success = Reflect.set(obj, prop, value, receiver);
481
475
  if (success) {
482
476
  context.eventTarget.dispatchEvent({
@@ -502,7 +496,7 @@ function createObservableProxyInternal(target, path, context) {
502
496
  return Reflect.deleteProperty(obj, prop);
503
497
  }
504
498
  const propPath = path ? `${path}.${String(prop)}` : String(prop);
505
- const previousState = cloneForComparison(context.originalRoot, context.options.cloneStrategy, propPath);
499
+ const previousState = cloneForComparison(context.originalRoot, context.options.cloneStrategy, propPath, context.options.deepClone);
506
500
  const success = Reflect.deleteProperty(obj, prop);
507
501
  if (success) {
508
502
  context.eventTarget.dispatchEvent({
@@ -535,6 +529,8 @@ function isEventTarget(obj) {
535
529
  }
536
530
  function setupEventForwarding(source, target) {
537
531
  const handlers = new Map;
532
+ const sourceAddEventListener = source.addEventListener.bind(source);
533
+ const sourceRemoveEventListener = source.removeEventListener.bind(source);
538
534
  const forwardHandler = (type) => (event) => {
539
535
  const detail = event.detail ?? event;
540
536
  target.dispatchEvent({
@@ -547,7 +543,7 @@ function setupEventForwarding(source, target) {
547
543
  if (!handlers.has(type) && type !== "update" && !type.startsWith("update:")) {
548
544
  const handler = forwardHandler(type);
549
545
  handlers.set(type, handler);
550
- source.addEventListener(type, handler);
546
+ sourceAddEventListener(type, handler);
551
547
  }
552
548
  return originalAddEventListener(type, listener, options);
553
549
  };
@@ -555,7 +551,7 @@ function setupEventForwarding(source, target) {
555
551
  return () => {
556
552
  target.addEventListener = originalAddEventListener;
557
553
  for (const [type, handler] of handlers) {
558
- source.removeEventListener(type, handler);
554
+ sourceRemoveEventListener(type, handler);
559
555
  }
560
556
  handlers.clear();
561
557
  };
@@ -572,7 +568,8 @@ function getOriginal(proxy) {
572
568
  function createObservableProxy(target, eventTarget, options) {
573
569
  const resolvedOptions = {
574
570
  deep: options?.deep ?? true,
575
- cloneStrategy: options?.cloneStrategy ?? "path"
571
+ cloneStrategy: options?.cloneStrategy ?? "path",
572
+ deepClone: options?.deepClone
576
573
  };
577
574
  const context = {
578
575
  eventTarget,
@@ -581,21 +578,47 @@ function createObservableProxy(target, eventTarget, options) {
581
578
  };
582
579
  const proxy = createObservableProxyInternal(target, "", context);
583
580
  if (isEventTarget(target)) {
584
- setupEventForwarding(target, eventTarget);
581
+ const cleanupForwarding = setupEventForwarding(target, eventTarget);
582
+ const maybeComplete = eventTarget.complete;
583
+ if (typeof maybeComplete === "function") {
584
+ const originalComplete = maybeComplete.bind(eventTarget);
585
+ let cleaned = false;
586
+ eventTarget.complete = () => {
587
+ if (!cleaned) {
588
+ cleaned = true;
589
+ cleanupForwarding();
590
+ }
591
+ return originalComplete();
592
+ };
593
+ }
585
594
  }
586
595
  return proxy;
587
596
  }
588
597
 
598
+ // src/index.ts
599
+ var exports_src = {};
600
+ __export(exports_src, {
601
+ createEventTarget: () => createEventTarget,
602
+ SymbolObservable: () => SymbolObservable,
603
+ EventEmission: () => EventEmission,
604
+ BufferOverflowError: () => BufferOverflowError
605
+ });
606
+ module.exports = __toCommonJS(exports_src);
607
+
608
+ // src/errors.ts
609
+ class BufferOverflowError extends Error {
610
+ constructor(eventType, bufferSize) {
611
+ super(`Buffer overflow for event type "${eventType}" (max: ${bufferSize})`);
612
+ this.name = "BufferOverflowError";
613
+ }
614
+ }
589
615
  // src/factory.ts
590
616
  function matchesWildcard(eventType, pattern) {
591
617
  if (pattern === "*")
592
618
  return true;
593
- if (pattern.endsWith(":*")) {
594
- const namespace = pattern.slice(0, -2);
595
- return eventType.startsWith(namespace + ":");
596
- }
597
- return false;
619
+ return pattern.endsWith(":*") && eventType.startsWith(pattern.slice(0, -2) + ":");
598
620
  }
621
+ var EVENT_STATE = Symbol("event-emission:event-state");
599
622
  function createEventTarget(targetOrOpts, opts) {
600
623
  if (opts?.observe === true && targetOrOpts && typeof targetOrOpts === "object") {
601
624
  const target = targetOrOpts;
@@ -604,7 +627,8 @@ function createEventTarget(targetOrOpts, opts) {
604
627
  });
605
628
  const proxy = createObservableProxy(target, eventTarget, {
606
629
  deep: opts.deep,
607
- cloneStrategy: opts.cloneStrategy
630
+ cloneStrategy: opts.cloneStrategy,
631
+ deepClone: opts.deepClone
608
632
  });
609
633
  const methodNames = [
610
634
  "addEventListener",
@@ -644,38 +668,202 @@ function createEventTargetInternal(opts) {
644
668
  const wildcardListeners = new Set;
645
669
  let isCompleted = false;
646
670
  const completionCallbacks = new Set;
647
- const augmentEvent = (type, detail) => {
648
- const baseEvent = {
649
- bubbles: false,
650
- cancelable: false,
651
- composed: false,
652
- defaultPrevented: false,
653
- eventPhase: 2,
654
- isTrusted: false,
655
- timeStamp: Date.now(),
656
- NONE: 0,
657
- CAPTURING_PHASE: 1,
658
- AT_TARGET: 2,
659
- BUBBLING_PHASE: 3,
660
- composedPath: () => [target],
661
- stopImmediatePropagation: () => {},
662
- stopPropagation: () => {}
671
+ const now = () => typeof globalThis.performance?.now === "function" ? globalThis.performance.now() : Date.now();
672
+ const initializeEventState = (state, type, bubbles, cancelable) => {
673
+ state.initializedFlag = true;
674
+ state.stopPropagationFlag = false;
675
+ state.stopImmediatePropagationFlag = false;
676
+ state.canceledFlag = false;
677
+ state.isTrusted = false;
678
+ state.target = null;
679
+ state.currentTarget = null;
680
+ state.eventPhase = 0;
681
+ state.type = type;
682
+ state.bubbles = bubbles;
683
+ state.cancelable = cancelable;
684
+ };
685
+ const setCanceledFlag = (state) => {
686
+ if (state.cancelable && !state.inPassiveListenerFlag) {
687
+ state.canceledFlag = true;
688
+ }
689
+ };
690
+ const createEvent = (type, detail, init) => {
691
+ const state = {
692
+ dispatchFlag: false,
693
+ initializedFlag: true,
694
+ stopPropagationFlag: false,
695
+ stopImmediatePropagationFlag: false,
696
+ canceledFlag: false,
697
+ inPassiveListenerFlag: false,
698
+ composedFlag: Boolean(init?.composed),
699
+ eventPhase: init?.eventPhase ?? 0,
700
+ currentTarget: init?.currentTarget ?? init?.target ?? null,
701
+ target: init?.target ?? null,
702
+ timeStamp: init?.timeStamp ?? now(),
703
+ path: [],
704
+ type,
705
+ bubbles: Boolean(init?.bubbles),
706
+ cancelable: Boolean(init?.cancelable),
707
+ isTrusted: false
663
708
  };
664
- return Object.defineProperties({ ...baseEvent, type, detail }, {
665
- target: { value: target, enumerable: true, configurable: true },
666
- currentTarget: { value: target, enumerable: true, configurable: true },
709
+ const event = { detail };
710
+ Object.defineProperties(event, {
711
+ type: {
712
+ get: () => state.type,
713
+ enumerable: true,
714
+ configurable: true
715
+ },
716
+ bubbles: {
717
+ get: () => state.bubbles,
718
+ enumerable: true,
719
+ configurable: true
720
+ },
721
+ cancelable: {
722
+ get: () => state.cancelable,
723
+ enumerable: true,
724
+ configurable: true
725
+ },
726
+ cancelBubble: {
727
+ get: () => state.stopPropagationFlag,
728
+ set: (value) => {
729
+ if (value)
730
+ state.stopPropagationFlag = true;
731
+ },
732
+ enumerable: true,
733
+ configurable: true
734
+ },
735
+ composed: {
736
+ get: () => state.composedFlag,
737
+ enumerable: true,
738
+ configurable: true
739
+ },
740
+ currentTarget: {
741
+ get: () => state.currentTarget,
742
+ enumerable: true,
743
+ configurable: true
744
+ },
745
+ defaultPrevented: {
746
+ get: () => state.canceledFlag,
747
+ enumerable: true,
748
+ configurable: true
749
+ },
750
+ eventPhase: {
751
+ get: () => state.eventPhase,
752
+ enumerable: true,
753
+ configurable: true
754
+ },
755
+ isTrusted: {
756
+ get: () => state.isTrusted,
757
+ enumerable: true,
758
+ configurable: true
759
+ },
760
+ returnValue: {
761
+ get: () => !state.canceledFlag,
762
+ set: (value) => {
763
+ if (value === false)
764
+ setCanceledFlag(state);
765
+ },
766
+ enumerable: true,
767
+ configurable: true
768
+ },
769
+ srcElement: {
770
+ get: () => state.target,
771
+ enumerable: true,
772
+ configurable: true
773
+ },
774
+ target: {
775
+ get: () => state.target,
776
+ enumerable: true,
777
+ configurable: true
778
+ },
779
+ timeStamp: {
780
+ get: () => state.timeStamp,
781
+ enumerable: true,
782
+ configurable: true
783
+ },
784
+ composedPath: {
785
+ value: () => state.path.map((entry) => entry.invocationTarget),
786
+ enumerable: true,
787
+ configurable: true
788
+ },
789
+ initEvent: {
790
+ value: (newType, bubbles = false, cancelable = false) => {
791
+ if (state.dispatchFlag)
792
+ return;
793
+ initializeEventState(state, newType, Boolean(bubbles), Boolean(cancelable));
794
+ },
795
+ enumerable: true,
796
+ configurable: true
797
+ },
667
798
  preventDefault: {
668
- value: function() {
669
- Object.defineProperty(this, "defaultPrevented", {
670
- value: true,
671
- enumerable: true,
672
- configurable: true
673
- });
799
+ value: () => setCanceledFlag(state),
800
+ enumerable: true,
801
+ configurable: true
802
+ },
803
+ stopImmediatePropagation: {
804
+ value: () => {
805
+ state.stopPropagationFlag = true;
806
+ state.stopImmediatePropagationFlag = true;
807
+ },
808
+ enumerable: true,
809
+ configurable: true
810
+ },
811
+ stopPropagation: {
812
+ value: () => {
813
+ state.stopPropagationFlag = true;
674
814
  },
675
815
  enumerable: true,
676
816
  configurable: true
817
+ },
818
+ NONE: { value: 0, enumerable: true, configurable: true },
819
+ CAPTURING_PHASE: { value: 1, enumerable: true, configurable: true },
820
+ AT_TARGET: { value: 2, enumerable: true, configurable: true },
821
+ BUBBLING_PHASE: { value: 3, enumerable: true, configurable: true },
822
+ [EVENT_STATE]: {
823
+ value: state,
824
+ enumerable: false,
825
+ configurable: false
677
826
  }
678
827
  });
828
+ return event;
829
+ };
830
+ const getEventState = (event) => event[EVENT_STATE];
831
+ const normalizeAddListenerOptions = (options) => {
832
+ if (typeof options === "boolean") {
833
+ return {
834
+ capture: options,
835
+ passive: false,
836
+ once: false,
837
+ signal: null
838
+ };
839
+ }
840
+ return {
841
+ capture: Boolean(options?.capture),
842
+ passive: Boolean(options?.passive),
843
+ once: Boolean(options?.once),
844
+ signal: options?.signal ?? null
845
+ };
846
+ };
847
+ const normalizeCaptureOption = (options) => {
848
+ if (typeof options === "boolean")
849
+ return options;
850
+ return Boolean(options?.capture);
851
+ };
852
+ const removeListenerRecord = (type, record) => {
853
+ if (record.removed)
854
+ return;
855
+ record.removed = true;
856
+ const list = listeners.get(type);
857
+ if (list) {
858
+ const idx = list.indexOf(record);
859
+ if (idx >= 0)
860
+ list.splice(idx, 1);
861
+ if (list.length === 0)
862
+ listeners.delete(type);
863
+ }
864
+ if (record.signal && record.abortHandler) {
865
+ record.signal.removeEventListener("abort", record.abortHandler);
866
+ }
679
867
  };
680
868
  const handleListenerError = (eventType, error2) => {
681
869
  if (eventType === "error")
@@ -685,28 +873,27 @@ function createEventTargetInternal(opts) {
685
873
  return;
686
874
  }
687
875
  const errorListeners = listeners.get("error");
688
- if (errorListeners && errorListeners.size > 0) {
689
- const errorEvent = augmentEvent("error", error2);
690
- for (const rec of Array.from(errorListeners)) {
691
- try {
692
- const fn = rec.fn;
693
- fn(errorEvent);
694
- } catch {}
695
- if (rec.once)
696
- errorListeners.delete(rec);
697
- }
876
+ if (errorListeners && errorListeners.length > 0) {
877
+ dispatchEvent({ type: "error", detail: error2 });
698
878
  } else {
699
879
  throw error2;
700
880
  }
701
881
  };
702
- const notifyWildcardListeners = (eventType, detail) => {
882
+ const notifyWildcardListeners = (eventType, event) => {
703
883
  if (wildcardListeners.size === 0)
704
884
  return;
705
885
  for (const rec of Array.from(wildcardListeners)) {
706
886
  if (!matchesWildcard(eventType, rec.pattern))
707
887
  continue;
708
- const baseAugmented = augmentEvent(rec.pattern, detail);
709
- const wildcardEvent = Object.defineProperties(baseAugmented, {
888
+ const baseEvent = createEvent(rec.pattern, event.detail, {
889
+ target,
890
+ currentTarget: target,
891
+ eventPhase: 2,
892
+ bubbles: event.bubbles,
893
+ cancelable: event.cancelable,
894
+ composed: event.composed
895
+ });
896
+ const wildcardEvent = Object.defineProperties(baseEvent, {
710
897
  originalType: { value: eventType, enumerable: true, configurable: true }
711
898
  });
712
899
  try {
@@ -729,36 +916,46 @@ function createEventTargetInternal(opts) {
729
916
  if (rec.once)
730
917
  wildcardListeners.delete(rec);
731
918
  }
919
+ const state = getEventState(wildcardEvent);
920
+ if (state?.stopImmediatePropagationFlag || state?.stopPropagationFlag) {
921
+ break;
922
+ }
732
923
  }
733
924
  };
734
925
  const addEventListener = (type, listener, options) => {
735
- if (isCompleted) {
926
+ if (isCompleted || !listener) {
736
927
  return () => {};
737
928
  }
738
- const opts2 = options ?? {};
739
- const record = {
740
- fn: listener,
741
- once: opts2.once,
742
- signal: opts2.signal
743
- };
744
- let set = listeners.get(type);
745
- if (!set) {
746
- set = new Set;
747
- listeners.set(type, set);
929
+ const { capture, passive, once, signal } = normalizeAddListenerOptions(options);
930
+ let list = listeners.get(type);
931
+ if (!list) {
932
+ list = [];
933
+ listeners.set(type, list);
748
934
  }
749
- set.add(record);
750
- const unsubscribe2 = () => {
751
- const setNow = listeners.get(type);
752
- setNow?.delete(record);
753
- if (record.signal && record.abortHandler) {
754
- record.signal.removeEventListener("abort", record.abortHandler);
935
+ for (const existing of list) {
936
+ if (existing.original === listener && existing.capture === capture) {
937
+ return () => removeEventListener(type, listener, options);
755
938
  }
939
+ }
940
+ const original = listener;
941
+ const callback = typeof listener === "function" ? listener : (event) => listener.handleEvent(event);
942
+ const record = {
943
+ type,
944
+ original,
945
+ callback,
946
+ capture,
947
+ passive,
948
+ once,
949
+ signal,
950
+ removed: false
756
951
  };
757
- if (opts2.signal) {
758
- const onAbort = () => unsubscribe2();
952
+ list.push(record);
953
+ const unsubscribe2 = () => removeListenerRecord(type, record);
954
+ if (signal) {
955
+ const onAbort = () => removeListenerRecord(type, record);
759
956
  record.abortHandler = onAbort;
760
- opts2.signal.addEventListener("abort", onAbort, { once: true });
761
- if (opts2.signal.aborted)
957
+ signal.addEventListener("abort", onAbort, { once: true });
958
+ if (signal.aborted)
762
959
  onAbort();
763
960
  }
764
961
  return unsubscribe2;
@@ -767,6 +964,11 @@ function createEventTargetInternal(opts) {
767
964
  if (isCompleted)
768
965
  return () => {};
769
966
  const opts2 = options ?? {};
967
+ for (const existing of wildcardListeners) {
968
+ if (existing.pattern === pattern && existing.fn === listener) {
969
+ return () => removeWildcardListener(pattern, listener);
970
+ }
971
+ }
770
972
  const record = {
771
973
  fn: listener,
772
974
  pattern,
@@ -790,31 +992,39 @@ function createEventTargetInternal(opts) {
790
992
  return unsubscribe2;
791
993
  };
792
994
  const removeWildcardListener = (pattern, listener) => {
793
- for (const record of wildcardListeners) {
995
+ for (const record of Array.from(wildcardListeners)) {
794
996
  if (record.pattern === pattern && record.fn === listener) {
795
997
  wildcardListeners.delete(record);
796
998
  if (record.signal && record.abortHandler) {
797
999
  record.signal.removeEventListener("abort", record.abortHandler);
798
1000
  }
799
- break;
800
1001
  }
801
1002
  }
802
1003
  };
803
- const dispatchEvent = (event) => {
804
- if (isCompleted)
805
- return false;
806
- const augmentedEvent = augmentEvent(event.type, event.detail);
807
- notifyWildcardListeners(event.type, event.detail);
808
- const set = listeners.get(event.type);
809
- if (!set || set.size === 0)
810
- return true;
811
- for (const rec of Array.from(set)) {
1004
+ const invokeListeners = (eventType, event, phase, listenersSnapshot) => {
1005
+ const state = getEventState(event);
1006
+ if (!state || state.stopPropagationFlag)
1007
+ return;
1008
+ state.currentTarget = target;
1009
+ state.target = target;
1010
+ state.eventPhase = event.AT_TARGET;
1011
+ for (const rec of listenersSnapshot) {
1012
+ if (rec.removed)
1013
+ continue;
1014
+ if (phase === "capturing" && !rec.capture)
1015
+ continue;
1016
+ if (phase === "bubbling" && rec.capture)
1017
+ continue;
1018
+ if (rec.once)
1019
+ removeListenerRecord(rec.type, rec);
1020
+ if (rec.passive)
1021
+ state.inPassiveListenerFlag = true;
812
1022
  try {
813
- const res = rec.fn(augmentedEvent);
1023
+ const res = rec.callback.call(state.currentTarget, event);
814
1024
  if (res && typeof res.then === "function") {
815
1025
  res.catch((error2) => {
816
1026
  try {
817
- handleListenerError(event.type, error2);
1027
+ handleListenerError(eventType, error2);
818
1028
  } catch (rethrown) {
819
1029
  queueMicrotask(() => {
820
1030
  throw rethrown;
@@ -823,36 +1033,94 @@ function createEventTargetInternal(opts) {
823
1033
  });
824
1034
  }
825
1035
  } catch (error2) {
826
- handleListenerError(event.type, error2);
1036
+ handleListenerError(eventType, error2);
827
1037
  } finally {
828
- if (rec.once)
829
- set.delete(rec);
1038
+ if (rec.passive)
1039
+ state.inPassiveListenerFlag = false;
830
1040
  }
1041
+ if (state.stopImmediatePropagationFlag)
1042
+ break;
831
1043
  }
832
- return true;
833
1044
  };
834
- const removeEventListener = (type, listener) => {
835
- const set = listeners.get(type);
836
- if (!set)
837
- return;
838
- for (const record of set) {
839
- if (record.fn === listener) {
840
- set.delete(record);
841
- if (record.signal && record.abortHandler) {
842
- record.signal.removeEventListener("abort", record.abortHandler);
1045
+ const dispatchEvent = (eventInput) => {
1046
+ if (isCompleted)
1047
+ return false;
1048
+ let event;
1049
+ let state;
1050
+ if (eventInput && typeof eventInput === "object") {
1051
+ state = getEventState(eventInput);
1052
+ if (state) {
1053
+ event = eventInput;
1054
+ } else {
1055
+ const input = eventInput;
1056
+ if (typeof input.type !== "string") {
1057
+ throw new TypeError("Event type must be a string");
843
1058
  }
844
- break;
1059
+ event = createEvent(input.type, input.detail, {
1060
+ bubbles: input.bubbles,
1061
+ cancelable: input.cancelable,
1062
+ composed: input.composed,
1063
+ timeStamp: input.timeStamp
1064
+ });
1065
+ state = getEventState(event);
1066
+ }
1067
+ } else {
1068
+ throw new TypeError("dispatchEvent expects an event object");
1069
+ }
1070
+ const dispatchState = state ?? getEventState(event);
1071
+ if (dispatchState.dispatchFlag || !dispatchState.initializedFlag) {
1072
+ const message = "Failed to execute dispatchEvent: event is already being dispatched";
1073
+ if (typeof globalThis.DOMException === "function") {
1074
+ throw new globalThis.DOMException(message, "InvalidStateError");
1075
+ }
1076
+ const err = new Error(message);
1077
+ err.name = "InvalidStateError";
1078
+ throw err;
1079
+ }
1080
+ dispatchState.isTrusted = false;
1081
+ dispatchState.dispatchFlag = true;
1082
+ dispatchState.path = [
1083
+ {
1084
+ invocationTarget: target,
1085
+ invocationTargetInShadowTree: false,
1086
+ shadowAdjustedTarget: target,
1087
+ relatedTarget: null,
1088
+ touchTargets: [],
1089
+ rootOfClosedTree: false,
1090
+ slotInClosedTree: false
1091
+ }
1092
+ ];
1093
+ notifyWildcardListeners(dispatchState.type, event);
1094
+ const list = listeners.get(dispatchState.type);
1095
+ const snapshot = list ? list.slice() : [];
1096
+ invokeListeners(dispatchState.type, event, "capturing", snapshot);
1097
+ invokeListeners(dispatchState.type, event, "bubbling", snapshot);
1098
+ dispatchState.eventPhase = event.NONE;
1099
+ dispatchState.currentTarget = null;
1100
+ dispatchState.path = [];
1101
+ dispatchState.dispatchFlag = false;
1102
+ dispatchState.stopPropagationFlag = false;
1103
+ dispatchState.stopImmediatePropagationFlag = false;
1104
+ return !dispatchState.canceledFlag;
1105
+ };
1106
+ const removeEventListener = (type, listener, options) => {
1107
+ if (!listener)
1108
+ return;
1109
+ const capture = normalizeCaptureOption(options);
1110
+ const list = listeners.get(type);
1111
+ if (!list)
1112
+ return;
1113
+ for (const record of [...list]) {
1114
+ if (record.original === listener && record.capture === capture) {
1115
+ removeListenerRecord(type, record);
845
1116
  }
846
1117
  }
847
1118
  };
848
1119
  const clear = () => {
849
- for (const set of listeners.values()) {
850
- for (const record of set) {
851
- if (record.signal && record.abortHandler) {
852
- record.signal.removeEventListener("abort", record.abortHandler);
853
- }
1120
+ for (const [type, list] of Array.from(listeners.entries())) {
1121
+ for (const record of [...list]) {
1122
+ removeListenerRecord(type, record);
854
1123
  }
855
- set.clear();
856
1124
  }
857
1125
  listeners.clear();
858
1126
  for (const record of wildcardListeners) {
@@ -866,7 +1134,7 @@ function createEventTargetInternal(opts) {
866
1134
  return new Observable((observer) => {
867
1135
  let opts2;
868
1136
  if (typeof options === "boolean") {
869
- opts2 = { signal: undefined };
1137
+ opts2 = { capture: options };
870
1138
  } else {
871
1139
  opts2 = options ?? {};
872
1140
  }
@@ -903,28 +1171,25 @@ function createEventTargetInternal(opts) {
903
1171
  });
904
1172
  };
905
1173
  const onceMethod = (type, listener, options) => {
906
- return addEventListener(type, listener, { ...options, once: true });
1174
+ if (typeof options === "boolean") {
1175
+ return addEventListener(type, listener, { capture: options, once: true });
1176
+ }
1177
+ return addEventListener(type, listener, { ...options ?? {}, once: true });
907
1178
  };
908
1179
  const removeAllListeners = (type) => {
909
1180
  if (type !== undefined) {
910
- const set = listeners.get(type);
911
- if (set) {
912
- for (const record of set) {
913
- if (record.signal && record.abortHandler) {
914
- record.signal.removeEventListener("abort", record.abortHandler);
915
- }
1181
+ const list = listeners.get(type);
1182
+ if (list) {
1183
+ for (const record of [...list]) {
1184
+ removeListenerRecord(type, record);
916
1185
  }
917
- set.clear();
918
1186
  listeners.delete(type);
919
1187
  }
920
1188
  } else {
921
- for (const set of listeners.values()) {
922
- for (const record of set) {
923
- if (record.signal && record.abortHandler) {
924
- record.signal.removeEventListener("abort", record.abortHandler);
925
- }
1189
+ for (const [eventType, list] of Array.from(listeners.entries())) {
1190
+ for (const record of [...list]) {
1191
+ removeListenerRecord(eventType, record);
926
1192
  }
927
- set.clear();
928
1193
  }
929
1194
  listeners.clear();
930
1195
  for (const record of wildcardListeners) {
@@ -939,38 +1204,33 @@ function createEventTargetInternal(opts) {
939
1204
  if (isCompleted) {
940
1205
  return () => {};
941
1206
  }
942
- const unsubscribes = [];
943
- const subscribedTypes = new Set;
944
- const subscribeToType = (type) => {
945
- if (subscribedTypes.has(type))
946
- return;
947
- subscribedTypes.add(type);
948
- const unsub = addEventListener(type, (event) => {
949
- if (mapFn) {
950
- const mapped = mapFn(event);
951
- if (mapped !== null) {
952
- target2.dispatchEvent(mapped);
953
- }
954
- } else {
955
- target2.dispatchEvent(event);
1207
+ const unsubscribe2 = addWildcardListener("*", (event) => {
1208
+ if (mapFn) {
1209
+ const mapped = mapFn(createEvent(event.originalType, event.detail, {
1210
+ target: target2,
1211
+ currentTarget: target2,
1212
+ eventPhase: 2,
1213
+ bubbles: event.bubbles,
1214
+ cancelable: event.cancelable,
1215
+ composed: event.composed
1216
+ }));
1217
+ if (mapped !== null) {
1218
+ target2.dispatchEvent(mapped);
956
1219
  }
957
- });
958
- unsubscribes.push(unsub);
959
- };
960
- for (const type of listeners.keys()) {
961
- subscribeToType(type);
962
- }
963
- const completionUnsub = () => {
964
- for (const unsub of unsubscribes) {
965
- unsub();
1220
+ } else {
1221
+ target2.dispatchEvent({
1222
+ type: event.originalType,
1223
+ detail: event.detail
1224
+ });
966
1225
  }
1226
+ });
1227
+ const completionUnsub = () => {
1228
+ unsubscribe2();
967
1229
  };
968
1230
  completionCallbacks.add(completionUnsub);
969
1231
  return () => {
970
1232
  completionCallbacks.delete(completionUnsub);
971
- for (const unsub of unsubscribes) {
972
- unsub();
973
- }
1233
+ unsubscribe2();
974
1234
  };
975
1235
  };
976
1236
  const complete2 = () => {
@@ -987,13 +1247,10 @@ function createEventTargetInternal(opts) {
987
1247
  }
988
1248
  }
989
1249
  completionCallbacks.clear();
990
- for (const set of listeners.values()) {
991
- for (const record of set) {
992
- if (record.signal && record.abortHandler) {
993
- record.signal.removeEventListener("abort", record.abortHandler);
994
- }
1250
+ for (const [eventType, list] of Array.from(listeners.entries())) {
1251
+ for (const record of [...list]) {
1252
+ removeListenerRecord(eventType, record);
995
1253
  }
996
- set.clear();
997
1254
  }
998
1255
  listeners.clear();
999
1256
  for (const record of wildcardListeners) {
@@ -1076,7 +1333,14 @@ function createEventTargetInternal(opts) {
1076
1333
  return;
1077
1334
  }
1078
1335
  const wildcardListener = (event) => {
1079
- observer.next(augmentEvent(event.originalType, event.detail));
1336
+ observer.next(createEvent(event.originalType, event.detail, {
1337
+ target,
1338
+ currentTarget: target,
1339
+ eventPhase: 2,
1340
+ bubbles: event.bubbles,
1341
+ cancelable: event.cancelable,
1342
+ composed: event.composed
1343
+ }));
1080
1344
  };
1081
1345
  const unsubscribe2 = addWildcardListener("*", wildcardListener);
1082
1346
  const onComplete = () => {
@@ -1116,19 +1380,26 @@ function createEventTargetInternal(opts) {
1116
1380
  let resolve = null;
1117
1381
  let done = false;
1118
1382
  let hasOverflow = false;
1383
+ let onAbort = null;
1384
+ const cleanupAbortListener = () => {
1385
+ if (signal && onAbort) {
1386
+ signal.removeEventListener("abort", onAbort);
1387
+ }
1388
+ };
1119
1389
  const unsub = addEventListener(type, (event) => {
1120
1390
  if (done)
1121
1391
  return;
1392
+ const typedEvent = event;
1122
1393
  if (resolve) {
1123
1394
  const r = resolve;
1124
1395
  resolve = null;
1125
- r({ value: event, done: false });
1396
+ r({ value: typedEvent, done: false });
1126
1397
  } else {
1127
1398
  if (buffer.length >= bufferSize && bufferSize !== Infinity) {
1128
1399
  switch (overflowStrategy) {
1129
1400
  case "drop-oldest":
1130
1401
  buffer.shift();
1131
- buffer.push(event);
1402
+ buffer.push(typedEvent);
1132
1403
  break;
1133
1404
  case "drop-latest":
1134
1405
  break;
@@ -1137,15 +1408,17 @@ function createEventTargetInternal(opts) {
1137
1408
  completionCallbacks.delete(onComplete);
1138
1409
  done = true;
1139
1410
  hasOverflow = true;
1411
+ cleanupAbortListener();
1140
1412
  return;
1141
1413
  }
1142
1414
  } else {
1143
- buffer.push(event);
1415
+ buffer.push(typedEvent);
1144
1416
  }
1145
1417
  }
1146
1418
  });
1147
1419
  const onComplete = () => {
1148
1420
  done = true;
1421
+ cleanupAbortListener();
1149
1422
  if (resolve) {
1150
1423
  const r = resolve;
1151
1424
  resolve = null;
@@ -1153,7 +1426,6 @@ function createEventTargetInternal(opts) {
1153
1426
  }
1154
1427
  };
1155
1428
  completionCallbacks.add(onComplete);
1156
- let onAbort = null;
1157
1429
  if (signal) {
1158
1430
  onAbort = () => {
1159
1431
  done = true;
@@ -1177,26 +1449,22 @@ function createEventTargetInternal(opts) {
1177
1449
  if (buffer.length > 0) {
1178
1450
  return { value: buffer.shift(), done: false };
1179
1451
  }
1180
- if (hasOverflow) {
1181
- hasOverflow = false;
1182
- throw new BufferOverflowError(type, bufferSize);
1183
- }
1184
- if (done) {
1185
- return { value: undefined, done: true };
1186
- }
1187
1452
  if (resolve !== null) {
1188
1453
  return Promise.reject(new Error("Concurrent calls to next() are not supported on this async iterator"));
1189
1454
  }
1190
1455
  return new Promise((_resolve, _reject) => {
1191
- if (done) {
1192
- _resolve({ value: undefined, done: true });
1193
- return;
1194
- }
1195
1456
  if (hasOverflow) {
1196
1457
  hasOverflow = false;
1197
1458
  _reject(new BufferOverflowError(type, bufferSize));
1198
1459
  return;
1199
1460
  }
1461
+ if (done) {
1462
+ _resolve({
1463
+ value: undefined,
1464
+ done: true
1465
+ });
1466
+ return;
1467
+ }
1200
1468
  resolve = _resolve;
1201
1469
  });
1202
1470
  },
@@ -1209,9 +1477,7 @@ function createEventTargetInternal(opts) {
1209
1477
  done = true;
1210
1478
  completionCallbacks.delete(onComplete);
1211
1479
  unsub();
1212
- if (signal && onAbort) {
1213
- signal.removeEventListener("abort", onAbort);
1214
- }
1480
+ cleanupAbortListener();
1215
1481
  return Promise.resolve({
1216
1482
  value: undefined,
1217
1483
  done: true
@@ -1244,83 +1510,6 @@ function createEventTargetInternal(opts) {
1244
1510
  };
1245
1511
  return target;
1246
1512
  }
1247
- // src/interop.ts
1248
- function forwardToEventTarget(source, target, options) {
1249
- const unsubscribe2 = source.addWildcardListener("*", (event) => {
1250
- const domEvent = {
1251
- type: event.originalType,
1252
- detail: event.detail
1253
- };
1254
- target.dispatchEvent(domEvent);
1255
- }, options);
1256
- return unsubscribe2;
1257
- }
1258
- function fromEventTarget(domTarget, eventTypes, options) {
1259
- const emitter = createEventTarget({
1260
- onListenerError: options?.onListenerError
1261
- });
1262
- const handlers = new Map;
1263
- for (const type of eventTypes) {
1264
- const handler = (event) => {
1265
- emitter.dispatchEvent({
1266
- type,
1267
- detail: event.detail ?? event
1268
- });
1269
- };
1270
- handlers.set(type, handler);
1271
- domTarget.addEventListener(type, handler);
1272
- }
1273
- let onAbort = null;
1274
- if (options?.signal) {
1275
- onAbort = () => {
1276
- for (const [type, handler] of handlers) {
1277
- domTarget.removeEventListener(type, handler);
1278
- }
1279
- handlers.clear();
1280
- emitter.complete();
1281
- };
1282
- options.signal.addEventListener("abort", onAbort, { once: true });
1283
- if (options.signal.aborted)
1284
- onAbort();
1285
- }
1286
- return {
1287
- addEventListener: emitter.addEventListener,
1288
- removeEventListener: emitter.removeEventListener,
1289
- dispatchEvent: emitter.dispatchEvent,
1290
- clear: emitter.clear,
1291
- once: emitter.once,
1292
- removeAllListeners: emitter.removeAllListeners,
1293
- pipe: emitter.pipe,
1294
- addWildcardListener: emitter.addWildcardListener,
1295
- removeWildcardListener: emitter.removeWildcardListener,
1296
- on: emitter.on,
1297
- subscribe: emitter.subscribe,
1298
- toObservable: emitter.toObservable,
1299
- complete: emitter.complete,
1300
- get completed() {
1301
- return emitter.completed;
1302
- },
1303
- events: emitter.events,
1304
- destroy: () => {
1305
- if (options?.signal && onAbort) {
1306
- options.signal.removeEventListener("abort", onAbort);
1307
- }
1308
- for (const [type, handler] of handlers) {
1309
- domTarget.removeEventListener(type, handler);
1310
- }
1311
- handlers.clear();
1312
- emitter.complete();
1313
- }
1314
- };
1315
- }
1316
- function pipe(source, target, options) {
1317
- return source.addWildcardListener("*", (event) => {
1318
- target.dispatchEvent({
1319
- type: event.originalType,
1320
- detail: event.detail
1321
- });
1322
- }, options);
1323
- }
1324
1513
  // src/event-emission.ts
1325
1514
  class EventEmission {
1326
1515
  #target;
@@ -1330,8 +1519,8 @@ class EventEmission {
1330
1519
  addEventListener(type, listener, options) {
1331
1520
  return this.#target.addEventListener(type, listener, options);
1332
1521
  }
1333
- removeEventListener(type, listener) {
1334
- this.#target.removeEventListener(type, listener);
1522
+ removeEventListener(type, listener, options) {
1523
+ this.#target.removeEventListener(type, listener, options);
1335
1524
  }
1336
1525
  dispatchEvent(event) {
1337
1526
  return this.#target.dispatchEvent(event);
@@ -1391,4 +1580,4 @@ class EventEmission {
1391
1580
  }
1392
1581
  })
1393
1582
 
1394
- //# debugId=4DEDBDE095DEBD3664756E2164756E21
1583
+ //# debugId=3C805781BACAE6AD64756E2164756E21