arcane-os 0.3.0 → 0.3.2

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 (153) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +86 -117
  3. package/bin/arcane-test.mjs +170 -46
  4. package/browser-runtime/ai/browser-speech-artifacts.mjs +887 -909
  5. package/browser-runtime/ai/browser-speech-providers.mjs +96 -152
  6. package/browser-runtime/ai/browser-wasm-llm-provider.mjs +627 -819
  7. package/browser-runtime/ai/browser-wasm.mjs +24 -35
  8. package/browser-runtime/ai/browser-wllama-runtime.mjs +64 -316
  9. package/browser-runtime/ai/model-controller.mjs +584 -181
  10. package/browser-runtime/ai/speech-worker-client.mjs +8 -146
  11. package/browser-runtime/ai/speech-worker-runtime.mjs +643 -363
  12. package/browser-runtime/dom-event-instrumentation.mjs +55 -147
  13. package/browser-runtime/event-manager.mjs +239 -624
  14. package/package.json +5 -6
  15. package/runtime/arcane/components/app-bar.html +3 -15
  16. package/runtime/arcane/components/assistant-panel.html +10 -10
  17. package/runtime/arcane/components/calculator.html +1 -1
  18. package/runtime/arcane/components/chat.html +1359 -135
  19. package/runtime/arcane/components/conversation-view.html +2 -2
  20. package/runtime/arcane/components/document-inspector.html +11 -17
  21. package/runtime/arcane/components/file-manager.html +13 -56
  22. package/runtime/arcane/components/markdown-document.html +82 -281
  23. package/runtime/arcane/components/markdown-editor.html +7 -10
  24. package/runtime/arcane/components/media-embed.html +6 -6
  25. package/runtime/arcane/components/screen-capture.html +4 -4
  26. package/runtime/arcane/components/source-explanation.html +2 -2
  27. package/runtime/arcane/components/speech.html +112 -68
  28. package/runtime/arcane/components/terminal-workspace.html +4 -4
  29. package/runtime/arcane/components/theme-editor.html +1 -1
  30. package/runtime/arcane/components/unified-inbox.html +2 -2
  31. package/runtime/arcane/components/voice-transcription.html +31 -21
  32. package/runtime/arcane/entities/Calculation.js +2 -3
  33. package/runtime/arcane/entities/Chat.js +228 -43
  34. package/runtime/arcane/entities/Preference.js +3 -5
  35. package/runtime/arcane/entities/Weather.js +5 -5
  36. package/runtime/arcane/modules/AI.js +1050 -427
  37. package/runtime/arcane/modules/AIProviderRuntime.js +658 -363
  38. package/runtime/arcane/modules/AIResponseLength.js +9 -19
  39. package/runtime/arcane/modules/AIRuntimeState.js +109 -72
  40. package/runtime/arcane/modules/ArcaneNavigationPolicy.js +45 -32
  41. package/runtime/arcane/modules/BrowserTestSuite.js +78 -122
  42. package/runtime/arcane/modules/CalculatorEngine.js +9 -9
  43. package/runtime/arcane/modules/CommunicationAppController.js +3 -7
  44. package/runtime/arcane/modules/ComponentContracts.js +30 -32
  45. package/runtime/arcane/modules/ConfiguredAIChatSession.js +281 -230
  46. package/runtime/arcane/modules/ConversationActionItems.js +26 -59
  47. package/runtime/arcane/modules/ConversationClosingReport.js +34 -61
  48. package/runtime/arcane/modules/ConversationTimebox.js +27 -15
  49. package/runtime/arcane/modules/DBOPFSDocumentLibrary.js +152 -344
  50. package/runtime/arcane/modules/DocumentLexicalSearch.js +25 -91
  51. package/runtime/arcane/modules/HTMLImport.js +54 -1
  52. package/runtime/arcane/modules/IsolatedModelQuestionRunner.js +40 -203
  53. package/runtime/arcane/modules/LocalAIReadiness.js +40 -60
  54. package/runtime/arcane/modules/LocalAIReadinessController.js +15 -13
  55. package/runtime/arcane/modules/MD.js +1 -45
  56. package/runtime/arcane/modules/Mail.js +51 -103
  57. package/runtime/arcane/modules/MailOutbox.mjs +95 -193
  58. package/runtime/arcane/modules/MailTransport.mjs +36 -57
  59. package/runtime/arcane/modules/ModelDefinition.js +22 -106
  60. package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +39 -101
  61. package/runtime/arcane/modules/PersistentAIChatSession.js +281 -18
  62. package/runtime/arcane/modules/PreferenceStore.js +102 -30
  63. package/runtime/arcane/modules/RiskSignalAnalyzer.js +8 -9
  64. package/runtime/arcane/modules/ScopedOPFSCache.js +7 -42
  65. package/runtime/arcane/modules/ScreenCapture.js +175 -128
  66. package/runtime/arcane/modules/SpeechPlayback.js +46 -149
  67. package/runtime/arcane/modules/StaticDocumentCatalog.js +173 -407
  68. package/runtime/arcane/modules/ToolCallRouter.js +25 -12
  69. package/runtime/arcane/modules/YouTubeMedia.js +6 -5
  70. package/schemas/arcane-app-bundle.schema.json +13 -78
  71. package/schemas/arcane-app.schema.json +9 -25
  72. package/schemas/arcane-lock.schema.json +18 -151
  73. package/schemas/arcane-package.schema.json +2 -16
  74. package/schemas/native-build-plan.schema.json +119 -122
  75. package/src/app-descriptor.mjs +75 -132
  76. package/src/application-tests.mjs +200 -0
  77. package/src/cli/main.mjs +27 -46
  78. package/src/constants.mjs +3 -4
  79. package/src/dev-server.mjs +30 -324
  80. package/src/doctor.mjs +92 -154
  81. package/src/dom-event-instrumentation.mjs +55 -147
  82. package/src/errors.mjs +2 -3
  83. package/src/event-manager.mjs +239 -624
  84. package/src/event-queue.mjs +3 -3
  85. package/src/import-map.mjs +273 -1028
  86. package/src/index.mjs +14 -16
  87. package/src/installed-sdk-runtime.mjs +40 -62
  88. package/src/integrated-provider-loader.mjs +53 -382
  89. package/src/mail-api.mjs +0 -2
  90. package/src/mail-server.mjs +224 -580
  91. package/src/mail.mjs +4 -10
  92. package/src/native-plan.mjs +163 -598
  93. package/src/native-provider-loader.mjs +104 -1063
  94. package/src/packager/core.mjs +485 -3229
  95. package/src/process.mjs +5 -10
  96. package/src/release-bundle.mjs +292 -2405
  97. package/src/runtime.mjs +76 -396
  98. package/src/scaffold.mjs +30 -80
  99. package/src/sdk-browser-runtime.mjs +70 -626
  100. package/src/source-server.mjs +588 -0
  101. package/src/targets/index.mjs +78 -188
  102. package/src/templates/workspace-template.mjs +19 -135
  103. package/src/testing-loader.mjs +164 -0
  104. package/src/testing.mjs +1 -1
  105. package/src/toolchain.mjs +131 -544
  106. package/src/update-check.mjs +26 -64
  107. package/src/workspace-operation-lock.mjs +139 -430
  108. package/src/workspace-runtime.mjs +112 -779
  109. package/src/workspace.mjs +40 -302
  110. package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +0 -218
  111. package/browser-runtime/ai/ARCANE_AI_BROWSER_SPEECH_COMPONENTS.json +0 -203
  112. package/browser-runtime/ai/ARCANE_AI_BROWSER_WASM_COMPONENTS.json +0 -80
  113. package/browser-runtime/ai/internal/sha256.mjs +0 -166
  114. package/docs/architecture.md +0 -344
  115. package/docs/compatibility.md +0 -36
  116. package/docs/event-manager.md +0 -294
  117. package/docs/platform-targets.md +0 -108
  118. package/docs/publishing.md +0 -201
  119. package/docs/reference/README.md +0 -187
  120. package/docs/reference/ai/browser-speech-package-authority.json +0 -835
  121. package/docs/reference/ai/browser-speech.md +0 -1252
  122. package/docs/reference/ai/browser-wasm.md +0 -530
  123. package/docs/reference/arcane-ollama.md +0 -288
  124. package/docs/reference/availability-and-normalization.md +0 -183
  125. package/docs/reference/behavioral-testing.md +0 -133
  126. package/docs/reference/cli.md +0 -779
  127. package/docs/reference/core/README.md +0 -62
  128. package/docs/reference/core/arcane-ai-contracts.md +0 -907
  129. package/docs/reference/core/arcane-api.md +0 -601
  130. package/docs/reference/core/arcane-entities.md +0 -65
  131. package/docs/reference/core/arcane-events.md +0 -134
  132. package/docs/reference/core/ollama-module.md +0 -181
  133. package/docs/reference/core/reference/arcane-api/ai-and-ollama.md +0 -1909
  134. package/docs/reference/core/reference/arcane-api/applications-terminal-capabilities.md +0 -1057
  135. package/docs/reference/core/reference/arcane-api/core-and-events.md +0 -320
  136. package/docs/reference/core/reference/arcane-api/filesystem-storage-preferences-appearance.md +0 -610
  137. package/docs/reference/core/reference/arcane-api/namespaces.md +0 -1157
  138. package/docs/reference/core/reference/arcane-api/platform-installation-users-system.md +0 -1423
  139. package/docs/reference/core/reference/arcane-api/session-provisioning-diagnostics-development.md +0 -315
  140. package/docs/reference/event-manager.md +0 -1511
  141. package/docs/reference/inventory/package-api.json +0 -3284
  142. package/docs/reference/inventory/runtime-components.json +0 -1011
  143. package/docs/reference/inventory/runtime-entities.json +0 -26
  144. package/docs/reference/inventory/runtime-modules.json +0 -1431
  145. package/docs/reference/mail.md +0 -316
  146. package/docs/reference/protocols.md +0 -677
  147. package/docs/reference/runtime-components.md +0 -1366
  148. package/docs/reference/runtime-entities.md +0 -303
  149. package/docs/reference/runtime-modules.md +0 -2960
  150. package/docs/reference/sdk-api.md +0 -6694
  151. package/docs/roadmap.md +0 -79
  152. package/docs/work-amplification.md +0 -129
  153. package/runtime/ARCANE_RUNTIME_RELEASE.json +0 -826
@@ -23,7 +23,6 @@ export const PLAYBACK_RECORD_EVENT='arcane.time-travel.playback.record';
23
23
  export const PLAYBACK_COMPLETED_EVENT='arcane.time-travel.playback.completed';
