@matter/general 0.14.1-alpha.0-20250607-a93593303 → 0.15.0-alpha.0-20250612-ddd428561

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 (185) hide show
  1. package/dist/cjs/codec/DerCodec.d.ts +12 -17
  2. package/dist/cjs/codec/DerCodec.d.ts.map +1 -1
  3. package/dist/cjs/codec/DerCodec.js +90 -51
  4. package/dist/cjs/codec/DerCodec.js.map +1 -1
  5. package/dist/cjs/codec/DerTypes.js +1 -1
  6. package/dist/cjs/codec/DnsCodec.d.ts +5 -5
  7. package/dist/cjs/crypto/Crypto.d.ts +111 -62
  8. package/dist/cjs/crypto/Crypto.d.ts.map +1 -1
  9. package/dist/cjs/crypto/Crypto.js +92 -31
  10. package/dist/cjs/crypto/Crypto.js.map +1 -1
  11. package/dist/cjs/crypto/CryptoError.d.ts +32 -0
  12. package/dist/cjs/crypto/CryptoError.d.ts.map +1 -0
  13. package/dist/cjs/crypto/CryptoError.js +44 -0
  14. package/dist/cjs/crypto/CryptoError.js.map +6 -0
  15. package/dist/cjs/crypto/Key.d.ts +2 -2
  16. package/dist/cjs/crypto/Key.d.ts.map +1 -1
  17. package/dist/cjs/crypto/Key.js +15 -16
  18. package/dist/cjs/crypto/Key.js.map +1 -1
  19. package/dist/cjs/crypto/Spake2p.js +5 -5
  20. package/dist/cjs/crypto/Spake2p.js.map +1 -1
  21. package/dist/cjs/crypto/StandardCrypto.d.ts +33 -0
  22. package/dist/cjs/crypto/StandardCrypto.d.ts.map +1 -0
  23. package/dist/cjs/crypto/StandardCrypto.js +208 -0
  24. package/dist/cjs/crypto/StandardCrypto.js.map +6 -0
  25. package/dist/cjs/crypto/aes/Aes.d.ts +21 -0
  26. package/dist/cjs/crypto/aes/Aes.d.ts.map +1 -0
  27. package/dist/cjs/crypto/aes/Aes.js +132 -0
  28. package/dist/cjs/crypto/aes/Aes.js.map +6 -0
  29. package/dist/cjs/crypto/aes/Ccm.d.ts +71 -0
  30. package/dist/cjs/crypto/aes/Ccm.d.ts.map +1 -0
  31. package/dist/cjs/crypto/aes/Ccm.js +194 -0
  32. package/dist/cjs/crypto/aes/Ccm.js.map +6 -0
  33. package/dist/cjs/crypto/aes/WordArray.d.ts +30 -0
  34. package/dist/cjs/crypto/aes/WordArray.d.ts.map +1 -0
  35. package/dist/cjs/crypto/aes/WordArray.js +91 -0
  36. package/dist/cjs/crypto/aes/WordArray.js.map +6 -0
  37. package/dist/cjs/crypto/index.d.ts +3 -0
  38. package/dist/cjs/crypto/index.d.ts.map +1 -1
  39. package/dist/cjs/crypto/index.js +3 -0
  40. package/dist/cjs/crypto/index.js.map +1 -1
  41. package/dist/cjs/crypto/nonentropic.d.ts +16 -0
  42. package/dist/cjs/crypto/nonentropic.d.ts.map +1 -0
  43. package/dist/cjs/crypto/nonentropic.js +70 -0
  44. package/dist/cjs/crypto/nonentropic.js.map +6 -0
  45. package/dist/cjs/environment/Environment.d.ts.map +1 -1
  46. package/dist/cjs/environment/Environment.js +1 -5
  47. package/dist/cjs/environment/Environment.js.map +1 -1
  48. package/dist/cjs/environment/RuntimeService.d.ts +2 -4
  49. package/dist/cjs/environment/RuntimeService.d.ts.map +1 -1
  50. package/dist/cjs/environment/RuntimeService.js +4 -4
  51. package/dist/cjs/environment/RuntimeService.js.map +1 -1
  52. package/dist/cjs/environment/VariableService.d.ts.map +1 -1
  53. package/dist/cjs/environment/VariableService.js +1 -0
  54. package/dist/cjs/environment/VariableService.js.map +1 -1
  55. package/dist/cjs/log/LogFormat.js +17 -11
  56. package/dist/cjs/log/LogFormat.js.map +1 -1
  57. package/dist/cjs/net/Network.d.ts +0 -1
  58. package/dist/cjs/net/Network.d.ts.map +1 -1
  59. package/dist/cjs/net/Network.js +0 -4
  60. package/dist/cjs/net/Network.js.map +1 -1
  61. package/dist/cjs/time/Time.d.ts.map +1 -1
  62. package/dist/cjs/time/Time.js +2 -2
  63. package/dist/cjs/time/Time.js.map +1 -1
  64. package/dist/cjs/util/Bytes.d.ts +6 -0
  65. package/dist/cjs/util/Bytes.d.ts.map +1 -1
  66. package/dist/cjs/util/Bytes.js +15 -1
  67. package/dist/cjs/util/Bytes.js.map +1 -1
  68. package/dist/cjs/util/DataWriter.d.ts +1 -1
  69. package/dist/cjs/util/DataWriter.js +2 -2
  70. package/dist/cjs/util/DataWriter.js.map +1 -1
  71. package/dist/cjs/util/DeepCopy.js +1 -1
  72. package/dist/cjs/util/DeepCopy.js.map +1 -1
  73. package/dist/cjs/util/GeneratedClass.d.ts +3 -3
  74. package/dist/cjs/util/GeneratedClass.d.ts.map +1 -1
  75. package/dist/cjs/util/GeneratedClass.js +99 -73
  76. package/dist/cjs/util/GeneratedClass.js.map +2 -2
  77. package/dist/cjs/util/Number.d.ts +0 -1
  78. package/dist/cjs/util/Number.d.ts.map +1 -1
  79. package/dist/cjs/util/Number.js +0 -4
  80. package/dist/cjs/util/Number.js.map +1 -1
  81. package/dist/esm/codec/DerCodec.d.ts +12 -17
  82. package/dist/esm/codec/DerCodec.d.ts.map +1 -1
  83. package/dist/esm/codec/DerCodec.js +90 -51
  84. package/dist/esm/codec/DerCodec.js.map +1 -1
  85. package/dist/esm/codec/DerTypes.js +2 -2
  86. package/dist/esm/codec/DnsCodec.d.ts +5 -5
  87. package/dist/esm/crypto/Crypto.d.ts +111 -62
  88. package/dist/esm/crypto/Crypto.d.ts.map +1 -1
  89. package/dist/esm/crypto/Crypto.js +93 -32
  90. package/dist/esm/crypto/Crypto.js.map +1 -1
  91. package/dist/esm/crypto/CryptoError.d.ts +32 -0
  92. package/dist/esm/crypto/CryptoError.d.ts.map +1 -0
  93. package/dist/esm/crypto/CryptoError.js +24 -0
  94. package/dist/esm/crypto/CryptoError.js.map +6 -0
  95. package/dist/esm/crypto/Key.d.ts +2 -2
  96. package/dist/esm/crypto/Key.d.ts.map +1 -1
  97. package/dist/esm/crypto/Key.js +15 -16
  98. package/dist/esm/crypto/Key.js.map +1 -1
  99. package/dist/esm/crypto/Spake2p.js +5 -5
  100. package/dist/esm/crypto/Spake2p.js.map +1 -1
  101. package/dist/esm/crypto/StandardCrypto.d.ts +33 -0
  102. package/dist/esm/crypto/StandardCrypto.d.ts.map +1 -0
  103. package/dist/esm/crypto/StandardCrypto.js +188 -0
  104. package/dist/esm/crypto/StandardCrypto.js.map +6 -0
  105. package/dist/esm/crypto/aes/Aes.d.ts +21 -0
  106. package/dist/esm/crypto/aes/Aes.d.ts.map +1 -0
  107. package/dist/esm/crypto/aes/Aes.js +112 -0
  108. package/dist/esm/crypto/aes/Aes.js.map +6 -0
  109. package/dist/esm/crypto/aes/Ccm.d.ts +71 -0
  110. package/dist/esm/crypto/aes/Ccm.d.ts.map +1 -0
  111. package/dist/esm/crypto/aes/Ccm.js +174 -0
  112. package/dist/esm/crypto/aes/Ccm.js.map +6 -0
  113. package/dist/esm/crypto/aes/WordArray.d.ts +30 -0
  114. package/dist/esm/crypto/aes/WordArray.d.ts.map +1 -0
  115. package/dist/esm/crypto/aes/WordArray.js +71 -0
  116. package/dist/esm/crypto/aes/WordArray.js.map +6 -0
  117. package/dist/esm/crypto/index.d.ts +3 -0
  118. package/dist/esm/crypto/index.d.ts.map +1 -1
  119. package/dist/esm/crypto/index.js +3 -0
  120. package/dist/esm/crypto/index.js.map +1 -1
  121. package/dist/esm/crypto/nonentropic.d.ts +16 -0
  122. package/dist/esm/crypto/nonentropic.d.ts.map +1 -0
  123. package/dist/esm/crypto/nonentropic.js +50 -0
  124. package/dist/esm/crypto/nonentropic.js.map +6 -0
  125. package/dist/esm/environment/Environment.d.ts.map +1 -1
  126. package/dist/esm/environment/Environment.js +1 -5
  127. package/dist/esm/environment/Environment.js.map +1 -1
  128. package/dist/esm/environment/RuntimeService.d.ts +2 -4
  129. package/dist/esm/environment/RuntimeService.d.ts.map +1 -1
  130. package/dist/esm/environment/RuntimeService.js +4 -4
  131. package/dist/esm/environment/RuntimeService.js.map +1 -1
  132. package/dist/esm/environment/VariableService.d.ts.map +1 -1
  133. package/dist/esm/environment/VariableService.js +1 -0
  134. package/dist/esm/environment/VariableService.js.map +1 -1
  135. package/dist/esm/log/LogFormat.js +17 -11
  136. package/dist/esm/log/LogFormat.js.map +1 -1
  137. package/dist/esm/net/Network.d.ts +0 -1
  138. package/dist/esm/net/Network.d.ts.map +1 -1
  139. package/dist/esm/net/Network.js +1 -5
  140. package/dist/esm/net/Network.js.map +1 -1
  141. package/dist/esm/time/Time.d.ts.map +1 -1
  142. package/dist/esm/time/Time.js +2 -2
  143. package/dist/esm/time/Time.js.map +1 -1
  144. package/dist/esm/util/Bytes.d.ts +6 -0
  145. package/dist/esm/util/Bytes.d.ts.map +1 -1
  146. package/dist/esm/util/Bytes.js +15 -1
  147. package/dist/esm/util/Bytes.js.map +1 -1
  148. package/dist/esm/util/DataWriter.d.ts +1 -1
  149. package/dist/esm/util/DataWriter.js +3 -3
  150. package/dist/esm/util/DataWriter.js.map +1 -1
  151. package/dist/esm/util/DeepCopy.js +1 -1
  152. package/dist/esm/util/DeepCopy.js.map +1 -1
  153. package/dist/esm/util/GeneratedClass.d.ts +3 -3
  154. package/dist/esm/util/GeneratedClass.d.ts.map +1 -1
  155. package/dist/esm/util/GeneratedClass.js +97 -71
  156. package/dist/esm/util/GeneratedClass.js.map +2 -2
  157. package/dist/esm/util/Number.d.ts +0 -1
  158. package/dist/esm/util/Number.d.ts.map +1 -1
  159. package/dist/esm/util/Number.js +0 -4
  160. package/dist/esm/util/Number.js.map +1 -1
  161. package/package.json +3 -3
  162. package/src/codec/DerCodec.ts +106 -52
  163. package/src/codec/DerTypes.ts +2 -2
  164. package/src/crypto/Crypto.ts +196 -76
  165. package/src/crypto/CryptoError.ts +32 -0
  166. package/src/crypto/Key.ts +17 -18
  167. package/src/crypto/Spake2p.ts +5 -5
  168. package/src/crypto/StandardCrypto.ts +252 -0
  169. package/src/crypto/aes/Aes.ts +210 -0
  170. package/src/crypto/aes/Ccm.ts +350 -0
  171. package/src/crypto/aes/README.md +4 -0
  172. package/src/crypto/aes/WordArray.ts +105 -0
  173. package/src/crypto/index.ts +3 -0
  174. package/src/crypto/nonentropic.ts +65 -0
  175. package/src/environment/Environment.ts +1 -6
  176. package/src/environment/RuntimeService.ts +5 -5
  177. package/src/environment/VariableService.ts +1 -0
  178. package/src/log/LogFormat.ts +19 -11
  179. package/src/net/Network.ts +1 -7
  180. package/src/time/Time.ts +4 -4
  181. package/src/util/Bytes.ts +19 -0
  182. package/src/util/DataWriter.ts +3 -3
  183. package/src/util/DeepCopy.ts +2 -2
  184. package/src/util/GeneratedClass.ts +161 -102
  185. package/src/util/Number.ts +0 -4
