@gtkx/runtime 1.0.0-rc.1 → 1.0.0-rc.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 (116) hide show
  1. package/dist/arg.d.ts +6 -5
  2. package/dist/arg.d.ts.map +1 -1
  3. package/dist/arg.js +5 -4
  4. package/dist/arg.js.map +1 -1
  5. package/dist/bind.d.ts +3 -2
  6. package/dist/bind.d.ts.map +1 -1
  7. package/dist/bind.js +5 -3
  8. package/dist/bind.js.map +1 -1
  9. package/dist/callback.d.ts +3 -3
  10. package/dist/callback.d.ts.map +1 -1
  11. package/dist/callback.js +51 -33
  12. package/dist/callback.js.map +1 -1
  13. package/dist/descriptors.d.ts +67 -64
  14. package/dist/descriptors.d.ts.map +1 -1
  15. package/dist/descriptors.js +92 -60
  16. package/dist/descriptors.js.map +1 -1
  17. package/dist/error.d.ts +5 -6
  18. package/dist/error.d.ts.map +1 -1
  19. package/dist/error.js +10 -6
  20. package/dist/error.js.map +1 -1
  21. package/dist/exit-hook.d.ts +2 -0
  22. package/dist/exit-hook.d.ts.map +1 -0
  23. package/dist/exit-hook.js +3 -0
  24. package/dist/exit-hook.js.map +1 -0
  25. package/dist/fn.d.ts +2 -2
  26. package/dist/fn.d.ts.map +1 -1
  27. package/dist/fn.js +26 -15
  28. package/dist/fn.js.map +1 -1
  29. package/dist/index.d.ts +3 -2
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +2 -1
  32. package/dist/index.js.map +1 -1
  33. package/dist/library.d.ts +6 -5
  34. package/dist/library.d.ts.map +1 -1
  35. package/dist/library.js +6 -5
  36. package/dist/library.js.map +1 -1
  37. package/dist/lifecycle.d.ts +10 -9
  38. package/dist/lifecycle.d.ts.map +1 -1
  39. package/dist/lifecycle.js +38 -23
  40. package/dist/lifecycle.js.map +1 -1
  41. package/dist/listeners.d.ts +8 -8
  42. package/dist/listeners.d.ts.map +1 -1
  43. package/dist/listeners.js +28 -15
  44. package/dist/listeners.js.map +1 -1
  45. package/dist/mixin.d.ts +5 -11
  46. package/dist/mixin.d.ts.map +1 -1
  47. package/dist/mixin.js +24 -14
  48. package/dist/mixin.js.map +1 -1
  49. package/dist/native-value.d.ts +3 -2
  50. package/dist/native-value.d.ts.map +1 -1
  51. package/dist/native-value.js +75 -42
  52. package/dist/native-value.js.map +1 -1
  53. package/dist/object.d.ts +4 -3
  54. package/dist/object.d.ts.map +1 -1
  55. package/dist/object.js +8 -5
  56. package/dist/object.js.map +1 -1
  57. package/dist/promisify.d.ts +9 -1
  58. package/dist/promisify.d.ts.map +1 -1
  59. package/dist/promisify.js +18 -15
  60. package/dist/promisify.js.map +1 -1
  61. package/dist/properties.d.ts +14 -0
  62. package/dist/properties.d.ts.map +1 -0
  63. package/dist/properties.js +79 -0
  64. package/dist/properties.js.map +1 -0
  65. package/dist/register-class.d.ts +10 -2
  66. package/dist/register-class.d.ts.map +1 -1
  67. package/dist/register-class.js +83 -29
  68. package/dist/register-class.js.map +1 -1
  69. package/dist/registry.d.ts +23 -21
  70. package/dist/registry.d.ts.map +1 -1
  71. package/dist/registry.js +54 -35
  72. package/dist/registry.js.map +1 -1
  73. package/dist/signal.d.ts +7 -6
  74. package/dist/signal.d.ts.map +1 -1
  75. package/dist/signal.js +19 -12
  76. package/dist/signal.js.map +1 -1
  77. package/dist/t.d.ts +2 -2
  78. package/dist/t.d.ts.map +1 -1
  79. package/dist/t.js +2 -1
  80. package/dist/t.js.map +1 -1
  81. package/dist/tuple.d.ts +3 -2
  82. package/dist/tuple.d.ts.map +1 -1
  83. package/dist/tuple.js +7 -4
  84. package/dist/tuple.js.map +1 -1
  85. package/dist/type.d.ts +48 -41
  86. package/dist/type.d.ts.map +1 -1
  87. package/dist/type.js +107 -87
  88. package/dist/type.js.map +1 -1
  89. package/dist/value.d.ts +19 -10
  90. package/dist/value.d.ts.map +1 -1
  91. package/dist/value.js +164 -99
  92. package/dist/value.js.map +1 -1
  93. package/package.json +4 -6
  94. package/src/arg.ts +7 -5
  95. package/src/bind.ts +13 -4
  96. package/src/callback.ts +97 -35
  97. package/src/descriptors.ts +227 -85
  98. package/src/error.ts +18 -9
  99. package/src/exit-hook.ts +3 -0
  100. package/src/fn.ts +53 -22
  101. package/src/index.ts +4 -2
  102. package/src/library.ts +7 -5
  103. package/src/lifecycle.ts +54 -26
  104. package/src/listeners.ts +46 -18
  105. package/src/mixin.ts +39 -14
  106. package/src/native-value.ts +103 -46
  107. package/src/object.ts +19 -7
  108. package/src/promisify.ts +42 -15
  109. package/src/properties.ts +115 -0
  110. package/src/register-class.ts +157 -30
  111. package/src/registry.ts +144 -54
  112. package/src/signal.ts +53 -13
  113. package/src/t.ts +3 -1
  114. package/src/tuple.ts +16 -4
  115. package/src/type.ts +183 -93
  116. package/src/value.ts +231 -108