24
24
  export const PLAYBACK_CANCELLED_EVENT='arcane.time-travel.playback.cancelled';
25
25
  export const PLAYBACK_FAILED_EVENT='arcane.time-travel.playback.failed';
26
- export const TIME_TRAVEL_OVERFLOW_EVENT='arcane.time-travel.overflow';
27
26
 
28
27
  export const ARCANE_EVENT_AUTHORITY_KIND='arcane-event-authority';
29
28
  export const ARCANE_EVENT_SOURCE_KIND='arcane-event-source';
@@ -32,18 +31,18 @@ export const ARCANE_EVENT_SOURCE_DISPOSED_EVENT='arcane.event.source.disposed';
32
31
  const ARCANE_EVENT_TARGET_COMPATIBILITY_SOURCE='event-target-compatibility';
33
32
  const ARCANE_EVENT_NAME_PATTERN=/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*$/u;
34
33
  const ARCANE_EVENT_CHANNEL_PREFIX='arcane.event.authority.internal:';
35
- const ARCANE_EVENT_PROJECTION_KEYS=Object.freeze([
34
+ const ARCANE_EVENT_PROJECTION_KEYS=[
36
35
  'occurrenceId','arcaneSource','instanceId','operationId'
37
- ]);
38
- const ARCANE_EVENT_REQUIRED_AUTHORITY_API=Object.freeze([
36
+ ];
37
+ const ARCANE_EVENT_REQUIRED_AUTHORITY_API=[
39
38
  'on','once','off','reset','emit','instrument','forward','subscribe','createSource',
40
39
  'projectDOMEvent','isOccurrence','addEventListener','removeEventListener','dispatchEvent'
41
- ]);
40
+ ];
42
41
  const EVENT_MANAGER_BUS_ON=Symbol('EventManager.busOn');
43
42
  const EVENT_MANAGER_BUS_OFF=Symbol('EventManager.busOff');
44
43
  const EVENT_MANAGER_DISPATCH=Symbol('EventManager.dispatch');
45
44
 
