arcane-os 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +8 -8
  3. package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +29 -22
  4. package/browser-runtime/ai/ARCANE_AI_BROWSER_SPEECH_COMPONENTS.json +203 -0
  5. package/browser-runtime/ai/browser-kokoro-worker.mjs +11 -2
  6. package/browser-runtime/ai/browser-speech-artifacts.mjs +3230 -397
  7. package/browser-runtime/ai/browser-speech-providers.mjs +1141 -157
  8. package/browser-runtime/ai/browser-speech.mjs +2 -0
  9. package/browser-runtime/ai/browser-whisper-worker.mjs +11 -2
  10. package/browser-runtime/ai/model-controller.mjs +285 -95
  11. package/browser-runtime/ai/speech-worker-client.mjs +247 -32
  12. package/browser-runtime/ai/speech-worker-runtime.mjs +2310 -167
  13. package/browser-runtime/event-manager.mjs +1097 -1
  14. package/docs/architecture.md +2 -2
  15. package/docs/event-manager.md +155 -27
  16. package/docs/reference/README.md +20 -20
  17. package/docs/reference/ai/browser-speech-package-authority.json +835 -0
  18. package/docs/reference/ai/browser-speech.md +1162 -246
  19. package/docs/reference/ai/browser-wasm.md +18 -7
  20. package/docs/reference/availability-and-normalization.md +2 -2
  21. package/docs/reference/behavioral-testing.md +28 -5
  22. package/docs/reference/cli.md +115 -7
  23. package/docs/reference/core/arcane-ai-contracts.md +1 -1
  24. package/docs/reference/event-manager.md +577 -32
  25. package/docs/reference/inventory/package-api.json +478 -2
  26. package/docs/reference/inventory/runtime-components.json +86 -37
  27. package/docs/reference/inventory/runtime-modules.json +126 -49
  28. package/docs/reference/mail.md +316 -0
  29. package/docs/reference/protocols.md +143 -33
  30. package/docs/reference/runtime-components.md +192 -80
  31. package/docs/reference/runtime-modules.md +584 -70
  32. package/docs/reference/sdk-api.md +1014 -25
  33. package/package.json +5 -4
  34. package/runtime/ARCANE_RUNTIME_RELEASE.json +145 -140
  35. package/runtime/arcane/components/app-bar.html +34 -13
  36. package/runtime/arcane/components/assistant-panel.html +110 -57
  37. package/runtime/arcane/components/calculator.html +7 -4
  38. package/runtime/arcane/components/chart.html +58 -17
  39. package/runtime/arcane/components/chat.html +606 -136
  40. package/runtime/arcane/components/conversation-view.html +13 -6
  41. package/runtime/arcane/components/dashboard-config.html +96 -59
  42. package/runtime/arcane/components/data-maintenance.html +69 -14
  43. package/runtime/arcane/components/data-view.html +53 -7
  44. package/runtime/arcane/components/directory-picker.html +118 -32
  45. package/runtime/arcane/components/document-inspector.html +47 -10
  46. package/runtime/arcane/components/file-drop.html +81 -35
  47. package/runtime/arcane/components/file-inspector.html +72 -22
  48. package/runtime/arcane/components/file-manager.html +374 -79
  49. package/runtime/arcane/components/integration-settings.html +12 -5
  50. package/runtime/arcane/components/local-ai-status.html +48 -19
  51. package/runtime/arcane/components/markdown-document.html +161 -68
  52. package/runtime/arcane/components/markdown-editor.html +110 -33
  53. package/runtime/arcane/components/media-embed.html +8 -5
  54. package/runtime/arcane/components/modal.html +15 -5
  55. package/runtime/arcane/components/output-panel.html +28 -23
  56. package/runtime/arcane/components/preferences-form.html +22 -4
  57. package/runtime/arcane/components/record-timeline.html +18 -2
  58. package/runtime/arcane/components/relationship-board.html +23 -3
  59. package/runtime/arcane/components/screen-capture.html +10 -4
  60. package/runtime/arcane/components/source-code-viewer.html +76 -9
  61. package/runtime/arcane/components/source-explanation.html +23 -3
  62. package/runtime/arcane/components/speech.html +453 -131
  63. package/runtime/arcane/components/summary-strip.html +22 -11
  64. package/runtime/arcane/components/table.html +39 -21
  65. package/runtime/arcane/components/task-progress.html +79 -21
  66. package/runtime/arcane/components/terminal-workspace.html +7 -4
  67. package/runtime/arcane/components/theme-editor.html +7 -3
  68. package/runtime/arcane/components/unified-inbox.html +9 -4
  69. package/runtime/arcane/components/voice-transcription.html +244 -72
  70. package/runtime/arcane/components/weather-widget.html +5 -3
  71. package/runtime/arcane/components/web-navigator.html +48 -8
  72. package/runtime/arcane/entities/Chat.js +1 -1
  73. package/runtime/arcane/entities/User.js +110 -23
  74. package/runtime/arcane/modules/AI.js +2109 -130
  75. package/runtime/arcane/modules/AIProviderRuntime.js +720 -13
  76. package/runtime/arcane/modules/AIRuntimeState.js +109 -52
  77. package/runtime/arcane/modules/ApiModelDatabase.js +390 -17
  78. package/runtime/arcane/modules/BrowserTestSuite.js +205 -28
  79. package/runtime/arcane/modules/CalculatorEngine.js +63 -3
  80. package/runtime/arcane/modules/CommunicationAppController.js +588 -28
  81. package/runtime/arcane/modules/CommunicationHub.js +590 -10
  82. package/runtime/arcane/modules/ComponentContracts.js +235 -37
  83. package/runtime/arcane/modules/ConversationTimebox.js +152 -33
  84. package/runtime/arcane/modules/DBLS.js +40 -7
  85. package/runtime/arcane/modules/DBOPFS.js +35 -11
  86. package/runtime/arcane/modules/DataMaintenance.js +12 -2
  87. package/runtime/arcane/modules/Errors.js +65 -7
  88. package/runtime/arcane/modules/HTMLImport.js +198 -14
  89. package/runtime/arcane/modules/LocalAIReadinessController.js +208 -29
  90. package/runtime/arcane/modules/Mail.js +738 -115
  91. package/runtime/arcane/modules/MailOutbox.mjs +1395 -0
  92. package/runtime/arcane/modules/MailTransport.mjs +197 -39
  93. package/runtime/arcane/modules/Ollama.js +36 -1
  94. package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +583 -7
  95. package/runtime/arcane/modules/PreferenceStore.js +367 -33
  96. package/runtime/arcane/modules/RecordReviewStore.js +322 -23
  97. package/runtime/arcane/modules/ScreenCapture.js +1397 -15
  98. package/runtime/arcane/modules/SpeechPlayback.js +438 -41
  99. package/runtime/arcane/modules/TerminalClient.js +277 -12
  100. package/runtime/arcane/modules/ThemeBootstrap.js +80 -6
  101. package/runtime/arcane/modules/ThemeManager.js +39 -7
  102. package/runtime/arcane/modules/TimeGuard.js +131 -20
  103. package/runtime/arcane/modules/WaitForComponent.js +386 -33
  104. package/schemas/arcane-lock.schema.json +2 -2
  105. package/src/cli/main.mjs +435 -9
  106. package/src/event-manager.mjs +1097 -1
  107. package/src/import-map.mjs +21 -3
  108. package/src/index.mjs +13 -0
  109. package/src/installed-sdk-runtime.mjs +112 -0
  110. package/src/mail-api.mjs +22 -0
  111. package/src/mail-credentials.mjs +667 -0
  112. package/src/mail-server.mjs +1769 -0
  113. package/src/mail.mjs +261 -0
  114. package/src/sdk-browser-runtime.mjs +85 -41
  115. package/src/testing-loader.mjs +7 -0
  116. package/src/toolchain.mjs +3 -0
  117. package/src/workspace.mjs +1 -1
