@gtkx/runtime 1.6.0 → 2.0.0-beta.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.
- package/README.md +5 -5
- package/dist/application-class.d.ts +1 -1
- package/dist/application-class.d.ts.map +1 -1
- package/dist/application-class.js +1 -2
- package/dist/application-class.js.map +1 -1
- package/dist/arg.d.ts +4 -1
- package/dist/arg.d.ts.map +1 -1
- package/dist/arg.js.map +1 -1
- package/dist/bind.d.ts.map +1 -1
- package/dist/bind.js +1 -9
- package/dist/bind.js.map +1 -1
- package/dist/callback.d.ts +6 -1
- package/dist/callback.d.ts.map +1 -1
- package/dist/callback.js +33 -21
- package/dist/callback.js.map +1 -1
- package/dist/closure.d.ts +3 -1
- package/dist/closure.d.ts.map +1 -1
- package/dist/closure.js +17 -6
- package/dist/closure.js.map +1 -1
- package/dist/descriptors.d.ts +22 -51
- package/dist/descriptors.d.ts.map +1 -1
- package/dist/descriptors.js +53 -27
- package/dist/descriptors.js.map +1 -1
- package/dist/fn.d.ts.map +1 -1
- package/dist/fn.js +23 -9
- package/dist/fn.js.map +1 -1
- package/dist/folded-lengths.d.ts +2 -1
- package/dist/folded-lengths.d.ts.map +1 -1
- package/dist/folded-lengths.js +17 -7
- package/dist/folded-lengths.js.map +1 -1
- package/dist/index.d.ts +2 -24
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -24
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +18 -2
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +14 -2
- package/dist/internal.js.map +1 -1
- package/dist/listeners.d.ts +3 -13
- package/dist/listeners.d.ts.map +1 -1
- package/dist/listeners.js +12 -12
- package/dist/listeners.js.map +1 -1
- package/dist/mixin.d.ts +5 -3
- package/dist/mixin.d.ts.map +1 -1
- package/dist/mixin.js +36 -9
- package/dist/mixin.js.map +1 -1
- package/dist/native-value.d.ts +9 -1
- package/dist/native-value.d.ts.map +1 -1
- package/dist/native-value.js +20 -3
- package/dist/native-value.js.map +1 -1
- package/dist/object.d.ts +11 -0
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +18 -25
- package/dist/object.js.map +1 -1
- package/dist/properties.d.ts +5 -3
- package/dist/properties.d.ts.map +1 -1
- package/dist/properties.js +67 -23
- package/dist/properties.js.map +1 -1
- package/dist/property-brand.d.ts +5 -0
- package/dist/property-brand.d.ts.map +1 -0
- package/dist/property-brand.js +5 -0
- package/dist/property-brand.js.map +1 -0
- package/dist/register-class.d.ts +142 -264
- package/dist/register-class.d.ts.map +1 -1
- package/dist/register-class.js +19 -37
- package/dist/register-class.js.map +1 -1
- package/dist/registry.d.ts +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +4 -4
- package/dist/registry.js.map +1 -1
- package/dist/signal-brand.d.ts +12 -0
- package/dist/signal-brand.d.ts.map +1 -0
- package/dist/signal-brand.js +6 -0
- package/dist/signal-brand.js.map +1 -0
- package/dist/signal.d.ts +39 -2
- package/dist/signal.d.ts.map +1 -1
- package/dist/signal.js +84 -27
- package/dist/signal.js.map +1 -1
- package/dist/t.d.ts +5 -21
- package/dist/t.d.ts.map +1 -1
- package/dist/t.js +1 -5
- package/dist/t.js.map +1 -1
- package/dist/type.d.ts.map +1 -1
- package/dist/type.js +8 -2
- package/dist/type.js.map +1 -1
- package/dist/value.d.ts.map +1 -1
- package/dist/value.js +7 -1
- package/dist/value.js.map +1 -1
- package/dist/variant.d.ts +2 -6
- package/dist/variant.d.ts.map +1 -1
- package/dist/variant.js.map +1 -1
- package/dist/vfunc-call.d.ts.map +1 -1
- package/dist/vfunc-call.js +2 -11
- package/dist/vfunc-call.js.map +1 -1
- package/package.json +9 -5
- package/src/application-class.ts +2 -2
- package/src/arg.ts +4 -1
- package/src/bind.ts +1 -12
- package/src/callback.ts +53 -29
- package/src/closure.ts +31 -6
- package/src/descriptors.ts +95 -59
- package/src/fn.ts +31 -10
- package/src/folded-lengths.ts +23 -10
- package/src/index.ts +2 -24
- package/src/internal.ts +43 -2
- package/src/listeners.ts +21 -26
- package/src/mixin.ts +55 -9
- package/src/native-value.ts +24 -3
- package/src/object.ts +55 -5
- package/src/properties.ts +90 -26
- package/src/property-brand.ts +5 -0
- package/src/register-class.ts +338 -341
- package/src/registry.ts +4 -4
- package/src/signal-brand.ts +29 -0
- package/src/signal.ts +185 -39
- package/src/t.ts +5 -21
- package/src/type.ts +10 -2
- package/src/value.ts +9 -1
- package/src/variant.ts +2 -6
- package/src/vfunc-call.ts +3 -16
package/src/registry.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
setWrapper,
|
|
11
11
|
} from "@gtkx/native";
|
|
12
12
|
import { type AnyClass, walkClassChain } from "@gtkx/utils";
|
|
13
|
-
import { copyLayerMembers, installMixins, type Mixin, type MixinReceiver } from "./mixin.js";
|
|
13
|
+
import { copyLayerMembers, createMixinLayer, installMixins, type Mixin, type MixinReceiver } from "./mixin.js";
|
|
14
14
|
import {
|
|
15
15
|
TYPE_INVALID,
|
|
16
16
|
TYPE_OBJECT,
|
|
@@ -402,7 +402,7 @@ function registerInterface(cls: AnyClass, type: bigint, mixin: Mixin, layout?: I
|
|
|
402
402
|
* @param interfaces Registered interface classes to adopt, in order.
|
|
403
403
|
* @throws If an entry is not a registered interface.
|
|
404
404
|
*/
|
|
405
|
-
function installInterfaces(cls: AnyClass, interfaces: AnyClass[]): void {
|
|
405
|
+
function installInterfaces(cls: AnyClass, interfaces: AnyClass[], inheritedOverrides: string[] = []): void {
|
|
406
406
|
const mixins = interfaces.map((iface) => {
|
|
407
407
|
const mixin = getInterfaceMixin(getClassType(iface));
|
|
408
408
|
|
|
@@ -413,7 +413,7 @@ function installInterfaces(cls: AnyClass, interfaces: AnyClass[]): void {
|
|
|
413
413
|
return mixin;
|
|
414
414
|
});
|
|
415
415
|
|
|
416
|
-
installMixins(cls, mixins);
|
|
416
|
+
installMixins(cls, mixins, inheritedOverrides);
|
|
417
417
|
}
|
|
418
418
|
|
|
419
419
|
/**
|
|
@@ -535,7 +535,7 @@ function applyInterfaceMixin(cls: AnyClass, type: bigint, baseType: bigint, appl
|
|
|
535
535
|
|
|
536
536
|
applied.add(type);
|
|
537
537
|
|
|
538
|
-
return
|
|
538
|
+
return createMixinLayer(cls as AnyClass<MixinReceiver>, mixin, new Set());
|
|
539
539
|
}
|
|
540
540
|
|
|
541
541
|
function createComposedClass(base: AnyClass, runtimeType: bigint): AnyClass {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const naturalSignalMember: unique symbol = Symbol("gtkx.naturalSignalMember");
|
|
2
|
+
const classSignalMember: unique symbol = Symbol("gtkx.classSignalMember");
|
|
3
|
+
const signalMapOverride: unique symbol = Symbol("gtkx.signalMapOverride");
|
|
4
|
+
const signalEmitMapOverride: unique symbol = Symbol("gtkx.signalEmitMapOverride");
|
|
5
|
+
|
|
6
|
+
type ResolvedSignalMap<T, TFallback> = T extends {
|
|
7
|
+
[signalMapOverride]?: infer TResolver;
|
|
8
|
+
}
|
|
9
|
+
? TResolver extends () => infer TMap
|
|
10
|
+
? NonNullable<TMap>
|
|
11
|
+
: TFallback
|
|
12
|
+
: TFallback;
|
|
13
|
+
|
|
14
|
+
type ResolvedSignalEmitMap<T, TFallback> = T extends {
|
|
15
|
+
[signalEmitMapOverride]?: infer TResolver;
|
|
16
|
+
}
|
|
17
|
+
? TResolver extends () => infer TMap
|
|
18
|
+
? NonNullable<TMap>
|
|
19
|
+
: TFallback
|
|
20
|
+
: TFallback;
|
|
21
|
+
|
|
22
|
+
export {
|
|
23
|
+
classSignalMember,
|
|
24
|
+
naturalSignalMember,
|
|
25
|
+
signalEmitMapOverride,
|
|
26
|
+
type ResolvedSignalEmitMap,
|
|
27
|
+
type ResolvedSignalMap,
|
|
28
|
+
signalMapOverride,
|
|
29
|
+
};
|
package/src/signal.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { Descriptor, ExternalObject, Handle } from "@gtkx/native";
|
|
2
|
-
import {
|
|
2
|
+
import { type AnyClass, toCamelIdentifier, upperFirst } from "@gtkx/utils";
|
|
3
|
+
import type { ResolvedSignalEmitMap, ResolvedSignalMap } from "./signal-brand.js";
|
|
3
4
|
import { type Arg, isCallerAllocatedArg, isInoutArg, isOutputArg } from "./arg.js";
|
|
4
|
-
import { bind
|
|
5
|
+
import { bind } from "./bind.js";
|
|
5
6
|
import { wrapCallback } from "./callback.js";
|
|
6
|
-
import { toClosure } from "./closure.js";
|
|
7
|
+
import { newCCallbackClosure, toClosure } from "./closure.js";
|
|
7
8
|
import {
|
|
8
9
|
arrayT,
|
|
9
10
|
biguint64T,
|
|
@@ -19,7 +20,7 @@ import {
|
|
|
19
20
|
voidT,
|
|
20
21
|
} from "./descriptors.js";
|
|
21
22
|
import { LIB, VALUE_SIZE, VALUE_T } from "./library.js";
|
|
22
|
-
import { getHandle } from "./registry.js";
|
|
23
|
+
import { getClassType, getHandle, getInstanceType } from "./registry.js";
|
|
23
24
|
import { packTupleResult } from "./tuple.js";
|
|
24
25
|
import { TYPE_INVALID, type TypedClass, typeInterfaces, typeParent } from "./type.js";
|
|
25
26
|
import {
|
|
@@ -37,6 +38,55 @@ import {
|
|
|
37
38
|
/** Function invoked when a connected GObject signal is emitted. */
|
|
38
39
|
type SignalHandler = (...args: unknown[]) => unknown;
|
|
39
40
|
|
|
41
|
+
const isSignalHandler = (value: unknown): value is SignalHandler => typeof value === "function";
|
|
42
|
+
|
|
43
|
+
type DeclaredSignalMap<T> = T extends { __signals__?: infer TSignals } ? NonNullable<TSignals> : never;
|
|
44
|
+
type SignalMap<T> = ResolvedSignalMap<T, DeclaredSignalMap<T>>;
|
|
45
|
+
type SignalName<T> = Extract<keyof SignalMap<T>, string>;
|
|
46
|
+
type DeclaredSignalEmitMap<T> = T extends { __signalEmit__?: infer TSignals }
|
|
47
|
+
? NonNullable<TSignals>
|
|
48
|
+
: T extends { __signals__?: infer TSignals }
|
|
49
|
+
? {
|
|
50
|
+
[K in keyof NonNullable<TSignals>]: NonNullable<TSignals>[K] extends (
|
|
51
|
+
...args: infer TArgs
|
|
52
|
+
) => infer TResult
|
|
53
|
+
? { args: TArgs; result: TResult }
|
|
54
|
+
: never;
|
|
55
|
+
}
|
|
56
|
+
: never;
|
|
57
|
+
type SignalEmitMap<T> = ResolvedSignalEmitMap<T, DeclaredSignalEmitMap<T>>;
|
|
58
|
+
type SignalEmitName<T> = Extract<keyof SignalEmitMap<T>, string>;
|
|
59
|
+
type SignalEmitArguments<T, K extends SignalEmitName<T>> = SignalEmitMap<T>[K] extends {
|
|
60
|
+
args: infer TArgs extends unknown[];
|
|
61
|
+
}
|
|
62
|
+
? TArgs
|
|
63
|
+
: never;
|
|
64
|
+
type SignalEmitResult<T, K extends SignalEmitName<T>> = SignalEmitMap<T>[K] extends {
|
|
65
|
+
result: infer TResult;
|
|
66
|
+
}
|
|
67
|
+
? TResult
|
|
68
|
+
: never;
|
|
69
|
+
|
|
70
|
+
type SignalConnector = (
|
|
71
|
+
instance: object,
|
|
72
|
+
signal: string,
|
|
73
|
+
handler: SignalHandler,
|
|
74
|
+
isAfter?: boolean,
|
|
75
|
+
) => number;
|
|
76
|
+
type SignalEmitter = (instance: object, signal: string, args: unknown[]) => unknown;
|
|
77
|
+
type SignalDispatch = {
|
|
78
|
+
connect: SignalConnector;
|
|
79
|
+
emit: SignalEmitter;
|
|
80
|
+
};
|
|
81
|
+
type SignalDispatchSpec = {
|
|
82
|
+
connect: SignalConnector;
|
|
83
|
+
emit: SignalEmitter;
|
|
84
|
+
};
|
|
85
|
+
type PendingSignalDispatch = {
|
|
86
|
+
ownerType: bigint;
|
|
87
|
+
spec: SignalDispatchSpec;
|
|
88
|
+
};
|
|
89
|
+
|
|
40
90
|
type DeclaredSignalTypes = {
|
|
41
91
|
paramTypes: bigint[];
|
|
42
92
|
returnType?: bigint;
|
|
@@ -69,8 +119,9 @@ type EmitArg = Arg & {
|
|
|
69
119
|
value?: unknown;
|
|
70
120
|
};
|
|
71
121
|
|
|
72
|
-
const connectCache = createBindCache();
|
|
73
122
|
const connectionTable: WeakMap<object, Map<string, Set<number>>> = new WeakMap();
|
|
123
|
+
const signalDispatchTable: Map<number, SignalDispatch> = new Map();
|
|
124
|
+
const pendingSignalDispatches: Map<string, PendingSignalDispatch[]> = new Map();
|
|
74
125
|
const gQuarkFromString = bind(LIB, "g_quark_from_string", [stringT("borrowed")], uint32T);
|
|
75
126
|
const gSignalLookup = bind(LIB, "g_signal_lookup", [stringT("borrowed"), biguint64T], uint32T);
|
|
76
127
|
const gSignalName = bind(LIB, "g_signal_name", [uint32T], stringT("borrowed"));
|
|
@@ -115,6 +166,15 @@ const getSignalBaseName = (signal: string): string => {
|
|
|
115
166
|
return detailIndex === -1 ? signal : signal.slice(0, detailIndex);
|
|
116
167
|
};
|
|
117
168
|
|
|
169
|
+
const canonicalSignalName = (signal: string): string => getSignalBaseName(signal).replaceAll("_", "-");
|
|
170
|
+
|
|
171
|
+
const canonicalDetailedSignalName = (signal: string): string => {
|
|
172
|
+
const detailIndex = signal.indexOf("::");
|
|
173
|
+
const base = canonicalSignalName(signal);
|
|
174
|
+
|
|
175
|
+
return detailIndex === -1 ? base : `${base}${signal.slice(detailIndex)}`;
|
|
176
|
+
};
|
|
177
|
+
|
|
118
178
|
function getSignalDetailQuark(signal: string): number {
|
|
119
179
|
const detailIndex = signal.indexOf("::");
|
|
120
180
|
|
|
@@ -129,21 +189,8 @@ const isSignalHandlerConnected = (instance: object, handlerId: number): boolean
|
|
|
129
189
|
gSignalHandlerIsConnected(getHandle(instance), handlerId) as boolean;
|
|
130
190
|
|
|
131
191
|
const trackConnection = (instance: object, signal: string, handlerId: number): void => {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
if (!bySignal) {
|
|
135
|
-
bySignal = new Map();
|
|
136
|
-
connectionTable.set(instance, bySignal);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
let handlerIds = bySignal.get(signal);
|
|
140
|
-
|
|
141
|
-
if (!handlerIds) {
|
|
142
|
-
handlerIds = new Set();
|
|
143
|
-
bySignal.set(signal, handlerIds);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
handlerIds.add(handlerId);
|
|
192
|
+
const bySignal = connectionTable.getOrInsertComputed(instance, () => new Map<string, Set<number>>());
|
|
193
|
+
bySignal.getOrInsertComputed(signal, () => new Set<number>()).add(handlerId);
|
|
147
194
|
};
|
|
148
195
|
|
|
149
196
|
const untrackConnection = (instance: object, handlerId: number): void => {
|
|
@@ -194,7 +241,7 @@ function hasSignalListener(instance: object, signals?: string[]): boolean {
|
|
|
194
241
|
}
|
|
195
242
|
|
|
196
243
|
const names =
|
|
197
|
-
signals === undefined ? bySignal.keys().toArray() : signals.map((signal) =>
|
|
244
|
+
signals === undefined ? bySignal.keys().toArray() : signals.map((signal) => canonicalSignalName(signal));
|
|
198
245
|
|
|
199
246
|
return names.some((name) => {
|
|
200
247
|
const handlerIds = bySignal.get(name);
|
|
@@ -238,23 +285,11 @@ const buildSignalNames = (type: bigint): string[] => {
|
|
|
238
285
|
return [...names];
|
|
239
286
|
};
|
|
240
287
|
|
|
241
|
-
const signalNamesFor = (type: bigint): string[] =>
|
|
288
|
+
const signalNamesFor = (type: bigint): string[] => signalNameCache.getOrInsertComputed(type, buildSignalNames);
|
|
242
289
|
|
|
243
290
|
const getSignalId = (instance: object, signal: string): number =>
|
|
244
291
|
signalIdFor((instance as TypedClass).__type__, signal);
|
|
245
292
|
|
|
246
|
-
function connectBind(type: bigint, signal: string, callback: CallbackDescriptor): (...values: unknown[]) => unknown {
|
|
247
|
-
const key = `${String(type)}\0${getSignalBaseName(signal)}`;
|
|
248
|
-
|
|
249
|
-
return connectCache(
|
|
250
|
-
key,
|
|
251
|
-
LIB,
|
|
252
|
-
"g_signal_connect_data",
|
|
253
|
-
[objectT("borrowed"), stringT("borrowed"), callback, uint32T],
|
|
254
|
-
uint64T,
|
|
255
|
-
);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
293
|
/**
|
|
259
294
|
* Connects a handler to a GObject signal on an instance and returns the handler id.
|
|
260
295
|
* @param instance Emitter to connect to.
|
|
@@ -265,9 +300,10 @@ function connectSignal(instance: object, signal: string, spec: SignalConnectSpec
|
|
|
265
300
|
const { callback, handler, isAfter } = spec;
|
|
266
301
|
const wrapped = wrapCallback(handler, callback, "signal");
|
|
267
302
|
const type: bigint = (instance as TypedClass).__type__;
|
|
268
|
-
const
|
|
269
|
-
const
|
|
270
|
-
|
|
303
|
+
const key = `${String(type)}\0${getSignalBaseName(signal)}`;
|
|
304
|
+
const closure = newCCallbackClosure(key, callback, wrapped);
|
|
305
|
+
const handlerId = gSignalConnectClosure(getHandle(instance), signal, closure, isAfter) as number;
|
|
306
|
+
trackConnection(instance, canonicalSignalName(signal), handlerId);
|
|
271
307
|
|
|
272
308
|
return handlerId;
|
|
273
309
|
}
|
|
@@ -279,7 +315,7 @@ function overrideSignalClassClosure(type: bigint, signalId: number, handler: Sig
|
|
|
279
315
|
function connectClosureSignal(instance: object, signal: string, handler: SignalHandler, isAfter: boolean): number {
|
|
280
316
|
const closure = toClosure((...args: unknown[]) => Reflect.apply(handler, null, args.slice(1)));
|
|
281
317
|
const handlerId = gSignalConnectClosure(getHandle(instance), signal, closure, isAfter) as number;
|
|
282
|
-
trackConnection(instance,
|
|
318
|
+
trackConnection(instance, canonicalSignalName(signal), handlerId);
|
|
283
319
|
|
|
284
320
|
return handlerId;
|
|
285
321
|
}
|
|
@@ -375,19 +411,129 @@ function emitSignal(instance: object, signal: string, args: EmitArg[], returns?:
|
|
|
375
411
|
return packTupleResult(readEmitOutputs(reads), fromValue(returnValue), true);
|
|
376
412
|
}
|
|
377
413
|
|
|
414
|
+
function installSignalDispatch(
|
|
415
|
+
klass: AnyClass,
|
|
416
|
+
names: readonly string[],
|
|
417
|
+
spec: SignalDispatchSpec,
|
|
418
|
+
): void {
|
|
419
|
+
const ownerType = getClassType(klass);
|
|
420
|
+
|
|
421
|
+
for (const rawName of names) {
|
|
422
|
+
const name = canonicalSignalName(rawName);
|
|
423
|
+
pendingSignalDispatches.getOrInsertComputed(name, () => []).push({ ownerType, spec });
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
const resolvePendingSignalDispatch = (signalId: number, name: string): SignalDispatch | undefined => {
|
|
428
|
+
const pending = pendingSignalDispatches.get(name) ?? [];
|
|
429
|
+
|
|
430
|
+
for (let index = pending.length - 1; index >= 0; index -= 1) {
|
|
431
|
+
const entry = pending[index];
|
|
432
|
+
|
|
433
|
+
if (
|
|
434
|
+
entry !== undefined &&
|
|
435
|
+
entry.ownerType !== TYPE_INVALID &&
|
|
436
|
+
signalIdFor(entry.ownerType, name) === signalId
|
|
437
|
+
) {
|
|
438
|
+
signalDispatchTable.set(signalId, entry.spec);
|
|
439
|
+
|
|
440
|
+
return entry.spec;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return undefined;
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
const signalDispatchFor = (instance: object, signal: string): SignalDispatch | undefined => {
|
|
448
|
+
const name = canonicalSignalName(signal);
|
|
449
|
+
const instanceType = getInstanceType(instance);
|
|
450
|
+
|
|
451
|
+
if (instanceType === TYPE_INVALID) {
|
|
452
|
+
return undefined;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
const signalId = signalIdFor(instanceType, name);
|
|
456
|
+
|
|
457
|
+
if (signalId === 0) {
|
|
458
|
+
return undefined;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
return signalDispatchTable.get(signalId) ?? resolvePendingSignalDispatch(signalId, name);
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
const connectDispatcherFor = (instance: object, signal: string): SignalConnector => {
|
|
465
|
+
const dispatch = signalDispatchFor(instance, signal);
|
|
466
|
+
|
|
467
|
+
if (dispatch === undefined) {
|
|
468
|
+
throw new TypeError("connectSignal: unknown signal");
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
return dispatch.connect;
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
const emitDispatcherFor = (instance: object, signal: string): SignalEmitter => {
|
|
475
|
+
const dispatch = signalDispatchFor(instance, signal);
|
|
476
|
+
|
|
477
|
+
if (dispatch === undefined) {
|
|
478
|
+
throw new TypeError("emitSignal: unknown signal");
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
return dispatch.emit;
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
function signalConnect<T extends object, K extends SignalName<NoInfer<T>>>(
|
|
485
|
+
instance: T,
|
|
486
|
+
signal: K,
|
|
487
|
+
handler: SignalMap<NoInfer<T>>[K],
|
|
488
|
+
isAfter?: boolean,
|
|
489
|
+
): number {
|
|
490
|
+
return connectSignalByName(instance, signal, handler, isAfter);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
function connectSignalByName(
|
|
494
|
+
instance: object,
|
|
495
|
+
signal: string,
|
|
496
|
+
handler: unknown,
|
|
497
|
+
isAfter?: boolean,
|
|
498
|
+
): number {
|
|
499
|
+
if (!isSignalHandler(handler)) {
|
|
500
|
+
throw new TypeError("connectSignal: handler must be a function");
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
return connectDispatcherFor(instance, signal)(instance, signal, handler, isAfter);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
function emitSignalByName(instance: object, signal: string, args: unknown[]): unknown {
|
|
507
|
+
return emitDispatcherFor(instance, signal)(instance, signal, args);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
function signalEmit<T extends object, K extends SignalEmitName<NoInfer<T>>>(
|
|
511
|
+
instance: T,
|
|
512
|
+
signal: K,
|
|
513
|
+
...args: SignalEmitArguments<NoInfer<T>, K>
|
|
514
|
+
): SignalEmitResult<NoInfer<T>, K> {
|
|
515
|
+
return emitSignalByName(instance, signal, args) as SignalEmitResult<NoInfer<T>, K>;
|
|
516
|
+
}
|
|
517
|
+
|
|
378
518
|
export {
|
|
519
|
+
canonicalDetailedSignalName,
|
|
520
|
+
canonicalSignalName,
|
|
379
521
|
signalForHandlerName,
|
|
380
522
|
getSignalBaseName,
|
|
381
523
|
signalIdFor,
|
|
382
524
|
connectClosureSignal,
|
|
383
525
|
connectSignal,
|
|
526
|
+
connectSignalByName,
|
|
384
527
|
type DeclaredSignalTypes,
|
|
385
528
|
disconnectSignal,
|
|
386
529
|
emitDeclaredSignal,
|
|
387
530
|
emitSignal,
|
|
531
|
+
emitSignalByName,
|
|
388
532
|
hasSignalListener,
|
|
389
533
|
isSignalHandlerConnected,
|
|
534
|
+
installSignalDispatch,
|
|
390
535
|
overrideSignalClassClosure,
|
|
391
|
-
|
|
536
|
+
signalConnect,
|
|
537
|
+
signalEmit,
|
|
392
538
|
type SignalHandler,
|
|
393
539
|
};
|
package/src/t.ts
CHANGED
|
@@ -41,10 +41,7 @@ type T = {
|
|
|
41
41
|
unichar: typeof helpers.unicharT;
|
|
42
42
|
/** Descriptor for an opaque `gpointer` argument, taken from a typed array's memory or a numeric address. */
|
|
43
43
|
buffer: typeof helpers.bufferT;
|
|
44
|
-
/**
|
|
45
|
-
* Builds a descriptor for a C string, whose optional length sizes the caller-allocated buffer
|
|
46
|
-
* used when the string is passed by reference.
|
|
47
|
-
*/
|
|
44
|
+
/** Builds a C-string descriptor with optional caller-allocated length. */
|
|
48
45
|
string: typeof helpers.stringT;
|
|
49
46
|
/** Builds a descriptor for a `GObject`, wrapped in the class registered for its runtime GType. */
|
|
50
47
|
object: typeof helpers.objectT;
|
|
@@ -82,28 +79,15 @@ type T = {
|
|
|
82
79
|
cursorArray: typeof helpers.cursorArrayT;
|
|
83
80
|
/** Builds a descriptor for a function pointer, marshalling a JavaScript function into a native closure. */
|
|
84
81
|
callback: typeof helpers.callbackT;
|
|
85
|
-
/**
|
|
86
|
-
* Binds a native function, wiring up argument directions, `GError` checking, and packing output
|
|
87
|
-
* arguments into the result.
|
|
88
|
-
*/
|
|
82
|
+
/** Binds a native function with argument directions, errors, and packed outputs. */
|
|
89
83
|
fn: typeof fn;
|
|
90
|
-
/**
|
|
91
|
-
* Binds a struct field at a fixed offset, compiling its descriptor once into an accessor that
|
|
92
|
-
* reads and writes it.
|
|
93
|
-
*/
|
|
84
|
+
/** Binds a struct field at a fixed offset. */
|
|
94
85
|
field: typeof field;
|
|
95
|
-
/**
|
|
96
|
-
* Binds a struct field whose offset is supplied per access, for walking records stored at a
|
|
97
|
-
* stride in a buffer.
|
|
98
|
-
*/
|
|
86
|
+
/** Binds a struct field whose offset is supplied per access. */
|
|
99
87
|
fieldAt: typeof fieldAt;
|
|
100
88
|
};
|
|
101
89
|
|
|
102
|
-
/**
|
|
103
|
-
* Type descriptor builder: a collection of factory helpers that describe C types for
|
|
104
|
-
* FFI marshalling, plus `bind` to bind a native function and `fn` to describe a
|
|
105
|
-
* function signature.
|
|
106
|
-
*/
|
|
90
|
+
/** FFI descriptor factories and native function binders. */
|
|
107
91
|
const t: T = {
|
|
108
92
|
bind,
|
|
109
93
|
int8: helpers.int8T,
|
package/src/type.ts
CHANGED
|
@@ -86,7 +86,7 @@ const TYPE_VARIANT: bigint = typeFromName("GVariant");
|
|
|
86
86
|
/** GType tag for a Unicode character stored as `guint`. */
|
|
87
87
|
const TYPE_UNICHAR: bigint = typeFromName("guint");
|
|
88
88
|
const getErrorType: () => bigint = lazyType("GError");
|
|
89
|
-
const getStrvType
|
|
89
|
+
const getStrvType = (): bigint => resolveType(LIB, "g_strv_get_type");
|
|
90
90
|
|
|
91
91
|
const PLAIN_DESCRIPTOR_TYPES: Partial<Record<Descriptor["kind"], bigint>> = {
|
|
92
92
|
boolean: TYPE_BOOLEAN,
|
|
@@ -244,6 +244,14 @@ function isResolvableDescriptor(descriptor: Descriptor): descriptor is Resolvabl
|
|
|
244
244
|
return RESOLVABLE_DESCRIPTOR_KINDS.has(descriptor.kind);
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
+
function resolveEnumOrFlagsType(descriptor: Extract<Descriptor, { kind: "enum" | "flags" }>): bigint {
|
|
248
|
+
if (descriptor.getTypeFnName === "") {
|
|
249
|
+
return descriptor.isSigned ? TYPE_INT : TYPE_UINT;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return resolveType(descriptor.sharedLibrary, descriptor.getTypeFnName);
|
|
253
|
+
}
|
|
254
|
+
|
|
247
255
|
function resolveDescriptorType(descriptor: Descriptor): bigint {
|
|
248
256
|
if (descriptor.kind === "biguint64" && "type" in descriptor) {
|
|
249
257
|
return TYPE_GTYPE;
|
|
@@ -262,7 +270,7 @@ function resolveDescriptorType(descriptor: Descriptor): bigint {
|
|
|
262
270
|
switch (descriptor.kind) {
|
|
263
271
|
case "enum":
|
|
264
272
|
case "flags": {
|
|
265
|
-
return
|
|
273
|
+
return resolveEnumOrFlagsType(descriptor);
|
|
266
274
|
}
|
|
267
275
|
case "boxed": {
|
|
268
276
|
return resolveBoxedType(descriptor);
|
package/src/value.ts
CHANGED
|
@@ -422,6 +422,14 @@ const arrayValueType = (descriptor: ArrayDescriptor): ValueType => {
|
|
|
422
422
|
throw new Error(`Unsupported array type ${descriptor.arrayKind} of ${descriptor.itemDescriptor.kind}`);
|
|
423
423
|
};
|
|
424
424
|
|
|
425
|
+
const resolveEnumOrFlagsValueType = (descriptor: Extract<Descriptor, { kind: "enum" | "flags" }>): ValueType => {
|
|
426
|
+
if (descriptor.getTypeFnName === "") {
|
|
427
|
+
return descriptor.kind === "flags" ? flagsValueType : enumValueType;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
return enumOrFlagsValueType(resolveType(descriptor.sharedLibrary, descriptor.getTypeFnName));
|
|
431
|
+
};
|
|
432
|
+
|
|
425
433
|
const resolveValueType = (descriptor: Descriptor): ValueType => {
|
|
426
434
|
if (descriptor.kind === "biguint64" && "type" in descriptor) {
|
|
427
435
|
return typeValueType;
|
|
@@ -440,7 +448,7 @@ const resolveValueType = (descriptor: Descriptor): ValueType => {
|
|
|
440
448
|
switch (descriptor.kind) {
|
|
441
449
|
case "enum":
|
|
442
450
|
case "flags": {
|
|
443
|
-
return
|
|
451
|
+
return resolveEnumOrFlagsValueType(descriptor);
|
|
444
452
|
}
|
|
445
453
|
case "boxed": {
|
|
446
454
|
return boxedValueType(resolveBoxedType(descriptor));
|
package/src/variant.ts
CHANGED
|
@@ -34,10 +34,7 @@ type BasicValueMap<Nested> = {
|
|
|
34
34
|
|
|
35
35
|
/** Single-character code of one of the GVariant basic types in {@link BasicValueMap}. */
|
|
36
36
|
type BasicCode = keyof BasicValueMap<unknown>;
|
|
37
|
-
/**
|
|
38
|
-
* JavaScript type a byte array (`ay`) unpacks to: the same one the generated bindings use for byte sequences, so a
|
|
39
|
-
* `Uint8Array` under the `v2ByteArrays` future flag and a `number[]` otherwise.
|
|
40
|
-
*/
|
|
37
|
+
/** JavaScript type a byte array (`ay`) unpacks to. */
|
|
41
38
|
type ByteArray = ReturnType<GLib.Bytes["unrefToArray"]>;
|
|
42
39
|
/** Values a byte array (`ay`) packs from. */
|
|
43
40
|
type ByteArrayInput = Uint8Array | number[];
|
|
@@ -503,8 +500,7 @@ const toVariant = <S extends string>(typeString: S, value: VariantInput<S>): GLi
|
|
|
503
500
|
/**
|
|
504
501
|
* Unpacks a `GLib.Variant` into the JavaScript value its GVariant type describes, the inverse of
|
|
505
502
|
* {@link toVariant}. A dictionary keyed by strings unpacks to a record and one keyed by anything
|
|
506
|
-
* else to a `Map`, an array to an array, a byte array (`ay`) to
|
|
507
|
-
* bindings use (`Uint8Array` under the `v2ByteArrays` future flag, `number[]` otherwise), a tuple
|
|
503
|
+
* else to a `Map`, an array to an array, a byte array (`ay`) to a `Uint8Array`, a tuple
|
|
508
504
|
* to an array of its members, a maybe to its value or `null`, and a nested variant to the
|
|
509
505
|
* `GLib.Variant` itself unless `recursive` is set, in which case it is unwrapped all the way down.
|
|
510
506
|
*
|
package/src/vfunc-call.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import type { BindVfuncOptions } from "@gtkx/native";
|
|
2
1
|
import type { AnyClass } from "@gtkx/utils";
|
|
3
|
-
import { bindVfunc } from "@gtkx/native";
|
|
2
|
+
import { bindVfunc, type BindVfuncOptions } from "@gtkx/native";
|
|
4
3
|
import { type Arg, isCallerAllocatedArg, requiresInputArg } from "./arg.js";
|
|
5
4
|
import { buildNativeArgTypes, fromNativeCallable } from "./fn.js";
|
|
6
5
|
import { toNative } from "./native-value.js";
|
|
@@ -106,21 +105,9 @@ function buildInvoker(slot: ResolvedSlot, instanceType: bigint | undefined, call
|
|
|
106
105
|
}
|
|
107
106
|
|
|
108
107
|
function cachedInvoker(cache: InvokerCache, owner: AnyClass, key: string, build: () => Invoker): Invoker {
|
|
109
|
-
|
|
108
|
+
const byKey = cache.getOrInsertComputed(owner, () => new Map<string, Invoker>());
|
|
110
109
|
|
|
111
|
-
|
|
112
|
-
byKey = new Map();
|
|
113
|
-
cache.set(owner, byKey);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
let invoker = byKey.get(key);
|
|
117
|
-
|
|
118
|
-
if (invoker === undefined) {
|
|
119
|
-
invoker = build();
|
|
120
|
-
byKey.set(key, invoker);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return invoker;
|
|
110
|
+
return byKey.getOrInsertComputed(key, build);
|
|
124
111
|
}
|
|
125
112
|
|
|
126
113
|
function resolveParentSlot(klass: AnyClass, parentType: bigint, methodName: string): ResolvedSlot | undefined {
|