package/src/registry.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { AnyClass } from "@gtkx/utils";
1
2
  import {
2
3
  type ExternalObject,
3
4
  getType,
@@ -6,7 +7,6 @@ import {
6
7
  type RegisterClassVfunc as NativeRegisterClassVfunc,
7
8
  setWrapper,
8
9
  } from "@gtkx/native";
9
- import type { AnyClass } from "@gtkx/utils";
10
10
  import type { Mixin, MixinReceiver } from "./mixin.js";
11
11
  import { TYPE_INVALID, type TypedClass, typeInterfaces, typeIsA, typeName, typeParent } from "./type.js";
12
12
 
@@ -14,46 +14,50 @@ import { TYPE_INVALID, type TypedClass, typeInterfaces, typeIsA, typeName, typeP
14
14
  * Static side of class `C` with its construct signature preserved but the member
15
15
  * named `K` (default `"new"`) removed.
16
16
  */
17
- export type StaticBase<C, K extends PropertyKey = "new"> = Omit<C, K> &
17
+ type StaticBase<C, K extends PropertyKey = "new"> = Omit<C, K> &
18
18
  (C extends new (...args: infer A) => infer R ? new (...args: A) => R : never);
19
19
 
20
- export type VfuncDescriptor<K extends "class" | "interface"> = {
20
+ type VfuncDescriptor<K extends "class" | "interface"> = {
21
21
  kind: K;
22
22
  className: string;
23
23
  vfuncName: string;
24
24
  byteOffset: number;
25
+ vtableSize: number;
25
26
  argDescriptors: NativeRegisterClassVfunc["argDescriptors"];
26
27
  returnDescriptor: NativeRegisterClassVfunc["returnDescriptor"];
27
28
  };
28
29
 
29
- export type VfuncRegistry = Record<string, VfuncDescriptor<"class"> | VfuncDescriptor<"interface">>;
30
+ type VfuncRegistry = Record<string, VfuncDescriptor<"class"> | VfuncDescriptor<"interface">>;
30
31
 
31
- const classRegistry = new Map<bigint, AnyClass>();
32
- const interfaceMixinRegistry = new Map<bigint, Mixin>();
33
- const composedClassRegistry = new Map<bigint, AnyClass>();
34
- const handleMap = new WeakMap<object, ExternalObject<Handle>>();
35
- const vfuncRegistry = new WeakMap<object, VfuncRegistry>();
36
- const interfaceVfuncRegistry = new Map<bigint, VfuncRegistry>();
32
+ const classRegistry: Map<bigint, AnyClass> = new Map();
33
+ const interfaceMixinRegistry: Map<bigint, Mixin> = new Map();
34
+ const composedClassRegistry: Map<bigint, AnyClass> = new Map();
35
+ const handleMap: WeakMap<object, ExternalObject<Handle>> = new WeakMap();
36
+ const vfuncRegistry: WeakMap<object, VfuncRegistry> = new WeakMap();
37
+ const interfaceVfuncRegistry: Map<bigint, VfuncRegistry> = new Map();
37
38
 
38
39
  function setClassType(cls: AnyClass, type: bigint): void {
39
40
  (cls.prototype as { [K in keyof TypedClass]: TypedClass[K] }).__type__ = type;
40
41
  }
41
42
 
42
- export function getClassType(cls: AnyClass): bigint {
43
+ function getClassType(cls: AnyClass): bigint {
43
44
  const proto: object = cls.prototype;
45
+
44
46
  return Object.hasOwn(proto, "__type__") ? (proto as TypedClass).__type__ : TYPE_INVALID;
45
47
  }
46
48
 
47
49
  /** Returns the GType tag of the given wrapper instance. */
48
- export function getInstanceType(instance: object): bigint {
50
+ function getInstanceType(instance: object): bigint {
49
51
  return getClassType(instance.constructor as AnyClass);
50
52
  }
51
53
 
52
- export function registerClassType(cls: AnyClass, type: bigint): void {
53
- if (type !== TYPE_INVALID) {
54
- classRegistry.set(type, cls);
55
- setClassType(cls, type);
54
+ function registerClassType(cls: AnyClass, type: bigint): void {
55
+ if (type === TYPE_INVALID) {
56
+ return;
56
57
  }
58
+
59
+ classRegistry.set(type, cls);
60
+ setClassType(cls, type);
57
61
  }
58
62
 
59
63
  /**
@@ -63,9 +67,12 @@ export function registerClassType(cls: AnyClass, type: bigint): void {
63
67
  * @param type GType the class wraps.
64
68
  * @param vfuncs Virtual functions the class overrides.
65
69
  */
66
- export function registerWrapperClass(cls: AnyClass, type: bigint, vfuncs?: VfuncRegistry): void {
70
+ function registerWrapperClass(cls: AnyClass, type: bigint, vfuncs?: VfuncRegistry): void {
67
71
  registerClassType(cls, type);
68
- if (vfuncs) registerVfuncRegistry(cls, vfuncs);
72
+
73
+ if (vfuncs) {
74
+ registerVfuncRegistry(cls, vfuncs);
75
+ }
69
76
  }
70
77
 
71
78
  /**
@@ -76,11 +83,17 @@ export function registerWrapperClass(cls: AnyClass, type: bigint, vfuncs?: Vfunc
76
83
  * @param mixin Mixin that applies the interface to a wrapper class.
77
84
  * @param vfuncs Virtual functions the interface exposes.
78
85
  */
79
- export function registerInterface(cls: AnyClass, type: bigint, mixin: Mixin, vfuncs?: VfuncRegistry): void {
80
- if (type === TYPE_INVALID) return;
86
+ function registerInterface(cls: AnyClass, type: bigint, mixin: Mixin, vfuncs?: VfuncRegistry): void {
87
+ if (type === TYPE_INVALID) {
88
+ return;
89
+ }
90
+
81
91
  setClassType(cls, type);
82
92
  interfaceMixinRegistry.set(type, mixin);
83
- if (vfuncs) registerInterfaceVfuncRegistry(type, vfuncs);
93
+
94
+ if (vfuncs) {
95
+ registerInterfaceVfuncRegistry(type, vfuncs);
96
+ }
84
97
  }
85
98
 
86
99
  /**
@@ -91,24 +104,29 @@ export function registerInterface(cls: AnyClass, type: bigint, mixin: Mixin, vfu
91
104
  * @param handle Native handle to wrap.
92
105
  * @param cls Wrapper class to instantiate, or omitted to resolve it from the runtime type.
93
106
  */
94
- export function wrapHandle(handle: null | undefined, cls?: AnyClass): null;
95
- export function wrapHandle<T extends object>(handle: ExternalObject<Handle>, cls: AnyClass<T>): T;
96
- export function wrapHandle<T extends object>(
107
+ function wrapHandle(handle: null | undefined, cls?: AnyClass): null;
108
+ function wrapHandle<T extends object>(handle: ExternalObject<Handle>, cls: AnyClass<T>): T;
109
+
110
+ function wrapHandle<T extends object>(
97
111
  handle: ExternalObject<Handle> | null | undefined,
98
112
  cls: AnyClass<T>,
99
113
  ): T | null;
100
- export function wrapHandle<T extends object = TypedClass>(handle: ExternalObject<Handle>, cls?: AnyClass): T;
101
- export function wrapHandle<T extends object = TypedClass>(
102
- handle: ExternalObject<Handle> | null | undefined,
103
- cls?: AnyClass,
104
- ): T | null;
105
- export function wrapHandle(handle: ExternalObject<Handle> | null | undefined, cls?: AnyClass): object | null {
106
- if (handle === null || handle === undefined) return null;
114
+
115
+ function wrapHandle(handle: ExternalObject<Handle>, cls?: AnyClass): TypedClass;
116
+ function wrapHandle(handle: ExternalObject<Handle> | null | undefined, cls?: AnyClass): TypedClass | null;
117
+
118
+ function wrapHandle(handle: ExternalObject<Handle> | null | undefined, cls?: AnyClass): object | null {
119
+ if (handle === null || handle === undefined) {
120
+ return null;
121
+ }
122
+
107
123
  if (cls === undefined) {
108
124
  return getOrCreateWrapper(handle);
109
125
  }
110
- const instance: object = Object.create(cls.prototype);
126
+
127
+ const instance: object = Object.create(cls.prototype) as object;
111
128
  setHandle(instance, handle);
129
+
112
130
  return instance;
113
131
  }
114
132
 
@@ -116,85 +134,135 @@ export function wrapHandle(handle: ExternalObject<Handle> | null | undefined, cl
116
134
  * Returns the wrapper class registered for a GType, walking up to ancestor types,
117
135
  * and throws if none is registered.
118
136
  */
119
- export function getWrapperClass(type: bigint): AnyClass {
137
+ function getWrapperClass(type: bigint): AnyClass {
120
138
  const cls = resolveWrapperClass(type);
139
+
121
140
  if (!cls) {
122
141
  throw new Error(`No registered wrapper class for type '${typeName(type) ?? String(type)}'`);
123
142
  }
143
+
124
144
  return cls;
125
145
  }
126
146
 
127
- export function resolveWrapperClass(type: bigint): AnyClass | null {
147
+ function resolveWrapperClass(type: bigint): AnyClass | null {
128
148
  let currentType = type;
149
+
129
150
  while (currentType !== TYPE_INVALID) {
130
151
  const cls = classRegistry.get(currentType);
131
- if (cls) return cls;
152
+
153
+ if (cls) {
154
+ return cls;
155
+ }
156
+
132
157
  currentType = typeParent(currentType);
133
158
  }
159
+
134
160
  return null;
135
161
  }
136
162
 
163
+ function applyInterfaceMixin(cls: AnyClass, type: bigint, baseType: bigint, applied: Set<bigint>): AnyClass {
164
+ if (applied.has(type) || typeIsA(baseType, type)) {
165
+ return cls;
166
+ }
167
+
168
+ const mixin = interfaceMixinRegistry.get(type);
169
+
170
+ if (mixin === undefined) {
171
+ return cls;
172
+ }
173
+
174
+ applied.add(type);
175
+
176
+ return mixin(cls as AnyClass<MixinReceiver>);
177
+ }
178
+
137
179
  function createComposedClass(base: AnyClass, runtimeType: bigint): AnyClass {
138
180
  const baseType = getClassType(base);
139
- const applied = new Set<bigint>();
181
+ const applied: Set<bigint> = new Set();
140
182
  let cls: AnyClass = base;
183
+
141
184
  for (const type of typeInterfaces(runtimeType)) {
142
- if (applied.has(type) || typeIsA(baseType, type)) continue;
143
- const mixin = interfaceMixinRegistry.get(type);
144
- if (mixin === undefined) continue;
145
- applied.add(type);
146
- cls = mixin(cls as AnyClass<MixinReceiver>);
185
+ cls = applyInterfaceMixin(cls, type, baseType, applied);
147
186
  }
187
+
148
188
  return applied.size === 0 ? base : cls;
149
189
  }
150
190
 
151
191
  function resolveComposedClass(runtimeType: bigint): AnyClass | null {
152
192
  const exact = classRegistry.get(runtimeType);
153
- if (exact) return exact;
193
+
194
+ if (exact) {
195
+ return exact;
196
+ }
197
+
154
198
  const cached = composedClassRegistry.get(runtimeType);
155
- if (cached) return cached;
199
+
200
+ if (cached) {
201
+ return cached;
202
+ }
203
+
156
204
  const base = resolveWrapperClass(runtimeType);
157
- if (base === null) return null;
205
+
206
+ if (base === null) {
207
+ return null;
208
+ }
209
+
158
210
  const composed = createComposedClass(base, runtimeType);
159
- if (composed === base) return base;
211
+
212
+ if (composed === base) {
213
+ return base;
214
+ }
215
+
160
216
  setClassType(composed, runtimeType);
161
217
  composedClassRegistry.set(runtimeType, composed);
218
+
162
219
  return composed;
163
220
  }
164
221
 
165
222
  function getOrCreateWrapper(handle: ExternalObject<Handle>): object {
166
223
  const existing = getWrapper(handle);
167
- if (existing) return existing;
224
+
225
+ if (existing) {
226
+ return existing;
227
+ }
168
228
 
169
229
  const runtimeType: bigint = getType(handle);
230
+
170
231
  if (runtimeType === TYPE_INVALID) {
171
232
  throw new Error("Cannot resolve runtime GLib type from handle");
172
233
  }
173
234
 
174
235
  const cls = resolveComposedClass(runtimeType);
175
- if (!cls) throw new Error(`Expected registered GLib type, got type ${String(runtimeType)}`);
176
- const instance: object = Object.create(cls.prototype);
236
+
237
+ if (!cls) {
238
+ throw new Error(`Expected registered GLib type, got type ${String(runtimeType)}`);
239
+ }
240
+
241
+ const instance: object = Object.create(cls.prototype) as object;
177
242
  registerWrapper(handle, instance);
243
+
178
244
  return instance;
179
245
  }
180
246
 
181
247
  /** Returns the native handle bound to a wrapper instance, throwing if none is set. */
182
- export function getHandle(instance: object): ExternalObject<Handle> {
248
+ function getHandle(instance: object): ExternalObject<Handle> {
183
249
  const handle = handleMap.get(instance);
250
+
184
251
  if (handle === undefined) {
185
252
  const name = (instance as { constructor?: { name?: string } }).constructor?.name ?? "object";
186
253
  throw new Error(`No native handle associated with ${name}`);
187
254
  }
255
+
188
256
  return handle;
189
257
  }
190
258
 
191
259
  /** Returns the native handle bound to an instance, or undefined when there is none or the instance is null. */
192
- export function tryGetHandle(instance: object | null | undefined): ExternalObject<Handle> | undefined {
260
+ function tryGetHandle(instance: object | null | undefined): ExternalObject<Handle> | undefined {
193
261
  return instance == null ? undefined : handleMap.get(instance);
194
262
  }
195
263
 
196
264
  /** Associates a native handle with a wrapper instance. */
197
- export function setHandle(instance: object, handle: ExternalObject<Handle>): void {
265
+ function setHandle(instance: object, handle: ExternalObject<Handle>): void {
198
266
  handleMap.set(instance, handle);
199
267
  }
200
268
 
@@ -207,15 +275,37 @@ function registerVfuncRegistry(cls: object, registry: VfuncRegistry): void {
207
275
  vfuncRegistry.set(cls, registry);
208
276
  }
209
277
 
210
- export function getVfuncRegistry(cls: object): VfuncRegistry | undefined {
278
+ function getVfuncRegistry(cls: object): VfuncRegistry | undefined {
211
279
  return vfuncRegistry.get(cls);
212
280
  }
213
281
 
214
282
  function registerInterfaceVfuncRegistry(type: bigint, registry: VfuncRegistry): void {
215
- if (type === TYPE_INVALID) return;
283
+ if (type === TYPE_INVALID) {
284
+ return;
285
+ }
286
+
216
287
  interfaceVfuncRegistry.set(type, registry);
217
288
  }
218
289
 
219
- export function getInterfaceVfuncRegistry(type: bigint): VfuncRegistry | undefined {
290
+ function getInterfaceVfuncRegistry(type: bigint): VfuncRegistry | undefined {
220
291
  return interfaceVfuncRegistry.get(type);
221
292
  }
293
+
294
+ export {
295
+ getClassType,
296
+ getInstanceType,
297
+ registerClassType,
298
+ registerWrapperClass,
299
+ registerInterface,
300
+ wrapHandle,
301
+ getWrapperClass,
302
+ resolveWrapperClass,
303
+ getHandle,
304
+ tryGetHandle,
305
+ setHandle,
306
+ getVfuncRegistry,
307
+ getInterfaceVfuncRegistry,
308
+ type StaticBase,
309
+ type VfuncDescriptor,
310
+ type VfuncRegistry,
311
+ };
package/src/signal.ts CHANGED
@@ -1,10 +1,12 @@
1
1
  import type { Descriptor, ExternalObject, Handle } from "@gtkx/native";
2
+ import type { TypedClass } from "./type.js";
2
3
  import { type Arg, isCallerAllocatedArg, isInoutArg, isOutputArg } from "./arg.js";
3
4
  import { bind, createBindCache } from "./bind.js";
4
5
  import { wrapCallback } from "./callback.js";
5
6
  import {
6
7
  arrayT,
7
8
  biguint64T,
9
+ booleanT,
8
10
  type CallbackDescriptor,
9
11
  objectT,
10
12
  stringT,
@@ -15,7 +17,6 @@ import {
15
17
  import { LIB, VALUE_SIZE, VALUE_T } from "./library.js";
16
18
  import { getHandle } from "./registry.js";
17
19
  import { packTupleResult } from "./tuple.js";
18
- import type { TypedClass } from "./type.js";
19
20
  import {
20
21
  fromValue,
21
22
  getBoxedValue,
@@ -27,7 +28,7 @@ import {
27
28
  } from "./value.js";
28
29
 
29
30
  /** Function invoked when a connected GObject signal is emitted. */
30
- export type SignalHandler = (...args: unknown[]) => unknown;
31
+ type SignalHandler = (...args: unknown[]) => unknown;
31
32
 
32
33
  type SignalConnectSpec = {
33
34
  callback: CallbackDescriptor;
@@ -55,25 +56,42 @@ const gSignalHandlersBlockMatched = bind(
55
56
  uint32T,
56
57
  );
57
58
 
59
+ const gSignalHandlerIsConnected = bind(
60
+ LIB,
61
+ "g_signal_handler_is_connected",
62
+ [objectT("borrowed"), uint64T],
63
+ booleanT,
64
+ );
65
+
58
66
  /** Returns the signal name without its detail suffix (the part after `::`). */
59
- export const getSignalBaseName = (signal: string): string => {
67
+ const getSignalBaseName = (signal: string): string => {
60
68
  const detailIndex = signal.indexOf("::");
69
+
61
70
  return detailIndex === -1 ? signal : signal.slice(0, detailIndex);
62
71
  };
63
72
 
64
- function getQuarkForSignalDetail(signal: string): number {
73
+ function getSignalDetailQuark(signal: string): number {
65
74
  const detailIndex = signal.indexOf("::");
66
- if (detailIndex === -1) return 0;
75
+
76
+ if (detailIndex === -1) {
77
+ return 0;
78
+ }
79
+
67
80
  return gQuarkFromString(signal.slice(detailIndex + 2)) as number;
68
81
  }
69
82
 
83
+ const isSignalHandlerConnected = (instance: object, handlerId: number): boolean =>
84
+ gSignalHandlerIsConnected(getHandle(instance), handlerId) as boolean;
85
+
70
86
  const getSignalId = (instance: object, signal: string): number => {
71
87
  const type: bigint = (instance as TypedClass).__type__;
88
+
72
89
  return gSignalLookup(getSignalBaseName(signal), type) as number;
73
90
  };
74
91
 
75
92
  function connectBind(type: bigint, signal: string, callback: CallbackDescriptor): (...values: unknown[]) => unknown {
76
- const key = `${type}\0${getSignalBaseName(signal)}`;
93
+ const key = `${String(type)}\0${getSignalBaseName(signal)}`;
94
+
77
95
  return connectCache(
78
96
  key,
79
97
  LIB,
@@ -89,26 +107,35 @@ function connectBind(type: bigint, signal: string, callback: CallbackDescriptor)
89
107
  * @param signal Signal name, optionally including a `::detail` suffix.
90
108
  * @param spec Callback descriptor, handler function, and whether to run after the default handler.
91
109
  */
92
- export function connectSignal(instance: object, signal: string, spec: SignalConnectSpec): number {
110
+ function connectSignal(instance: object, signal: string, spec: SignalConnectSpec): number {
93
111
  const { callback, handler, after } = spec;
94
112
  const wrapped = wrapCallback(handler, callback, "emitter");
95
113
  const type: bigint = (instance as TypedClass).__type__;
96
114
  const connect = connectBind(type, signal, callback);
115
+
97
116
  return connect(getHandle(instance), signal, wrapped, after ? 1 : 0) as number;
98
117
  }
99
118
 
100
- export function blockMatchedSignalHandlers(instance: object, signal: string): void {
119
+ function blockMatchedSignalHandlers(instance: object, signal: string): void {
101
120
  const signalId = getSignalId(instance, signal);
102
121
  gSignalHandlersBlockMatched(getHandle(instance), 1, signalId, 0, undefined, undefined, undefined);
103
122
  }
104
123
 
105
124
  const createEmitValue = (arg: EmitArg): { value: ExternalObject<Handle>; read?: () => unknown } => {
106
- if (!isOutputArg(arg)) return { value: toValue(arg.type, arg.value) };
125
+ if (!isOutputArg(arg)) {
126
+ return { value: toValue(arg.type, arg.value) };
127
+ }
128
+
107
129
  if (isCallerAllocatedArg(arg)) {
108
- if (isInoutArg(arg)) return { value: inoutValueForBoxedDescriptor(arg.type, arg.value as object) };
130
+ if (isInoutArg(arg)) {
131
+ return { value: inoutValueForBoxedDescriptor(arg.type, arg.value as object) };
132
+ }
133
+
109
134
  const value = outValueForBoxedDescriptor(arg.type, arg.value as object);
135
+
110
136
  return { value, read: () => getBoxedValue(value) };
111
137
  }
138
+
112
139
  return isInoutArg(arg) ? outValueForDescriptor(arg.type, arg.value) : outValueForDescriptor(arg.type);
113
140
  };
114
141
 
@@ -120,21 +147,25 @@ const createEmitValue = (arg: EmitArg): { value: ExternalObject<Handle>; read?:
120
147
  * @param args Arguments to pass, including output and inout arguments.
121
148
  * @param returnDescriptor Descriptor for the signal's return value, omitted when it returns void.
122
149
  */
123
- export function emitSignal(instance: object, signal: string, args: EmitArg[], returnDescriptor?: Descriptor): unknown {
150
+ function emitSignal(instance: object, signal: string, args: EmitArg[], returnDescriptor?: Descriptor): unknown {
124
151
  const signalId = getSignalId(instance, signal);
125
- const detail = getQuarkForSignalDetail(signal);
152
+ const detail = getSignalDetailQuark(signal);
126
153
  const values: ExternalObject<Handle>[] = [toValue(objectT("full"), instance)];
127
154
  const reads: (() => unknown)[] = [];
128
155
 
129
156
  for (const arg of args) {
130
157
  const { value, read } = createEmitValue(arg);
131
158
  values.push(value);
132
- if (read) reads.push(read);
159
+
160
+ if (read) {
161
+ reads.push(read);
162
+ }
133
163
  }
134
164
 
135
165
  if (returnDescriptor !== undefined) {
136
166
  const returnValue = newValueForDescriptor(returnDescriptor);
137
167
  gSignalEmitv(values, signalId, detail, returnValue);
168
+
138
169
  return packTupleResult(
139
170
  reads.map((read) => read()),
140
171
  fromValue(returnValue),
@@ -150,3 +181,12 @@ export function emitSignal(instance: object, signal: string, args: EmitArg[], re
150
181
  false,
151
182
  );
152
183
  }
184
+
185
+ export {
186
+ getSignalBaseName,
187
+ connectSignal,
188
+ blockMatchedSignalHandlers,
189
+ emitSignal,
190
+ isSignalHandlerConnected,
191
+ type SignalHandler,
192
+ };
package/src/t.ts CHANGED
@@ -47,7 +47,7 @@ type T = {
47
47
  * FFI marshalling, plus `bind` to bind a native function and `fn` to describe a
48
48
  * function signature.
49
49
  */
50
- export const t: T = {
50
+ const t: T = {
51
51
  bind,
52
52
  int8: helpers.int8T,
53
53
  uint8: helpers.uint8T,
@@ -86,3 +86,5 @@ export const t: T = {
86
86
  callback: helpers.callbackT,
87
87
  fn,
88
88
  };
89
+
90
+ export { t };
package/src/tuple.ts CHANGED
@@ -1,13 +1,20 @@
1
- export const packTupleResult = (outs: unknown[], primary: unknown, hasPrimary: boolean): unknown => {
1
+ const packTupleResult = (outs: unknown[], primary: unknown, hasPrimary: boolean): unknown => {
2
2
  if (hasPrimary) {
3
3
  return outs.length === 0 ? primary : [primary, ...outs];
4
4
  }
5
- if (outs.length === 0) return undefined;
6
- if (outs.length === 1) return outs[0];
5
+
6
+ if (outs.length === 0) {
7
+ return undefined;
8
+ }
9
+
10
+ if (outs.length === 1) {
11
+ return outs[0];
12
+ }
13
+
7
14
  return outs;
8
15
  };
9
16
 
10
- export const splitTupleResult = (
17
+ const splitTupleResult = (
11
18
  result: unknown,
12
19
  hasPrimary: boolean,
13
20
  outCount: number,
@@ -16,10 +23,15 @@ export const splitTupleResult = (
16
23
  if (Array.isArray(result)) {
17
24
  return { primary: result[0], outValues: result.slice(1) };
18
25
  }
26
+
19
27
  return { primary: result, outValues: [] };
20
28
  }
29
+
21
30
  if (outCount === 1) {
22
31
  return { primary: undefined, outValues: [result] };
23
32
  }
33
+
24
34
  return { primary: undefined, outValues: Array.isArray(result) ? result : [] };
25
35
  };
36
+
37
+ export { packTupleResult, splitTupleResult };