@@ -13,6 +13,10 @@ export {
13
13
  } from './dom-event-instrumentation.mjs';
14
14
 
15
15
  export const ARCANE_EVENT_STACK_PROTOCOL='arcane-event-stack/1';
16
+ export const ARCANE_EVENT_AUTHORITY_PROTOCOL='arcane-event-authority/1';
17
+ export const ARCANE_EVENT_OCCURRENCE_PROTOCOL='arcane-event-occurrence/1';
18
+ export const ARCANE_EVENT_SOURCE_PROTOCOL='arcane-event-source/1';
19
+ export const ARCANE_EVENT_AUTHORITY_BRAND=Symbol.for('arcane-os.arcane-events-authority');
16
20
  export const TIME_TRAVEL_SEEK_EVENT='arcane.time-travel.seek';
17
21
  export const PLAYBACK_STARTED_EVENT='arcane.time-travel.playback.started';
18
22
  export const PLAYBACK_RECORD_EVENT='arcane.time-travel.playback.record';
@@ -21,6 +25,76 @@ export const PLAYBACK_CANCELLED_EVENT='arcane.time-travel.playback.cancelled';
21
25
  export const PLAYBACK_FAILED_EVENT='arcane.time-travel.playback.failed';
22
26
  export const TIME_TRAVEL_OVERFLOW_EVENT='arcane.time-travel.overflow';
23
27
 
28
+ export const ARCANE_EVENT_AUTHORITY_KIND='arcane-event-authority';
29
+ export const ARCANE_EVENT_SOURCE_KIND='arcane-event-source';
30
+ export const ARCANE_EVENT_LISTENER_ERROR_EVENT='arcane.event.listener.error';
31
+ export const ARCANE_EVENT_SOURCE_DISPOSED_EVENT='arcane.event.source.disposed';
32
+ const ARCANE_EVENT_TARGET_COMPATIBILITY_SOURCE='event-target-compatibility';
33
+ const ARCANE_EVENT_NAME_PATTERN=/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*$/u;
34
+ const ARCANE_EVENT_CHANNEL_PREFIX='arcane.event.authority.internal:';
35
+ const ARCANE_EVENT_PROJECTION_KEYS=Object.freeze([
36
+ 'occurrenceId','arcaneSource','instanceId','operationId'
37
+ ]);
38
+ const ARCANE_EVENT_REQUIRED_AUTHORITY_API=Object.freeze([
39
+ 'on','once','off','reset','emit','instrument','forward','subscribe','createSource',
40
+ 'projectDOMEvent','isOccurrence','addEventListener','removeEventListener','dispatchEvent'
41
+ ]);
42
+ const EVENT_MANAGER_BUS_ON=Symbol('EventManager.busOn');
43
+ const EVENT_MANAGER_BUS_OFF=Symbol('EventManager.busOff');
44
+ const EVENT_MANAGER_DISPATCH=Symbol('EventManager.dispatch');
45
+
46
+ const ARCANE_EVENT_ERRORS=Object.freeze({
47
+ ARCANE_EVENT_AUTHORITY_ACCESSOR_COLLISION:
48
+ 'globalThis.arcaneEvents must be an own data property.',
49
+ ARCANE_EVENT_AUTHORITY_VALUE_COLLISION:
50
+ 'globalThis.arcaneEvents is occupied by an unbranded value.',
51
+ ARCANE_EVENT_AUTHORITY_DESCRIPTOR_MISMATCH:
52
+ 'The globalThis.arcaneEvents property, authority brand, or protocol descriptor is incompatible.',
53
+ ARCANE_EVENT_AUTHORITY_PROTOCOL_MISMATCH:
54
+ 'globalThis.arcaneEvents uses an incompatible authority protocol.',
55
+ ARCANE_EVENT_AUTHORITY_API_MISMATCH:
56
+ 'globalThis.arcaneEvents does not expose the required authority API.',
57
+ ARCANE_EVENT_AUTHORITY_INSTALL_FAILED:
58
+ 'The Arcane event authority could not be installed on globalThis.',
59
+ ARCANE_EVENT_SOURCE_INVALID:
60
+ 'Arcane event source options are invalid.',
61
+ ARCANE_EVENT_SOURCE_ALREADY_REGISTERED:
62
+ 'The owner already has an active Arcane event source.',
63
+ ARCANE_EVENT_SOURCE_DISPOSED:
64
+ 'The Arcane event source is disposed.',
65
+ ARCANE_EVENT_SOURCE_EVENT_TYPE_UNDECLARED:
66
+ 'The Arcane event source cannot publish an undeclared event type.',
67
+ ARCANE_EVENT_COMPATIBILITY_DETAIL_INVALID:
68
+ 'Arcane event compatibility detail must be immutable or safely shallow-copyable.',
69
+ ARCANE_EVENT_OCCURRENCE_INVALID:
70
+ 'The Arcane event occurrence value or creation options are invalid.',
71
+ ARCANE_EVENT_OCCURRENCE_SEQUENCE_EXHAUSTED:
72
+ 'The Arcane event occurrence sequence is exhausted.',
73
+ ARCANE_EVENT_SOURCE_SEQUENCE_EXHAUSTED:
74
+ 'The Arcane event source sequence is exhausted.',
75
+ ARCANE_EVENT_LISTENER_CALLBACK_FAILED:
76
+ 'An Arcane event listener threw during observational delivery.',
77
+ ARCANE_EVENT_DOM_DETAIL_COLLISION:
78
+ 'Arcane DOM projection metadata conflicts with compatibility detail.',
79
+ ARCANE_EVENT_DOM_TARGET_INVALID:
80
+ 'Arcane DOM projection requires a target with dispatchEvent and CustomEvent support.',
81
+ ARCANE_EVENT_DOM_OPTIONS_INVALID:
82
+ 'Arcane DOM projection options are invalid.',
83
+ ARCANE_EVENT_SUBSCRIPTION_TYPE_INVALID:
84
+ 'Arcane event subscription type must be a nonempty trimmed string.',
85
+ ARCANE_EVENT_SUBSCRIPTION_HANDLER_INVALID:
86
+ 'Arcane event subscription handler must be a function or EventListener object.',
87
+ ARCANE_EVENT_SUBSCRIPTION_OPTIONS_INVALID:
88
+ 'Arcane event subscription options are invalid.',
89
+ ARCANE_EVENT_SUBSCRIPTION_SIGNAL_INVALID:
90
+ 'Arcane event subscription signal must be an AbortSignal.',
91
+ ARCANE_EVENT_DISPATCH_EVENT_INVALID:
92
+ 'arcaneEvents.dispatchEvent requires an Event-like object with a valid type and data detail.'
93
+ });
94
+ export const ARCANE_EVENT_ERROR_CODES=Object.freeze(Object.fromEntries(
95
+ Object.keys(ARCANE_EVENT_ERRORS).map(code=>[code,code])
96
+ ));
97
+
24
98
  const SENSITIVE_KEY_PATTERN=/(?:authorization|cookie|credential|pass(?:word|phrase)?|private.?key|secret|session.?token|token|api.?key)/iu;
25
99
  const PRIVATE_CONTENT_KEY_PATTERN=/^(?:data|detail|key)$/iu;