package/src/time/Time.ts CHANGED
@@ -101,10 +101,6 @@ if (!performance || typeof performance.now !== "function" || typeof performance.
101
101
  Time.prototype.nowUs = () => Time.nowMs() * 1000; // Fallback is a bit less accurate
102
102
  }
103
103
 
104
- const time = new Time();
105
-
106
- Time.startup.systemMs = Time.startup.processMs = time.nowMs();
107
-
108
104
  export interface Timer {
109
105
  /** Name (diagnostics) */
110
106
  name: string;
@@ -221,6 +217,10 @@ DiagnosticSource.add({
221
217
  });
222
218
 
223
219
  Boot.init(() => {
220
+ const time = new Time();
221
+
222
+ Time.startup.systemMs = Time.startup.processMs = time.nowMs();
223
+
224
224
  Time.get = () => time;
225
225
 
226
226
  // Hook for testing frameworks
package/src/util/Bytes.ts CHANGED
@@ -11,6 +11,25 @@ export enum Endian {
11
11
  Big,
12
12
  }
13
13
 
14
+ /**
15
+ * A string tag for hex literals.
16
+ *
17
+ * Example: b$`01020304` creates a four-byte Uint8Array.
18
+ */
19
+ export function b$(strings: TemplateStringsArray, ...values: unknown[]) {
20
+ if (strings.length === 1 && values.length === 0) {
21
+ return Bytes.fromHex(strings[0]);
22
+ }
23
+ const parts = Array<string>();
24
+ for (let i = 0; i < strings.length; i++) {
25
+ parts.push(strings[i]);
26
+ if (i < values.length) {
27
+ parts.push(`${values[i]}`);
28
+ }
29
+ }
30
+ return Bytes.fromHex(parts.join(""));
31
+ }
32
+
14
33
  /**
15
34
  * Utility functions for manipulating Uint8Array.
16
35
  */
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import { Endian } from "./Bytes.js";
8
- import { toBigInt, toNumber } from "./Number.js";
8
+ import { toNumber } from "./Number.js";
9
9
 
10
10
  /** Writer that auto-increments its offset after each write. */
11
11
  // TODO: some research should be done to make sure this is most performant implementation.
@@ -39,7 +39,7 @@ export class DataWriter<E extends Endian = Endian.Big> {
39
39
 
40
40
  writeUInt64(value: number | bigint) {
41
41
  const chunk = new Uint8Array(8);
42
- new DataView(chunk.buffer, 0, 8).setBigUint64(0, toBigInt(value), this.littleEndian);
42
+ new DataView(chunk.buffer, 0, 8).setBigUint64(0, BigInt(value), this.littleEndian);
43
43
  this.chunks.push(chunk);
44
44
  this.length += 8;
45
45
  }
@@ -67,7 +67,7 @@ export class DataWriter<E extends Endian = Endian.Big> {
67
67
 
68
68
  writeInt64(value: number | bigint) {
69
69
  const chunk = new Uint8Array(8);
70
- new DataView(chunk.buffer, 0, 8).setBigInt64(0, toBigInt(value), this.littleEndian);
70
+ new DataView(chunk.buffer, 0, 8).setBigInt64(0, BigInt(value), this.littleEndian);
71
71
  this.chunks.push(chunk);
72
72
  this.length += 8;
73
73
  }
@@ -26,8 +26,8 @@ export function deepCopy<T>(value: T): T {
26
26
  if (Array.isArray(value)) {
27
27
  clone = value.map(copy);
28
28
  } else if (ArrayBuffer.isView(value)) {
29
- const ViewType = value.constructor as new (buffer: ArrayBuffer | SharedArrayBuffer) => unknown;
30
- clone = new ViewType(value.buffer.slice(value.byteOffset, value.byteOffset + value.byteLength));
29
+ const ViewType = value.constructor as unknown as { from(v: typeof value): typeof value };
30
+ clone = ViewType.from(value);
31
31
  } else {
32
32
  clone = Object.fromEntries(Object.entries(value).map(([k, v]) => [k, copy(v)]));
33
33
  }
@@ -4,48 +4,29 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
- import { InternalError } from "../MatterError.js";
8
-
9
7
  /**
10
8
  * Helper function for class generation.
11
9
  *
12
10
  * This factory does not offer TypeScript types for the resulting class. You must cast separately.
13
11
  */
14
12
  export function GeneratedClass(options: GeneratedClass.Options) {
15
- const { base, name, args, mixins } = options;
13
+ const { base, name, beforeSuper, mixins: extraMixins } = options;
16
14
 
17
15
  // Options + any additional mixins defines complete functionality
18
- const allMixins = mixins ? [...mixins, options] : [options];
16
+ const mixins = extraMixins ? [...extraMixins, options] : [options];
19
17
 
20
18
  // Create the constructor function
21
- const type = createConstructor({
19
+ const klass = createConstructor({
22
20
  name: name ?? (base ? `${base.name}$` : "GeneratedClass"),
23
21
  base,
24
- args,
25
- mixins: allMixins,
22
+ beforeSuper,
23
+ mixins,
26
24
  });
27
25
 
28
- // Install properties
29
- for (const mixin of allMixins) {
30
- applyMixin(type, mixin);
31
- }
26
+ // Configure inheritance and other class aspects not handled by the constructor
27
+ configureClass(klass, base, mixins);
32
28
 
33
- return type;
34
- }
35
-
36
- function applyMixin(
37
- constructor: new (...args: any) => any,
38
- { staticProperties, staticDescriptors, instanceDescriptors }: GeneratedClass.Mixin,
39
- ) {
40
- if (staticProperties) {
41
- Object.assign(constructor, staticProperties);
42
- }
43
- if (staticDescriptors) {
44
- Object.defineProperties(constructor, staticDescriptors);
45
- }
46
- if (instanceDescriptors) {
47
- Object.defineProperties(constructor.prototype, instanceDescriptors);
48
- }
29
+ return klass;
49
30
  }
50
31
 
51
32
  export namespace GeneratedClass {
@@ -98,107 +79,185 @@ export namespace GeneratedClass {
98
79
  * A preprocessor for arguments. Derivatives may use this to transform arguments prior to call to super() and
99
80
  * initialize().
100
81
  */
101
- args?: (...args: any[]) => any[];
82
+ beforeSuper?: (...args: any[]) => any[];
102
83
 
103
84
  /**
104
- * Options is a default mixin but you can provide others here.
85
+ * Other {@link Mixin} objects in addition to this one.
105
86
  */
106
87
  mixins?: Mixin[];
107
88
  }
108
89
  }
109
90
 
110
- interface ConstructorOptions {
111
- name: string;
112
- mixins: GeneratedClass.Mixin[];
113
- base?: new (...args: any[]) => any;
114
- args?: (...args: any[]) => any[];
115
- }
91
+ function createConstructor({ name, base, beforeSuper, mixins }: ConstructorOptions) {
92
+ // We generate this function to execute construction logic based on input options; invoked by the actual constructor
93
+ let construct: ConstructFn;
116
94
 
117
- function createConstructor({ name, base, args, mixins }: ConstructorOptions) {
118
- // CJS Transpilation renames this symbol so bring it local to access
119
- // @ts-expect-error this is used by generated code that TS knows nothing of
120
- const _InternalError = InternalError;
121
-
122
- // Have to use eval if we don't want every class to be called "GeneratedClass" in the debugger but we can ensure
123
- // this won't be abused.
124
- //
125
- // "name" is the only input to this function that appears textually in the eval. We limit it to letters, numbers,
126
- // "$" and "_".
127
- if (!name.match(/^[\p{L}0-9$_]+$/u)) {
128
- throw new InternalError("Refusing to generate class with untrustworthy name");
129
- }
130
-
131
- let ext;
95
+ // Base constructor
132
96
  if (base) {
133
- ext = `extends base `;
97
+ construct = function (self, args) {
98
+ return reflectConstruct(base, args, self.constructor as new (...args: unknown[]) => unknown);
99
+ };
134
100
  } else {
135
- ext = "";
101
+ construct = function (self) {
102
+ return self;
103
+ };
136
104
  }
137
105
 
138
- const code = [`class ${name} ${ext}{`];
139
-
140
- // Consolidate mixins to a single initialize and instanceProperties
141
- let initialize: undefined | GeneratedClass.Options["initialize"];
142
- let instanceProperties: undefined | GeneratedClass.Options["instanceProperties"];
143
-
144
- for (const mixin of mixins) {
145
- const mixinInitialize = mixin.initialize;
146
-
147
- // Add initializer
148
- if (mixinInitialize) {
106
+ // Next apply mixins in order. We create a specialized function depending on whether the mixin has an initialize
107
+ // function and/or includes instance properties
108
+ if (mixins) {
109
+ for (const { initialize, instanceProperties } of mixins) {
110
+ const before: ConstructFn = construct;
149
111
  if (initialize) {
150
- const baseInitialize = initialize;
151
- initialize = function (this: any, ...args) {
152
- baseInitialize.call(this, ...args);
153
- mixinInitialize.call(this, ...args);
112
+ if (instanceProperties) {
113
+ // Has initialize + instanceProperties
114
+ construct = function (self: {}, args: unknown[]) {
115
+ self = before(self, args);
116
+ for (const k in instanceProperties) {
117
+ (self as Record<any, any>)[k] = (instanceProperties as any)[k];
118
+ }
119
+ initialize.apply(self, args);
120
+ return self;
121
+ };
122
+ } else {
123
+ // Has initialize
124
+ construct = function (self: {}, args: unknown[]) {
125
+ self = before(self, args);
126
+ initialize.apply(self, args);
127
+ return self;
128
+ };
129
+ }
130
+ } else if (instanceProperties) {
131
+ // Has instanceProperties
132
+ construct = function (self: {}, args: unknown[]) {
133
+ self = before(self, args) as Record<any, any>;
134
+ for (const k in instanceProperties) {
135
+ (self as Record<any, any>)[k] = (instanceProperties as any)[k];
136
+ }
137
+ return self;
154
138
  };
155
- } else {
156
- initialize = mixinInitialize;
157
139
  }
158
140
  }
141
+ }
159
142
 
160
- // Add instance properties
161
- if (mixin.instanceProperties) {
162
- if (instanceProperties) {
163
- instanceProperties = {
164
- ...instanceProperties,
165
- ...mixin.instanceProperties,
166
- };
167
- } else {
168
- instanceProperties = mixin.instanceProperties;
169
- }
170
- }
143
+ // This is the actual constructor.
144
+ //
145
+ // We install the function into a named property of a temporary object because the VM will then assign it a name.
146
+ // Otherwise it would be anonymous which is confusing in diagnostics and the debugger
147
+ //
148
+ // The "beforeSuper" function contains logic that would appear before the "super" call in a normal ES6 class. We
149
+ // generate a different function if present to avoid an extra conditional on every instantiation
150
+ let klass: (...args: unknown[]) => unknown;
151
+ if (beforeSuper) {
152
+ // "beforeSuper" is present; generate a constructor that invokes it before proceeding
153
+ ({ [name]: klass } = {
154
+ [name]: function (...args: unknown[]) {
155
+ // This is mandated for ES6 classes; try to behave the same
156
+ if (!(this instanceof klass)) {
157
+ throw new TypeError(`Class constructor ${klass.name} cannot be invoked without 'new'`);
158
+ }
159
+
160
+ // Apply pre-construction logic
161
+ args = beforeSuper(...args);
162
+
163
+ // Actual construction logic
164
+ return construct(this, args);
165
+ },
166
+ });
167
+ } else {
168
+ // Delegate to "construct" function
169
+ ({ [name]: klass } = {
170
+ [name]: function (...args: unknown[]) {
171
+ // See the comment above
172
+ if (!(this instanceof klass)) {
173
+ throw new TypeError(`Class constructor ${klass.name} cannot be invoked without 'new'`);
174
+ }
175
+
176
+ // Actual construction logic
177
+ return construct(this, args);
178
+ },
179
+ });
171
180
  }
172
181
 
173
- // If we need a constructor, add it
174
- if (args || initialize || instanceProperties) {
175
- code.push("constructor() {");
182
+ // Cast to constructor type
183
+ return klass as unknown as new (...args: unknown[]) => {};
184
+ }
176
185
 
177
- let argsName;
178
- if (args) {
179
- argsName = "a";
180
- code.push(`const a = args(...arguments)`);
181
- } else {
182
- argsName = "arguments";
183
- }
186
+ function configureClass(
187
+ klass: new (...args: unknown[]) => unknown,
188
+ base: undefined | (new (...args: any[]) => any),
189
+ mixins: GeneratedClass.Mixin[],
190
+ ) {
191
+ // Configure inheritance for derived classes
192
+ if (base) {
193
+ // Enable static inheritance
194
+ Object.setPrototypeOf(klass, base);
184
195
 
185
- if (base) {
186
- code.push(`super(...${argsName})`);
187
- }
196
+ // Enable instance inheritance
197
+ klass.prototype = Reflect.construct(base, []);
198
+ }
199
+
200
+ // Expose the correct constructor for instances via the prototype
201
+ Object.defineProperty(klass.prototype, "constructor", { value: klass });
188
202
 
189
- if (instanceProperties) {
190
- // Do not use Object.assign because we want to support accessors
191
- code.push(`for (const k in instanceProperties) this[k] = instanceProperties[k]`);
203
+ // Install properties. "Own instance" properties we install in the constructor but this handles static properties
204
+ // and those installed on the prototype
205
+ if (mixins) {
206
+ for (const { staticProperties, staticDescriptors, instanceDescriptors } of mixins) {
207
+ if (staticProperties) {
208
+ Object.assign(klass, staticProperties);
209
+ }
210
+ if (staticDescriptors) {
211
+ Object.defineProperties(klass, staticDescriptors);
212
+ }
213
+ if (instanceDescriptors) {
214
+ Object.defineProperties(klass.prototype, instanceDescriptors);
215
+ }
192
216
  }
217
+ }
218
+ }
193
219
 
194
- if (initialize) {
195
- code.push(`initialize.apply(this, ${argsName})`);
220
+ /**
221
+ * {@link Reflect.construct} equivalent.
222
+ *
223
+ * On modern VMs this is just {@link Reflect.construct} but we fall back to an ES5 version if necessary.
224
+ */
225
+ let reflectConstruct: (
226
+ target: new (...args: unknown[]) => unknown,
227
+ args: unknown[],
228
+ newTarget?: new (...args: unknown[]) => unknown,
229
+ ) => {};
230
+
231
+ if (typeof globalThis.Reflect?.construct === "function") {
232
+ reflectConstruct = Reflect.construct;
233
+ } else {
234
+ reflectConstruct = (
235
+ target: new (...args: unknown[]) => unknown,
236
+ args: unknown[],
237
+ newTarget?: new (...args: unknown[]) => unknown,
238
+ ) => {
239
+ if (typeof newTarget === "undefined") {
240
+ newTarget = target;
196
241
  }
197
242
 
198
- code.push("}");
199
- }
243
+ const initialThis = Object.create(newTarget.prototype);
244
+ const constructorResult = target.apply(initialThis, args);
245
+ if (
246
+ (typeof constructorResult === "object" && constructorResult !== null) ||
247
+ typeof constructorResult === "function"
248
+ ) {
249
+ return constructorResult;
250
+ }
200
251
 
201
- code.push("}", name);
252
+ return initialThis;
253
+ };
254
+ }
202
255
 
203
- return eval(code.join("\n")) as new (...args: any) => any;
256
+ interface ConstructorOptions {
257
+ name: string;
258
+ base?: new (...args: any[]) => any;
259
+ beforeSuper?: (...args: any[]) => any[];
260
+ mixins: GeneratedClass.Mixin[];
204
261
  }
262
+
263
+ type ConstructFn = (self: {}, args: unknown[]) => {};
@@ -26,10 +26,6 @@ export function toNumber(value: bigint | number): number {
26
26
  return typeof value === "bigint" ? Number(value) : value;
27
27
  }
28
28
 
29
- export function toBigInt(value: bigint | number): bigint {
30
- return typeof value === "number" ? BigInt(value) : value;
31
- }
32
-
33
29
  export function minValue<T extends bigint | number>(a: T | undefined, b: T | undefined) {
34
30
  if (a === undefined) return b;
35
31
  if (b === undefined) return a;