@gtkx/runtime 1.2.2 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/arg.d.ts +6 -1
- package/dist/arg.d.ts.map +1 -1
- package/dist/arg.js +2 -1
- package/dist/arg.js.map +1 -1
- package/dist/closure.d.ts.map +1 -1
- package/dist/closure.js +2 -11
- package/dist/closure.js.map +1 -1
- package/dist/descriptors.d.ts +21 -3
- package/dist/descriptors.d.ts.map +1 -1
- package/dist/descriptors.js +50 -21
- package/dist/descriptors.js.map +1 -1
- package/dist/fn.d.ts +2 -0
- package/dist/fn.d.ts.map +1 -1
- package/dist/fn.js +50 -10
- package/dist/fn.js.map +1 -1
- package/dist/index.d.ts +11 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/mixin.d.ts +2 -1
- package/dist/mixin.d.ts.map +1 -1
- package/dist/mixin.js +1 -1
- package/dist/mixin.js.map +1 -1
- package/dist/native-value.d.ts +9 -3
- package/dist/native-value.d.ts.map +1 -1
- package/dist/native-value.js +86 -9
- package/dist/native-value.js.map +1 -1
- package/dist/object.d.ts +14 -6
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +21 -10
- package/dist/object.js.map +1 -1
- package/dist/param-spec.d.ts +31 -1
- package/dist/param-spec.d.ts.map +1 -1
- package/dist/param-spec.js +66 -5
- package/dist/param-spec.js.map +1 -1
- package/dist/promisify.d.ts +13 -1
- package/dist/promisify.d.ts.map +1 -1
- package/dist/promisify.js +14 -1
- package/dist/promisify.js.map +1 -1
- package/dist/properties.d.ts +28 -1
- package/dist/properties.d.ts.map +1 -1
- package/dist/properties.js +139 -8
- package/dist/properties.js.map +1 -1
- package/dist/regex.d.ts +25 -0
- package/dist/regex.d.ts.map +1 -0
- package/dist/regex.js +59 -0
- package/dist/regex.js.map +1 -0
- package/dist/register-class.d.ts +154 -11
- package/dist/register-class.d.ts.map +1 -1
- package/dist/register-class.js +157 -19
- package/dist/register-class.js.map +1 -1
- package/dist/registry.d.ts +48 -4
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +147 -3
- package/dist/registry.js.map +1 -1
- package/dist/signal.d.ts +8 -1
- package/dist/signal.d.ts.map +1 -1
- package/dist/signal.js +41 -3
- package/dist/signal.js.map +1 -1
- package/dist/type.d.ts +2 -1
- package/dist/type.d.ts.map +1 -1
- package/dist/type.js +5 -1
- package/dist/type.js.map +1 -1
- package/dist/value.d.ts +48 -4
- package/dist/value.d.ts.map +1 -1
- package/dist/value.js +172 -16
- package/dist/value.js.map +1 -1
- package/dist/variant.d.ts +75 -26
- package/dist/variant.d.ts.map +1 -1
- package/dist/variant.js +44 -29
- package/dist/variant.js.map +1 -1
- package/package.json +4 -4
- package/src/arg.ts +6 -1
- package/src/closure.ts +2 -14
- package/src/descriptors.ts +74 -21
- package/src/fn.ts +73 -17
- package/src/index.ts +31 -4
- package/src/mixin.ts +1 -1
- package/src/native-value.ts +146 -14
- package/src/object.ts +23 -11
- package/src/param-spec.ts +94 -8
- package/src/promisify.ts +27 -1
- package/src/properties.ts +184 -5
- package/src/regex.ts +92 -0
- package/src/register-class.ts +446 -38
- package/src/registry.ts +219 -4
- package/src/signal.ts +77 -0
- package/src/type.ts +7 -0
- package/src/value.ts +268 -14
- package/src/variant.ts +184 -53
package/src/registry.ts
CHANGED
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type ExternalObject,
|
|
3
|
+
getFundamentalWrapper,
|
|
3
4
|
getType,
|
|
5
|
+
getTypeClass,
|
|
4
6
|
getWrapper,
|
|
5
7
|
type Handle,
|
|
6
8
|
type RegisterClassVfunc as NativeRegisterClassVfunc,
|
|
9
|
+
setFundamentalWrapper,
|
|
7
10
|
setWrapper,
|
|
8
11
|
} from "@gtkx/native";
|
|
9
12
|
import { type AnyClass, walkClassChain } from "@gtkx/utils";
|
|
10
|
-
import type
|
|
11
|
-
import {
|
|
13
|
+
import { copyLayerMembers, type Mixin, type MixinReceiver } from "./mixin.js";
|
|
14
|
+
import {
|
|
15
|
+
TYPE_INVALID,
|
|
16
|
+
TYPE_OBJECT,
|
|
17
|
+
type TypedClass,
|
|
18
|
+
typeInterfaces,
|
|
19
|
+
typeIsA,
|
|
20
|
+
typeName,
|
|
21
|
+
typeParent,
|
|
22
|
+
} from "./type.js";
|
|
12
23
|
|
|
13
24
|
/**
|
|
14
25
|
* Static side of class `C` with its construct signature preserved but the members named `K`
|
|
@@ -58,6 +69,11 @@ type VfuncDescriptor = {
|
|
|
58
69
|
*/
|
|
59
70
|
type VfuncRegistry = Record<string, VfuncDescriptor>;
|
|
60
71
|
type WrapperBinding = (handle: ExternalObject<Handle>, instance: object) => void;
|
|
72
|
+
/**
|
|
73
|
+
* Picks the wrapper class for one handle of a registered type, such as a subclass keyed on a tag the
|
|
74
|
+
* handle carries.
|
|
75
|
+
*/
|
|
76
|
+
type WrapperClassResolver = (handle: ExternalObject<Handle>) => AnyClass;
|
|
61
77
|
|
|
62
78
|
/**
|
|
63
79
|
* How one property an interface declares reaches the vtable, given as the interface's own accessor
|
|
@@ -88,6 +104,8 @@ type InterfaceLayout = {
|
|
|
88
104
|
};
|
|
89
105
|
|
|
90
106
|
const classRegistry: Map<bigint, AnyClass> = new Map();
|
|
107
|
+
const classStructRegistry: Map<bigint, AnyClass> = new Map();
|
|
108
|
+
const composedClassStructRegistry: Map<bigint, AnyClass> = new Map();
|
|
91
109
|
const interfaceMixinRegistry: Map<bigint, Mixin> = new Map();
|
|
92
110
|
const composedClassRegistry: Map<bigint, AnyClass> = new Map();
|
|
93
111
|
const handleMap: WeakMap<object, ExternalObject<Handle>> = new WeakMap();
|
|
@@ -95,6 +113,8 @@ const vfuncRegistry: WeakMap<object, VfuncRegistry> = new WeakMap();
|
|
|
95
113
|
const interfaceLayoutRegistry: Map<bigint, InterfaceLayout> = new Map();
|
|
96
114
|
const wrapperClasses: WeakSet<AnyClass> = new WeakSet();
|
|
97
115
|
const derivedClasses: WeakSet<AnyClass> = new WeakSet();
|
|
116
|
+
const typeClassHandles: Map<bigint, ExternalObject<Handle>> = new Map();
|
|
117
|
+
const wrapperClassResolvers: WeakMap<AnyClass, WrapperClassResolver> = new WeakMap();
|
|
98
118
|
|
|
99
119
|
function setClassType(cls: AnyClass, type: bigint): void {
|
|
100
120
|
(cls.prototype as { [K in keyof TypedClass]: TypedClass[K] }).__type__ = type;
|
|
@@ -127,6 +147,16 @@ function getInstanceType(instance: object): bigint {
|
|
|
127
147
|
return handle === undefined ? TYPE_INVALID : getType(handle);
|
|
128
148
|
}
|
|
129
149
|
|
|
150
|
+
function coerceGType(value: unknown): unknown {
|
|
151
|
+
if (typeof value !== "function") {
|
|
152
|
+
return value;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const type = getClassType(value as AnyClass);
|
|
156
|
+
|
|
157
|
+
return type === TYPE_INVALID ? value : type;
|
|
158
|
+
}
|
|
159
|
+
|
|
130
160
|
function registerClassType(cls: AnyClass, type: bigint): void {
|
|
131
161
|
if (type === TYPE_INVALID) {
|
|
132
162
|
return;
|
|
@@ -156,10 +186,154 @@ function registerWrapperClass(cls: AnyClass, type: bigint, vfuncs?: VfuncRegistr
|
|
|
156
186
|
}
|
|
157
187
|
}
|
|
158
188
|
|
|
189
|
+
/**
|
|
190
|
+
* Lets a class registered with `registerWrapperClass` pick a subclass for each handle it wraps, for
|
|
191
|
+
* types whose one GType covers several C-level subtypes, the way a cairo surface reports image or
|
|
192
|
+
* recording through `cairo_surface_get_type`. The resolver runs when a handle is wrapped as that class
|
|
193
|
+
* explicitly, the way a boxed value a binding hands back is; a wrapper resolved from a handle's runtime
|
|
194
|
+
* GType never consults it, and a subclass passed to `wrapHandle` directly is used as given.
|
|
195
|
+
* @param cls Registered wrapper class whose handles the resolver classifies.
|
|
196
|
+
* @param resolver Returns the class to instantiate for one handle, `cls` itself included.
|
|
197
|
+
* @throws If `cls` is not a registered wrapper class.
|
|
198
|
+
*/
|
|
199
|
+
function registerWrapperClassResolver(cls: AnyClass, resolver: WrapperClassResolver): void {
|
|
200
|
+
if (!wrapperClasses.has(cls)) {
|
|
201
|
+
throw new Error(
|
|
202
|
+
`Cannot register a wrapper class resolver for ${cls.name}: ` +
|
|
203
|
+
"register the class with registerWrapperClass first",
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
wrapperClassResolvers.set(cls, resolver);
|
|
208
|
+
}
|
|
209
|
+
|
|
159
210
|
function markDerivedClass(cls: AnyClass): void {
|
|
160
211
|
derivedClasses.add(cls);
|
|
161
212
|
}
|
|
162
213
|
|
|
214
|
+
/**
|
|
215
|
+
* Registers the wrapper class of a type's class struct, such as `Gtk.WidgetClass` for `Gtk.Widget`,
|
|
216
|
+
* so `registerClass` can hand a `classInit` hook the new type's class struct wrapped in it.
|
|
217
|
+
* @param cls Wrapper class of the type's instances, already registered through
|
|
218
|
+
* `registerWrapperClass`.
|
|
219
|
+
* @param structClass Wrapper class of the type's class struct.
|
|
220
|
+
*/
|
|
221
|
+
function registerClassStruct(cls: AnyClass, structClass: AnyClass): void {
|
|
222
|
+
const type = getClassType(cls);
|
|
223
|
+
|
|
224
|
+
if (type !== TYPE_INVALID) {
|
|
225
|
+
classStructRegistry.set(type, structClass);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function collectClassStructClasses(type: bigint): AnyClass[] {
|
|
230
|
+
const structs: AnyClass[] = [];
|
|
231
|
+
let current = type;
|
|
232
|
+
|
|
233
|
+
while (current !== TYPE_INVALID) {
|
|
234
|
+
const structClass = classStructRegistry.get(current);
|
|
235
|
+
|
|
236
|
+
if (structClass !== undefined) {
|
|
237
|
+
structs.push(structClass);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
current = typeParent(current);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return structs;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function composeClassStructClass(structs: AnyClass[]): AnyClass | undefined {
|
|
247
|
+
const [nearest, ...ancestors] = structs;
|
|
248
|
+
|
|
249
|
+
if (nearest === undefined || ancestors.length === 0) {
|
|
250
|
+
return nearest;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const composed: AnyClass = class extends nearest {};
|
|
254
|
+
Object.defineProperty(composed, "name", { value: nearest.name });
|
|
255
|
+
|
|
256
|
+
for (const structClass of ancestors) {
|
|
257
|
+
copyLayerMembers(composed, structClass.prototype);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return composed;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function getClassStructClass(type: bigint): AnyClass | undefined {
|
|
264
|
+
const cached = composedClassStructRegistry.get(type);
|
|
265
|
+
|
|
266
|
+
if (cached !== undefined) {
|
|
267
|
+
return cached;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const composed = composeClassStructClass(collectClassStructClasses(type));
|
|
271
|
+
|
|
272
|
+
if (composed !== undefined) {
|
|
273
|
+
composedClassStructRegistry.set(type, composed);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return composed;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function peekedTypeLabel(type: bigint | AnyClass, gtype: bigint): string {
|
|
280
|
+
const name = typeName(gtype);
|
|
281
|
+
|
|
282
|
+
if (name !== null) {
|
|
283
|
+
return name;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return typeof type === "bigint" ? String(type) : type.name;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function getTypeClassHandle(gtype: bigint): ExternalObject<Handle> {
|
|
290
|
+
const cached = typeClassHandles.get(gtype);
|
|
291
|
+
|
|
292
|
+
if (cached !== undefined) {
|
|
293
|
+
return cached;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const handle = getTypeClass(gtype);
|
|
297
|
+
typeClassHandles.set(gtype, handle);
|
|
298
|
+
|
|
299
|
+
return handle;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Returns a GObject type's class struct, wrapped in the class-struct wrapper classes registered
|
|
304
|
+
* for the type's ancestry, such as `Gtk.WidgetClass` composed with `GObject.ObjectClass` for a
|
|
305
|
+
* widget type. The class is referenced so it exists even before the type's first instance, and
|
|
306
|
+
* the reference is deliberately never released: once created, a class struct lives for the rest
|
|
307
|
+
* of the process. Backs the `peek` statics of generated GTypeStruct wrappers, such as
|
|
308
|
+
* `GObject.ObjectClass.peek` and `Gtk.WidgetClass.peek`.
|
|
309
|
+
*
|
|
310
|
+
* @param type GType to peek the class struct of, or a registered wrapper class of the type.
|
|
311
|
+
* @param base When given, wrapper class of the type the peeked type must derive from; the peek
|
|
312
|
+
* throws for a type outside that lineage. Without it any GObject type is accepted.
|
|
313
|
+
* @returns The wrapped class struct.
|
|
314
|
+
*/
|
|
315
|
+
function peekTypeClass(type: bigint | AnyClass, base?: AnyClass): object {
|
|
316
|
+
const gtype = typeof type === "bigint" ? type : getClassType(type);
|
|
317
|
+
|
|
318
|
+
if (!typeIsA(gtype, TYPE_OBJECT)) {
|
|
319
|
+
throw new TypeError(`peekTypeClass: '${peekedTypeLabel(type, gtype)}' is not a GObject type`);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (base !== undefined && !typeIsA(gtype, getClassType(base))) {
|
|
323
|
+
throw new TypeError(`peekTypeClass: '${peekedTypeLabel(type, gtype)}' does not derive from '${base.name}'`);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const structClass = getClassStructClass(gtype);
|
|
327
|
+
|
|
328
|
+
if (structClass === undefined) {
|
|
329
|
+
throw new TypeError(
|
|
330
|
+
`peekTypeClass: no ancestor of '${peekedTypeLabel(type, gtype)}' registers a class struct wrapper`,
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
return wrapHandle(getTypeClassHandle(gtype), structClass);
|
|
335
|
+
}
|
|
336
|
+
|
|
163
337
|
function resolveAncestorType(ancestor: AnyClass): bigint | undefined {
|
|
164
338
|
if (derivedClasses.has(ancestor) || !wrapperClasses.has(ancestor)) {
|
|
165
339
|
return undefined;
|
|
@@ -204,8 +378,9 @@ function registerInterface(cls: AnyClass, type: bigint, mixin: Mixin, layout?: I
|
|
|
204
378
|
* Wraps a native handle in a JS wrapper instance. With no class, resolves and
|
|
205
379
|
* reuses the wrapper for the handle's runtime GType (composing interface mixins),
|
|
206
380
|
* and hands back an instance that already carries a handle unchanged; with an
|
|
207
|
-
* explicit class, creates a bare instance backed by the handle
|
|
208
|
-
*
|
|
381
|
+
* explicit class, creates a bare instance backed by the handle, of the subclass the
|
|
382
|
+
* class's `registerWrapperClassResolver` resolver picks when it has one. Returns null
|
|
383
|
+
* for a null or undefined handle.
|
|
209
384
|
* @param handle Native handle to wrap.
|
|
210
385
|
* @param cls Wrapper class to instantiate, or omitted to resolve it from the runtime type.
|
|
211
386
|
*/
|
|
@@ -229,8 +404,27 @@ function wrapHandle(handle: ExternalObject<Handle> | null | undefined, cls?: Any
|
|
|
229
404
|
return getOrCreateWrapper(handle);
|
|
230
405
|
}
|
|
231
406
|
|
|
407
|
+
const resolver = wrapperClassResolvers.get(cls);
|
|
408
|
+
const instance: object = Object.create((resolver === undefined ? cls : resolver(handle)).prototype) as object;
|
|
409
|
+
setHandle(instance, handle);
|
|
410
|
+
|
|
411
|
+
return instance;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function wrapFundamentalHandle(handle: ExternalObject<Handle> | null | undefined, cls: AnyClass): object | null {
|
|
415
|
+
if (handle === null || handle === undefined) {
|
|
416
|
+
return null;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const existing = getFundamentalWrapper(handle);
|
|
420
|
+
|
|
421
|
+
if (existing) {
|
|
422
|
+
return existing;
|
|
423
|
+
}
|
|
424
|
+
|
|
232
425
|
const instance: object = Object.create(cls.prototype) as object;
|
|
233
426
|
setHandle(instance, handle);
|
|
427
|
+
setFundamentalWrapper(handle, instance);
|
|
234
428
|
|
|
235
429
|
return instance;
|
|
236
430
|
}
|
|
@@ -378,6 +572,18 @@ function instanceClassName(instance: object): string {
|
|
|
378
572
|
return (instance as { constructor?: { name?: string } }).constructor?.name ?? "object";
|
|
379
573
|
}
|
|
380
574
|
|
|
575
|
+
function describeValueKind(value: unknown): string {
|
|
576
|
+
if (value === null) {
|
|
577
|
+
return "null";
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
if (typeof value !== "object") {
|
|
581
|
+
return typeof value;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
return instanceClassName(value);
|
|
585
|
+
}
|
|
586
|
+
|
|
381
587
|
/** Returns the native handle bound to a wrapper instance, throwing if none is set. */
|
|
382
588
|
function getHandle(instance: object): ExternalObject<Handle> {
|
|
383
589
|
const handle = handleMap.get(instance);
|
|
@@ -420,12 +626,20 @@ function getInterfaceProperties(type: bigint): Record<string, InterfaceProperty>
|
|
|
420
626
|
}
|
|
421
627
|
|
|
422
628
|
export {
|
|
629
|
+
coerceGType,
|
|
630
|
+
describeValueKind,
|
|
631
|
+
getClassStructClass,
|
|
423
632
|
getClassType,
|
|
424
633
|
getInstanceType,
|
|
634
|
+
getTypeClassHandle,
|
|
425
635
|
markDerivedClass,
|
|
636
|
+
peekTypeClass,
|
|
637
|
+
registerClassStruct,
|
|
426
638
|
registerClassType,
|
|
427
639
|
registerWrapperClass,
|
|
640
|
+
registerWrapperClassResolver,
|
|
428
641
|
registerInterface,
|
|
642
|
+
wrapFundamentalHandle,
|
|
429
643
|
wrapHandle,
|
|
430
644
|
getWrapperClass,
|
|
431
645
|
resolveWrapperClass,
|
|
@@ -443,4 +657,5 @@ export {
|
|
|
443
657
|
type InterfaceProperty,
|
|
444
658
|
type StaticBase,
|
|
445
659
|
type VfuncDescriptor,
|
|
660
|
+
type WrapperClassResolver,
|
|
446
661
|
};
|
package/src/signal.ts
CHANGED
|
@@ -3,10 +3,12 @@ import type { TypedClass } from "./type.js";
|
|
|
3
3
|
import { type Arg, isCallerAllocatedArg, isInoutArg, isOutputArg } from "./arg.js";
|
|
4
4
|
import { bind, createBindCache } from "./bind.js";
|
|
5
5
|
import { wrapCallback } from "./callback.js";
|
|
6
|
+
import { toClosure } from "./closure.js";
|
|
6
7
|
import {
|
|
7
8
|
arrayT,
|
|
8
9
|
biguint64T,
|
|
9
10
|
booleanT,
|
|
11
|
+
boxedT,
|
|
10
12
|
type CallbackDescriptor,
|
|
11
13
|
objectT,
|
|
12
14
|
stringT,
|
|
@@ -21,7 +23,9 @@ import {
|
|
|
21
23
|
fromValue,
|
|
22
24
|
getBoxedValue,
|
|
23
25
|
inoutValueForBoxedDescriptor,
|
|
26
|
+
intoValue,
|
|
24
27
|
newValueForDescriptor,
|
|
28
|
+
newValueForType,
|
|
25
29
|
outValueForBoxedDescriptor,
|
|
26
30
|
outValueForDescriptor,
|
|
27
31
|
toValue,
|
|
@@ -30,6 +34,11 @@ import {
|
|
|
30
34
|
/** Function invoked when a connected GObject signal is emitted. */
|
|
31
35
|
type SignalHandler = (...args: unknown[]) => unknown;
|
|
32
36
|
|
|
37
|
+
type DeclaredSignalTypes = {
|
|
38
|
+
paramTypes: bigint[];
|
|
39
|
+
returnType?: bigint;
|
|
40
|
+
};
|
|
41
|
+
|
|
33
42
|
/** The marshalling and handler that make up a single signal connection. */
|
|
34
43
|
type SignalConnectSpec = {
|
|
35
44
|
/**
|
|
@@ -77,6 +86,21 @@ const gSignalHandlerIsConnected = bind(
|
|
|
77
86
|
);
|
|
78
87
|
|
|
79
88
|
const gSignalHandlerDisconnect = bind(LIB, "g_signal_handler_disconnect", [objectT("borrowed"), uint64T], voidT);
|
|
89
|
+
const CLOSURE_T = boxedT("GClosure", { sharedLibrary: LIB, getTypeFnName: "g_closure_get_type" });
|
|
90
|
+
|
|
91
|
+
const gSignalConnectClosure = bind(
|
|
92
|
+
LIB,
|
|
93
|
+
"g_signal_connect_closure",
|
|
94
|
+
[objectT("borrowed"), stringT("borrowed"), CLOSURE_T, booleanT],
|
|
95
|
+
uint64T,
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
const gSignalOverrideClassClosure = bind(
|
|
99
|
+
LIB,
|
|
100
|
+
"g_signal_override_class_closure",
|
|
101
|
+
[uint32T, biguint64T, CLOSURE_T],
|
|
102
|
+
voidT,
|
|
103
|
+
);
|
|
80
104
|
|
|
81
105
|
/** Returns the signal name without its detail suffix (the part after `::`). */
|
|
82
106
|
const getSignalBaseName = (signal: string): string => {
|
|
@@ -208,6 +232,55 @@ function connectSignal(instance: object, signal: string, spec: SignalConnectSpec
|
|
|
208
232
|
return handlerId;
|
|
209
233
|
}
|
|
210
234
|
|
|
235
|
+
function overrideSignalClassClosure(type: bigint, signal: string, handler: SignalHandler): void {
|
|
236
|
+
const signalId = gSignalLookup(signal, type) as number;
|
|
237
|
+
|
|
238
|
+
if (signalId === 0) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
gSignalOverrideClassClosure(signalId, type, toClosure(handler));
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function connectClosureSignal(instance: object, signal: string, handler: SignalHandler, isAfter: boolean): number {
|
|
246
|
+
const closure = toClosure((...args: unknown[]) => Reflect.apply(handler, null, args.slice(1)));
|
|
247
|
+
const handlerId = gSignalConnectClosure(getHandle(instance), signal, closure, isAfter) as number;
|
|
248
|
+
trackConnection(instance, getSignalBaseName(signal), handlerId);
|
|
249
|
+
|
|
250
|
+
return handlerId;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function emitDeclaredSignal(instance: object, signal: string, types: DeclaredSignalTypes, args: unknown[]): unknown {
|
|
254
|
+
const { paramTypes, returnType } = types;
|
|
255
|
+
|
|
256
|
+
if (args.length !== paramTypes.length) {
|
|
257
|
+
throw new TypeError(
|
|
258
|
+
`emit: signal '${signal}' takes ${String(paramTypes.length)} arguments, got ${String(args.length)}`,
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const signalId = getSignalId(instance, signal);
|
|
263
|
+
const detail = getSignalDetailQuark(signal);
|
|
264
|
+
const values = [toValue(objectT("full"), instance)];
|
|
265
|
+
|
|
266
|
+
for (const [index, paramType] of paramTypes.entries()) {
|
|
267
|
+
const value = newValueForType(paramType);
|
|
268
|
+
intoValue(value, args[index]);
|
|
269
|
+
values.push(value);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (returnType === undefined) {
|
|
273
|
+
gSignalEmitv(values, signalId, detail, undefined);
|
|
274
|
+
|
|
275
|
+
return undefined;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const returnValue = newValueForType(returnType);
|
|
279
|
+
gSignalEmitv(values, signalId, detail, returnValue);
|
|
280
|
+
|
|
281
|
+
return fromValue(returnValue);
|
|
282
|
+
}
|
|
283
|
+
|
|
211
284
|
const createEmitValue = (arg: EmitArg): { value: ExternalObject<Handle>; read?: () => unknown } => {
|
|
212
285
|
if (!isOutputArg(arg)) {
|
|
213
286
|
return { value: toValue(arg.type, arg.value) };
|
|
@@ -270,11 +343,15 @@ function emitSignal(instance: object, signal: string, args: EmitArg[], returns?:
|
|
|
270
343
|
|
|
271
344
|
export {
|
|
272
345
|
getSignalBaseName,
|
|
346
|
+
connectClosureSignal,
|
|
273
347
|
connectSignal,
|
|
348
|
+
type DeclaredSignalTypes,
|
|
274
349
|
disconnectSignal,
|
|
350
|
+
emitDeclaredSignal,
|
|
275
351
|
emitSignal,
|
|
276
352
|
hasSignalListener,
|
|
277
353
|
isSignalHandlerConnected,
|
|
354
|
+
overrideSignalClassClosure,
|
|
278
355
|
untrackConnection,
|
|
279
356
|
type SignalHandler,
|
|
280
357
|
};
|
package/src/type.ts
CHANGED
|
@@ -203,11 +203,17 @@ const resolveFundamentalType = (descriptor: FundamentalDescriptor): bigint => {
|
|
|
203
203
|
throw new Error("Cannot resolve gtype for fundamental type without a typeName");
|
|
204
204
|
};
|
|
205
205
|
|
|
206
|
+
const getByteArrayType = (): bigint => resolveType(LIB, "g_byte_array_get_type");
|
|
207
|
+
|
|
206
208
|
function resolveArrayType(descriptor: ArrayDescriptor): bigint {
|
|
207
209
|
if (descriptor.itemDescriptor.kind === "string" && descriptor.arrayKind === "array") {
|
|
208
210
|
return getStrvType();
|
|
209
211
|
}
|
|
210
212
|
|
|
213
|
+
if (descriptor.arrayKind === "gbytearray") {
|
|
214
|
+
return getByteArrayType();
|
|
215
|
+
}
|
|
216
|
+
|
|
211
217
|
throw new Error(`Unsupported array type ${descriptor.arrayKind} of ${descriptor.itemDescriptor.kind}`);
|
|
212
218
|
}
|
|
213
219
|
|
|
@@ -272,6 +278,7 @@ export {
|
|
|
272
278
|
TYPE_GTYPE,
|
|
273
279
|
TYPE_VARIANT,
|
|
274
280
|
TYPE_UNICHAR,
|
|
281
|
+
getByteArrayType,
|
|
275
282
|
getErrorType,
|
|
276
283
|
getStrvType,
|
|
277
284
|
isResolvableDescriptor,
|