26
100
  const INTERNAL_STACK_PATTERN=/(?:EventManager\.|#dispatch|event-manager\.mjs)/u;
@@ -899,6 +973,20 @@ export class EventManager{
899
973
  get history(){return Object.freeze([...this.#history]);}
900
974
  get domInstrumentation(){return this.#domInstrumentation;}
901
975
 
976
+ [EVENT_MANAGER_BUS_ON](type,handler,once=false){
977
+ this.#bus.on(type,handler,once);
978
+ return this;
979
+ }
980
+
981
+ [EVENT_MANAGER_BUS_OFF](type,handler='*'){
982
+ this.#bus.off(type,handler);
983
+ return this;
984
+ }
985
+
986
+ [EVENT_MANAGER_DISPATCH](type,payload,metadata={}){
987
+ return this.#dispatch(type,[payload],metadata);
988
+ }
989
+
902
990
  on(type,handler,once=false){
903
991
  this.#bus.on(type,handler,once);
904
992
  return this;
@@ -1339,4 +1427,1012 @@ export function createEventManager(options){
1339
1427
  return new EventManager(options);
1340
1428
  }
1341
1429
 
1342
- export const arcaneEvents=new EventManager();
1430
+ function eventAuthorityError(code,cause,ErrorType=Error){
1431
+ const message=ARCANE_EVENT_ERRORS[code]??'The Arcane event authority failed.';
1432
+ const error=cause===undefined
1433
+ ?new ErrorType(message)
1434
+ :new ErrorType(message,{cause});
1435
+ error.code=code;
1436
+ return error;
1437
+ }
1438
+
1439
+ function eventName(value,code='ARCANE_EVENT_SUBSCRIPTION_TYPE_INVALID'){
1440
+ if(typeof value!=='string'
1441
+ ||value.trim()!==value
1442
+ ||value.length<1
1443
+ ||value.length>128
1444
+ ||!ARCANE_EVENT_NAME_PATTERN.test(value)){
1445
+ throw eventAuthorityError(code,undefined,TypeError);
1446
+ }
1447
+ return value;
1448
+ }
1449
+
1450
+ function eventDataOptions(value,allowed,code){
1451
+ if(value===undefined)return Object.create(null);
1452
+ if(!value||typeof value!=='object'||Array.isArray(value)){
1453
+ throw eventAuthorityError(code,undefined,TypeError);
1454
+ }
1455
+ const prototype=Object.getPrototypeOf(value);
1456
+ if(prototype!==Object.prototype&&prototype!==null){
1457
+ throw eventAuthorityError(code,undefined,TypeError);
1458
+ }
1459
+ const result=Object.create(null);
1460
+ for(const key of Reflect.ownKeys(value)){
1461
+ if(typeof key!=='string'||!allowed.has(key)){
1462
+ throw eventAuthorityError(code,undefined,TypeError);
1463
+ }
1464
+ const descriptor=Object.getOwnPropertyDescriptor(value,key);
1465
+ if(!descriptor||!('value' in descriptor)){
1466
+ throw eventAuthorityError(code,undefined,TypeError);
1467
+ }
1468
+ result[key]=descriptor.value;
1469
+ }
1470
+ return result;
1471
+ }
1472
+
1473
+ function eventSignal(value){
1474
+ if(value===undefined||value===null)return null;
1475
+ if(!value
1476
+ ||typeof value!=='object'
1477
+ ||typeof value.aborted!=='boolean'
1478
+ ||typeof value.addEventListener!=='function'
1479
+ ||typeof value.removeEventListener!=='function'){
1480
+ throw eventAuthorityError(
1481
+ 'ARCANE_EVENT_SUBSCRIPTION_SIGNAL_INVALID',
1482
+ undefined,
1483
+ TypeError
1484
+ );
1485
+ }
1486
+ return value;
1487
+ }
1488
+
1489
+ function eventListener(value){
1490
+ if(typeof value==='function'){
1491
+ return Object.freeze({
1492
+ identity:value,
1493
+ invoke(event,thisArg,...rest){return value.call(thisArg,event,...rest);}
1494
+ });
1495
+ }
1496
+ if(value&&typeof value==='object'&&typeof value.handleEvent==='function'){
1497
+ return Object.freeze({
1498
+ identity:value,
1499
+ invoke(event){return value.handleEvent(event);}
1500
+ });
1501
+ }
1502
+ throw eventAuthorityError(
1503
+ 'ARCANE_EVENT_SUBSCRIPTION_HANDLER_INVALID',
1504
+ undefined,
1505
+ TypeError
1506
+ );
1507
+ }
1508
+
1509
+ function eventTargetListener(value){
1510
+ if(typeof value==='function'){
1511
+ return Object.freeze({
1512
+ identity:value,
1513
+ invoke(event,thisArg,...rest){return value.call(thisArg,event,...rest);}
1514
+ });
1515
+ }
1516
+ if(value&&typeof value==='object'&&typeof value.handleEvent==='function'){
1517
+ return Object.freeze({
1518
+ identity:value,
1519
+ invoke(event){return value.handleEvent(event);}
1520
+ });
1521
+ }
1522
+ return null;
1523
+ }
1524
+
1525
+ function compatibilityDetail(value){
1526
+ if(value===null||(typeof value!=='object'&&typeof value!=='function'))return value;
1527
+ if(Object.isFrozen(value))return value;
1528
+ if(Array.isArray(value))return Object.freeze(value.slice());
1529
+ const prototype=Object.getPrototypeOf(value);
1530
+ if(prototype!==Object.prototype&&prototype!==null)return value;
1531
+ const copy=prototype===null?Object.create(null):{};
1532
+ for(const key of Reflect.ownKeys(value)){
1533
+ const descriptor=Object.getOwnPropertyDescriptor(value,key);
1534
+ if(!descriptor||!('value' in descriptor)){
1535
+ throw eventAuthorityError(
1536
+ 'ARCANE_EVENT_COMPATIBILITY_DETAIL_INVALID',
1537
+ undefined,
1538
+ TypeError
1539
+ );
1540
+ }
1541
+ Object.defineProperty(copy,key,{
1542
+ value:descriptor.value,
1543
+ enumerable:descriptor.enumerable,
1544
+ configurable:false,
1545
+ writable:false
1546
+ });
1547
+ }
1548
+ return Object.freeze(copy);
1549
+ }
1550
+
1551
+ function eventTargetOptions(value){
1552
+ if(value===undefined)return Object.freeze({capture:false,once:false,signal:null});
1553
+ if(typeof value==='boolean'){
1554
+ return Object.freeze({capture:value,once:false,signal:null});
1555
+ }
1556
+ const options=eventDataOptions(
1557
+ value,
1558
+ new Set(['capture','once','passive','signal']),
1559
+ 'ARCANE_EVENT_SUBSCRIPTION_OPTIONS_INVALID'
1560
+ );
1561
+ for(const key of ['capture','once','passive']){
1562
+ if(options[key]!==undefined&&typeof options[key]!=='boolean'){
1563
+ throw eventAuthorityError(
1564
+ 'ARCANE_EVENT_SUBSCRIPTION_OPTIONS_INVALID',
1565
+ undefined,
1566
+ TypeError
1567
+ );
1568
+ }
1569
+ }
1570
+ return Object.freeze({
1571
+ capture:options.capture===true,
1572
+ once:options.once===true,
1573
+ signal:eventSignal(options.signal)
1574
+ });
1575
+ }
1576
+
1577
+ function subscriptionOptions(value){
1578
+ const options=eventDataOptions(
1579
+ value,
1580
+ new Set(['once','signal']),
1581
+ 'ARCANE_EVENT_SUBSCRIPTION_OPTIONS_INVALID'
1582
+ );
1583
+ if(options.once!==undefined&&typeof options.once!=='boolean'){
1584
+ throw eventAuthorityError(
1585
+ 'ARCANE_EVENT_SUBSCRIPTION_OPTIONS_INVALID',
1586
+ undefined,
1587
+ TypeError
1588
+ );
1589
+ }
1590
+ return Object.freeze({
1591
+ once:options.once===true,
1592
+ signal:eventSignal(options.signal)
1593
+ });
1594
+ }
1595
+
1596
+ function defineDisposable(unsubscribe){
1597
+ Object.defineProperty(unsubscribe,'dispose',{
1598
+ value:unsubscribe,
1599
+ enumerable:false,
1600
+ configurable:false,
1601
+ writable:false
1602
+ });
1603
+ return unsubscribe;
1604
+ }
1605
+
1606
+ function eventLikeRecord(value){
1607
+ try{
1608
+ if(!value||typeof value!=='object'||Array.isArray(value))throw new TypeError();
1609
+ const EventConstructor=globalThis.Event;
1610
+ if(typeof EventConstructor==='function'&&value instanceof EventConstructor){
1611
+ if(!('detail' in value))throw new TypeError();
1612
+ return {
1613
+ type:eventName(value.type,'ARCANE_EVENT_DISPATCH_EVENT_INVALID'),
1614
+ detail:value.detail,
1615
+ cancelable:value.cancelable===true,
1616
+ defaultPrevented:value.defaultPrevented===true,
1617
+ preventDefault:typeof value.preventDefault==='function'
1618
+ ?()=>value.preventDefault()
1619
+ :null
1620
+ };
1621
+ }
1622
+ const typeDescriptor=Object.getOwnPropertyDescriptor(value,'type');
1623
+ const detailDescriptor=Object.getOwnPropertyDescriptor(value,'detail');
1624
+ const cancelableDescriptor=Object.getOwnPropertyDescriptor(value,'cancelable');
1625
+ const preventedDescriptor=Object.getOwnPropertyDescriptor(value,'defaultPrevented');
1626
+ if(!typeDescriptor||!('value' in typeDescriptor)
1627
+ ||!detailDescriptor||!('value' in detailDescriptor)
1628
+ ||(cancelableDescriptor&&!('value' in cancelableDescriptor))
1629
+ ||(preventedDescriptor&&!('value' in preventedDescriptor))){
1630
+ throw new TypeError();
1631
+ }
1632
+ return {
1633
+ type:eventName(typeDescriptor.value,'ARCANE_EVENT_DISPATCH_EVENT_INVALID'),
1634
+ detail:detailDescriptor?.value,
1635
+ cancelable:cancelableDescriptor?.value===true,
1636
+ defaultPrevented:preventedDescriptor?.value===true,
1637
+ preventDefault:typeof value.preventDefault==='function'
1638
+ ?()=>value.preventDefault()
1639
+ :null
1640
+ };
1641
+ }catch(error){
1642
+ if(error?.code==='ARCANE_EVENT_DISPATCH_EVENT_INVALID')throw error;
1643
+ throw eventAuthorityError(
1644
+ 'ARCANE_EVENT_DISPATCH_EVENT_INVALID',
1645
+ error,
1646
+ TypeError
1647
+ );
1648
+ }
1649
+ }
1650
+
1651
+ function createArcaneEventAuthority(){
1652
+ const manager=new EventManager();
1653
+ const sourceByOwner=new WeakMap();
1654
+ const occurrences=new WeakSet();
1655
+ const canonicalByView=new WeakMap();
1656
+ const compatibilityByOccurrence=new WeakMap();
1657
+ const sourceRecordByOccurrence=new WeakMap();
1658
+ const authorityTargetListeners=[];
1659
+ const legacyListeners=[];
1660
+ let occurrenceSequence=0;
1661
+ let sourceSequence=0;
1662
+ let reportingListenerError=false;
1663
+ let canonicalDispatchDepth=0;
1664
+ const pendingChannelRemovals=[];
1665
+
1666
+ const descriptor=Object.freeze({
1667
+ kind:ARCANE_EVENT_AUTHORITY_KIND,
1668
+ protocol:ARCANE_EVENT_AUTHORITY_PROTOCOL,
1669
+ realm:'current'
1670
+ });
1671
+
1672
+ function nextOccurrenceId(){
1673
+ if(occurrenceSequence===Number.MAX_SAFE_INTEGER){
1674
+ throw eventAuthorityError('ARCANE_EVENT_OCCURRENCE_SEQUENCE_EXHAUSTED');
1675
+ }
1676
+ occurrenceSequence+=1;
1677
+ return `arcane-event-${occurrenceSequence.toString(36)}`;
1678
+ }
1679
+
1680
+ function nextSourceId(){
1681
+ if(sourceSequence===Number.MAX_SAFE_INTEGER){
1682
+ throw eventAuthorityError('ARCANE_EVENT_SOURCE_SEQUENCE_EXHAUSTED');
1683
+ }
1684
+ sourceSequence+=1;
1685
+ return `arcane-source-${sourceSequence.toString(36)}`;
1686
+ }
1687
+
1688
+ function directListenerFailure(error){
1689
+ try{
1690
+ if(typeof globalThis.reportError==='function'){
1691
+ globalThis.reportError(error);
1692
+ return;
1693
+ }
1694
+ }catch{}
1695
+ try{globalThis.console?.error?.('Arcane event listener failed.',error);}
1696
+ catch{}
1697
+ }
1698
+
1699
+ function publicEventDetail(value){
1700
+ return frozenSnapshot(value??{}, {
1701
+ redactSensitive:true,
1702
+ captureStacks:false,
1703
+ maxDepth:16,
1704
+ maxEntries:256,
1705
+ maxStringLength:2_048
1706
+ });
1707
+ }
1708
+
1709
+ function canonicalOccurrence({
1710
+ type,
1711
+ source,
1712
+ instanceId,
1713
+ operationId,
1714
+ detail,
1715
+ cancelable,
1716
+ defaultPrevented=false
1717
+ }){
1718
+ let prevented=cancelable&&defaultPrevented;
1719
+ const occurrence={};
1720
+ Object.defineProperties(occurrence,{
1721
+ protocol:{value:ARCANE_EVENT_OCCURRENCE_PROTOCOL,enumerable:true},
1722
+ occurrenceId:{value:nextOccurrenceId(),enumerable:true},
1723
+ type:{value:type,enumerable:true},
1724
+ source:{value:source,enumerable:true},
1725
+ instanceId:{value:instanceId,enumerable:true},
1726
+ operationId:{value:operationId,enumerable:true},
1727
+ detail:{value:detail,enumerable:true},
1728
+ cancelable:{value:cancelable,enumerable:true},
1729
+ defaultPrevented:{get(){return prevented;},enumerable:true},
1730
+ preventDefault:{
1731
+ value:function preventArcaneEventDefault(){
1732
+ if(cancelable)prevented=true;
1733
+ },
1734
+ enumerable:true
1735
+ }
1736
+ });
1737
+ Object.freeze(occurrence);
1738
+ occurrences.add(occurrence);
1739
+ return occurrence;
1740
+ }
1741
+
1742
+ function compatibilityView(occurrence,detail,target=null){
1743
+ const view={};
1744
+ Object.defineProperties(view,{
1745
+ protocol:{value:occurrence.protocol,enumerable:true},
1746
+ occurrenceId:{value:occurrence.occurrenceId,enumerable:true},
1747
+ type:{value:occurrence.type,enumerable:true},
1748
+ source:{value:occurrence.source,enumerable:true},
1749
+ instanceId:{value:occurrence.instanceId,enumerable:true},
1750
+ operationId:{value:occurrence.operationId,enumerable:true},
1751
+ detail:{value:detail,enumerable:true},
1752
+ target:{value:target,enumerable:true},
1753
+ currentTarget:{value:target,enumerable:true},
1754
+ cancelable:{value:occurrence.cancelable,enumerable:true},
1755
+ defaultPrevented:{get(){return occurrence.defaultPrevented;},enumerable:true},
1756
+ preventDefault:{value:()=>occurrence.preventDefault(),enumerable:true}
1757
+ });
1758
+ Object.freeze(view);
1759
+ canonicalByView.set(view,occurrence);
1760
+ return view;
1761
+ }
1762
+
1763
+ function removeChannelListener(channel,handler){
1764
+ if(canonicalDispatchDepth>0){
1765
+ pendingChannelRemovals.push(Object.freeze({channel,handler}));
1766
+ return;
1767
+ }
1768
+ manager[EVENT_MANAGER_BUS_OFF](channel,handler);
1769
+ }
1770
+
1771
+ function flushChannelRemovals(){
1772
+ if(canonicalDispatchDepth>0)return;
1773
+ for(const {channel,handler} of pendingChannelRemovals.splice(0)){
1774
+ manager[EVENT_MANAGER_BUS_OFF](channel,handler);
1775
+ }
1776
+ }
1777
+
1778
+ function dispatchChannel(channel,value,metadata){
1779
+ canonicalDispatchDepth+=1;
1780
+ try{return manager[EVENT_MANAGER_DISPATCH](channel,value,metadata);}
1781
+ finally{
1782
+ canonicalDispatchDepth-=1;
1783
+ flushChannelRemovals();
1784
+ }
1785
+ }
1786
+
1787
+ function subscribeChannel(channel,handler,options,{
1788
+ thisArg=undefined,
1789
+ sourceRecord=null,
1790
+ select=value=>value,
1791
+ onRemove=null
1792
+ }={}){
1793
+ const admitted=eventListener(handler);
1794
+ const normalized=subscriptionOptions(options);
1795
+ let active=false;
1796
+ let abortHandler=null;
1797
+ function unsubscribeArcaneEvent(){
1798
+ if(!active)return false;
1799
+ active=false;
1800
+ removeChannelListener(channel,deliverArcaneEvent);
1801
+ if(abortHandler){
1802
+ normalized.signal?.removeEventListener('abort',abortHandler);
1803
+ abortHandler=null;
1804
+ }
1805
+ onRemove?.(unsubscribeArcaneEvent);
1806
+ return true;
1807
+ }
1808
+ defineDisposable(unsubscribeArcaneEvent);
1809
+ if(normalized.signal?.aborted)return unsubscribeArcaneEvent;
1810
+ function deliverArcaneEvent(value){
1811
+ if(!active)return;
1812
+ if(normalized.once)unsubscribeArcaneEvent();
1813
+ const delivered=select(value);
1814
+ try{admitted.invoke(delivered,thisArg);}
1815
+ catch(error){reportListenerFailure(error,delivered,sourceRecord);}
1816
+ }
1817
+ manager[EVENT_MANAGER_BUS_ON](channel,deliverArcaneEvent);
1818
+ active=true;
1819
+ if(normalized.signal){
1820
+ abortHandler=unsubscribeArcaneEvent;
1821
+ normalized.signal.addEventListener('abort',abortHandler,{once:true});
1822
+ }
1823
+ return unsubscribeArcaneEvent;
1824
+ }
1825
+
1826
+ function reportListenerFailure(error,event,sourceRecord){
1827
+ const occurrence=occurrences.has(event)
1828
+ ?event
1829
+ :canonicalByView.get(event)??null;
1830
+ const ownerRecord=sourceRecord??(occurrence
1831
+ ?sourceRecordByOccurrence.get(occurrence)??null
1832
+ :null);
1833
+ if(reportingListenerError){
1834
+ directListenerFailure(error);
1835
+ return;
1836
+ }
1837
+ reportingListenerError=true;
1838
+ let errorOccurrence=null;
1839
+ try{
1840
+ const detail=Object.freeze({
1841
+ code:'ARCANE_EVENT_LISTENER_CALLBACK_FAILED',
1842
+ reason:'listener-threw',
1843
+ eventType:occurrence?.type??null,
1844
+ occurrenceId:occurrence?.occurrenceId??null,
1845
+ source:occurrence?.source??ownerRecord?.source??'event-authority',
1846
+ instanceId:occurrence?.instanceId??ownerRecord?.instanceId??null,
1847
+ operationId:occurrence?.operationId??null
1848
+ });
1849
+ errorOccurrence=dispatchOccurrence({
1850
+ type:ARCANE_EVENT_LISTENER_ERROR_EVENT,
1851
+ sourceRecord:null,
1852
+ source:'event-authority',
1853
+ instanceId:'arcane-source-authority',
1854
+ compatibility:detail,
1855
+ publicDetail:detail,
1856
+ operationId:occurrence?.operationId??null,
1857
+ cancelable:false
1858
+ }).occurrence;
1859
+ }catch(reportingError){
1860
+ directListenerFailure(reportingError);
1861
+ }
1862
+ directListenerFailure(error);
1863
+ try{ownerRecord?.onListenerError?.(error,errorOccurrence);}
1864
+ catch(callbackError){directListenerFailure(callbackError);}
1865
+ reportingListenerError=false;
1866
+ }
1867
+
1868
+ function globalChannel(type){return `${ARCANE_EVENT_CHANNEL_PREFIX}global:${type}`;}
1869
+ function sourceChannel(instanceId,type){
1870
+ return `${ARCANE_EVENT_CHANNEL_PREFIX}source:${instanceId}:${type}`;
1871
+ }
1872
+
1873
+ function dispatchOccurrence({
1874
+ type,
1875
+ sourceRecord,
1876
+ source,
1877
+ instanceId,
1878
+ compatibility,
1879
+ publicDetail,
1880
+ operationId=null,
1881
+ cancelable=false,
1882
+ defaultPrevented=false
1883
+ }){
1884
+ const admittedType=eventName(type,'ARCANE_EVENT_OCCURRENCE_INVALID');
1885
+ const admittedCompatibility=compatibilityDetail(compatibility);
1886
+ const occurrence=canonicalOccurrence({
1887
+ type:admittedType,
1888
+ source,
1889
+ instanceId,
1890
+ operationId,
1891
+ detail:publicEventDetail(publicDetail),
1892
+ cancelable,
1893
+ defaultPrevented
1894
+ });
1895
+ const view=compatibilityView(
1896
+ occurrence,
1897
+ admittedCompatibility,
1898
+ sourceRecord?.owner??null
1899
+ );
1900
+ compatibilityByOccurrence.set(occurrence,admittedCompatibility);
1901
+ if(sourceRecord)sourceRecordByOccurrence.set(occurrence,sourceRecord);
1902
+ dispatchChannel(globalChannel(admittedType),occurrence,{
1903
+ source:'event-authority',
1904
+ category:'semantic'
1905
+ });
1906
+ if(sourceRecord){
1907
+ dispatchChannel(
1908
+ sourceChannel(instanceId,admittedType),
1909
+ view,
1910
+ {source,category:'semantic',correlationId:operationId}
1911
+ );
1912
+ }
1913
+ return Object.freeze({occurrence,accepted:!occurrence.defaultPrevented});
1914
+ }
1915
+
1916
+ function subscribe(type,handler,options){
1917
+ const admittedType=eventName(type);
1918
+ return subscribeChannel(globalChannel(admittedType),handler,options,{
1919
+ thisArg:manager
1920
+ });
1921
+ }
1922
+
1923
+ function addEventTargetListener(registrations,type,handler,options,subscribeWith,thisArg){
1924
+ const admittedType=eventName(type);
1925
+ const admitted=eventTargetListener(handler);
1926
+ if(!admitted)return;
1927
+ const normalized=eventTargetOptions(options);
1928
+ if(normalized.signal?.aborted)return;
1929
+ if(registrations.some(record=>record.type===admittedType
1930
+ &&record.identity===admitted.identity
1931
+ &&record.capture===normalized.capture))return;
1932
+ const record={
1933
+ type:admittedType,
1934
+ identity:admitted.identity,
1935
+ capture:normalized.capture,
1936
+ unsubscribe:null
1937
+ };
1938
+ const unsubscribe=subscribeWith(
1939
+ admittedType,
1940
+ function deliverEventTargetOccurrence(event){
1941
+ if(normalized.once){
1942
+ const index=registrations.indexOf(record);
1943
+ if(index>=0)registrations.splice(index,1);
1944
+ record.unsubscribe?.();
1945
+ }
1946
+ return admitted.invoke(event,thisArg);
1947
+ },
1948
+ {once:false,signal:normalized.signal}
1949
+ );
1950
+ record.unsubscribe=unsubscribe;
1951
+ registrations.push(record);
1952
+ if(normalized.signal){
1953
+ normalized.signal.addEventListener('abort',function removeAbortedEventTargetRecord(){
1954
+ const index=registrations.indexOf(record);
1955
+ if(index>=0)registrations.splice(index,1);
1956
+ },{once:true});
1957
+ }
1958
+ }
1959
+
1960
+ function removeEventTargetListener(registrations,type,handler,options){
1961
+ const admittedType=eventName(type);
1962
+ const admitted=eventTargetListener(handler);
1963
+ if(!admitted)return;
1964
+ const normalized=eventTargetOptions(options);
1965
+ const index=registrations.findIndex(record=>record.type===admittedType
1966
+ &&record.identity===admitted.identity
1967
+ &&record.capture===normalized.capture);
1968
+ if(index<0)return;
1969
+ const [record]=registrations.splice(index,1);
1970
+ record.unsubscribe();
1971
+ }
1972
+
1973
+ function dispatchEventLike(value,sourceRecord=null){
1974
+ const admitted=eventLikeRecord(value);
1975
+ if(sourceRecord&&!sourceRecord.eventTypes.has(admitted.type)){
1976
+ throw eventAuthorityError('ARCANE_EVENT_SOURCE_EVENT_TYPE_UNDECLARED');
1977
+ }
1978
+ const detail=compatibilityDetail(admitted.detail);
1979
+ const operationId=detail&&typeof detail==='object'
1980
+ &&typeof detail.operationId==='string'
1981
+ &&detail.operationId.trim()===detail.operationId
1982
+ &&detail.operationId
1983
+ ?detail.operationId
1984
+ :null;
1985
+ const publication=dispatchOccurrence({
1986
+ type:admitted.type,
1987
+ sourceRecord,
1988
+ source:sourceRecord?.source??ARCANE_EVENT_TARGET_COMPATIBILITY_SOURCE,
1989
+ instanceId:sourceRecord?.instanceId??'arcane-source-compatibility',
1990
+ compatibility:detail,
1991
+ publicDetail:detail,
1992
+ operationId,
1993
+ cancelable:admitted.cancelable,
1994
+ defaultPrevented:admitted.defaultPrevented
1995
+ });
1996
+ if(publication.occurrence.defaultPrevented)admitted.preventDefault?.();
1997
+ return !publication.occurrence.defaultPrevented;
1998
+ }
1999
+
2000
+ function createSource(owner,options){
2001
+ if(!owner||(typeof owner!=='object'&&typeof owner!=='function')){
2002
+ throw eventAuthorityError('ARCANE_EVENT_SOURCE_INVALID',undefined,TypeError);
2003
+ }
2004
+ const admitted=eventDataOptions(
2005
+ options,
2006
+ new Set(['source','eventTypes','onListenerError']),
2007
+ 'ARCANE_EVENT_SOURCE_INVALID'
2008
+ );
2009
+ const source=eventName(admitted.source,'ARCANE_EVENT_SOURCE_INVALID');
2010
+ if(!Array.isArray(admitted.eventTypes)
2011
+ ||admitted.eventTypes.length<1
2012
+ ||admitted.eventTypes.length>256){
2013
+ throw eventAuthorityError('ARCANE_EVENT_SOURCE_INVALID',undefined,TypeError);
2014
+ }
2015
+ const eventTypes=[];
2016
+ const seen=new Set();
2017
+ for(const type of admitted.eventTypes){
2018
+ const normalized=eventName(type,'ARCANE_EVENT_SOURCE_INVALID');
2019
+ if(seen.has(normalized)){
2020
+ throw eventAuthorityError('ARCANE_EVENT_SOURCE_INVALID',undefined,TypeError);
2021
+ }
2022
+ seen.add(normalized);
2023
+ eventTypes.push(normalized);
2024
+ }
2025
+ if(admitted.onListenerError!==undefined
2026
+ &&typeof admitted.onListenerError!=='function'){
2027
+ throw eventAuthorityError('ARCANE_EVENT_SOURCE_INVALID',undefined,TypeError);
2028
+ }
2029
+ const existing=sourceByOwner.get(owner);
2030
+ if(existing&&!existing.disposed){
2031
+ throw eventAuthorityError('ARCANE_EVENT_SOURCE_ALREADY_REGISTERED');
2032
+ }
2033
+ const record={
2034
+ owner,
2035
+ source,
2036
+ instanceId:nextSourceId(),
2037
+ eventTypes:new Set(eventTypes),
2038
+ onListenerError:admitted.onListenerError??null,
2039
+ subscriptions:new Set(),
2040
+ targetListeners:[],
2041
+ disposing:false,
2042
+ disposed:false,
2043
+ handle:null
2044
+ };
2045
+ function assertOpen(){
2046
+ if(record.disposing||record.disposed){
2047
+ throw eventAuthorityError('ARCANE_EVENT_SOURCE_DISPOSED');
2048
+ }
2049
+ }
2050
+ function sourceSubscribe(type,handler,subscribeOptions){
2051
+ assertOpen();
2052
+ const admittedType=eventName(type);
2053
+ if(!record.eventTypes.has(admittedType)
2054
+ &&admittedType!==ARCANE_EVENT_SOURCE_DISPOSED_EVENT){
2055
+ throw eventAuthorityError('ARCANE_EVENT_SOURCE_EVENT_TYPE_UNDECLARED');
2056
+ }
2057
+ let unsubscribe;
2058
+ unsubscribe=subscribeChannel(
2059
+ sourceChannel(record.instanceId,admittedType),
2060
+ handler,
2061
+ subscribeOptions,
2062
+ {
2063
+ thisArg:record.owner,
2064
+ sourceRecord:record,
2065
+ onRemove(){record.subscriptions.delete(unsubscribe);}
2066
+ }
2067
+ );
2068
+ record.subscriptions.add(unsubscribe);
2069
+ return unsubscribe;
2070
+ }
2071
+ function dispatch(type,detail,dispatchOptions){
2072
+ assertOpen();
2073
+ const admittedType=eventName(type,'ARCANE_EVENT_SOURCE_EVENT_TYPE_UNDECLARED');
2074
+ if(!record.eventTypes.has(admittedType)){
2075
+ throw eventAuthorityError('ARCANE_EVENT_SOURCE_EVENT_TYPE_UNDECLARED');
2076
+ }
2077
+ const normalized=eventDataOptions(
2078
+ dispatchOptions,
2079
+ new Set(['operationId','publicDetail','cancelable']),
2080
+ 'ARCANE_EVENT_OCCURRENCE_INVALID'
2081
+ );
2082
+ const operationId=normalized.operationId??null;
2083
+ if(operationId!==null&&(typeof operationId!=='string'
2084
+ ||operationId.trim()!==operationId
2085
+ ||operationId.length<1
2086
+ ||operationId.length>256)){
2087
+ throw eventAuthorityError('ARCANE_EVENT_OCCURRENCE_INVALID',undefined,TypeError);
2088
+ }
2089
+ if(normalized.cancelable!==undefined&&typeof normalized.cancelable!=='boolean'){
2090
+ throw eventAuthorityError('ARCANE_EVENT_OCCURRENCE_INVALID',undefined,TypeError);
2091
+ }
2092
+ return dispatchOccurrence({
2093
+ type:admittedType,
2094
+ sourceRecord:record,
2095
+ source:record.source,
2096
+ instanceId:record.instanceId,
2097
+ compatibility:detail,
2098
+ publicDetail:normalized.publicDetail??{},
2099
+ operationId,
2100
+ cancelable:normalized.cancelable===true
2101
+ });
2102
+ }
2103
+ function dispose(){
2104
+ if(record.disposed||record.disposing)return false;
2105
+ record.disposing=true;
2106
+ try{
2107
+ dispatchOccurrence({
2108
+ type:ARCANE_EVENT_SOURCE_DISPOSED_EVENT,
2109
+ sourceRecord:record,
2110
+ source:record.source,
2111
+ instanceId:record.instanceId,
2112
+ compatibility:Object.freeze({
2113
+ source:record.source,
2114
+ instanceId:record.instanceId,
2115
+ reason:'source-disposed'
2116
+ }),
2117
+ publicDetail:Object.freeze({reason:'source-disposed'}),
2118
+ operationId:null,
2119
+ cancelable:false
2120
+ });
2121
+ return true;
2122
+ }finally{
2123
+ record.disposed=true;
2124
+ for(const unsubscribe of [...record.subscriptions])unsubscribe();
2125
+ record.targetListeners.length=0;
2126
+ sourceByOwner.delete(owner);
2127
+ record.disposing=false;
2128
+ }
2129
+ }
2130
+ const sourceDescriptor=Object.freeze({
2131
+ kind:ARCANE_EVENT_SOURCE_KIND,
2132
+ protocol:ARCANE_EVENT_SOURCE_PROTOCOL,
2133
+ source,
2134
+ instanceId:record.instanceId,
2135
+ eventTypes:Object.freeze([...eventTypes,ARCANE_EVENT_SOURCE_DISPOSED_EVENT])
2136
+ });
2137
+ const handle={
2138
+ protocol:ARCANE_EVENT_SOURCE_PROTOCOL,
2139
+ descriptor:sourceDescriptor,
2140
+ source,
2141
+ instanceId:record.instanceId,
2142
+ eventTypes:sourceDescriptor.eventTypes,
2143
+ subscribe:sourceSubscribe,
2144
+ on:sourceSubscribe,
2145
+ once(type,handler,options={}){
2146
+ const normalized=subscriptionOptions(options);
2147
+ return sourceSubscribe(type,handler,{
2148
+ once:true,
2149
+ signal:normalized.signal
2150
+ });
2151
+ },
2152
+ addEventListener(type,handler,options){
2153
+ assertOpen();
2154
+ addEventTargetListener(
2155
+ record.targetListeners,
2156
+ type,
2157
+ handler,
2158
+ options,
2159
+ sourceSubscribe,
2160
+ record.owner
2161
+ );
2162
+ },
2163
+ removeEventListener(type,handler,options){
2164
+ removeEventTargetListener(record.targetListeners,type,handler,options);
2165
+ },
2166
+ dispatch,
2167
+ dispatchEvent(value){assertOpen();return dispatchEventLike(value,record);},
2168
+ dispose,
2169
+ destroy:dispose
2170
+ };
2171
+ Object.defineProperty(handle,'disposed',{
2172
+ get(){return record.disposing||record.disposed;},
2173
+ enumerable:true
2174
+ });
2175
+ record.handle=Object.freeze(handle);
2176
+ sourceByOwner.set(owner,record);
2177
+ return record.handle;
2178
+ }
2179
+
2180
+ function projectDOMEvent(target,occurrence,options){
2181
+ if(!occurrences.has(occurrence)){
2182
+ throw eventAuthorityError('ARCANE_EVENT_OCCURRENCE_INVALID',undefined,TypeError);
2183
+ }
2184
+ if(occurrence.defaultPrevented)return false;
2185
+ const admitted=eventDataOptions(
2186
+ options,
2187
+ new Set(['type','bubbles','composed','cancelable']),
2188
+ 'ARCANE_EVENT_DOM_OPTIONS_INVALID'
2189
+ );
2190
+ const type=admitted.type===undefined
2191
+ ?occurrence.type
2192
+ :eventName(admitted.type,'ARCANE_EVENT_DOM_OPTIONS_INVALID');
2193
+ for(const key of ['bubbles','composed','cancelable']){
2194
+ if(admitted[key]!==undefined&&typeof admitted[key]!=='boolean'){
2195
+ throw eventAuthorityError('ARCANE_EVENT_DOM_OPTIONS_INVALID',undefined,TypeError);
2196
+ }
2197
+ }
2198
+ if(!target||typeof target.dispatchEvent!=='function'
2199
+ ||typeof globalThis.CustomEvent!=='function'){
2200
+ throw eventAuthorityError('ARCANE_EVENT_DOM_TARGET_INVALID',undefined,TypeError);
2201
+ }
2202
+ const compatibility=compatibilityByOccurrence.get(occurrence);
2203
+ let detail;
2204
+ const compatibilityPrototype=compatibility&&typeof compatibility==='object'
2205
+ ?Object.getPrototypeOf(compatibility)
2206
+ :undefined;
2207
+ if(compatibility&&typeof compatibility==='object'
2208
+ &&!Array.isArray(compatibility)
2209
+ &&(compatibilityPrototype===Object.prototype||compatibilityPrototype===null)){
2210
+ detail={};
2211
+ for(const key of Reflect.ownKeys(compatibility)){
2212
+ const descriptor=Object.getOwnPropertyDescriptor(compatibility,key);
2213
+ if(!descriptor||!('value' in descriptor)){
2214
+ throw eventAuthorityError('ARCANE_EVENT_COMPATIBILITY_DETAIL_INVALID');
2215
+ }
2216
+ Object.defineProperty(detail,key,{
2217
+ value:descriptor.value,
2218
+ enumerable:descriptor.enumerable,
2219
+ configurable:false,
2220
+ writable:false
2221
+ });
2222
+ }
2223
+ }else{
2224
+ detail={value:compatibility};
2225
+ }
2226
+ const metadata={
2227
+ occurrenceId:occurrence.occurrenceId,
2228
+ arcaneSource:occurrence.source,
2229
+ instanceId:occurrence.instanceId,
2230
+ operationId:occurrence.operationId
2231
+ };
2232
+ for(const key of ARCANE_EVENT_PROJECTION_KEYS){
2233
+ if(Object.hasOwn(detail,key)&&detail[key]!==metadata[key]){
2234
+ throw eventAuthorityError('ARCANE_EVENT_DOM_DETAIL_COLLISION');
2235
+ }
2236
+ Object.defineProperty(detail,key,{
2237
+ value:metadata[key],
2238
+ enumerable:true,
2239
+ configurable:false,
2240
+ writable:false
2241
+ });
2242
+ }
2243
+ if(!Object.hasOwn(detail,'source')){
2244
+ Object.defineProperty(detail,'source',{
2245
+ value:metadata.arcaneSource,
2246
+ enumerable:true,
2247
+ configurable:false,
2248
+ writable:false
2249
+ });
2250
+ }
2251
+ Object.freeze(detail);
2252
+ const cancelable=admitted.cancelable??occurrence.cancelable;
2253
+ const event=new CustomEvent(type,{
2254
+ detail,
2255
+ bubbles:admitted.bubbles===true,
2256
+ composed:admitted.composed===true,
2257
+ cancelable
2258
+ });
2259
+ const accepted=target.dispatchEvent(event)!==false&&!event.defaultPrevented;
2260
+ if(!accepted&&occurrence.cancelable)occurrence.preventDefault();
2261
+ return accepted&&!occurrence.defaultPrevented;
2262
+ }
2263
+
2264
+ function safeLegacyOn(type,handler,once=false){
2265
+ const admittedType=type==='*'?'*':eventName(type);
2266
+ const admitted=eventListener(handler);
2267
+ if(typeof once!=='boolean'){
2268
+ throw eventAuthorityError('ARCANE_EVENT_SUBSCRIPTION_OPTIONS_INVALID',undefined,TypeError);
2269
+ }
2270
+ const record={type:admittedType,identity:admitted.identity,wrapper:null};
2271
+ function safeLegacyListener(value,...rest){
2272
+ if(once)removeLegacyRecord(record);
2273
+ try{admitted.invoke(value,manager,...rest);}
2274
+ catch(error){reportListenerFailure(error,null,null);}
2275
+ }
2276
+ record.wrapper=safeLegacyListener;
2277
+ legacyListeners.push(record);
2278
+ manager[EVENT_MANAGER_BUS_ON](admittedType,safeLegacyListener);
2279
+ return manager;
2280
+ }
2281
+
2282
+ function removeLegacyRecord(record){
2283
+ const index=legacyListeners.indexOf(record);
2284
+ if(index<0)return false;
2285
+ legacyListeners.splice(index,1);
2286
+ manager[EVENT_MANAGER_BUS_OFF](record.type,record.wrapper);
2287
+ return true;
2288
+ }
2289
+
2290
+ function safeLegacyOff(type='*',handler='*'){
2291
+ const admittedType=type==='*'?'*':eventName(type);
2292
+ const selected=legacyListeners.filter(record=>(admittedType==='*'||record.type===admittedType)
2293
+ &&(handler==='*'||record.identity===handler));
2294
+ if(handler!=='*')eventListener(handler);
2295
+ for(const record of selected)removeLegacyRecord(record);
2296
+ return manager;
2297
+ }
2298
+
2299
+ function safeLegacyReset(){
2300
+ for(const record of [...legacyListeners])removeLegacyRecord(record);
2301
+ return manager;
2302
+ }
2303
+
2304
+ Object.defineProperties(manager,{
2305
+ [ARCANE_EVENT_AUTHORITY_BRAND]:{
2306
+ value:ARCANE_EVENT_AUTHORITY_PROTOCOL,
2307
+ enumerable:false,
2308
+ configurable:false,
2309
+ writable:false
2310
+ },
2311
+ protocol:{value:ARCANE_EVENT_AUTHORITY_PROTOCOL,enumerable:true},
2312
+ descriptor:{value:descriptor,enumerable:true},
2313
+ on:{value:safeLegacyOn},
2314
+ once:{value:(type,handler)=>safeLegacyOn(type,handler,true)},
2315
+ off:{value:safeLegacyOff},
2316
+ reset:{value:safeLegacyReset},
2317
+ subscribe:{value:subscribe,enumerable:true},
2318
+ createSource:{value:createSource,enumerable:true},
2319
+ projectDOMEvent:{value:projectDOMEvent,enumerable:true},
2320
+ isOccurrence:{
2321
+ value:value=>occurrences.has(value)||canonicalByView.has(value),
2322
+ enumerable:true
2323
+ },
2324
+ addEventListener:{
2325
+ value(type,handler,options){
2326
+ addEventTargetListener(
2327
+ authorityTargetListeners,
2328
+ type,
2329
+ handler,
2330
+ options,
2331
+ subscribe,
2332
+ manager
2333
+ );
2334
+ },
2335
+ enumerable:true
2336
+ },
2337
+ removeEventListener:{
2338
+ value(type,handler,options){
2339
+ removeEventTargetListener(authorityTargetListeners,type,handler,options);
2340
+ },
2341
+ enumerable:true
2342
+ },
2343
+ dispatchEvent:{value:value=>dispatchEventLike(value),enumerable:true}
2344
+ });
2345
+ return Object.freeze(manager);
2346
+ }
2347
+
2348
+ function validateInstalledArcaneEventAuthority(value,descriptor){
2349
+ if(!descriptor||!('value' in descriptor)){
2350
+ throw eventAuthorityError('ARCANE_EVENT_AUTHORITY_ACCESSOR_COLLISION');
2351
+ }
2352
+ if(descriptor.enumerable!==false
2353
+ ||descriptor.writable!==false
2354
+ ||descriptor.configurable!==false){
2355
+ throw eventAuthorityError('ARCANE_EVENT_AUTHORITY_DESCRIPTOR_MISMATCH');
2356
+ }
2357
+ if(!value||(typeof value!=='object'&&typeof value!=='function')){
2358
+ throw eventAuthorityError('ARCANE_EVENT_AUTHORITY_VALUE_COLLISION');
2359
+ }
2360
+ const brand=Object.getOwnPropertyDescriptor(value,ARCANE_EVENT_AUTHORITY_BRAND);
2361
+ if(!brand||!('value' in brand)){
2362
+ throw eventAuthorityError('ARCANE_EVENT_AUTHORITY_VALUE_COLLISION');
2363
+ }
2364
+ if(brand.enumerable!==false
2365
+ ||brand.writable!==false
2366
+ ||brand.configurable!==false){
2367
+ throw eventAuthorityError('ARCANE_EVENT_AUTHORITY_DESCRIPTOR_MISMATCH');
2368
+ }
2369
+ const protocol=Object.getOwnPropertyDescriptor(value,'protocol');
2370
+ if(!protocol||!('value' in protocol)){
2371
+ throw eventAuthorityError('ARCANE_EVENT_AUTHORITY_API_MISMATCH');
2372
+ }
2373
+ if(brand.value!==ARCANE_EVENT_AUTHORITY_PROTOCOL
2374
+ ||protocol.value!==ARCANE_EVENT_AUTHORITY_PROTOCOL){
2375
+ throw eventAuthorityError('ARCANE_EVENT_AUTHORITY_PROTOCOL_MISMATCH');
2376
+ }
2377
+ let current=value;
2378
+ const callables=new Map();
2379
+ try{
2380
+ while(current!==null&&callables.size<ARCANE_EVENT_REQUIRED_AUTHORITY_API.length){
2381
+ for(const name of ARCANE_EVENT_REQUIRED_AUTHORITY_API){
2382
+ if(callables.has(name))continue;
2383
+ const method=Object.getOwnPropertyDescriptor(current,name);
2384
+ if(method)callables.set(name,method);
2385
+ }
2386
+ current=Object.getPrototypeOf(current);
2387
+ }
2388
+ }catch(error){
2389
+ throw eventAuthorityError('ARCANE_EVENT_AUTHORITY_API_MISMATCH',error);
2390
+ }
2391
+ if(ARCANE_EVENT_REQUIRED_AUTHORITY_API.some(name=>{
2392
+ const method=callables.get(name);
2393
+ return !method||!('value' in method)||typeof method.value!=='function';
2394
+ })){
2395
+ throw eventAuthorityError('ARCANE_EVENT_AUTHORITY_API_MISMATCH');
2396
+ }
2397
+ if(protocol.enumerable!==true
2398
+ ||protocol.writable!==false
2399
+ ||protocol.configurable!==false){
2400
+ throw eventAuthorityError('ARCANE_EVENT_AUTHORITY_DESCRIPTOR_MISMATCH');
2401
+ }
2402
+ return value;
2403
+ }
2404
+
2405
+ function installArcaneEventAuthority(){
2406
+ const own=Object.getOwnPropertyDescriptor(globalThis,'arcaneEvents');
2407
+ if(own)return validateInstalledArcaneEventAuthority(own.value,own);
2408
+ if('arcaneEvents' in globalThis){
2409
+ throw eventAuthorityError('ARCANE_EVENT_AUTHORITY_VALUE_COLLISION');
2410
+ }
2411
+ const authority=createArcaneEventAuthority();
2412
+ try{
2413
+ Object.defineProperty(globalThis,'arcaneEvents',{
2414
+ value:authority,
2415
+ enumerable:false,
2416
+ configurable:false,
2417
+ writable:false
2418
+ });
2419
+ }catch(error){
2420
+ throw eventAuthorityError('ARCANE_EVENT_AUTHORITY_INSTALL_FAILED',error);
2421
+ }
2422
+ const installed=Object.getOwnPropertyDescriptor(globalThis,'arcaneEvents');
2423
+ return validateInstalledArcaneEventAuthority(installed?.value,installed);
2424
+ }
2425
+
2426
+ export const arcaneEvents=installArcaneEventAuthority();
2427
+
2428
+ export function createArcaneEventSource(owner,options){
2429
+ return arcaneEvents.createSource(owner,options);
2430
+ }
2431
+
2432
+ export function projectArcaneDOMEvent(target,occurrence,options){
2433
+ return arcaneEvents.projectDOMEvent(target,occurrence,options);
2434
+ }
2435
+
2436
+ export function isArcaneEventOccurrence(value){
2437
+ return arcaneEvents.isOccurrence(value);
2438
+ }