@matter/general 0.16.0-alpha.0-20251205-dfb1e1556 → 0.16.0-alpha.0-20251207-37e501b18

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 (260) hide show
  1. package/dist/cjs/MatterError.js +2 -2
  2. package/dist/cjs/MatterError.js.map +1 -1
  3. package/dist/cjs/codec/DerTypes.d.ts.map +1 -1
  4. package/dist/cjs/codec/DerTypes.js +2 -1
  5. package/dist/cjs/codec/DerTypes.js.map +1 -1
  6. package/dist/cjs/environment/Environment.d.ts +4 -1
  7. package/dist/cjs/environment/Environment.d.ts.map +1 -1
  8. package/dist/cjs/environment/Environment.js +83 -3
  9. package/dist/cjs/environment/Environment.js.map +1 -1
  10. package/dist/cjs/environment/RuntimeService.d.ts +3 -44
  11. package/dist/cjs/environment/RuntimeService.d.ts.map +1 -1
  12. package/dist/cjs/environment/RuntimeService.js +65 -10
  13. package/dist/cjs/environment/RuntimeService.js.map +2 -2
  14. package/dist/cjs/environment/Worker.d.ts +56 -0
  15. package/dist/cjs/environment/Worker.d.ts.map +1 -0
  16. package/dist/cjs/environment/Worker.js +44 -0
  17. package/dist/cjs/environment/Worker.js.map +6 -0
  18. package/dist/cjs/environment/index.d.ts +1 -0
  19. package/dist/cjs/environment/index.d.ts.map +1 -1
  20. package/dist/cjs/environment/index.js +1 -0
  21. package/dist/cjs/environment/index.js.map +1 -1
  22. package/dist/cjs/log/Diagnostic.d.ts +11 -1
  23. package/dist/cjs/log/Diagnostic.d.ts.map +1 -1
  24. package/dist/cjs/log/Diagnostic.js +3 -0
  25. package/dist/cjs/log/Diagnostic.js.map +1 -1
  26. package/dist/cjs/log/DiagnosticPresentation.d.ts +4 -0
  27. package/dist/cjs/log/DiagnosticPresentation.d.ts.map +1 -1
  28. package/dist/cjs/log/DiagnosticPresentation.js +3 -2
  29. package/dist/cjs/log/DiagnosticPresentation.js.map +1 -1
  30. package/dist/cjs/log/DiagnosticSource.d.ts +1 -1
  31. package/dist/cjs/log/DiagnosticSource.d.ts.map +1 -1
  32. package/dist/cjs/log/DiagnosticSource.js +5 -1
  33. package/dist/cjs/log/DiagnosticSource.js.map +1 -1
  34. package/dist/cjs/log/LogFormat.js +2 -2
  35. package/dist/cjs/log/LogFormat.js.map +1 -1
  36. package/dist/cjs/net/Channel.d.ts +1 -1
  37. package/dist/cjs/net/Channel.d.ts.map +1 -1
  38. package/dist/cjs/net/Channel.js +1 -1
  39. package/dist/cjs/net/Channel.js.map +1 -1
  40. package/dist/cjs/net/mock/MockUdpChannel.d.ts +1 -1
  41. package/dist/cjs/net/mock/MockUdpChannel.d.ts.map +1 -1
  42. package/dist/cjs/net/mock/NetworkSimulator.d.ts.map +1 -1
  43. package/dist/cjs/net/mock/NetworkSimulator.js +2 -1
  44. package/dist/cjs/net/mock/NetworkSimulator.js.map +1 -1
  45. package/dist/cjs/net/udp/UdpChannel.d.ts +5 -1
  46. package/dist/cjs/net/udp/UdpChannel.d.ts.map +1 -1
  47. package/dist/cjs/net/udp/UdpMulticastServer.d.ts +4 -6
  48. package/dist/cjs/net/udp/UdpMulticastServer.d.ts.map +1 -1
  49. package/dist/cjs/net/udp/UdpMulticastServer.js +114 -37
  50. package/dist/cjs/net/udp/UdpMulticastServer.js.map +1 -1
  51. package/dist/cjs/time/StandardTime.d.ts +38 -0
  52. package/dist/cjs/time/StandardTime.d.ts.map +1 -0
  53. package/dist/cjs/time/StandardTime.js +172 -0
  54. package/dist/cjs/time/StandardTime.js.map +6 -0
  55. package/dist/cjs/time/Time.d.ts +4 -23
  56. package/dist/cjs/time/Time.d.ts.map +1 -1
  57. package/dist/cjs/time/Time.js +12 -88
  58. package/dist/cjs/time/Time.js.map +1 -1
  59. package/dist/cjs/time/Timestamp.d.ts +5 -0
  60. package/dist/cjs/time/Timestamp.d.ts.map +1 -1
  61. package/dist/cjs/time/Timestamp.js +4 -0
  62. package/dist/cjs/time/Timestamp.js.map +1 -1
  63. package/dist/cjs/time/index.d.ts +1 -0
  64. package/dist/cjs/time/index.d.ts.map +1 -1
  65. package/dist/cjs/time/index.js +1 -0
  66. package/dist/cjs/time/index.js.map +1 -1
  67. package/dist/cjs/transaction/Transaction.d.ts +12 -4
  68. package/dist/cjs/transaction/Transaction.d.ts.map +1 -1
  69. package/dist/cjs/transaction/Transaction.js +4 -4
  70. package/dist/cjs/transaction/Transaction.js.map +1 -1
  71. package/dist/cjs/transaction/Tx.d.ts +2 -1
  72. package/dist/cjs/transaction/Tx.d.ts.map +1 -1
  73. package/dist/cjs/transaction/Tx.js +92 -6
  74. package/dist/cjs/transaction/Tx.js.map +1 -1
  75. package/dist/cjs/util/Abort.js +1 -1
  76. package/dist/cjs/util/Abort.js.map +1 -1
  77. package/dist/cjs/util/Construction.d.ts +2 -1
  78. package/dist/cjs/util/Construction.d.ts.map +1 -1
  79. package/dist/cjs/util/Construction.js +60 -16
  80. package/dist/cjs/util/Construction.js.map +2 -2
  81. package/dist/cjs/util/DataReadQueue.d.ts +1 -5
  82. package/dist/cjs/util/DataReadQueue.d.ts.map +1 -1
  83. package/dist/cjs/util/DataReadQueue.js +12 -11
  84. package/dist/cjs/util/DataReadQueue.js.map +1 -1
  85. package/dist/cjs/util/FormattedText.d.ts +1 -1
  86. package/dist/cjs/util/FormattedText.d.ts.map +1 -1
  87. package/dist/cjs/util/FormattedText.js +1 -3
  88. package/dist/cjs/util/FormattedText.js.map +1 -1
  89. package/dist/cjs/util/Lifetime.d.ts +97 -0
  90. package/dist/cjs/util/Lifetime.d.ts.map +1 -0
  91. package/dist/cjs/util/Lifetime.js +166 -0
  92. package/dist/cjs/util/Lifetime.js.map +6 -0
  93. package/dist/cjs/util/Multiplex.js +2 -2
  94. package/dist/cjs/util/Multiplex.js.map +1 -1
  95. package/dist/cjs/util/Observable.d.ts +27 -26
  96. package/dist/cjs/util/Observable.d.ts.map +1 -1
  97. package/dist/cjs/util/Observable.js +76 -35
  98. package/dist/cjs/util/Observable.js.map +2 -2
  99. package/dist/cjs/util/String.d.ts +5 -29
  100. package/dist/cjs/util/String.d.ts.map +1 -1
  101. package/dist/cjs/util/String.js +16 -158
  102. package/dist/cjs/util/String.js.map +2 -2
  103. package/dist/cjs/util/identifier-case.d.ts +19 -0
  104. package/dist/cjs/util/identifier-case.d.ts.map +1 -0
  105. package/dist/cjs/util/identifier-case.js +99 -0
  106. package/dist/cjs/util/identifier-case.js.map +6 -0
  107. package/dist/cjs/util/index.d.ts +3 -0
  108. package/dist/cjs/util/index.d.ts.map +1 -1
  109. package/dist/cjs/util/index.js +3 -0
  110. package/dist/cjs/util/index.js.map +1 -1
  111. package/dist/cjs/util/serialize.d.ts +25 -0
  112. package/dist/cjs/util/serialize.d.ts.map +1 -0
  113. package/dist/cjs/util/serialize.js +116 -0
  114. package/dist/cjs/util/serialize.js.map +6 -0
  115. package/dist/esm/MatterError.js +1 -1
  116. package/dist/esm/codec/DerTypes.d.ts.map +1 -1
  117. package/dist/esm/codec/DerTypes.js +2 -1
  118. package/dist/esm/codec/DerTypes.js.map +1 -1
  119. package/dist/esm/environment/Environment.d.ts +4 -1
  120. package/dist/esm/environment/Environment.d.ts.map +1 -1
  121. package/dist/esm/environment/Environment.js +83 -3
  122. package/dist/esm/environment/Environment.js.map +1 -1
  123. package/dist/esm/environment/RuntimeService.d.ts +3 -44
  124. package/dist/esm/environment/RuntimeService.d.ts.map +1 -1
  125. package/dist/esm/environment/RuntimeService.js +65 -10
  126. package/dist/esm/environment/RuntimeService.js.map +2 -2
  127. package/dist/esm/environment/Worker.d.ts +56 -0
  128. package/dist/esm/environment/Worker.d.ts.map +1 -0
  129. package/dist/esm/environment/Worker.js +24 -0
  130. package/dist/esm/environment/Worker.js.map +6 -0
  131. package/dist/esm/environment/index.d.ts +1 -0
  132. package/dist/esm/environment/index.d.ts.map +1 -1
  133. package/dist/esm/environment/index.js +1 -0
  134. package/dist/esm/environment/index.js.map +1 -1
  135. package/dist/esm/log/Diagnostic.d.ts +11 -1
  136. package/dist/esm/log/Diagnostic.d.ts.map +1 -1
  137. package/dist/esm/log/Diagnostic.js +3 -0
  138. package/dist/esm/log/Diagnostic.js.map +1 -1
  139. package/dist/esm/log/DiagnosticPresentation.d.ts +4 -0
  140. package/dist/esm/log/DiagnosticPresentation.d.ts.map +1 -1
  141. package/dist/esm/log/DiagnosticPresentation.js +3 -2
  142. package/dist/esm/log/DiagnosticPresentation.js.map +1 -1
  143. package/dist/esm/log/DiagnosticSource.d.ts +1 -1
  144. package/dist/esm/log/DiagnosticSource.d.ts.map +1 -1
  145. package/dist/esm/log/DiagnosticSource.js +5 -1
  146. package/dist/esm/log/DiagnosticSource.js.map +1 -1
  147. package/dist/esm/log/LogFormat.js +1 -1
  148. package/dist/esm/log/LogFormat.js.map +1 -1
  149. package/dist/esm/net/Channel.d.ts +1 -1
  150. package/dist/esm/net/Channel.d.ts.map +1 -1
  151. package/dist/esm/net/Channel.js +1 -1
  152. package/dist/esm/net/Channel.js.map +1 -1
  153. package/dist/esm/net/mock/MockUdpChannel.d.ts +1 -1
  154. package/dist/esm/net/mock/MockUdpChannel.d.ts.map +1 -1
  155. package/dist/esm/net/mock/NetworkSimulator.d.ts.map +1 -1
  156. package/dist/esm/net/mock/NetworkSimulator.js +2 -1
  157. package/dist/esm/net/mock/NetworkSimulator.js.map +1 -1
  158. package/dist/esm/net/udp/UdpChannel.d.ts +5 -1
  159. package/dist/esm/net/udp/UdpChannel.d.ts.map +1 -1
  160. package/dist/esm/net/udp/UdpMulticastServer.d.ts +4 -6
  161. package/dist/esm/net/udp/UdpMulticastServer.d.ts.map +1 -1
  162. package/dist/esm/net/udp/UdpMulticastServer.js +114 -37
  163. package/dist/esm/net/udp/UdpMulticastServer.js.map +1 -1
  164. package/dist/esm/time/StandardTime.d.ts +38 -0
  165. package/dist/esm/time/StandardTime.d.ts.map +1 -0
  166. package/dist/esm/time/StandardTime.js +152 -0
  167. package/dist/esm/time/StandardTime.js.map +6 -0
  168. package/dist/esm/time/Time.d.ts +4 -23
  169. package/dist/esm/time/Time.d.ts.map +1 -1
  170. package/dist/esm/time/Time.js +12 -88
  171. package/dist/esm/time/Time.js.map +1 -1
  172. package/dist/esm/time/Timestamp.d.ts +5 -0
  173. package/dist/esm/time/Timestamp.d.ts.map +1 -1
  174. package/dist/esm/time/Timestamp.js +4 -0
  175. package/dist/esm/time/Timestamp.js.map +1 -1
  176. package/dist/esm/time/index.d.ts +1 -0
  177. package/dist/esm/time/index.d.ts.map +1 -1
  178. package/dist/esm/time/index.js +1 -0
  179. package/dist/esm/time/index.js.map +1 -1
  180. package/dist/esm/transaction/Transaction.d.ts +12 -4
  181. package/dist/esm/transaction/Transaction.d.ts.map +1 -1
  182. package/dist/esm/transaction/Transaction.js +4 -4
  183. package/dist/esm/transaction/Transaction.js.map +1 -1
  184. package/dist/esm/transaction/Tx.d.ts +2 -1
  185. package/dist/esm/transaction/Tx.d.ts.map +1 -1
  186. package/dist/esm/transaction/Tx.js +92 -6
  187. package/dist/esm/transaction/Tx.js.map +1 -1
  188. package/dist/esm/util/Abort.js +1 -1
  189. package/dist/esm/util/Abort.js.map +1 -1
  190. package/dist/esm/util/Construction.d.ts +2 -1
  191. package/dist/esm/util/Construction.d.ts.map +1 -1
  192. package/dist/esm/util/Construction.js +60 -16
  193. package/dist/esm/util/Construction.js.map +2 -2
  194. package/dist/esm/util/DataReadQueue.d.ts +1 -5
  195. package/dist/esm/util/DataReadQueue.d.ts.map +1 -1
  196. package/dist/esm/util/DataReadQueue.js +12 -11
  197. package/dist/esm/util/DataReadQueue.js.map +1 -1
  198. package/dist/esm/util/FormattedText.d.ts +1 -1
  199. package/dist/esm/util/FormattedText.d.ts.map +1 -1
  200. package/dist/esm/util/FormattedText.js +2 -4
  201. package/dist/esm/util/FormattedText.js.map +1 -1
  202. package/dist/esm/util/Lifetime.d.ts +97 -0
  203. package/dist/esm/util/Lifetime.d.ts.map +1 -0
  204. package/dist/esm/util/Lifetime.js +146 -0
  205. package/dist/esm/util/Lifetime.js.map +6 -0
  206. package/dist/esm/util/Multiplex.js +2 -2
  207. package/dist/esm/util/Multiplex.js.map +1 -1
  208. package/dist/esm/util/Observable.d.ts +27 -26
  209. package/dist/esm/util/Observable.d.ts.map +1 -1
  210. package/dist/esm/util/Observable.js +76 -35
  211. package/dist/esm/util/Observable.js.map +2 -2
  212. package/dist/esm/util/String.d.ts +5 -29
  213. package/dist/esm/util/String.d.ts.map +1 -1
  214. package/dist/esm/util/String.js +16 -158
  215. package/dist/esm/util/String.js.map +2 -2
  216. package/dist/esm/util/identifier-case.d.ts +19 -0
  217. package/dist/esm/util/identifier-case.d.ts.map +1 -0
  218. package/dist/esm/util/identifier-case.js +79 -0
  219. package/dist/esm/util/identifier-case.js.map +6 -0
  220. package/dist/esm/util/index.d.ts +3 -0
  221. package/dist/esm/util/index.d.ts.map +1 -1
  222. package/dist/esm/util/index.js +3 -0
  223. package/dist/esm/util/index.js.map +1 -1
  224. package/dist/esm/util/serialize.d.ts +25 -0
  225. package/dist/esm/util/serialize.d.ts.map +1 -0
  226. package/dist/esm/util/serialize.js +96 -0
  227. package/dist/esm/util/serialize.js.map +6 -0
  228. package/package.json +2 -2
  229. package/src/MatterError.ts +1 -1
  230. package/src/codec/DerTypes.ts +2 -1
  231. package/src/environment/Environment.ts +29 -4
  232. package/src/environment/RuntimeService.ts +19 -55
  233. package/src/environment/Worker.ts +75 -0
  234. package/src/environment/index.ts +1 -0
  235. package/src/log/Diagnostic.ts +15 -1
  236. package/src/log/DiagnosticPresentation.ts +7 -2
  237. package/src/log/DiagnosticSource.ts +5 -1
  238. package/src/log/LogFormat.ts +1 -1
  239. package/src/net/Channel.ts +2 -2
  240. package/src/net/mock/MockUdpChannel.ts +1 -1
  241. package/src/net/mock/NetworkSimulator.ts +2 -1
  242. package/src/net/udp/UdpChannel.ts +6 -1
  243. package/src/net/udp/UdpMulticastServer.ts +72 -34
  244. package/src/time/StandardTime.ts +122 -0
  245. package/src/time/Time.ts +13 -105
  246. package/src/time/Timestamp.ts +8 -0
  247. package/src/time/index.ts +1 -0
  248. package/src/transaction/Transaction.ts +19 -6
  249. package/src/transaction/Tx.ts +49 -2
  250. package/src/util/Abort.ts +1 -1
  251. package/src/util/Construction.ts +76 -18
  252. package/src/util/DataReadQueue.ts +14 -12
  253. package/src/util/FormattedText.ts +1 -1
  254. package/src/util/Lifetime.ts +284 -0
  255. package/src/util/Multiplex.ts +2 -2
  256. package/src/util/Observable.ts +132 -53
  257. package/src/util/String.ts +14 -215
  258. package/src/util/identifier-case.ts +101 -0
  259. package/src/util/index.ts +3 -0
  260. package/src/util/serialize.ts +129 -0
