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.js CHANGED
@@ -4,13 +4,7 @@ var SymbolObservable = typeof Symbol === "function" && Symbol.observable || Symb
4
4
  if (typeof Symbol === "function") {
5
5
  Symbol.observable = SymbolObservable;
6
6
  }
7
- // src/errors.ts
8
- class BufferOverflowError extends Error {
9
- constructor(eventType, bufferSize) {
10
- super(`Buffer overflow for event type "${eventType}" (max: ${bufferSize})`);
11
- this.name = "BufferOverflowError";
12
- }
13
- }
7
+
14
8
  // src/observable.ts
15
9
  function getMethod(obj, key) {
16
10
  if (obj === null || obj === undefined)
@@ -277,17 +271,13 @@ function isArrayMutator(prop) {
277
271
  return typeof prop === "string" && ARRAY_MUTATORS.has(prop);
278
272
  }
279
273
  function cloneAlongPath(obj, path) {
280
- if (obj === null || typeof obj !== "object") {
281
- return obj;
282
- }
283
- if (!path) {
284
- return Array.isArray(obj) ? [...obj] : { ...obj };
274
+ const isArray = Array.isArray(obj);
275
+ const rootClone = isArray ? [...obj] : { ...obj };
276
+ if (!path || isArray) {
277
+ return rootClone;
285
278
  }
286
279
  const parts = path.split(".");
287
- if (Array.isArray(obj)) {
288
- return [...obj];
289
- }
290
- const result = { ...obj };
280
+ const result = rootClone;
291
281
  let current = result;
292
282
  for (let i = 0;i < parts.length; i++) {
293
283
  const key = parts[i];
@@ -303,13 +293,19 @@ function cloneAlongPath(obj, path) {
303
293
  }
304
294
  return result;
305
295
  }
306
- function cloneForComparison(obj, strategy, changedPath) {
296
+ function cloneForComparison(obj, strategy, changedPath, deepClone) {
307
297
  if (obj === null || typeof obj !== "object")
308
298
  return obj;
309
299
  switch (strategy) {
310
300
  case "shallow":
311
301
  return Array.isArray(obj) ? [...obj] : { ...obj };
312
302
  case "deep":
303
+ if (deepClone) {
304
+ return deepClone(obj);
305
+ }
306
+ if (typeof structuredClone !== "function") {
307
+ throw new Error("structuredClone is not available in this runtime; provide observe.deepClone, or use cloneStrategy 'path' or 'shallow'.");
308
+ }
313
309
  return structuredClone(obj);
314
310
  case "path":
315
311
  return cloneAlongPath(obj, changedPath);
@@ -357,7 +353,7 @@ function getContextRegistry(target) {
357
353
  function createArrayMethodInterceptor(array, method, path, context) {
358
354
  const original = array[method];
359
355
  return function(...args) {
360
- const previousState = cloneForComparison(context.originalRoot, context.options.cloneStrategy, path);
356
+ const previousState = cloneForComparison(context.originalRoot, context.options.cloneStrategy, path, context.options.deepClone);
361
357
  const previousItems = [...array];
362
358
  const result = original.apply(this, args);
363
359
  const { added, removed } = computeArrayDiff(method, previousItems, array, args);
@@ -429,7 +425,7 @@ function createObservableProxyInternal(target, path, context) {
429
425
  return true;
430
426
  }
431
427
  const propPath = path ? `${path}.${prop}` : prop;
432
- const previousState = cloneForComparison(context.originalRoot, context.options.cloneStrategy, propPath);
428
+ const previousState = cloneForComparison(context.originalRoot, context.options.cloneStrategy, propPath, context.options.deepClone);
433
429
  const success = Reflect.set(obj, prop, value, receiver);
434
430
  if (success) {
435
431
  context.eventTarget.dispatchEvent({
@@ -455,7 +451,7 @@ function createObservableProxyInternal(target, path, context) {
455
451
  return Reflect.deleteProperty(obj, prop);
456
452
  }
457
453
  const propPath = path ? `${path}.${String(prop)}` : String(prop);
458
- const previousState = cloneForComparison(context.originalRoot, context.options.cloneStrategy, propPath);
454
+ const previousState = cloneForComparison(context.originalRoot, context.options.cloneStrategy, propPath, context.options.deepClone);
459
455
  const success = Reflect.deleteProperty(obj, prop);
460
456
  if (success) {
461
457
  context.eventTarget.dispatchEvent({
@@ -488,6 +484,8 @@ function isEventTarget(obj) {
488
484
  }
489
485
  function setupEventForwarding(source, target) {
490
486
  const handlers = new Map;
487
+ const sourceAddEventListener = source.addEventListener.bind(source);
488
+ const sourceRemoveEventListener = source.removeEventListener.bind(source);
491
489
  const forwardHandler = (type) => (event) => {
492
490
  const detail = event.detail ?? event;
493
491
  target.dispatchEvent({
@@ -500,7 +498,7 @@ function setupEventForwarding(source, target) {
500
498
  if (!handlers.has(type) && type !== "update" && !type.startsWith("update:")) {
501
499
  const handler = forwardHandler(type);
502
500
  handlers.set(type, handler);
503
- source.addEventListener(type, handler);
501
+ sourceAddEventListener(type, handler);
504
502
  }
505
503
  return originalAddEventListener(type, listener, options);
506
504
  };
@@ -508,7 +506,7 @@ function setupEventForwarding(source, target) {
508
506
  return () => {
509
507
  target.addEventListener = originalAddEventListener;
510
508
  for (const [type, handler] of handlers) {
511
- source.removeEventListener(type, handler);
509
+ sourceRemoveEventListener(type, handler);
512
510
  }
513
511
  handlers.clear();
514
512
  };
@@ -525,7 +523,8 @@ function getOriginal(proxy) {
525
523
  function createObservableProxy(target, eventTarget, options) {
526
524
  const resolvedOptions = {
527
525
  deep: options?.deep ?? true,
528
- cloneStrategy: options?.cloneStrategy ?? "path"
526
+ cloneStrategy: options?.cloneStrategy ?? "path",
527
+ deepClone: options?.deepClone
529
528
  };
530
529
  const context = {
531
530
  eventTarget,
@@ -534,21 +533,36 @@ function createObservableProxy(target, eventTarget, options) {
534
533
  };
535
534
  const proxy = createObservableProxyInternal(target, "", context);
536
535
  if (isEventTarget(target)) {
537
- setupEventForwarding(target, eventTarget);
536
+ const cleanupForwarding = setupEventForwarding(target, eventTarget);
537
+ const maybeComplete = eventTarget.complete;
538
+ if (typeof maybeComplete === "function") {
539
+ const originalComplete = maybeComplete.bind(eventTarget);
540
+ let cleaned = false;
541
+ eventTarget.complete = () => {
542
+ if (!cleaned) {
543
+ cleaned = true;
544
+ cleanupForwarding();
545
+ }
546
+ return originalComplete();
547
+ };
548
+ }
538
549
  }
539
550
  return proxy;
540
551
  }
541
-
552
+ // src/errors.ts
553
+ class BufferOverflowError extends Error {
554
+ constructor(eventType, bufferSize) {
555
+ super(`Buffer overflow for event type "${eventType}" (max: ${bufferSize})`);
556
+ this.name = "BufferOverflowError";
557
+ }
558
+ }
542
559
  // src/factory.ts
543
560
  function matchesWildcard(eventType, pattern) {
544
561
  if (pattern === "*")
545
562
  return true;
546
- if (pattern.endsWith(":*")) {
547
- const namespace = pattern.slice(0, -2);
548
- return eventType.startsWith(namespace + ":");
549
- }
550
- return false;
563
+ return pattern.endsWith(":*") && eventType.startsWith(pattern.slice(0, -2) + ":");
551
564
  }
565
+ var EVENT_STATE = Symbol("event-emission:event-state");
552
566
  function createEventTarget(targetOrOpts, opts) {
553
567
  if (opts?.observe === true && targetOrOpts && typeof targetOrOpts === "object") {
554
568
  const target = targetOrOpts;
@@ -557,7 +571,8 @@ function createEventTarget(targetOrOpts, opts) {
557
571
  });
558
572
  const proxy = createObservableProxy(target, eventTarget, {
559
573
  deep: opts.deep,
560
- cloneStrategy: opts.cloneStrategy
574
+ cloneStrategy: opts.cloneStrategy,
575
+ deepClone: opts.deepClone
561
576
  });
562
577
  const methodNames = [
563
578
  "addEventListener",
@@ -597,38 +612,202 @@ function createEventTargetInternal(opts) {
597
612
  const wildcardListeners = new Set;
598
613
  let isCompleted = false;
599
614
  const completionCallbacks = new Set;
600
- const augmentEvent = (type, detail) => {
601
- const baseEvent = {
602
- bubbles: false,
603
- cancelable: false,
604
- composed: false,
605
- defaultPrevented: false,
606
- eventPhase: 2,
607
- isTrusted: false,
608
- timeStamp: Date.now(),
609
- NONE: 0,
610
- CAPTURING_PHASE: 1,
611
- AT_TARGET: 2,
612
- BUBBLING_PHASE: 3,
613
- composedPath: () => [target],
614
- stopImmediatePropagation: () => {},
615
- stopPropagation: () => {}
615
+ const now = () => typeof globalThis.performance?.now === "function" ? globalThis.performance.now() : Date.now();
616
+ const initializeEventState = (state, type, bubbles, cancelable) => {
617
+ state.initializedFlag = true;
618
+ state.stopPropagationFlag = false;
619
+ state.stopImmediatePropagationFlag = false;
620
+ state.canceledFlag = false;
621
+ state.isTrusted = false;
622
+ state.target = null;
623
+ state.currentTarget = null;
624
+ state.eventPhase = 0;
625
+ state.type = type;
626
+ state.bubbles = bubbles;
627
+ state.cancelable = cancelable;
628
+ };
629
+ const setCanceledFlag = (state) => {
630
+ if (state.cancelable && !state.inPassiveListenerFlag) {
631
+ state.canceledFlag = true;
632
+ }
633
+ };
634
+ const createEvent = (type, detail, init) => {
635
+ const state = {
636
+ dispatchFlag: false,
637
+ initializedFlag: true,
638
+ stopPropagationFlag: false,
639
+ stopImmediatePropagationFlag: false,
640
+ canceledFlag: false,
641
+ inPassiveListenerFlag: false,
642
+ composedFlag: Boolean(init?.composed),
643
+ eventPhase: init?.eventPhase ?? 0,
644
+ currentTarget: init?.currentTarget ?? init?.target ?? null,
645
+ target: init?.target ?? null,
646
+ timeStamp: init?.timeStamp ?? now(),
647
+ path: [],
648
+ type,
649
+ bubbles: Boolean(init?.bubbles),
650
+ cancelable: Boolean(init?.cancelable),
651
+ isTrusted: false
616
652
  };
617
- return Object.defineProperties({ ...baseEvent, type, detail }, {
618
- target: { value: target, enumerable: true, configurable: true },
619
- currentTarget: { value: target, enumerable: true, configurable: true },
653
+ const event = { detail };
654
+ Object.defineProperties(event, {
655
+ type: {
656
+ get: () => state.type,
657
+ enumerable: true,
658
+ configurable: true
659
+ },
660
+ bubbles: {
661
+ get: () => state.bubbles,
662
+ enumerable: true,
663
+ configurable: true
664
+ },
665
+ cancelable: {
666
+ get: () => state.cancelable,
667
+ enumerable: true,
668
+ configurable: true
669
+ },
670
+ cancelBubble: {
671
+ get: () => state.stopPropagationFlag,
672
+ set: (value) => {
673
+ if (value)
674
+ state.stopPropagationFlag = true;
675
+ },
676
+ enumerable: true,
677
+ configurable: true
678
+ },
679
+ composed: {
680
+ get: () => state.composedFlag,
681
+ enumerable: true,
682
+ configurable: true
683
+ },
684
+ currentTarget: {
685
+ get: () => state.currentTarget,
686
+ enumerable: true,
687
+ configurable: true
688
+ },
689
+ defaultPrevented: {
690
+ get: () => state.canceledFlag,
691
+ enumerable: true,
692
+ configurable: true
693
+ },
694
+ eventPhase: {
695
+ get: () => state.eventPhase,
696
+ enumerable: true,
697
+ configurable: true
698
+ },
699
+ isTrusted: {
700
+ get: () => state.isTrusted,
701
+ enumerable: true,
702
+ configurable: true
703
+ },
704
+ returnValue: {
705
+ get: () => !state.canceledFlag,
706
+ set: (value) => {
707
+ if (value === false)
708
+ setCanceledFlag(state);
709
+ },
710
+ enumerable: true,
711
+ configurable: true
712
+ },
713
+ srcElement: {
714
+ get: () => state.target,
715
+ enumerable: true,
716
+ configurable: true
717
+ },
718
+ target: {
719
+ get: () => state.target,
720
+ enumerable: true,
721
+ configurable: true
722
+ },
723
+ timeStamp: {
724
+ get: () => state.timeStamp,
725
+ enumerable: true,
726
+ configurable: true
727
+ },
728
+ composedPath: {
729
+ value: () => state.path.map((entry) => entry.invocationTarget),
730
+ enumerable: true,
731
+ configurable: true
732
+ },
733
+ initEvent: {
734
+ value: (newType, bubbles = false, cancelable = false) => {
735
+ if (state.dispatchFlag)
736
+ return;
737
+ initializeEventState(state, newType, Boolean(bubbles), Boolean(cancelable));
738
+ },
739
+ enumerable: true,
740
+ configurable: true
741
+ },
620
742
  preventDefault: {
621
- value: function() {
622
- Object.defineProperty(this, "defaultPrevented", {
623
- value: true,
624
- enumerable: true,
625
- configurable: true
626
- });
743
+ value: () => setCanceledFlag(state),
744
+ enumerable: true,
745
+ configurable: true
746
+ },
747
+ stopImmediatePropagation: {
748
+ value: () => {
749
+ state.stopPropagationFlag = true;
750
+ state.stopImmediatePropagationFlag = true;
627
751
  },
628
752
  enumerable: true,
629
753
  configurable: true
754
+ },
755
+ stopPropagation: {
756
+ value: () => {
757
+ state.stopPropagationFlag = true;
758
+ },
759
+ enumerable: true,
760
+ configurable: true
761
+ },
762
+ NONE: { value: 0, enumerable: true, configurable: true },
763
+ CAPTURING_PHASE: { value: 1, enumerable: true, configurable: true },
764
+ AT_TARGET: { value: 2, enumerable: true, configurable: true },
765
+ BUBBLING_PHASE: { value: 3, enumerable: true, configurable: true },
766
+ [EVENT_STATE]: {
767
+ value: state,
768
+ enumerable: false,
769
+ configurable: false
630
770
  }
631
771
  });
772
+ return event;
773
+ };
774
+ const getEventState = (event) => event[EVENT_STATE];
775
+ const normalizeAddListenerOptions = (options) => {
776
+ if (typeof options === "boolean") {
777
+ return {
778
+ capture: options,
779
+ passive: false,
780
+ once: false,
781
+ signal: null
782
+ };
783
+ }
784
+ return {
785
+ capture: Boolean(options?.capture),
786
+ passive: Boolean(options?.passive),
787
+ once: Boolean(options?.once),
788
+ signal: options?.signal ?? null
789
+ };
790
+ };
791
+ const normalizeCaptureOption = (options) => {
792
+ if (typeof options === "boolean")
793
+ return options;
794
+ return Boolean(options?.capture);
795
+ };
796
+ const removeListenerRecord = (type, record) => {
797
+ if (record.removed)
798
+ return;
799
+ record.removed = true;
800
+ const list = listeners.get(type);
801
+ if (list) {
802
+ const idx = list.indexOf(record);
803
+ if (idx >= 0)
804
+ list.splice(idx, 1);
805
+ if (list.length === 0)
806
+ listeners.delete(type);
807
+ }
808
+ if (record.signal && record.abortHandler) {
809
+ record.signal.removeEventListener("abort", record.abortHandler);
810
+ }
632
811
  };
633
812
  const handleListenerError = (eventType, error2) => {
634
813
  if (eventType === "error")
@@ -638,28 +817,27 @@ function createEventTargetInternal(opts) {
638
817
  return;
639
818
  }
640
819
  const errorListeners = listeners.get("error");
641
- if (errorListeners && errorListeners.size > 0) {
642
- const errorEvent = augmentEvent("error", error2);
643
- for (const rec of Array.from(errorListeners)) {
644
- try {
645
- const fn = rec.fn;
646
- fn(errorEvent);
647
- } catch {}
648
- if (rec.once)
649
- errorListeners.delete(rec);
650
- }
820
+ if (errorListeners && errorListeners.length > 0) {
821
+ dispatchEvent({ type: "error", detail: error2 });
651
822
  } else {
652
823
  throw error2;
653
824
  }
654
825
  };
655
- const notifyWildcardListeners = (eventType, detail) => {
826
+ const notifyWildcardListeners = (eventType, event) => {
656
827
  if (wildcardListeners.size === 0)
657
828
  return;
658
829
  for (const rec of Array.from(wildcardListeners)) {
659
830
  if (!matchesWildcard(eventType, rec.pattern))
660
831
  continue;
661
- const baseAugmented = augmentEvent(rec.pattern, detail);
662
- const wildcardEvent = Object.defineProperties(baseAugmented, {
832
+ const baseEvent = createEvent(rec.pattern, event.detail, {
833
+ target,
834
+ currentTarget: target,
835
+ eventPhase: 2,
836
+ bubbles: event.bubbles,
837
+ cancelable: event.cancelable,
838
+ composed: event.composed
839
+ });
840
+ const wildcardEvent = Object.defineProperties(baseEvent, {
663
841
  originalType: { value: eventType, enumerable: true, configurable: true }
664
842
  });
665
843
  try {
@@ -682,36 +860,46 @@ function createEventTargetInternal(opts) {
682
860
  if (rec.once)
683
861
  wildcardListeners.delete(rec);
684
862
  }
863
+ const state = getEventState(wildcardEvent);
864
+ if (state?.stopImmediatePropagationFlag || state?.stopPropagationFlag) {
865
+ break;
866
+ }
685
867
  }
686
868
  };
687
869
  const addEventListener = (type, listener, options) => {
688
- if (isCompleted) {
870
+ if (isCompleted || !listener) {
689
871
  return () => {};
690
872
  }
691
- const opts2 = options ?? {};
692
- const record = {
693
- fn: listener,
694
- once: opts2.once,
695
- signal: opts2.signal
696
- };
697
- let set = listeners.get(type);
698
- if (!set) {
699
- set = new Set;
700
- listeners.set(type, set);
873
+ const { capture, passive, once, signal } = normalizeAddListenerOptions(options);
874
+ let list = listeners.get(type);
875
+ if (!list) {
876
+ list = [];
877
+ listeners.set(type, list);
701
878
  }
702
- set.add(record);
703
- const unsubscribe2 = () => {
704
- const setNow = listeners.get(type);
705
- setNow?.delete(record);
706
- if (record.signal && record.abortHandler) {
707
- record.signal.removeEventListener("abort", record.abortHandler);
879
+ for (const existing of list) {
880
+ if (existing.original === listener && existing.capture === capture) {
881
+ return () => removeEventListener(type, listener, options);
708
882
  }
883
+ }
884
+ const original = listener;
885
+ const callback = typeof listener === "function" ? listener : (event) => listener.handleEvent(event);
886
+ const record = {
887
+ type,
888
+ original,
889
+ callback,
890
+ capture,
891
+ passive,
892
+ once,
893
+ signal,
894
+ removed: false
709
895
  };
710
- if (opts2.signal) {
711
- const onAbort = () => unsubscribe2();
896
+ list.push(record);
897
+ const unsubscribe2 = () => removeListenerRecord(type, record);
898
+ if (signal) {
899
+ const onAbort = () => removeListenerRecord(type, record);
712
900
  record.abortHandler = onAbort;
713
- opts2.signal.addEventListener("abort", onAbort, { once: true });
714
- if (opts2.signal.aborted)
901
+ signal.addEventListener("abort", onAbort, { once: true });
902
+ if (signal.aborted)
715
903
  onAbort();
716
904
  }
717
905
  return unsubscribe2;
@@ -720,6 +908,11 @@ function createEventTargetInternal(opts) {
720
908
  if (isCompleted)
721
909
  return () => {};
722
910
  const opts2 = options ?? {};
911
+ for (const existing of wildcardListeners) {
912
+ if (existing.pattern === pattern && existing.fn === listener) {
913
+ return () => removeWildcardListener(pattern, listener);
914
+ }
915
+ }
723
916
  const record = {
724
917
  fn: listener,
725
918
  pattern,
@@ -743,31 +936,39 @@ function createEventTargetInternal(opts) {
743
936
  return unsubscribe2;
744
937
  };
745
938
  const removeWildcardListener = (pattern, listener) => {
746
- for (const record of wildcardListeners) {
939
+ for (const record of Array.from(wildcardListeners)) {
747
940
  if (record.pattern === pattern && record.fn === listener) {
748
941
  wildcardListeners.delete(record);
749
942
  if (record.signal && record.abortHandler) {
750
943
  record.signal.removeEventListener("abort", record.abortHandler);
751
944
  }
752
- break;
753
945
  }
754
946
  }
755
947
  };
756
- const dispatchEvent = (event) => {
757
- if (isCompleted)
758
- return false;
759
- const augmentedEvent = augmentEvent(event.type, event.detail);
760
- notifyWildcardListeners(event.type, event.detail);
761
- const set = listeners.get(event.type);
762
- if (!set || set.size === 0)
763
- return true;
764
- for (const rec of Array.from(set)) {
948
+ const invokeListeners = (eventType, event, phase, listenersSnapshot) => {
949
+ const state = getEventState(event);
950
+ if (!state || state.stopPropagationFlag)
951
+ return;
952
+ state.currentTarget = target;
953
+ state.target = target;
954
+ state.eventPhase = event.AT_TARGET;
955
+ for (const rec of listenersSnapshot) {
956
+ if (rec.removed)
957
+ continue;
958
+ if (phase === "capturing" && !rec.capture)
959
+ continue;
960
+ if (phase === "bubbling" && rec.capture)
961
+ continue;
962
+ if (rec.once)
963
+ removeListenerRecord(rec.type, rec);
964
+ if (rec.passive)
965
+ state.inPassiveListenerFlag = true;
765
966
  try {
766
- const res = rec.fn(augmentedEvent);
967
+ const res = rec.callback.call(state.currentTarget, event);
767
968
  if (res && typeof res.then === "function") {
768
969
  res.catch((error2) => {
769
970
  try {
770
- handleListenerError(event.type, error2);
971
+ handleListenerError(eventType, error2);
771
972
  } catch (rethrown) {
772
973
  queueMicrotask(() => {
773
974
  throw rethrown;
@@ -776,36 +977,94 @@ function createEventTargetInternal(opts) {
776
977
  });
777
978
  }
778
979
  } catch (error2) {
779
- handleListenerError(event.type, error2);
980
+ handleListenerError(eventType, error2);
780
981
  } finally {
781
- if (rec.once)
782
- set.delete(rec);
982
+ if (rec.passive)
983
+ state.inPassiveListenerFlag = false;
783
984
  }
985
+ if (state.stopImmediatePropagationFlag)
986
+ break;
784
987
  }
785
- return true;
786
988
  };
787
- const removeEventListener = (type, listener) => {
788
- const set = listeners.get(type);
789
- if (!set)
790
- return;
791
- for (const record of set) {
792
- if (record.fn === listener) {
793
- set.delete(record);
794
- if (record.signal && record.abortHandler) {
795
- record.signal.removeEventListener("abort", record.abortHandler);
989
+ const dispatchEvent = (eventInput) => {
990
+ if (isCompleted)
991
+ return false;
992
+ let event;
993
+ let state;
994
+ if (eventInput && typeof eventInput === "object") {
995
+ state = getEventState(eventInput);
996
+ if (state) {
997
+ event = eventInput;
998
+ } else {
999
+ const input = eventInput;
1000
+ if (typeof input.type !== "string") {
1001
+ throw new TypeError("Event type must be a string");
796
1002
  }
797
- break;
1003
+ event = createEvent(input.type, input.detail, {
1004
+ bubbles: input.bubbles,
1005
+ cancelable: input.cancelable,
1006
+ composed: input.composed,
1007
+ timeStamp: input.timeStamp
1008
+ });
1009
+ state = getEventState(event);
1010
+ }
1011
+ } else {
1012
+ throw new TypeError("dispatchEvent expects an event object");
1013
+ }
1014
+ const dispatchState = state ?? getEventState(event);
1015
+ if (dispatchState.dispatchFlag || !dispatchState.initializedFlag) {
1016
+ const message = "Failed to execute dispatchEvent: event is already being dispatched";
1017
+ if (typeof globalThis.DOMException === "function") {
1018
+ throw new globalThis.DOMException(message, "InvalidStateError");
1019
+ }
1020
+ const err = new Error(message);
1021
+ err.name = "InvalidStateError";
1022
+ throw err;
1023
+ }
1024
+ dispatchState.isTrusted = false;
1025
+ dispatchState.dispatchFlag = true;
1026
+ dispatchState.path = [
1027
+ {
1028
+ invocationTarget: target,
1029
+ invocationTargetInShadowTree: false,
1030
+ shadowAdjustedTarget: target,
1031
+ relatedTarget: null,
1032
+ touchTargets: [],
1033
+ rootOfClosedTree: false,
1034
+ slotInClosedTree: false
1035
+ }
1036
+ ];
1037
+ notifyWildcardListeners(dispatchState.type, event);
1038
+ const list = listeners.get(dispatchState.type);
1039
+ const snapshot = list ? list.slice() : [];
1040
+ invokeListeners(dispatchState.type, event, "capturing", snapshot);
1041
+ invokeListeners(dispatchState.type, event, "bubbling", snapshot);
1042
+ dispatchState.eventPhase = event.NONE;
1043
+ dispatchState.currentTarget = null;
1044
+ dispatchState.path = [];
1045
+ dispatchState.dispatchFlag = false;
1046
+ dispatchState.stopPropagationFlag = false;
1047
+ dispatchState.stopImmediatePropagationFlag = false;
1048
+ return !dispatchState.canceledFlag;
1049
+ };
1050
+ const removeEventListener = (type, listener, options) => {
1051
+ if (!listener)
1052
+ return;
1053
+ const capture = normalizeCaptureOption(options);
1054
+ const list = listeners.get(type);
1055
+ if (!list)
1056
+ return;
1057
+ for (const record of [...list]) {
1058
+ if (record.original === listener && record.capture === capture) {
1059
+ removeListenerRecord(type, record);
798
1060
  }
799
1061
  }
800
1062
  };
801
1063
  const clear = () => {
802
- for (const set of listeners.values()) {
803
- for (const record of set) {
804
- if (record.signal && record.abortHandler) {
805
- record.signal.removeEventListener("abort", record.abortHandler);
806
- }
1064
+ for (const [type, list] of Array.from(listeners.entries())) {
1065
+ for (const record of [...list]) {
1066
+ removeListenerRecord(type, record);
807
1067
  }
808
- set.clear();
809
1068
  }
810
1069
  listeners.clear();
811
1070
  for (const record of wildcardListeners) {
@@ -819,7 +1078,7 @@ function createEventTargetInternal(opts) {
819
1078
  return new Observable((observer) => {
820
1079
  let opts2;
821
1080
  if (typeof options === "boolean") {
822
- opts2 = { signal: undefined };
1081
+ opts2 = { capture: options };
823
1082
  } else {
824
1083
  opts2 = options ?? {};
825
1084
  }
@@ -856,28 +1115,25 @@ function createEventTargetInternal(opts) {
856
1115
  });
857
1116
  };
858
1117
  const onceMethod = (type, listener, options) => {
859
- return addEventListener(type, listener, { ...options, once: true });
1118
+ if (typeof options === "boolean") {
1119
+ return addEventListener(type, listener, { capture: options, once: true });
1120
+ }
1121
+ return addEventListener(type, listener, { ...options ?? {}, once: true });
860
1122
  };
861
1123
  const removeAllListeners = (type) => {
862
1124
  if (type !== undefined) {
863
- const set = listeners.get(type);
864
- if (set) {
865
- for (const record of set) {
866
- if (record.signal && record.abortHandler) {
867
- record.signal.removeEventListener("abort", record.abortHandler);
868
- }
1125
+ const list = listeners.get(type);
1126
+ if (list) {
1127
+ for (const record of [...list]) {
1128
+ removeListenerRecord(type, record);
869
1129
  }
870
- set.clear();
871
1130
  listeners.delete(type);
872
1131
  }
873
1132
  } else {
874
- for (const set of listeners.values()) {
875
- for (const record of set) {
876
- if (record.signal && record.abortHandler) {
877
- record.signal.removeEventListener("abort", record.abortHandler);
878
- }
1133
+ for (const [eventType, list] of Array.from(listeners.entries())) {
1134
+ for (const record of [...list]) {
1135
+ removeListenerRecord(eventType, record);
879
1136
  }
880
- set.clear();
881
1137
  }
882
1138
  listeners.clear();
883
1139
  for (const record of wildcardListeners) {
@@ -892,38 +1148,33 @@ function createEventTargetInternal(opts) {
892
1148
  if (isCompleted) {
893
1149
  return () => {};
894
1150
  }
895
- const unsubscribes = [];
896
- const subscribedTypes = new Set;
897
- const subscribeToType = (type) => {
898
- if (subscribedTypes.has(type))
899
- return;
900
- subscribedTypes.add(type);
901
- const unsub = addEventListener(type, (event) => {
902
- if (mapFn) {
903
- const mapped = mapFn(event);
904
- if (mapped !== null) {
905
- target2.dispatchEvent(mapped);
906
- }
907
- } else {
908
- target2.dispatchEvent(event);
1151
+ const unsubscribe2 = addWildcardListener("*", (event) => {
1152
+ if (mapFn) {
1153
+ const mapped = mapFn(createEvent(event.originalType, event.detail, {
1154
+ target: target2,
1155
+ currentTarget: target2,
1156
+ eventPhase: 2,
1157
+ bubbles: event.bubbles,
1158
+ cancelable: event.cancelable,
1159
+ composed: event.composed
1160
+ }));
1161
+ if (mapped !== null) {
1162
+ target2.dispatchEvent(mapped);
909
1163
  }
910
- });
911
- unsubscribes.push(unsub);
912
- };
913
- for (const type of listeners.keys()) {
914
- subscribeToType(type);
915
- }
916
- const completionUnsub = () => {
917
- for (const unsub of unsubscribes) {
918
- unsub();
1164
+ } else {
1165
+ target2.dispatchEvent({
1166
+ type: event.originalType,
1167
+ detail: event.detail
1168
+ });
919
1169
  }
1170
+ });
1171
+ const completionUnsub = () => {
1172
+ unsubscribe2();
920
1173
  };
921
1174
  completionCallbacks.add(completionUnsub);
922
1175
  return () => {
923
1176
  completionCallbacks.delete(completionUnsub);
924
- for (const unsub of unsubscribes) {
925
- unsub();
926
- }
1177
+ unsubscribe2();
927
1178
  };
928
1179
  };
929
1180
  const complete2 = () => {
@@ -940,13 +1191,10 @@ function createEventTargetInternal(opts) {
940
1191
  }
941
1192
  }
942
1193
  completionCallbacks.clear();
943
- for (const set of listeners.values()) {
944
- for (const record of set) {
945
- if (record.signal && record.abortHandler) {
946
- record.signal.removeEventListener("abort", record.abortHandler);
947
- }
1194
+ for (const [eventType, list] of Array.from(listeners.entries())) {
1195
+ for (const record of [...list]) {
1196
+ removeListenerRecord(eventType, record);
948
1197
  }
949
- set.clear();
950
1198
  }
951
1199
  listeners.clear();
952
1200
  for (const record of wildcardListeners) {
@@ -1029,7 +1277,14 @@ function createEventTargetInternal(opts) {
1029
1277
  return;
1030
1278
  }
1031
1279
  const wildcardListener = (event) => {
1032
- observer.next(augmentEvent(event.originalType, event.detail));
1280
+ observer.next(createEvent(event.originalType, event.detail, {
1281
+ target,
1282
+ currentTarget: target,
1283
+ eventPhase: 2,
1284
+ bubbles: event.bubbles,
1285
+ cancelable: event.cancelable,
1286
+ composed: event.composed
1287
+ }));
1033
1288
  };
1034
1289
  const unsubscribe2 = addWildcardListener("*", wildcardListener);
1035
1290
  const onComplete = () => {
@@ -1069,19 +1324,26 @@ function createEventTargetInternal(opts) {
1069
1324
  let resolve = null;
1070
1325
  let done = false;
1071
1326
  let hasOverflow = false;
1327
+ let onAbort = null;
1328
+ const cleanupAbortListener = () => {
1329
+ if (signal && onAbort) {
1330
+ signal.removeEventListener("abort", onAbort);
1331
+ }
1332
+ };
1072
1333
  const unsub = addEventListener(type, (event) => {
1073
1334
  if (done)
1074
1335
  return;
1336
+ const typedEvent = event;
1075
1337
  if (resolve) {
1076
1338
  const r = resolve;
1077
1339
  resolve = null;
1078
- r({ value: event, done: false });
1340
+ r({ value: typedEvent, done: false });
1079
1341
  } else {
1080
1342
  if (buffer.length >= bufferSize && bufferSize !== Infinity) {
1081
1343
  switch (overflowStrategy) {
1082
1344
  case "drop-oldest":
1083
1345
  buffer.shift();
1084
- buffer.push(event);
1346
+ buffer.push(typedEvent);
1085
1347
  break;
1086
1348
  case "drop-latest":
1087
1349
  break;
@@ -1090,15 +1352,17 @@ function createEventTargetInternal(opts) {
1090
1352
  completionCallbacks.delete(onComplete);
1091
1353
  done = true;
1092
1354
  hasOverflow = true;
1355
+ cleanupAbortListener();
1093
1356
  return;
1094
1357
  }
1095
1358
  } else {
1096
- buffer.push(event);
1359
+ buffer.push(typedEvent);
1097
1360
  }
1098
1361
  }
1099
1362
  });
1100
1363
  const onComplete = () => {
1101
1364
  done = true;
1365
+ cleanupAbortListener();
1102
1366
  if (resolve) {
1103
1367
  const r = resolve;
1104
1368
  resolve = null;
@@ -1106,7 +1370,6 @@ function createEventTargetInternal(opts) {
1106
1370
  }
1107
1371
  };
1108
1372
  completionCallbacks.add(onComplete);
1109
- let onAbort = null;
1110
1373
  if (signal) {
1111
1374
  onAbort = () => {
1112
1375
  done = true;
@@ -1130,26 +1393,22 @@ function createEventTargetInternal(opts) {
1130
1393
  if (buffer.length > 0) {
1131
1394
  return { value: buffer.shift(), done: false };
1132
1395
  }
1133
- if (hasOverflow) {
1134
- hasOverflow = false;
1135
- throw new BufferOverflowError(type, bufferSize);
1136
- }
1137
- if (done) {
1138
- return { value: undefined, done: true };
1139
- }
1140
1396
  if (resolve !== null) {
1141
1397
  return Promise.reject(new Error("Concurrent calls to next() are not supported on this async iterator"));
1142
1398
  }
1143
1399
  return new Promise((_resolve, _reject) => {
1144
- if (done) {
1145
- _resolve({ value: undefined, done: true });
1146
- return;
1147
- }
1148
1400
  if (hasOverflow) {
1149
1401
  hasOverflow = false;
1150
1402
  _reject(new BufferOverflowError(type, bufferSize));
1151
1403
  return;
1152
1404
  }
1405
+ if (done) {
1406
+ _resolve({
1407
+ value: undefined,
1408
+ done: true
1409
+ });
1410
+ return;
1411
+ }
1153
1412
  resolve = _resolve;
1154
1413
  });
1155
1414
  },
@@ -1162,9 +1421,7 @@ function createEventTargetInternal(opts) {
1162
1421
  done = true;
1163
1422
  completionCallbacks.delete(onComplete);
1164
1423
  unsub();
1165
- if (signal && onAbort) {
1166
- signal.removeEventListener("abort", onAbort);
1167
- }
1424
+ cleanupAbortListener();
1168
1425
  return Promise.resolve({
1169
1426
  value: undefined,
1170
1427
  done: true
@@ -1197,83 +1454,6 @@ function createEventTargetInternal(opts) {
1197
1454
  };
1198
1455
  return target;
1199
1456
  }
1200
- // src/interop.ts
1201
- function forwardToEventTarget(source, target, options) {
1202
- const unsubscribe2 = source.addWildcardListener("*", (event) => {
1203
- const domEvent = {
1204
- type: event.originalType,
1205
- detail: event.detail
1206
- };
1207
- target.dispatchEvent(domEvent);
1208
- }, options);
1209
- return unsubscribe2;
1210
- }
1211
- function fromEventTarget(domTarget, eventTypes, options) {
1212
- const emitter = createEventTarget({
1213
- onListenerError: options?.onListenerError
1214
- });
1215
- const handlers = new Map;
1216
- for (const type of eventTypes) {
1217
- const handler = (event) => {
1218
- emitter.dispatchEvent({
1219
- type,
1220
- detail: event.detail ?? event
1221
- });
1222
- };
1223
- handlers.set(type, handler);
1224
- domTarget.addEventListener(type, handler);
1225
- }
1226
- let onAbort = null;
1227
- if (options?.signal) {
1228
- onAbort = () => {
1229
- for (const [type, handler] of handlers) {
1230
- domTarget.removeEventListener(type, handler);
1231
- }
1232
- handlers.clear();
1233
- emitter.complete();
1234
- };
1235
- options.signal.addEventListener("abort", onAbort, { once: true });
1236
- if (options.signal.aborted)
1237
- onAbort();
1238
- }
1239
- return {
1240
- addEventListener: emitter.addEventListener,
1241
- removeEventListener: emitter.removeEventListener,
1242
- dispatchEvent: emitter.dispatchEvent,
1243
- clear: emitter.clear,
1244
- once: emitter.once,
1245
- removeAllListeners: emitter.removeAllListeners,
1246
- pipe: emitter.pipe,
1247
- addWildcardListener: emitter.addWildcardListener,
1248
- removeWildcardListener: emitter.removeWildcardListener,
1249
- on: emitter.on,
1250
- subscribe: emitter.subscribe,
1251
- toObservable: emitter.toObservable,
1252
- complete: emitter.complete,
1253
- get completed() {
1254
- return emitter.completed;
1255
- },
1256
- events: emitter.events,
1257
- destroy: () => {
1258
- if (options?.signal && onAbort) {
1259
- options.signal.removeEventListener("abort", onAbort);
1260
- }
1261
- for (const [type, handler] of handlers) {
1262
- domTarget.removeEventListener(type, handler);
1263
- }
1264
- handlers.clear();
1265
- emitter.complete();
1266
- }
1267
- };
1268
- }
1269
- function pipe(source, target, options) {
1270
- return source.addWildcardListener("*", (event) => {
1271
- target.dispatchEvent({
1272
- type: event.originalType,
1273
- detail: event.detail
1274
- });
1275
- }, options);
1276
- }
1277
1457
  // src/event-emission.ts
1278
1458
  class EventEmission {
1279
1459
  #target;
@@ -1283,8 +1463,8 @@ class EventEmission {
1283
1463
  addEventListener(type, listener, options) {
1284
1464
  return this.#target.addEventListener(type, listener, options);
1285
1465
  }
1286
- removeEventListener(type, listener) {
1287
- this.#target.removeEventListener(type, listener);
1466
+ removeEventListener(type, listener, options) {
1467
+ this.#target.removeEventListener(type, listener, options);
1288
1468
  }
1289
1469
  dispatchEvent(event) {
1290
1470
  return this.#target.dispatchEvent(event);
@@ -1343,19 +1523,10 @@ class EventEmission {
1343
1523
  }
1344
1524
  }
1345
1525
  export {
1346
- setupEventForwarding,
1347
- pipe,
1348
- isObserved,
1349
- getOriginal,
1350
- fromEventTarget,
1351
- forwardToEventTarget,
1352
1526
  createEventTarget,
1353
1527
  SymbolObservable,
1354
- PROXY_MARKER,
1355
- Observable,
1356
- ORIGINAL_TARGET,
1357
1528
  EventEmission,
1358
1529
  BufferOverflowError
1359
1530
  };
1360
1531
 
1361
- //# debugId=444E2053CE7B039864756E2164756E21
1532
+ //# debugId=60621EDDB80DC90E64756E2164756E21