46
- const ARCANE_EVENT_ERRORS=Object.freeze({
45
+ const ARCANE_EVENT_ERRORS={
47
46
  ARCANE_EVENT_AUTHORITY_ACCESSOR_COLLISION:
48
47
  'globalThis.arcaneEvents must be an own data property.',
49
48
  ARCANE_EVENT_AUTHORITY_VALUE_COLLISION:
@@ -65,7 +64,7 @@ const ARCANE_EVENT_ERRORS=Object.freeze({
65
64
  ARCANE_EVENT_SOURCE_EVENT_TYPE_UNDECLARED:
66
65
  'The Arcane event source cannot publish an undeclared event type.',
67
66
  ARCANE_EVENT_COMPATIBILITY_DETAIL_INVALID:
68
- 'Arcane event compatibility detail must be immutable or safely shallow-copyable.',
67
+ 'Arcane event compatibility detail must be safely shallow-copyable.',
69
68
  ARCANE_EVENT_OCCURRENCE_INVALID:
70
69
  'The Arcane event occurrence value or creation options are invalid.',
71
70
  ARCANE_EVENT_OCCURRENCE_SEQUENCE_EXHAUSTED:
@@ -90,30 +89,21 @@ const ARCANE_EVENT_ERRORS=Object.freeze({
90
89
  'Arcane event subscription signal must be an AbortSignal.',
91
90
  ARCANE_EVENT_DISPATCH_EVENT_INVALID:
92
91
  '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(
92
+ };
93
+ export const ARCANE_EVENT_ERROR_CODES=Object.fromEntries(
95
94
  Object.keys(ARCANE_EVENT_ERRORS).map(code=>[code,code])
96
- ));
97
-
98
- const SENSITIVE_KEY_PATTERN=/(?:authorization|cookie|credential|pass(?:word|phrase)?|private.?key|secret|session.?token|token|api.?key)/iu;
99
- const PRIVATE_CONTENT_KEY_PATTERN=/^(?:data|detail|key)$/iu;
100
- const INTERNAL_STACK_PATTERN=/(?:EventManager\.|#dispatch|event-manager\.mjs)/u;
101
- const URL_PATTERN=/\b(?:blob|data|file|ftp|ftps|http|https|ws|wss):[^\s<>'"\])}]+/giu;
102
- const DEFAULT_MAX_EVENTS=10_000;
103
- const DEFAULT_MAX_SNAPSHOT_DEPTH=50;
104
- const DEFAULT_MAX_SNAPSHOT_ENTRIES=1_000;
105
- const DEFAULT_MAX_SNAPSHOT_STRING_LENGTH=10_000;
106
- const MIN_SNAPSHOT_STRING_LENGTH=64;
107
- const DOCUMENT_KEYS=Object.freeze(['protocol','sessionId','createdAt','events']);
108
- const RECORD_KEYS=Object.freeze([
95
+ );
96
+
97
+ const DOCUMENT_KEYS=['protocol','sessionId','createdAt','events'];
98
+ const RECORD_KEYS=[
109
99
  'protocol','sessionId','id','sequence','timestamp','monotonicMs','type','source',
110
100
  'category','correlationId','causationId','parentSequence','depth','stack','payload',
111
101
  'metadata','status','completedAt','durationMs','error'
112
- ]);
102
+ ];
113
103
  const EVENT_STATUSES=new Set(['dispatching','completed','failed']);
114
104
  const DATE_TO_ISO=Date.prototype.toISOString;
115
105
  const REGEXP_SOURCE_GETTER=Object.getOwnPropertyDescriptor(RegExp.prototype,'source')?.get;
116
- const REGEXP_FLAG_GETTERS=Object.freeze([
106
+ const REGEXP_FLAG_GETTERS=[
117
107
  ['d',Object.getOwnPropertyDescriptor(RegExp.prototype,'hasIndices')?.get],
118
108
  ['g',Object.getOwnPropertyDescriptor(RegExp.prototype,'global')?.get],
119
109
  ['i',Object.getOwnPropertyDescriptor(RegExp.prototype,'ignoreCase')?.get],
@@ -122,7 +112,7 @@ const REGEXP_FLAG_GETTERS=Object.freeze([
122
112
  ['u',Object.getOwnPropertyDescriptor(RegExp.prototype,'unicode')?.get],
123
113
  ['v',Object.getOwnPropertyDescriptor(RegExp.prototype,'unicodeSets')?.get],
124
114
  ['y',Object.getOwnPropertyDescriptor(RegExp.prototype,'sticky')?.get]
125
- ]);
115
+ ];
126
116
  const MAP_ENTRIES=Map.prototype.entries;
127
117
  const MAP_SIZE_GETTER=Object.getOwnPropertyDescriptor(Map.prototype,'size')?.get;
128
118
  const SET_VALUES=Set.prototype.values;
@@ -134,10 +124,6 @@ const TYPED_ARRAY_VALUES=TYPED_ARRAY_PROTOTYPE.values;
134
124
  const TYPED_ARRAY_TAG_GETTER=
135
125
  Object.getOwnPropertyDescriptor(TYPED_ARRAY_PROTOTYPE,Symbol.toStringTag)?.get;
136
126
  const DATA_VIEW_BUFFER_GETTER=Object.getOwnPropertyDescriptor(DataView.prototype,'buffer')?.get;
137
- const DATA_VIEW_BYTE_LENGTH_GETTER=
138
- Object.getOwnPropertyDescriptor(DataView.prototype,'byteLength')?.get;
139
- const DATA_VIEW_BYTE_OFFSET_GETTER=
140
- Object.getOwnPropertyDescriptor(DataView.prototype,'byteOffset')?.get;
141
127
 
142
128
  function dataObject(entries=[]){
143
129
  const result=Object.create(null);
@@ -169,26 +155,10 @@ function taggedSnapshot(type,entries=[]){
169
155
  return snapshotObject([['$type',type],...entries]);
170
156
  }
171
157
 
172
- function dataProperty(value,key,{inherited=false}={}){
173
- let current=value;
174
- while(current!==null&&(typeof current==='object'||typeof current==='function')){
175
- const descriptor=Object.getOwnPropertyDescriptor(current,key);
176
- if(descriptor){
177
- return 'value' in descriptor
178
- ?{found:true,readable:true,value:descriptor.value}
179
- :{found:true,readable:false,value:undefined};
180
- }
181
- if(!inherited)break;
182
- current=Object.getPrototypeOf(current);
183
- }
184
- return {found:false,readable:false,value:undefined};
185
- }
186
-
187
- function safeDataString(value,key,{fallback='',inherited=false}={}){
158
+ function safeDataString(value,key,{fallback=''}={}){
188
159
  try{
189
- const property=dataProperty(value,key,{inherited});
190
- if(property.found&&!property.readable)return '[UNREADABLE]';
191
- if(property.readable&&typeof property.value==='string')return property.value;
160
+ const current=Reflect.get(value,key);
161
+ if(typeof current==='string')return current;
192
162
  }catch{}
193
163
  return fallback;
194
164
  }
@@ -201,13 +171,11 @@ function regexpFlags(value){
201
171
  return result;
202
172
  }
203
173
 
204
- function boundedString(value,maxLength,{redactSensitive=true}={}){
205
- let result=String(value);
206
- if(redactSensitive)result=result.replace(URL_PATTERN,'[REDACTED URL]');
207
- return result.length<=maxLength?result:`${result.slice(0,maxLength)}…`;
174
+ function safeString(value){
175
+ return String(value);
208
176
  }
209
177
 
210
- function safeErrorText(error,maxLength,{redactSensitive=true}={}){
178
+ function safeErrorText(error){
211
179
  let text='Snapshot capture failed.';
212
180
  try{
213
181
  if(error!==null&&(typeof error==='object'||typeof error==='function')){
@@ -217,7 +185,7 @@ function safeErrorText(error,maxLength,{redactSensitive=true}={}){
217
185
  text=String(error);
218
186
  }
219
187
  }catch{}
220
- try{return boundedString(text,maxLength,{redactSensitive});}
188
+ try{return safeString(text);}
221
189
  catch{return 'Snapshot capture failed.';}
222
190
  }
223
191
 
@@ -249,75 +217,56 @@ function defaultMonotonicClock(){
249
217
 
250
218
  function sourceStack(){
251
219
  const stack=new Error('Arcane event source').stack;
252
- if(typeof stack!=='string')return null;
253
- const lines=stack.split(/\r?\n/u);
254
- const filtered=[lines[0],...lines.slice(1).filter(line=>!INTERNAL_STACK_PATTERN.test(line))];
255
- return filtered.join('\n');
220
+ return typeof stack==='string'?stack:null;
256
221
  }
257
222
 
258
223
  function snapshot(value,{
259
- redactSensitive=true,
260
- captureStacks=false,
261
- maxDepth=DEFAULT_MAX_SNAPSHOT_DEPTH,
262
- maxEntries=DEFAULT_MAX_SNAPSHOT_ENTRIES,
263
- maxStringLength=DEFAULT_MAX_SNAPSHOT_STRING_LENGTH,
264
224
  key='',
265
225
  path='$',
266
226
  depth=0,
267
227
  seen=new Map()
268
228
  }={}){
269
- if(redactSensitive&&key
270
- &&(SENSITIVE_KEY_PATTERN.test(key)||PRIVATE_CONTENT_KEY_PATTERN.test(key))){
271
- return '[REDACTED]';
272
- }
273
229
  if(value===null||value===undefined||typeof value==='boolean')return value;
274
- if(typeof value==='string')return boundedString(value,maxStringLength,{redactSensitive});
230
+ if(typeof value==='string')return safeString(value);
275
231
  if(typeof value==='number')return Number.isFinite(value)
276
232
  ?value
277
233
  :taggedSnapshot('number',[['value',String(value)]]);
278
234
  if(typeof value==='bigint')return taggedSnapshot('bigint',[[
279
- 'value',boundedString(value.toString(),maxStringLength,{redactSensitive})
235
+ 'value',safeString(value.toString())
280
236
  ]]);
281
237
  if(typeof value==='symbol')return taggedSnapshot('symbol',[[
282
238
  'value',value.description===undefined
283
239
  ?null
284
- :boundedString(value.description,maxStringLength,{redactSensitive})
240
+ :safeString(value.description)
285
241
  ]]);
286
242
  if(typeof value==='function'){
287
243
  const name=safeDataString(value,'name');
288
244
  return taggedSnapshot('function',[[
289
- 'name',name?boundedString(name,maxStringLength,{redactSensitive}):null
245
+ 'name',name?safeString(name):null
290
246
  ]]);
291
247
  }
292
- if(depth>=maxDepth)return taggedSnapshot('depth-limit',[[
293
- 'path',boundedString(path,maxStringLength,{redactSensitive})
294
- ]]);
295
248
  if(seen.has(value))return snapshotObject([[
296
- '$ref',boundedString(seen.get(value),maxStringLength,{redactSensitive})
249
+ '$ref',safeString(seen.get(value))
297
250
  ]]);
298
251
  seen.set(value,path);
299
252
 
300
253
  const next=(item,itemKey,itemPath)=>{
301
254
  try{
302
255
  return snapshot(item,{
303
- redactSensitive,captureStacks,maxDepth,maxEntries,maxStringLength,
304
256
  key:itemKey,
305
- path:boundedString(itemPath,maxStringLength,{redactSensitive}),
257
+ path:safeString(itemPath),
306
258
  depth:depth+1,
307
259
  seen
308
260
  });
309
261
  }catch(error){
310
262
  return snapshotFailure(error,{
311
- redactSensitive,maxStringLength,
312
263
  path:itemPath
313
264
  });
314
265
  }
315
266
  };
316
267
  if(value instanceof Date)return taggedSnapshot('date',[['value',DATE_TO_ISO.call(value)]]);
317
268
  if(value instanceof RegExp)return taggedSnapshot('regexp',[
318
- ['source',boundedString(
319
- REGEXP_SOURCE_GETTER.call(value),maxStringLength,{redactSensitive}
320
- )],
269
+ ['source',safeString(REGEXP_SOURCE_GETTER.call(value))],
321
270
  ['flags',regexpFlags(value)]
322
271
  ]);
323
272
  if(value instanceof Error){
@@ -325,101 +274,75 @@ function snapshot(value,{
325
274
  const message=safeDataString(value,'message');
326
275
  const stack=safeDataString(value,'stack');
327
276
  const entries=[
328
- ['name',boundedString(name||'Error',maxStringLength,{redactSensitive})],
329
- ['message',boundedString(message,maxStringLength,{redactSensitive})],
330
- ['stack',captureStacks&&stack
331
- ?boundedString(stack,maxStringLength,{redactSensitive})
332
- :null]
277
+ ['name',safeString(name||'Error')],
278
+ ['message',safeString(message)],
279
+ ['stack',stack?safeString(stack):null]
333
280
  ];
334
281
  let causeDescriptor;
335
282
  try{causeDescriptor=Object.getOwnPropertyDescriptor(value,'cause');}catch{}
336
283
  if(causeDescriptor){
337
- entries.push(['cause','value' in causeDescriptor
338
- ?next(causeDescriptor.value,'cause',`${path}.cause`)
339
- :taggedSnapshot('unreadable',[['error','Accessor properties are not evaluated.']])]);
284
+ let cause;
285
+ try{cause=Reflect.get(value,'cause');}
286
+ catch(error){cause=snapshotFailure(error,{path:`${path}.cause`});}
287
+ entries.push(['cause',next(cause,'cause',`${path}.cause`)]);
340
288
  }
341
289
  return taggedSnapshot('error',entries);
342
290
  }
343
291
  if(Array.isArray(value)){
344
292
  const result=[];
345
- const limit=Math.min(value.length,maxEntries);
346
- for(let index=0;index<limit;index+=1){
347
- const descriptor=Object.getOwnPropertyDescriptor(value,String(index));
348
- const item=descriptor&&'value' in descriptor
349
- ?descriptor.value
350
- :taggedSnapshot('unreadable',[['error','Accessor properties are not evaluated.']]);
293
+ for(let index=0;index<value.length;index+=1){
294
+ let item;
295
+ try{item=Reflect.get(value,String(index));}
296
+ catch(error){item=snapshotFailure(error,{path:`${path}[${index}]`});}
351
297
  result.push(next(item,String(index),`${path}[${index}]`));
352
298
  }
353
- if(value.length>maxEntries){
354
- result.push(taggedSnapshot('entries-truncated',[
355
- ['omitted',value.length-maxEntries]
356
- ]));
357
- }
358
299
  return result;
359
300
  }
360
301
  if(value instanceof Map){
361
302
  const entries=[];
362
303
  let index=0;
363
304
  for(const [mapKey,item] of MAP_ENTRIES.call(value)){
364
- if(index>=maxEntries)break;
365
305
  entries.push([
366
306
  next(mapKey,'mapKey',`${path}.entries[${index}].key`),
367
307
  next(item,'value',`${path}.entries[${index}].value`)
368
308
  ]);
369
309
  index+=1;
370
310
  }
371
- const size=MAP_SIZE_GETTER.call(value);
372
- return taggedSnapshot('map',[
373
- ['entries',entries],
374
- ...(size>index?[['omitted',size-index]]:[])
375
- ]);
311
+ return taggedSnapshot('map',[['entries',entries]]);
376
312
  }
377
313
  if(value instanceof Set){
378
314
  const values=[];
379
315
  let index=0;
380
316
  for(const item of SET_VALUES.call(value)){
381
- if(index>=maxEntries)break;
382
317
  values.push(next(item,String(index),`${path}.values[${index}]`));
383
318
  index+=1;
384
319
  }
385
- const size=SET_SIZE_GETTER.call(value);
386
- return taggedSnapshot('set',[
387
- ['values',values],
388
- ...(size>index?[['omitted',size-index]]:[])
389
- ]);
320
+ return taggedSnapshot('set',[['values',values]]);
390
321
  }
391
322
  if(ArrayBuffer.isView(value)){
392
323
  const dataView=value instanceof DataView;
393
- const length=dataView
394
- ?DATA_VIEW_BYTE_LENGTH_GETTER.call(value)
395
- :TYPED_ARRAY_LENGTH_GETTER.call(value);
396
324
  let values;
397
325
  let type='DataView';
398
326
  if(dataView){
399
327
  const buffer=DATA_VIEW_BUFFER_GETTER.call(value);
400
- const byteOffset=DATA_VIEW_BYTE_OFFSET_GETTER.call(value);
401
- values=Array.from(new Uint8Array(buffer,byteOffset,Math.min(length,maxEntries)));
328
+ values=Array.from(new Uint8Array(buffer));
402
329
  }else{
330
+ const length=TYPED_ARRAY_LENGTH_GETTER.call(value);
403
331
  type=TYPED_ARRAY_TAG_GETTER.call(value)??'TypedArray';
404
332
  values=[];
405
333
  const iterator=TYPED_ARRAY_VALUES.call(value);
406
- while(values.length<Math.min(length,maxEntries)){
334
+ while(values.length<length){
407
335
  const step=iterator.next();
408
336
  if(step.done)break;
409
337
  values.push(step.value);
410
338
  }
411
339
  }
412
- return taggedSnapshot(type,[
413
- ['values',values],
414
- ...(length>maxEntries?[['omitted',length-maxEntries]]:[])
415
- ]);
340
+ return taggedSnapshot(type,[['values',values]]);
416
341
  }
417
342
  if(value instanceof ArrayBuffer){
418
- const bytes=new Uint8Array(value);
419
- return taggedSnapshot('ArrayBuffer',[
420
- ['values',Array.from(bytes.subarray(0,maxEntries))],
421
- ...(bytes.length>maxEntries?[['omitted',bytes.length-maxEntries]]:[])
422
- ]);
343
+ return taggedSnapshot('ArrayBuffer',[[
344
+ 'values',Array.from(new Uint8Array(value))
345
+ ]]);
423
346
  }
424
347
 
425
348
  const result=snapshotObject();
@@ -428,13 +351,12 @@ function snapshot(value,{
428
351
  const descriptor=Object.getOwnPropertyDescriptor(value,property);
429
352
  return descriptor?.enumerable===true;
430
353
  });
431
- for(let index=0;index<Math.min(properties.length,maxEntries);index+=1){
354
+ for(let index=0;index<properties.length;index+=1){
432
355
  const property=properties[index];
433
- const descriptor=Object.getOwnPropertyDescriptor(value,property);
434
- const item=descriptor&&'value' in descriptor
435
- ?descriptor.value
436
- :taggedSnapshot('unreadable',[['error','Accessor properties are not evaluated.']]);
437
- let outputKey=boundedString(property,maxStringLength,{redactSensitive:false});
356
+ let item;
357
+ try{item=Reflect.get(value,property);}
358
+ catch(error){item=snapshotFailure(error,{path:`${path}.${property}`});}
359
+ let outputKey=safeString(property);
438
360
  if(Object.hasOwn(result,outputKey))outputKey=`$arcaneCollision:${String(index)}`;
439
361
  Object.defineProperty(result,outputKey,{
440
362
  value:next(item,property,`${path}.${property}`),
@@ -443,49 +365,27 @@ function snapshot(value,{
443
365
  writable:true
444
366
  });
445
367
  }
446
- if(properties.length>maxEntries){
447
- Object.defineProperty(result,'$arcaneTruncated',{
448
- value:snapshotObject([['omitted',properties.length-maxEntries]]),
449
- enumerable:true,
450
- configurable:true,
451
- writable:true
452
- });
453
- }
454
368
  return result;
455
369
  }
456
370
 
457
- function snapshotFailure(error,{
458
- redactSensitive=true,
459
- maxStringLength=DEFAULT_MAX_SNAPSHOT_STRING_LENGTH,
460
- path='$'
461
- }={}){
371
+ function snapshotFailure(error,{path='$'}={}){
462
372
  const name=safeDataString(error,'name',{fallback:'Error',inherited:true})||'Error';
463
373
  return taggedSnapshot('snapshot-failed',[
464
- ['name',boundedString(name,maxStringLength,{redactSensitive})],
465
- ['message',safeErrorText(error,maxStringLength,{redactSensitive})],
466
- ['path',boundedString(path,maxStringLength,{redactSensitive})]
374
+ ['name',safeString(name)],
375
+ ['message',safeErrorText(error)],
376
+ ['path',safeString(path)]
467
377
  ]);
468
378
  }
469
379
 
470
- function deepFreeze(value,seen=new WeakSet()){
471
- if(!value||typeof value!=='object'||seen.has(value))return value;
472
- seen.add(value);
473
- for(const property of Reflect.ownKeys(value)){
474
- const descriptor=Object.getOwnPropertyDescriptor(value,property);
475
- if(descriptor&&'value' in descriptor)deepFreeze(descriptor.value,seen);
476
- }
477
- return Object.freeze(value);
380
+ function completeSnapshot(value,options){
381
+ try{return snapshot(value,options);}
382
+ catch(error){return snapshotFailure(error,options);}
478
383
  }
479
384
 
480
- function frozenSnapshot(value,options){
481
- try{return deepFreeze(snapshot(value,options));}
482
- catch(error){return deepFreeze(snapshotFailure(error,options));}
483
- }
484
-
485
- function frozenErrorSnapshot(value,options){
486
- const captured=frozenSnapshot(value,options);
385
+ function completeErrorSnapshot(value,options){
386
+ const captured=completeSnapshot(value,options);
487
387
  if(captured&&typeof captured==='object'&&!Array.isArray(captured))return captured;
488
- return deepFreeze(taggedSnapshot('thrown',[['value',captured]]));
388
+ return taggedSnapshot('thrown',[['value',captured]]);
489
389
  }
490
390
 
491
391
  function normalizeMetadata(metadata){
@@ -559,12 +459,11 @@ function exactDataObject(value,expectedKeys,label){
559
459
  }
560
460
  }
561
461
 
562
- function denseArrayValues(value,label,{maxLength}={}){
462
+ function denseArrayValues(value,label){
563
463
  try{
564
464
  if(!Array.isArray(value)||!Number.isSafeInteger(value.length)||value.length<0){
565
465
  invalidStack(label);
566
466
  }
567
- if(maxLength!==undefined&&value.length>maxLength)invalidStack(label);
568
467
  const keys=Reflect.ownKeys(value);
569
468
  if(keys.some(key=>typeof key!=='string'))invalidStack(label);
570
469
  const expected=new Set(['length']);
@@ -586,9 +485,6 @@ function denseArrayValues(value,label,{maxLength}={}){
586
485
  }
587
486
 
588
487
  function cloneImportedValue(value,{
589
- maxDepth,
590
- maxEntries,
591
- maxStringLength,
592
488
  path='$',
593
489
  depth=0,
594
490
  seen=new WeakSet()
@@ -598,23 +494,14 @@ function cloneImportedValue(value,{
598
494
  if(!Number.isFinite(value))invalidStack(`Event stack value at ${path}`);
599
495
  return value;
600
496
  }
601
- if(typeof value==='string'){
602
- if(value.length>maxStringLength+1
603
- ||(value.length===maxStringLength+1&&!value.endsWith('…'))){
604
- invalidStack(`Event stack value at ${path}`);
605
- }
606
- return value;
607
- }
497
+ if(typeof value==='string')return value;
608
498
  if(!value||typeof value!=='object')invalidStack(`Event stack value at ${path}`);
609
- if(depth>maxDepth||seen.has(value))invalidStack(`Event stack value at ${path}`);
499
+ if(seen.has(value))invalidStack(`Event stack value at ${path}`);
610
500
  seen.add(value);
611
501
 
612
502
  if(Array.isArray(value)){
613
- const items=denseArrayValues(value,`Event stack array at ${path}`,{
614
- maxLength:maxEntries+1
615
- });
503
+ const items=denseArrayValues(value,`Event stack array at ${path}`);
616
504
  return items.map((item,index)=>cloneImportedValue(item,{
617
- maxDepth,maxEntries,maxStringLength,
618
505
  path:`${path}[${String(index)}]`,
619
506
  depth:depth+1,
620
507
  seen
@@ -630,16 +517,11 @@ function cloneImportedValue(value,{
630
517
  throw new TypeError(`Event stack value at ${path} is invalid.`,{cause:error});
631
518
  }
632
519
  if((prototype!==Object.prototype&&prototype!==null)
633
- ||keys.some(key=>typeof key!=='string')
634
- ||keys.length>maxEntries+1){
520
+ ||keys.some(key=>typeof key!=='string')){
635
521
  invalidStack(`Event stack value at ${path}`);
636
522
  }
637
523
  const result=dataObject();
638
524
  for(const key of keys){
639
- if(key.length>maxStringLength+1
640
- ||(key.length===maxStringLength+1&&!key.endsWith('…'))){
641
- invalidStack(`Event stack value at ${path}`);
642
- }
643
525
  let descriptor;
644
526
  try{descriptor=Object.getOwnPropertyDescriptor(value,key);}catch(error){
645
527
  throw new TypeError(`Event stack value at ${path} is invalid.`,{cause:error});
@@ -649,7 +531,6 @@ function cloneImportedValue(value,{
649
531
  }
650
532
  Object.defineProperty(result,key,{
651
533
  value:cloneImportedValue(descriptor.value,{
652
- maxDepth,maxEntries,maxStringLength,
653
534
  path:`${path}.${key}`,
654
535
  depth:depth+1,
655
536
  seen
@@ -671,21 +552,16 @@ function canonicalTimestamp(value,label){
671
552
  return milliseconds;
672
553
  }
673
554
 
674
- function boundedRecordString(value,label,maxStringLength,{nullable=false,empty=true}={}){
555
+ function recordString(value,label,{nullable=false,empty=true}={}){
675
556
  if(nullable&&value===null)return null;
676
- if(typeof value!=='string'||(!empty&&!value)
677
- ||value.length>maxStringLength+1
678
- ||(value.length===maxStringLength+1&&!value.endsWith('…'))){
557
+ if(typeof value!=='string'||(!empty&&!value)){
679
558
  invalidStack(label);
680
559
  }
681
560
  return value;
682
561
  }
683
562
 
684
563
  function validateRecord(record,index,{
685
- sessionId,
686
- maxDepth,
687
- maxEntries,
688
- maxStringLength
564
+ sessionId
689
565
  }){
690
566
  const label=`Event stack record ${String(index)}`;
691
567
  const fields=exactDataObject(record,RECORD_KEYS,label);
@@ -701,15 +577,15 @@ function validateRecord(record,index,{
701
577
  ||fields.monotonicMs<0){
702
578
  invalidStack(`${label} monotonic timing`);
703
579
  }
704
- boundedRecordString(fields.type,`${label} type`,maxStringLength);
705
- boundedRecordString(fields.source,`${label} source`,maxStringLength,{empty:false});
706
- boundedRecordString(fields.category,`${label} category`,maxStringLength,{
580
+ recordString(fields.type,`${label} type`);
581
+ recordString(fields.source,`${label} source`,{empty:false});
582
+ recordString(fields.category,`${label} category`,{
707
583
  nullable:true,empty:false
708
584
  });
709
- boundedRecordString(fields.correlationId,`${label} correlation`,maxStringLength,{
585
+ recordString(fields.correlationId,`${label} correlation`,{
710
586
  nullable:true,empty:false
711
587
  });
712
- boundedRecordString(fields.causationId,`${label} causation`,maxStringLength,{
588
+ recordString(fields.causationId,`${label} causation`,{
713
589
  nullable:true,empty:false
714
590
  });
715
591
  if(fields.parentSequence!==null
@@ -721,20 +597,16 @@ function validateRecord(record,index,{
721
597
  ||(fields.parentSequence===null)!==(fields.depth===0)){
722
598
  invalidStack(`${label} depth`);
723
599
  }
724
- boundedRecordString(fields.stack,`${label} stack`,maxStringLength,{nullable:true});
600
+ recordString(fields.stack,`${label} stack`,{nullable:true});
725
601
  if(!EVENT_STATUSES.has(fields.status))invalidStack(`${label} status`);
726
602
 
727
- const payloadValues=denseArrayValues(fields.payload,`${label} payload`,{
728
- maxLength:maxEntries+1
729
- });
603
+ const payloadValues=denseArrayValues(fields.payload,`${label} payload`);
730
604
  const payload=payloadValues.map((item,payloadIndex)=>cloneImportedValue(item,{
731
- maxDepth,maxEntries,maxStringLength,
732
605
  path:`$.events[${String(index)}].payload[${String(payloadIndex)}]`,
733
606
  depth:1,
734
607
  seen:new WeakSet()
735
608
  }));
736
609
  const metadata=cloneImportedValue(fields.metadata,{
737
- maxDepth,maxEntries,maxStringLength,
738
610
  path:`$.events[${String(index)}].metadata`,
739
611
  depth:0,
740
612
  seen:new WeakSet()
@@ -763,7 +635,6 @@ function validateRecord(record,index,{
763
635
  if(fields.error!==null)invalidStack(`${label} error`);
764
636
  }else{
765
637
  error=cloneImportedValue(fields.error,{
766
- maxDepth,maxEntries,maxStringLength,
767
638
  path:`$.events[${String(index)}].error`,
768
639
  depth:0,
769
640
  seen:new WeakSet()
@@ -798,21 +669,7 @@ function validateRecord(record,index,{
798
669
  ]);
799
670
  }
800
671
 
801
- export function parseEventStack(source,{
802
- maxEvents=DEFAULT_MAX_EVENTS,
803
- maxSnapshotDepth=DEFAULT_MAX_SNAPSHOT_DEPTH,
804
- maxSnapshotEntries=DEFAULT_MAX_SNAPSHOT_ENTRIES,
805
- maxSnapshotStringLength=DEFAULT_MAX_SNAPSHOT_STRING_LENGTH
806
- }={}){
807
- if(!Number.isSafeInteger(maxEvents)||maxEvents<1
808
- ||!Number.isSafeInteger(maxSnapshotDepth)||maxSnapshotDepth<1
809
- ||!Number.isSafeInteger(maxSnapshotEntries)||maxSnapshotEntries<1
810
- ||!Number.isSafeInteger(maxSnapshotStringLength)
811
- ||maxSnapshotStringLength<MIN_SNAPSHOT_STRING_LENGTH){
812
- throw new RangeError(
813
- 'Event stack import limits must be positive safe integers and the string limit must be at least 64.'
814
- );
815
- }
672
+ export function parseEventStack(source){
816
673
  let document=source;
817
674
  if(typeof source==='string'){
818
675
  try{document=JSON.parse(source);}catch(error){
@@ -821,23 +678,15 @@ export function parseEventStack(source,{
821
678
  }
822
679
  const fields=exactDataObject(document,DOCUMENT_KEYS,'The event stack document');
823
680
  if(fields.protocol!==ARCANE_EVENT_STACK_PROTOCOL
824
- ||typeof fields.sessionId!=='string'||!fields.sessionId
825
- ||fields.sessionId.length>256){
681
+ ||typeof fields.sessionId!=='string'||!fields.sessionId){
826
682
  invalidStack('The event stack document');
827
683
  }
828
684
  canonicalTimestamp(fields.createdAt,'The event stack creation timestamp');
829
- const sourceEvents=denseArrayValues(fields.events,'The event stack events',{
830
- maxLength:maxEvents+1
831
- });
685
+ const sourceEvents=denseArrayValues(fields.events,'The event stack events');
832
686
  let previous=0;
833
687
  const bySequence=new Map();
834
688
  const events=sourceEvents.map((record,index)=>{
835
- const validated=validateRecord(record,index,{
836
- sessionId:fields.sessionId,
837
- maxDepth:maxSnapshotDepth,
838
- maxEntries:maxSnapshotEntries,
839
- maxStringLength:maxSnapshotStringLength
840
- });
689
+ const validated=validateRecord(record,index,{sessionId:fields.sessionId});
841
690
  if(validated.sequence<=previous){
842
691
  throw new TypeError('Event stack sequences must be strictly increasing.');
843
692
  }
@@ -851,67 +700,22 @@ export function parseEventStack(source,{
851
700
  bySequence.set(validated.sequence,validated);
852
701
  return validated;
853
702
  });
854
- const overflowIndexes=[];
855
- for(let index=0;index<events.length;index+=1){
856
- if(events[index].type===TIME_TRAVEL_OVERFLOW_EVENT)overflowIndexes.push(index);
857
- }
858
- if(overflowIndexes.length>1
859
- ||(overflowIndexes.length===1&&overflowIndexes[0]!==events.length-1)
860
- ||(events.length>maxEvents
861
- &&(events.length!==maxEvents+1||overflowIndexes[0]!==events.length-1))){
862
- invalidStack('The event stack overflow history');
863
- }
864
- if(overflowIndexes.length===1){
865
- const overflow=events.at(-1);
866
- const payload=denseArrayValues(
867
- overflow.payload,'The event stack overflow payload',{maxLength:1}
868
- );
869
- if(payload.length!==1)invalidStack('The event stack overflow payload');
870
- const counts=exactDataObject(
871
- payload[0],['maxEvents','retainedEvents'],'The event stack overflow payload counts'
872
- );
873
- const metadata=exactDataObject(
874
- overflow.metadata,['maxEvents'],'The event stack overflow metadata'
875
- );
876
- const retainedEvents=events.length-1;
877
- if(overflow.source!=='event-manager'||overflow.category!=='overflow'
878
- ||overflow.correlationId!==null||overflow.causationId!==null
879
- ||overflow.parentSequence!==null||overflow.depth!==0||overflow.stack!==null
880
- ||overflow.status!=='completed'||overflow.completedAt!==overflow.timestamp
881
- ||overflow.durationMs!==0||overflow.error!==null
882
- ||!Number.isSafeInteger(counts.maxEvents)||counts.maxEvents<1
883
- ||!Number.isSafeInteger(counts.retainedEvents)||counts.retainedEvents<1
884
- ||counts.maxEvents!==counts.retainedEvents
885
- ||metadata.maxEvents!==counts.maxEvents
886
- ||retainedEvents!==counts.retainedEvents
887
- ||overflow.sequence!==retainedEvents+1
888
- ||counts.maxEvents>maxEvents){
889
- invalidStack('The event stack overflow record');
890
- }
891
- }
892
- return deepFreeze(dataObject([
703
+ return dataObject([
893
704
  ['protocol',ARCANE_EVENT_STACK_PROTOCOL],
894
705
  ['sessionId',fields.sessionId],
895
706
  ['createdAt',fields.createdAt],
896
707
  ['events',events]
897
- ]));
708
+ ]);
898
709
  }
899
710
 
900
711
  export class EventManager{
901
712
  #activeDispatch=[];
902
713
  #bus=new EventPubSub();
903
- #captureStacks;
904
714
  #clock;
905
715
  #cursor=0;
906
716
  #domInstrumentation=null;
907
717
  #history=[];
908
- #maxEvents;
909
- #maxSnapshotDepth;
910
- #maxSnapshotEntries;
911
- #maxSnapshotStringLength;
912
718
  #now;
913
- #overflowed=false;
914
- #redactSensitive;
915
719
  #replaying=false;
916
720
  #sequence=0;
917
721
  #sessionId;
@@ -920,41 +724,19 @@ export class EventManager{
920
724
  constructor({
921
725
  timeTravel=false,
922
726
  dom=null,
923
- captureStacks=false,
924
- redactSensitive=true,
925
- maxEvents=DEFAULT_MAX_EVENTS,
926
- maxSnapshotDepth=DEFAULT_MAX_SNAPSHOT_DEPTH,
927
- maxSnapshotEntries=DEFAULT_MAX_SNAPSHOT_ENTRIES,
928
- maxSnapshotStringLength=DEFAULT_MAX_SNAPSHOT_STRING_LENGTH,
929
727
  clock=()=>new Date(),
930
728
  now=defaultMonotonicClock,
931
729
  sessionId=sessionIdentifier()
932
730
  }={}){
933
- if(typeof timeTravel!=='boolean'||typeof captureStacks!=='boolean'
934
- ||typeof redactSensitive!=='boolean'){
731
+ if(typeof timeTravel!=='boolean'){
935
732
  throw new TypeError('EventManager flags must be boolean values.');
936
733
  }
937
734
  if(typeof clock!=='function'||typeof now!=='function'){
938
735
  throw new TypeError('EventManager clocks must be functions.');
939
736
  }
940
- if(!Number.isSafeInteger(maxEvents)||maxEvents<1
941
- ||!Number.isSafeInteger(maxSnapshotDepth)||maxSnapshotDepth<1
942
- ||!Number.isSafeInteger(maxSnapshotEntries)||maxSnapshotEntries<1
943
- ||!Number.isSafeInteger(maxSnapshotStringLength)
944
- ||maxSnapshotStringLength<MIN_SNAPSHOT_STRING_LENGTH){
945
- throw new RangeError(
946
- 'EventManager retention limits must be positive safe integers and the string limit must be at least 64.'
947
- );
948
- }
949
- if(typeof sessionId!=='string'||!sessionId||sessionId.length>256){
737
+ if(typeof sessionId!=='string'||!sessionId){
950
738
  throw new TypeError('EventManager sessionId must be a non-empty string.');
951
739
  }
952
- this.#captureStacks=captureStacks;
953
- this.#redactSensitive=redactSensitive;
954
- this.#maxEvents=maxEvents;
955
- this.#maxSnapshotDepth=maxSnapshotDepth;
956
- this.#maxSnapshotEntries=maxSnapshotEntries;
957
- this.#maxSnapshotStringLength=maxSnapshotStringLength;
958
740
  this.#clock=clock;
959
741
  this.#now=now;
960
742
  this.#sessionId=sessionId;
@@ -968,9 +750,7 @@ export class EventManager{
968
750
  get replaying(){return this.#replaying;}
969
751
  get cursor(){return this.#cursor;}
970
752
  get eventCount(){return this.#history.length;}
971
- get maxEvents(){return this.#maxEvents;}
972
- get overflowed(){return this.#overflowed;}
973
- get history(){return Object.freeze([...this.#history]);}
753
+ get history(){return [...this.#history];}
974
754
  get domInstrumentation(){return this.#domInstrumentation;}
975
755
 
976
756
  [EVENT_MANAGER_BUS_ON](type,handler,once=false){
@@ -1028,25 +808,14 @@ export class EventManager{
1028
808
  return this;
1029
809
  }
1030
810
  let recording=this.#timeTravelEnabled&&!this.#replaying;
1031
- if(recording&&this.#history.length>=this.#maxEvents){
1032
- this.#recordOverflow();
1033
- recording=false;
1034
- }
1035
811
  let draft=null;
1036
812
  let startedMonotonic=null;
1037
813
  if(recording){
1038
814
  try{
1039
815
  const timestamp=clockDate(this.#clock).toISOString();
1040
816
  startedMonotonic=monotonicValue(this.#now);
1041
- const snapshotOptions={
1042
- redactSensitive:this.#redactSensitive,
1043
- captureStacks:this.#captureStacks,
1044
- maxDepth:this.#maxSnapshotDepth,
1045
- maxEntries:this.#maxSnapshotEntries,
1046
- maxStringLength:this.#maxSnapshotStringLength
1047
- };
1048
- const payloadSnapshot=frozenSnapshot(payload,snapshotOptions);
1049
- const metadataSnapshot=frozenSnapshot(metadata,snapshotOptions);
817
+ const payloadSnapshot=completeSnapshot(payload);
818
+ const metadataSnapshot=completeSnapshot(metadata);
1050
819
  const safeMetadata=metadataSnapshot&&typeof metadataSnapshot==='object'
1051
820
  &&!Array.isArray(metadataSnapshot)
1052
821
  ?metadataSnapshot
@@ -1054,14 +823,10 @@ export class EventManager{
1054
823
  const sequence=this.#sequence+1;
1055
824
  const parentSequence=this.#activeDispatch.at(-1)??null;
1056
825
  let stack=null;
1057
- if(this.#captureStacks){
1058
- try{
1059
- stack=boundedString(sourceStack()??'',this.#maxSnapshotStringLength,{
1060
- redactSensitive:this.#redactSensitive
1061
- });
1062
- }catch{
1063
- stack='[STACK CAPTURE FAILED]';
1064
- }
826
+ try{
827
+ stack=safeString(sourceStack()??'');
828
+ }catch{
829
+ stack='[STACK CAPTURE FAILED]';
1065
830
  }
1066
831
  draft={
1067
832
  protocol:ARCANE_EVENT_STACK_PROTOCOL,
@@ -1070,42 +835,33 @@ export class EventManager{
1070
835
  sequence,
1071
836
  timestamp,
1072
837
  monotonicMs:startedMonotonic,
1073
- type:boundedString(type,this.#maxSnapshotStringLength,{
1074
- redactSensitive:this.#redactSensitive
1075
- }),
838
+ type:safeString(type),
1076
839
  source:typeof safeMetadata.source==='string'&&safeMetadata.source
1077
- ?boundedString(safeMetadata.source,this.#maxSnapshotStringLength,{
1078
- redactSensitive:this.#redactSensitive
1079
- })
840
+ ?safeString(safeMetadata.source)
1080
841
  :'application',
1081
842
  category:typeof safeMetadata.category==='string'&&safeMetadata.category
1082
- ?boundedString(safeMetadata.category,this.#maxSnapshotStringLength,{
1083
- redactSensitive:this.#redactSensitive
1084
- })
843
+ ?safeString(safeMetadata.category)
1085
844
  :null,
1086
845
  correlationId:typeof safeMetadata.correlationId==='string'
1087
846
  &&safeMetadata.correlationId
1088
- ?boundedString(safeMetadata.correlationId,this.#maxSnapshotStringLength,{
1089
- redactSensitive:this.#redactSensitive
1090
- }):null,
847
+ ?safeString(safeMetadata.correlationId):null,
1091
848
  causationId:typeof safeMetadata.causationId==='string'
1092
849
  &&safeMetadata.causationId
1093
- ?boundedString(safeMetadata.causationId,this.#maxSnapshotStringLength,{
1094
- redactSensitive:this.#redactSensitive
1095
- }):(parentSequence===null?null:`${this.#sessionId}:${parentSequence}`),
850
+ ?safeString(safeMetadata.causationId)
851
+ :(parentSequence===null?null:`${this.#sessionId}:${parentSequence}`),
1096
852
  parentSequence,
1097
853
  depth:this.#activeDispatch.length,
1098
854
  stack,
1099
855
  payload:Array.isArray(payloadSnapshot)
1100
856
  ?payloadSnapshot
1101
- :deepFreeze([payloadSnapshot]),
857
+ :[payloadSnapshot],
1102
858
  metadata:safeMetadata,
1103
859
  status:'dispatching',
1104
860
  completedAt:null,
1105
861
  durationMs:null,
1106
862
  error:null
1107
863
  };
1108
- this.#history.push(deepFreeze({...draft}));
864
+ this.#history.push({...draft});
1109
865
  this.#sequence=sequence;
1110
866
  this.#cursor=sequence;
1111
867
  this.#activeDispatch.push(sequence);
@@ -1137,47 +893,6 @@ export class EventManager{
1137
893
  return this;
1138
894
  }
1139
895
 
1140
- #recordOverflow(){
1141
- this.#overflowed=true;
1142
- this.#timeTravelEnabled=false;
1143
- try{this.#domInstrumentation?.stop({emitLifecycle:false});}catch{}
1144
- let timestamp;
1145
- let monotonicMs;
1146
- try{timestamp=clockDate(this.#clock).toISOString();}
1147
- catch{timestamp=new Date().toISOString();}
1148
- try{monotonicMs=monotonicValue(this.#now);}
1149
- catch{monotonicMs=Math.max(0,Number(this.#history.at(-1)?.monotonicMs??0));}
1150
- const sequence=++this.#sequence;
1151
- const payload=deepFreeze([snapshotObject([
1152
- ['maxEvents',this.#maxEvents],
1153
- ['retainedEvents',this.#history.length]
1154
- ])]);
1155
- const record=deepFreeze({
1156
- protocol:ARCANE_EVENT_STACK_PROTOCOL,
1157
- sessionId:this.#sessionId,
1158
- id:`${this.#sessionId}:${sequence}`,
1159
- sequence,
1160
- timestamp,
1161
- monotonicMs,
1162
- type:TIME_TRAVEL_OVERFLOW_EVENT,
1163
- source:'event-manager',
1164
- category:'overflow',
1165
- correlationId:null,
1166
- causationId:null,
1167
- parentSequence:null,
1168
- depth:0,
1169
- stack:null,
1170
- payload,
1171
- metadata:deepFreeze(snapshotObject([['maxEvents',this.#maxEvents]])),
1172
- status:'completed',
1173
- completedAt:timestamp,
1174
- durationMs:0,
1175
- error:null
1176
- });
1177
- this.#history.push(record);
1178
- this.#cursor=sequence;
1179
- }
1180
-
1181
896
  #finalize(draft,startedMonotonic,status,error){
1182
897
  try{
1183
898
  const index=this.#history.findIndex(record=>record.sequence===draft.sequence);
@@ -1193,26 +908,17 @@ export class EventManager{
1193
908
  try{
1194
909
  durationMs=Math.max(0,monotonicValue(this.#now)-startedMonotonic);
1195
910
  }catch{}
1196
- this.#history[index]=deepFreeze({
911
+ this.#history[index]={
1197
912
  ...draft,
1198
913
  status,
1199
914
  completedAt,
1200
915
  durationMs,
1201
- error:error===null?null:frozenErrorSnapshot(error,{
1202
- redactSensitive:this.#redactSensitive,
1203
- captureStacks:this.#captureStacks,
1204
- maxDepth:this.#maxSnapshotDepth,
1205
- maxEntries:this.#maxSnapshotEntries,
1206
- maxStringLength:this.#maxSnapshotStringLength
1207
- })
1208
- });
916
+ error:error===null?null:completeErrorSnapshot(error)
917
+ };
1209
918
  }catch{}
1210
919
  }
1211
920
 
1212
921
  enableTimeTravel({dom}={}){
1213
- if(this.#overflowed){
1214
- throw new Error('Clear the overflowed event history before enabling time travel again.');
1215
- }
1216
922
  const wasEnabled=this.#timeTravelEnabled;
1217
923
  this.#timeTravelEnabled=true;
1218
924
  try{
@@ -1243,7 +949,7 @@ export class EventManager{
1243
949
  }
1244
950
  try{
1245
951
  if(this.#timeTravelEnabled)replacement.start();
1246
- if(!this.#timeTravelEnabled||this.#overflowed){
952
+ if(!this.#timeTravelEnabled){
1247
953
  replacement.stop({emitLifecycle:false});
1248
954
  }
1249
955
  }catch(error){
@@ -1287,7 +993,6 @@ export class EventManager{
1287
993
  this.#sequence=0;
1288
994
  this.#cursor=0;
1289
995
  this.#activeDispatch=[];
1290
- this.#overflowed=false;
1291
996
  if(newSession)this.#sessionId=sessionIdentifier();
1292
997
  return this;
1293
998
  }
@@ -1298,10 +1003,10 @@ export class EventManager{
1298
1003
  ||(type!==null&&typeof type!=='string')){
1299
1004
  throw new TypeError('The event stack range is invalid.');
1300
1005
  }
1301
- return Object.freeze(this.#history.filter(record=>
1006
+ return this.#history.filter(record=>
1302
1007
  record.sequence>=fromSequence&&record.sequence<=toSequence
1303
1008
  &&(type===null||record.type===type)
1304
- ));
1009
+ );
1305
1010
  }
1306
1011
 
1307
1012
  exportStack({space=2}={}){
@@ -1351,12 +1056,7 @@ export class EventManager{
1351
1056
  if(this.#replaying)throw new Error('Event playback is already active.');
1352
1057
  const document=stack===null
1353
1058
  ?{protocol:ARCANE_EVENT_STACK_PROTOCOL,sessionId:this.#sessionId,events:this.#history}
1354
- :parseEventStack(stack,{
1355
- maxEvents:this.#maxEvents,
1356
- maxSnapshotDepth:this.#maxSnapshotDepth,
1357
- maxSnapshotEntries:this.#maxSnapshotEntries,
1358
- maxSnapshotStringLength:this.#maxSnapshotStringLength
1359
- });
1059
+ :parseEventStack(stack);
1360
1060
  const records=document.events.filter(record=>
1361
1061
  record.sequence>=fromSequence&&record.sequence<=toSequence
1362
1062
  );
@@ -1393,29 +1093,23 @@ export class EventManager{
1393
1093
  this.#cursor=record.sequence;
1394
1094
  delivered+=1;
1395
1095
  }
1396
- const result=Object.freeze({
1096
+ const result={
1397
1097
  sessionId:document.sessionId,
1398
1098
  delivered,
1399
1099
  cursor:this.#cursor,
1400
1100
  completed:true
1401
- });
1101
+ };
1402
1102
  this.#bus.emit(PLAYBACK_COMPLETED_EVENT,result);
1403
1103
  return result;
1404
1104
  }catch(error){
1405
1105
  const cancelled=signal?.aborted||error?.name==='AbortError';
1406
- this.#bus.emit(cancelled?PLAYBACK_CANCELLED_EVENT:PLAYBACK_FAILED_EVENT,Object.freeze({
1106
+ this.#bus.emit(cancelled?PLAYBACK_CANCELLED_EVENT:PLAYBACK_FAILED_EVENT,{
1407
1107
  sessionId:document.sessionId,
1408
1108
  delivered,
1409
1109
  cursor:this.#cursor,
1410
1110
  completed:false,
1411
- error:frozenSnapshot(error,{
1412
- redactSensitive:this.#redactSensitive,
1413
- captureStacks:this.#captureStacks,
1414
- maxDepth:this.#maxSnapshotDepth,
1415
- maxEntries:this.#maxSnapshotEntries,
1416
- maxStringLength:this.#maxSnapshotStringLength
1417
- })
1418
- }));
1111
+ error:completeSnapshot(error)
1112
+ });
1419
1113
  throw error;
1420
1114
  }finally{
1421
1115
  this.#replaying=false;
@@ -1440,7 +1134,6 @@ function eventName(value,code='ARCANE_EVENT_SUBSCRIPTION_TYPE_INVALID'){
1440
1134
  if(typeof value!=='string'
1441
1135
  ||value.trim()!==value
1442
1136
  ||value.length<1
1443
- ||value.length>128
1444
1137
  ||!ARCANE_EVENT_NAME_PATTERN.test(value)){
1445
1138
  throw eventAuthorityError(code,undefined,TypeError);
1446
1139
  }
@@ -1488,16 +1181,16 @@ function eventSignal(value){
1488
1181
 
1489
1182
  function eventListener(value){
1490
1183
  if(typeof value==='function'){
1491
- return Object.freeze({
1184
+ return {
1492
1185
  identity:value,
1493
1186
  invoke(event,thisArg,...rest){return value.call(thisArg,event,...rest);}
1494
- });
1187
+ };
1495
1188
  }
1496
1189
  if(value&&typeof value==='object'&&typeof value.handleEvent==='function'){
1497
- return Object.freeze({
1190
+ return {
1498
1191
  identity:value,
1499
1192
  invoke(event){return value.handleEvent(event);}
1500
- });
1193
+ };
1501
1194
  }
1502
1195
  throw eventAuthorityError(
1503
1196
  'ARCANE_EVENT_SUBSCRIPTION_HANDLER_INVALID',
@@ -1508,50 +1201,46 @@ function eventListener(value){
1508
1201
 
1509
1202
  function eventTargetListener(value){
1510
1203
  if(typeof value==='function'){
1511
- return Object.freeze({
1204
+ return {
1512
1205
  identity:value,
1513
1206
  invoke(event,thisArg,...rest){return value.call(thisArg,event,...rest);}
1514
- });
1207
+ };
1515
1208
  }
1516
1209
  if(value&&typeof value==='object'&&typeof value.handleEvent==='function'){
1517
- return Object.freeze({
1210
+ return {
1518
1211
  identity:value,
1519
1212
  invoke(event){return value.handleEvent(event);}
1520
- });
1213
+ };
1521
1214
  }
1522
1215
  return null;
1523
1216
  }
1524
1217
 
1525
1218
  function compatibilityDetail(value){
1526
1219
  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());
1220
+ if(Array.isArray(value))return value.slice();
1529
1221
  const prototype=Object.getPrototypeOf(value);
1530
1222
  if(prototype!==Object.prototype&&prototype!==null)return value;
1531
1223
  const copy=prototype===null?Object.create(null):{};
1532
1224
  for(const key of Reflect.ownKeys(value)){
1533
1225
  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
- }
1226
+ if(!descriptor)continue;
1227
+ let item;
1228
+ try{item=Reflect.get(value,key);}
1229
+ catch(error){item=snapshotFailure(error,{path:`$.${String(key)}`});}
1541
1230
  Object.defineProperty(copy,key,{
1542
- value:descriptor.value,
1231
+ value:item,
1543
1232
  enumerable:descriptor.enumerable,
1544
- configurable:false,
1545
- writable:false
1233
+ configurable:true,
1234
+ writable:true
1546
1235
  });
1547
1236
  }
1548
- return Object.freeze(copy);
1237
+ return copy;
1549
1238
  }
1550
1239
 
1551
1240
  function eventTargetOptions(value){
1552
- if(value===undefined)return Object.freeze({capture:false,once:false,signal:null});
1241
+ if(value===undefined)return {capture:false,once:false,signal:null};
1553
1242
  if(typeof value==='boolean'){
1554
- return Object.freeze({capture:value,once:false,signal:null});
1243
+ return {capture:value,once:false,signal:null};
1555
1244
  }
1556
1245
  const options=eventDataOptions(
1557
1246
  value,
@@ -1567,11 +1256,11 @@ function eventTargetOptions(value){
1567
1256
  );
1568
1257
  }
1569
1258
  }
1570
- return Object.freeze({
1259
+ return {
1571
1260
  capture:options.capture===true,
1572
1261
  once:options.once===true,
1573
1262
  signal:eventSignal(options.signal)
1574
- });
1263
+ };
1575
1264
  }
1576
1265
 
1577
1266
  function subscriptionOptions(value){
@@ -1587,18 +1276,18 @@ function subscriptionOptions(value){
1587
1276
  TypeError
1588
1277
  );
1589
1278
  }
1590
- return Object.freeze({
1279
+ return {
1591
1280
  once:options.once===true,
1592
1281
  signal:eventSignal(options.signal)
1593
- });
1282
+ };
1594
1283
  }
1595
1284
 
1596
1285
  function defineDisposable(unsubscribe){
1597
1286
  Object.defineProperty(unsubscribe,'dispose',{
1598
1287
  value:unsubscribe,
1599
1288
  enumerable:false,
1600
- configurable:false,
1601
- writable:false
1289
+ configurable:true,
1290
+ writable:true
1602
1291
  });
1603
1292
  return unsubscribe;
1604
1293
  }
@@ -1663,11 +1352,11 @@ function createArcaneEventAuthority(){
1663
1352
  let canonicalDispatchDepth=0;
1664
1353
  const pendingChannelRemovals=[];
1665
1354
 
1666
- const descriptor=Object.freeze({
1355
+ const descriptor={
1667
1356
  kind:ARCANE_EVENT_AUTHORITY_KIND,
1668
1357
  protocol:ARCANE_EVENT_AUTHORITY_PROTOCOL,
1669
1358
  realm:'current'
1670
- });
1359
+ };
1671
1360
 
1672
1361
  function nextOccurrenceId(){
1673
1362
  if(occurrenceSequence===Number.MAX_SAFE_INTEGER){
@@ -1697,13 +1386,17 @@ function createArcaneEventAuthority(){
1697
1386
  }
1698
1387
 
1699
1388
  function publicEventDetail(value){
1700
- return frozenSnapshot(value??{}, {
1701
- redactSensitive:true,
1702
- captureStacks:false,
1703
- maxDepth:16,
1704
- maxEntries:256,
1705
- maxStringLength:2_048
1706
- });
1389
+ return completeSnapshot(value??{});
1390
+ }
1391
+
1392
+ function completeEventDetail(compatibility,publicDetail){
1393
+ if(publicDetail===undefined)return compatibility??{};
1394
+ const compatibilityRecord=compatibility&&typeof compatibility==='object'
1395
+ &&!Array.isArray(compatibility);
1396
+ const publicRecord=publicDetail&&typeof publicDetail==='object'
1397
+ &&!Array.isArray(publicDetail);
1398
+ if(compatibilityRecord&&publicRecord)return {...compatibility,...publicDetail};
1399
+ return {compatibility,publicDetail};
1707
1400
  }
1708
1401
 
1709
1402
  function canonicalOccurrence({
@@ -1718,23 +1411,24 @@ function createArcaneEventAuthority(){
1718
1411
  let prevented=cancelable&&defaultPrevented;
1719
1412
  const occurrence={};
1720
1413
  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},
1414
+ protocol:{value:ARCANE_EVENT_OCCURRENCE_PROTOCOL,enumerable:true,writable:true,configurable:true},
1415
+ occurrenceId:{value:nextOccurrenceId(),enumerable:true,writable:true,configurable:true},
1416
+ type:{value:type,enumerable:true,writable:true,configurable:true},
1417
+ source:{value:source,enumerable:true,writable:true,configurable:true},
1418
+ instanceId:{value:instanceId,enumerable:true,writable:true,configurable:true},
1419
+ operationId:{value:operationId,enumerable:true,writable:true,configurable:true},
1420
+ detail:{value:detail,enumerable:true,writable:true,configurable:true},
1421
+ cancelable:{value:cancelable,enumerable:true,writable:true,configurable:true},
1422
+ defaultPrevented:{get(){return prevented;},enumerable:true,configurable:true},
1730
1423
  preventDefault:{
1731
1424
  value:function preventArcaneEventDefault(){
1732
1425
  if(cancelable)prevented=true;
1733
1426
  },
1734
- enumerable:true
1427
+ enumerable:true,
1428
+ writable:true,
1429
+ configurable:true
1735
1430
  }
1736
1431
  });
1737
- Object.freeze(occurrence);
1738
1432
  occurrences.add(occurrence);
1739
1433
  return occurrence;
1740
1434
  }
@@ -1742,27 +1436,26 @@ function createArcaneEventAuthority(){
1742
1436
  function compatibilityView(occurrence,detail,target=null){
1743
1437
  const view={};
1744
1438
  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}
1439
+ protocol:{value:occurrence.protocol,enumerable:true,writable:true,configurable:true},
1440
+ occurrenceId:{value:occurrence.occurrenceId,enumerable:true,writable:true,configurable:true},
1441
+ type:{value:occurrence.type,enumerable:true,writable:true,configurable:true},
1442
+ source:{value:occurrence.source,enumerable:true,writable:true,configurable:true},
1443
+ instanceId:{value:occurrence.instanceId,enumerable:true,writable:true,configurable:true},
1444
+ operationId:{value:occurrence.operationId,enumerable:true,writable:true,configurable:true},
1445
+ detail:{value:detail,enumerable:true,writable:true,configurable:true},
1446
+ target:{value:target,enumerable:true,writable:true,configurable:true},
1447
+ currentTarget:{value:target,enumerable:true,writable:true,configurable:true},
1448
+ cancelable:{value:occurrence.cancelable,enumerable:true,writable:true,configurable:true},
1449
+ defaultPrevented:{get(){return occurrence.defaultPrevented;},enumerable:true,configurable:true},
1450
+ preventDefault:{value:()=>occurrence.preventDefault(),enumerable:true,writable:true,configurable:true}
1757
1451
  });
1758
- Object.freeze(view);
1759
1452
  canonicalByView.set(view,occurrence);
1760
1453
  return view;
1761
1454
  }
1762
1455
 
1763
1456
  function removeChannelListener(channel,handler){
1764
1457
  if(canonicalDispatchDepth>0){
1765
- pendingChannelRemovals.push(Object.freeze({channel,handler}));
1458
+ pendingChannelRemovals.push({channel,handler});
1766
1459
  return;
1767
1460
  }
1768
1461
  manager[EVENT_MANAGER_BUS_OFF](channel,handler);
@@ -1837,15 +1530,16 @@ function createArcaneEventAuthority(){
1837
1530
  reportingListenerError=true;
1838
1531
  let errorOccurrence=null;
1839
1532
  try{
1840
- const detail=Object.freeze({
1533
+ const detail={
1841
1534
  code:'ARCANE_EVENT_LISTENER_CALLBACK_FAILED',
1842
1535
  reason:'listener-threw',
1843
1536
  eventType:occurrence?.type??null,
1844
1537
  occurrenceId:occurrence?.occurrenceId??null,
1845
1538
  source:occurrence?.source??ownerRecord?.source??'event-authority',
1846
1539
  instanceId:occurrence?.instanceId??ownerRecord?.instanceId??null,
1847
- operationId:occurrence?.operationId??null
1848
- });
1540
+ operationId:occurrence?.operationId??null,
1541
+ error
1542
+ };
1849
1543
  errorOccurrence=dispatchOccurrence({
1850
1544
  type:ARCANE_EVENT_LISTENER_ERROR_EVENT,
1851
1545
  sourceRecord:null,
@@ -1888,7 +1582,7 @@ function createArcaneEventAuthority(){
1888
1582
  source,
1889
1583
  instanceId,
1890
1584
  operationId,
1891
- detail:publicEventDetail(publicDetail),
1585
+ detail:publicEventDetail(completeEventDetail(compatibility,publicDetail)),
1892
1586
  cancelable,
1893
1587
  defaultPrevented
1894
1588
  });
@@ -1910,7 +1604,7 @@ function createArcaneEventAuthority(){
1910
1604
  {source,category:'semantic',correlationId:operationId}
1911
1605
  );
1912
1606
  }
1913
- return Object.freeze({occurrence,accepted:!occurrence.defaultPrevented});
1607
+ return {occurrence,accepted:!occurrence.defaultPrevented};
1914
1608
  }
1915
1609
 
1916
1610
  function subscribe(type,handler,options){
@@ -2008,8 +1702,7 @@ function createArcaneEventAuthority(){
2008
1702
  );
2009
1703
  const source=eventName(admitted.source,'ARCANE_EVENT_SOURCE_INVALID');
2010
1704
  if(!Array.isArray(admitted.eventTypes)
2011
- ||admitted.eventTypes.length<1
2012
- ||admitted.eventTypes.length>256){
1705
+ ||admitted.eventTypes.length<1){
2013
1706
  throw eventAuthorityError('ARCANE_EVENT_SOURCE_INVALID',undefined,TypeError);
2014
1707
  }
2015
1708
  const eventTypes=[];
@@ -2082,8 +1775,7 @@ function createArcaneEventAuthority(){
2082
1775
  const operationId=normalized.operationId??null;
2083
1776
  if(operationId!==null&&(typeof operationId!=='string'
2084
1777
  ||operationId.trim()!==operationId
2085
- ||operationId.length<1
2086
- ||operationId.length>256)){
1778
+ ||operationId.length<1)){
2087
1779
  throw eventAuthorityError('ARCANE_EVENT_OCCURRENCE_INVALID',undefined,TypeError);
2088
1780
  }
2089
1781
  if(normalized.cancelable!==undefined&&typeof normalized.cancelable!=='boolean'){
@@ -2095,7 +1787,7 @@ function createArcaneEventAuthority(){
2095
1787
  source:record.source,
2096
1788
  instanceId:record.instanceId,
2097
1789
  compatibility:detail,
2098
- publicDetail:normalized.publicDetail??{},
1790
+ publicDetail:normalized.publicDetail,
2099
1791
  operationId,
2100
1792
  cancelable:normalized.cancelable===true
2101
1793
  });
@@ -2109,12 +1801,12 @@ function createArcaneEventAuthority(){
2109
1801
  sourceRecord:record,
2110
1802
  source:record.source,
2111
1803
  instanceId:record.instanceId,
2112
- compatibility:Object.freeze({
1804
+ compatibility:{
2113
1805
  source:record.source,
2114
1806
  instanceId:record.instanceId,
2115
1807
  reason:'source-disposed'
2116
- }),
2117
- publicDetail:Object.freeze({reason:'source-disposed'}),
1808
+ },
1809
+ publicDetail:{reason:'source-disposed'},
2118
1810
  operationId:null,
2119
1811
  cancelable:false
2120
1812
  });
@@ -2127,13 +1819,13 @@ function createArcaneEventAuthority(){
2127
1819
  record.disposing=false;
2128
1820
  }
2129
1821
  }
2130
- const sourceDescriptor=Object.freeze({
1822
+ const sourceDescriptor={
2131
1823
  kind:ARCANE_EVENT_SOURCE_KIND,
2132
1824
  protocol:ARCANE_EVENT_SOURCE_PROTOCOL,
2133
1825
  source,
2134
1826
  instanceId:record.instanceId,
2135
- eventTypes:Object.freeze([...eventTypes,ARCANE_EVENT_SOURCE_DISPOSED_EVENT])
2136
- });
1827
+ eventTypes:[...eventTypes,ARCANE_EVENT_SOURCE_DISPOSED_EVENT]
1828
+ };
2137
1829
  const handle={
2138
1830
  protocol:ARCANE_EVENT_SOURCE_PROTOCOL,
2139
1831
  descriptor:sourceDescriptor,
@@ -2172,7 +1864,7 @@ function createArcaneEventAuthority(){
2172
1864
  get(){return record.disposing||record.disposed;},
2173
1865
  enumerable:true
2174
1866
  });
2175
- record.handle=Object.freeze(handle);
1867
+ record.handle=handle;
2176
1868
  sourceByOwner.set(owner,record);
2177
1869
  return record.handle;
2178
1870
  }
@@ -2210,14 +1902,15 @@ function createArcaneEventAuthority(){
2210
1902
  detail={};
2211
1903
  for(const key of Reflect.ownKeys(compatibility)){
2212
1904
  const descriptor=Object.getOwnPropertyDescriptor(compatibility,key);
2213
- if(!descriptor||!('value' in descriptor)){
2214
- throw eventAuthorityError('ARCANE_EVENT_COMPATIBILITY_DETAIL_INVALID');
2215
- }
1905
+ if(!descriptor)continue;
1906
+ let item;
1907
+ try{item=Reflect.get(compatibility,key);}
1908
+ catch(error){item=snapshotFailure(error,{path:`$.${String(key)}`});}
2216
1909
  Object.defineProperty(detail,key,{
2217
- value:descriptor.value,
1910
+ value:item,
2218
1911
  enumerable:descriptor.enumerable,
2219
- configurable:false,
2220
- writable:false
1912
+ configurable:true,
1913
+ writable:true
2221
1914
  });
2222
1915
  }
2223
1916
  }else{
@@ -2233,22 +1926,11 @@ function createArcaneEventAuthority(){
2233
1926
  if(Object.hasOwn(detail,key)&&detail[key]!==metadata[key]){
2234
1927
  throw eventAuthorityError('ARCANE_EVENT_DOM_DETAIL_COLLISION');
2235
1928
  }
2236
- Object.defineProperty(detail,key,{
2237
- value:metadata[key],
2238
- enumerable:true,
2239
- configurable:false,
2240
- writable:false
2241
- });
1929
+ detail[key]=metadata[key];
2242
1930
  }
2243
1931
  if(!Object.hasOwn(detail,'source')){
2244
- Object.defineProperty(detail,'source',{
2245
- value:metadata.arcaneSource,
2246
- enumerable:true,
2247
- configurable:false,
2248
- writable:false
2249
- });
1932
+ detail.source=metadata.arcaneSource;
2250
1933
  }
2251
- Object.freeze(detail);
2252
1934
  const cancelable=admitted.cancelable??occurrence.cancelable;
2253
1935
  const event=new CustomEvent(type,{
2254
1936
  detail,
@@ -2301,126 +1983,59 @@ function createArcaneEventAuthority(){
2301
1983
  return manager;
2302
1984
  }
2303
1985
 
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
1986
+ Object.assign(manager,{
1987
+ [ARCANE_EVENT_AUTHORITY_BRAND]:ARCANE_EVENT_AUTHORITY_PROTOCOL,
1988
+ protocol:ARCANE_EVENT_AUTHORITY_PROTOCOL,
1989
+ descriptor,
1990
+ on:safeLegacyOn,
1991
+ once:(type,handler)=>safeLegacyOn(type,handler,true),
1992
+ off:safeLegacyOff,
1993
+ reset:safeLegacyReset,
1994
+ subscribe,
1995
+ createSource,
1996
+ projectDOMEvent,
1997
+ isOccurrence:value=>occurrences.has(value)||canonicalByView.has(value),
1998
+ addEventListener(type,handler,options){
1999
+ addEventTargetListener(
2000
+ authorityTargetListeners,
2001
+ type,
2002
+ handler,
2003
+ options,
2004
+ subscribe,
2005
+ manager
2006
+ );
2336
2007
  },
2337
- removeEventListener:{
2338
- value(type,handler,options){
2339
- removeEventTargetListener(authorityTargetListeners,type,handler,options);
2340
- },
2341
- enumerable:true
2008
+ removeEventListener(type,handler,options){
2009
+ removeEventTargetListener(authorityTargetListeners,type,handler,options);
2342
2010
  },
2343
- dispatchEvent:{value:value=>dispatchEventLike(value),enumerable:true}
2011
+ dispatchEvent:value=>dispatchEventLike(value)
2344
2012
  });
2345
- return Object.freeze(manager);
2013
+ return manager;
2346
2014
  }
2347
2015
 
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;
2016
+ function usableArcaneEventAuthority(value){
2017
+ return Boolean(value)
2018
+ &&(typeof value==='object'||typeof value==='function')
2019
+ &&value.protocol===ARCANE_EVENT_AUTHORITY_PROTOCOL
2020
+ &&ARCANE_EVENT_REQUIRED_AUTHORITY_API.every(name=>typeof value[name]==='function');
2403
2021
  }
2404
2022
 
2405
2023
  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
- }
2024
+ let existing=null;
2025
+ try{existing=globalThis.arcaneEvents??null;}catch{}
2026
+ if(usableArcaneEventAuthority(existing))return existing;
2411
2027
  const authority=createArcaneEventAuthority();
2412
2028
  try{
2413
2029
  Object.defineProperty(globalThis,'arcaneEvents',{
2414
2030
  value:authority,
2415
2031
  enumerable:false,
2416
- configurable:false,
2417
- writable:false
2032
+ configurable:true,
2033
+ writable:true
2418
2034
  });
2419
2035
  }catch(error){
2420
2036
  throw eventAuthorityError('ARCANE_EVENT_AUTHORITY_INSTALL_FAILED',error);
2421
2037
  }
2422
- const installed=Object.getOwnPropertyDescriptor(globalThis,'arcaneEvents');
2423
- return validateInstalledArcaneEventAuthority(installed?.value,installed);
2038
+ return authority;
2424
2039
  }
2425
2040
 
2426
2041
  export const arcaneEvents=installArcaneEventAuthority();