package/src/util/Abort.ts CHANGED
@@ -268,7 +268,7 @@ export namespace Abort {
268
268
  export function sleep(description: string, abort: Signal | undefined, duration: Duration) {
269
269
  let timer!: Timer;
270
270
  const rested = new Promise<void>(resolve => {
271
- timer = Time.getTimer(description, duration, resolve);
271
+ timer = Time.getTimer(description, duration, () => resolve());
272
272
  });
273
273
  return race(abort, rested).finally(timer.stop.bind(timer));
274
274
  }
@@ -4,10 +4,14 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ import { DiagnosticPresentation } from "#log/DiagnosticPresentation.js";
8
+ import { LogFormat } from "#log/LogFormat.js";
7
9
  import { Logger } from "../log/Logger.js";
8
10
  import { ImplementationError } from "../MatterError.js";
9
11
  import { asError, errorOf } from "./Error.js";
12
+ import { decamelize } from "./identifier-case.js";
10
13
  import { CrashedDependenciesError, CrashedDependencyError, Lifecycle } from "./Lifecycle.js";
14
+ import { Lifetime } from "./Lifetime.js";
11
15
  import { Observable } from "./Observable.js";
12
16
  import { MaybePromise } from "./Promises.js";
13
17
 
@@ -88,7 +92,7 @@ export namespace Constructable {
88
92
  /**
89
93
  * The promise implementing by an {@link Constructable#construction}.
90
94
  */
91
- export interface Construction<T> extends Promise<T> {
95
+ export interface Construction<T> extends Promise<T>, Lifetime.Owner {
92
96
  /**
93
97
  * If construction ends with an error, the error is saved here.
94
98
  */
@@ -237,9 +241,12 @@ export function Construction<const T extends Constructable>(
237
241
  let error: undefined | Error;
238
242
  let errorForDependencies: undefined | CrashedDependencyError;
239
243
  let primaryCauseHandled = false;
240
- let status = Lifecycle.Status.Inactive;
241
244
  let change: Observable<[status: Lifecycle.Status, subject: T]> | undefined;
242
245
 
246
+ // Lifecycle information that exists
247
+ let status = Lifecycle.Status.Inactive;
248
+ let lifetime: Lifetime | undefined;
249
+
243
250
  const self: Construction<any> = {
244
251
  [Symbol.toStringTag]: "Construction",
245
252
 
@@ -262,6 +269,10 @@ export function Construction<const T extends Constructable>(
262
269
  return primaryCauseHandled;
263
270
  },
264
271
 
272
+ join(...name: unknown[]) {
273
+ return activeLifetime().join(...name);
274
+ },
275
+
265
276
  start<const T, const A extends [], const This extends Construction<Constructable.Deferred<T, A>>>(
266
277
  this: This,
267
278
  ...args: A
@@ -272,7 +283,7 @@ export function Construction<const T extends Constructable>(
272
283
 
273
284
  assertDeferred(subject);
274
285
 
275
- status = Lifecycle.Status.Initializing;
286
+ setStatus(Lifecycle.Status.Initializing);
276
287
 
277
288
  try {
278
289
  const initializeDeferred = () => subject[Construction.construct](...args);
@@ -284,7 +295,7 @@ export function Construction<const T extends Constructable>(
284
295
  },
285
296
 
286
297
  assert(description?: string, dependency?: any) {
287
- Lifecycle.assertActive(status, description ?? subject.constructor.name);
298
+ Lifecycle.assertActive(status, description ?? nameOf(subject));
288
299
 
289
300
  if (arguments.length < 2) {
290
301
  return;
@@ -582,7 +593,7 @@ export function Construction<const T extends Constructable>(
582
593
 
583
594
  // Begin initialization. May throw synchronously or asynchronously
584
595
  function invokeInitializer(initializer: () => MaybePromise<void>) {
585
- status = Lifecycle.Status.Initializing;
596
+ setStatus(Lifecycle.Status.Initializing);
586
597
 
587
598
  initializerPromise = initializer();
588
599
 
@@ -609,14 +620,7 @@ export function Construction<const T extends Constructable>(
609
620
  return errorForDependencies;
610
621
  }
611
622
 
612
- let what;
613
- if (subject.toString === Object.prototype.toString) {
614
- what = subject.constructor.name;
615
- } else {
616
- what = subject.toString();
617
- }
618
-
619
- errorForDependencies = new CrashedDependencyError(what, "unavailable due to initialization error");
623
+ errorForDependencies = new CrashedDependencyError(nameOf(subject), "unavailable due to initialization error");
620
624
  errorForDependencies.subject = subject;
621
625
  errorForDependencies.cause = error;
622
626
  return errorForDependencies;
@@ -629,6 +633,28 @@ export function Construction<const T extends Constructable>(
629
633
 
630
634
  status = newStatus;
631
635
 
636
+ switch (status) {
637
+ case Lifecycle.Status.Initializing:
638
+ case Lifecycle.Status.Active:
639
+ case Lifecycle.Status.Destroying:
640
+ if (!lifetime) {
641
+ lifetime = joinOwner();
642
+ }
643
+
644
+ if (status === Lifecycle.Status.Destroying) {
645
+ lifetime.closing();
646
+ }
647
+ break;
648
+
649
+ default:
650
+ if (lifetime) {
651
+ lifetime.closing()[Symbol.dispose]();
652
+ lifetime[Symbol.dispose]();
653
+ lifetime = undefined;
654
+ }
655
+ break;
656
+ }
657
+
632
658
  if (change) {
633
659
  change.emit(status, subject);
634
660
  }
@@ -677,13 +703,30 @@ export function Construction<const T extends Constructable>(
677
703
 
678
704
  function createErrorHandler(name: string) {
679
705
  return (e: any) => {
680
- let what = subject.toString();
681
- if (what === "[object Object]") {
682
- what = subject.constructor.name;
683
- }
684
- unhandledError(`Unhandled error in ${what} ${name}:`, e);
706
+ unhandledError(`Unhandled error in ${nameOf(subject)} ${name}:`, e);
685
707
  };
686
708
  }
709
+
710
+ function activeLifetime() {
711
+ if (lifetime) {
712
+ if (status === Lifecycle.Status.Destroying) {
713
+ return lifetime.closing();
714
+ }
715
+
716
+ return lifetime;
717
+ }
718
+
719
+ // We are not in fact alive so create a zombie lifetime. Generally this is a bug but if it happens this allows
720
+ // us to handle without crashing and properly track lifetime spans
721
+ const zombie = joinOwner();
722
+ zombie[Symbol.dispose]();
723
+ return zombie;
724
+ }
725
+
726
+ function joinOwner() {
727
+ const lifetime = Lifetime.of(subject);
728
+ return lifetime.join(decamelize(nameOf(subject), " "));
729
+ }
687
730
  }
688
731
 
689
732
  export namespace Construction {
@@ -739,3 +782,18 @@ function assertDeferred<T>(subject: Constructable<T>): asserts subject is Constr
739
782
  throw new ImplementationError(`No initializer defined for ${subject}`);
740
783
  }
741
784
  }
785
+
786
+ function nameOf(subject: {}) {
787
+ if (DiagnosticPresentation.name in subject) {
788
+ const name = subject[DiagnosticPresentation.name];
789
+ if (name !== undefined) {
790
+ return LogFormat("plain")(name);
791
+ }
792
+ }
793
+
794
+ if (subject.toString === Object.prototype.toString) {
795
+ return subject.constructor.name;
796
+ }
797
+
798
+ return subject.toString();
799
+ }
@@ -10,6 +10,7 @@ import { Duration } from "#time/Duration.js";
10
10
  import { Minutes } from "#time/TimeUnit.js";
11
11
  import { MatterFlowError } from "../MatterError.js";
12
12
  import { Time, Timer } from "../time/Time.js";
13
+ import { asError } from "./Error.js";
13
14
  import { createPromise } from "./Promises.js";
14
15
  import { EndOfStreamError, NoResponseTimeoutError } from "./Streams.js";
15
16
 
@@ -37,21 +38,18 @@ export class DataReadQueue<T> {
37
38
  ),
38
39
  ).start(),
39
40
  };
40
- return promise;
41
- }
42
-
43
- async write(data: T) {
44
- this.push(data);
45
- }
46
41
 
47
- get size() {
48
- return this.#queue.length;
42
+ try {
43
+ return await promise;
44
+ } catch (e) {
45
+ // The stack trace where we created the error is useless (either a timer or close()) so replace here
46
+ const error = asError(e);
47
+ error.stack = new Error().stack;
48
+ throw error;
49
+ }
49
50
  }
50
51
 
51
- /**
52
- * Same as write but doesn't require the await required to satisfy {@link Stream#write}.
53
- */
54
- push(data: T) {
52
+ write(data: T) {
55
53
  if (this.#closed) throw new EndOfStreamError();
56
54
  if (this.#pendingRead !== undefined) {
57
55
  this.#pendingRead.timeoutTimer?.stop();
@@ -63,6 +61,10 @@ export class DataReadQueue<T> {
63
61
  this.#queue.push(data);
64
62
  }
65
63
 
64
+ get size() {
65
+ return this.#queue.length;
66
+ }
67
+
66
68
  close() {
67
69
  if (this.#closed) return;
68
70
  this.#closed = true;
@@ -6,7 +6,7 @@
6
6
 
7
7
  const INDENT = " ";
8
8
 
9
- export { camelize, describeList, serialize } from "./String.js";
9
+ export { describeList } from "./String.js";
10
10
 
11
11
  /**
12
12
  * Performs word wrap. Input is assumed to be a series of paragraphs separated by a newline. Output is an array of
@@ -0,0 +1,284 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { Diagnostic } from "#log/Diagnostic.js";
8
+ import { DiagnosticPresentation } from "#log/DiagnosticPresentation.js";
9
+ import { DiagnosticSource } from "#log/DiagnosticSource.js";
10
+ import { InternalError } from "#MatterError.js";
11
+ import { Duration } from "#time/Duration.js";
12
+ import "#time/StandardTime.js";
13
+ import { Time } from "#time/Time.js";
14
+ import { Timestamp } from "#time/Timestamp.js";
15
+
16
+ /**
17
+ * A "lifetime" represents the existence of an entity or ongoing task.
18
+ *
19
+ * This serves as a mechanism for tracking granular information about process state for diagnostic purposes. A lifetime
20
+ * is present in diagnostic reports until disposed.
21
+ *
22
+ * Lifetimes are hierarchical. Create sublifetimes using join().
23
+ */
24
+ export interface Lifetime extends Disposable, Diagnostic, Lifetime.Owner {
25
+ /**
26
+ * The name of the lifetime used for diagnostic presentation.
27
+ *
28
+ * Any diagnostic (so, any value) may serve as a name.
29
+ */
30
+ name: unknown;
31
+
32
+ /**
33
+ * The time at which the lifetime began.
34
+ */
35
+ readonly startedAt: Timestamp;
36
+
37
+ /**
38
+ * A "span" is a sub-lifetime created via {@link join}.
39
+ */
40
+ readonly spans: Set<Lifetime>;
41
+
42
+ /**
43
+ * Arbitrary details presented as a dictionary with {@link name}.
44
+ */
45
+ readonly details: Record<string, unknown>;
46
+
47
+ /**
48
+ * The inverse of {@link isClosing}.
49
+ */
50
+ readonly isOpen: boolean;
51
+
52
+ /**
53
+ * Set when the lifetime begins closing (via {@link closing}) or {@link isClosed} is true.
54
+ */
55
+ readonly isClosing: boolean;
56
+
57
+ /**
58
+ * Set when the lifetime has exited.
59
+ */
60
+ readonly isClosed: boolean;
61
+
62
+ /**
63
+ * The lifetime enclosing this lifetime.
64
+ *
65
+ * Only the process lifetime should have no owner. This field is writable so you can move ownership of a lifetime.
66
+ */
67
+ owner?: Lifetime;
68
+
69
+ /**
70
+ * Mark this lifetime as closing.
71
+ *
72
+ * Creates a sublifetime specifically for closing this lifetime. This supports the common pattern of tracking the
73
+ * close process associated with an active lifetime.
74
+ *
75
+ * Calling repeatedly returns the same sublifetime. Disposing the returned lifetime disposes this lifetime.
76
+ */
77
+ closing(): Lifetime;
78
+ }
79
+
80
+ export function Lifetime(...name: unknown[]) {
81
+ return Lifetime.process.join(...name);
82
+ }
83
+
84
+ class LifetimeImplementation implements Lifetime, Lifetime.Owner {
85
+ #name: unknown;
86
+ #owner?: Lifetime;
87
+ #startedAt: Timestamp;
88
+ #details?: Record<string, unknown>;
89
+ #spans?: Set<Lifetime>;
90
+ #closing?: Lifetime;
91
+ #isClosed = false;
92
+
93
+ declare [Diagnostic.presentation]: unknown;
94
+
95
+ constructor(name: unknown[], owner?: Lifetime) {
96
+ this.#name = name.length > 1 ? name : name[0];
97
+ this.#startedAt = Time.nowMs;
98
+ this.#owner = owner;
99
+
100
+ if (owner) {
101
+ owner.spans.add(this);
102
+ }
103
+ }
104
+
105
+ get spans() {
106
+ if (!this.#spans) {
107
+ this.#spans = new Set();
108
+ }
109
+ return this.#spans;
110
+ }
111
+
112
+ get name() {
113
+ return this.#name;
114
+ }
115
+
116
+ set name(name: unknown) {
117
+ this.#name = name;
118
+ }
119
+
120
+ get startedAt() {
121
+ return this.#startedAt;
122
+ }
123
+
124
+ get details() {
125
+ return this.#details ?? {};
126
+ }
127
+
128
+ get owner() {
129
+ return this.#owner;
130
+ }
131
+
132
+ set owner(owner: Lifetime | undefined) {
133
+ if (!this.#owner) {
134
+ throw new InternalError("Cannot move ownership of root lifetime");
135
+ }
136
+
137
+ if (this.#owner === owner) {
138
+ return;
139
+ }
140
+
141
+ removeSpan(this.owner, this);
142
+
143
+ this.#owner = owner;
144
+
145
+ this.#owner?.spans.add(this);
146
+ }
147
+
148
+ join(...name: unknown[]): Lifetime {
149
+ return new LifetimeImplementation(name, this);
150
+ }
151
+
152
+ closing(): Lifetime {
153
+ if (!this.#closing) {
154
+ this.#closing = this.join("closing");
155
+
156
+ const disposeClosing = this.#closing[Symbol.dispose].bind(this.#closing);
157
+
158
+ this.#closing[Symbol.dispose] = () => {
159
+ disposeClosing();
160
+
161
+ this[Symbol.dispose]();
162
+ };
163
+ }
164
+
165
+ return this.#closing;
166
+ }
167
+
168
+ get isOpen() {
169
+ return this.#closing === undefined && !this.#isClosed;
170
+ }
171
+
172
+ get isClosing() {
173
+ return this.#closing !== undefined || this.#isClosed;
174
+ }
175
+
176
+ get isClosed() {
177
+ return this.#isClosed;
178
+ }
179
+
180
+ get [DiagnosticPresentation.value]() {
181
+ // Special case for process lifetime
182
+ if (!this.#owner) {
183
+ return Diagnostic.node("🛠", "Lifetimes", {
184
+ children: this.spans,
185
+ });
186
+ }
187
+
188
+ const header: unknown[] = [this.#name];
189
+
190
+ if (this.isClosed) {
191
+ header.push(Diagnostic.weak("(zombie)"));
192
+ }
193
+
194
+ const details: Record<string, unknown> = {
195
+ up: Duration.format(Timestamp.delta(this.startedAt, Time.nowMs)),
196
+ ...this.#details,
197
+ };
198
+
199
+ header.push(Diagnostic.dict(details));
200
+
201
+ const result: unknown[] = [header];
202
+
203
+ if (this.#spans?.size) {
204
+ result.push(Diagnostic.list(this.spans));
205
+ }
206
+
207
+ return result;
208
+ }
209
+
210
+ [Symbol.dispose]() {
211
+ if (!this.#owner) {
212
+ // Can't dispose of process lifetime
213
+ return;
214
+ }
215
+
216
+ this.#isClosed = true;
217
+
218
+ // If we are disposed with active sublifetimess we become a zombie
219
+ if (this.#spans?.size) {
220
+ return;
221
+ }
222
+
223
+ removeSpan(this.#owner, this);
224
+ }
225
+ }
226
+
227
+ function removeSpan(owner: Lifetime | undefined, span: Lifetime) {
228
+ if (!owner) {
229
+ return;
230
+ }
231
+
232
+ owner.spans.delete(span);
233
+ if (owner.isClosed && !owner.spans?.size) {
234
+ owner[Symbol.dispose]();
235
+ }
236
+ }
237
+
238
+ export namespace Lifetime {
239
+ /**
240
+ * The lifetime of the system process.
241
+ *
242
+ * This is effectively a "global" lifetime. It parents all other lifetimes.
243
+ */
244
+ export const process: Lifetime.Owner = new LifetimeImplementation(["process"]);
245
+
246
+ /**
247
+ * Obtain a lifetime not attached to {@link process} for testing purposes.
248
+ */
249
+ export declare const mock: Lifetime;
250
+
251
+ /**
252
+ * An object associated with a lifetime.
253
+ */
254
+ export interface Owner {
255
+ /**
256
+ * Create or move a sublifetime.
257
+ */
258
+ join(...name: unknown[]): Lifetime;
259
+ }
260
+
261
+ /**
262
+ * A lifetime subject that exists for a portion of a larger timespan.
263
+ */
264
+ export interface Contributor {
265
+ [owner]: Owner;
266
+ }
267
+
268
+ /**
269
+ * Determine the lifetime of the owner of a component.
270
+ */
271
+ export function of(subject?: {}) {
272
+ return (subject as Partial<Contributor> | undefined)?.[owner] ?? process;
273
+ }
274
+
275
+ export const owner = Symbol("owner");
276
+ }
277
+
278
+ Object.defineProperty(Lifetime, "mock", {
279
+ get() {
280
+ return new LifetimeImplementation(["mock"]);
281
+ },
282
+ });
283
+
284
+ DiagnosticSource.add(Lifetime.process as Lifetime);
@@ -39,9 +39,9 @@ export class BasicMultiplex implements PromiseLike<void> {
39
39
  const entry = {
40
40
  done: Promise.resolve(worker)
41
41
  .catch(e => {
42
- let message = "Unhandled error";
42
+ let message = "Error";
43
43
  if (description) {
44
- message = `${message} in ${description}`;
44
+ message = `${message} ${description}`;
45
45
  }
46
46
  logger.error(`${message}:`, e);
47
47
  })