@gtkx/runtime 2.0.0-beta.1 → 2.0.0-beta.3
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/dist/descriptors.d.ts +2 -1
- package/dist/descriptors.d.ts.map +1 -1
- package/dist/descriptors.js +5 -1
- package/dist/descriptors.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +17 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +13 -0
- 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/object.d.ts +14 -3
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +20 -27
- package/dist/object.js.map +1 -1
- package/dist/properties.d.ts +4 -2
- package/dist/properties.d.ts.map +1 -1
- package/dist/properties.js +69 -16
- 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 +102 -20
- 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 +75 -5
- package/dist/signal.js.map +1 -1
- package/dist/type.d.ts.map +1 -1
- package/dist/type.js +1 -1
- package/dist/type.js.map +1 -1
- package/dist/value.d.ts +2 -1
- package/dist/value.d.ts.map +1 -1
- package/dist/value.js +28 -7
- package/dist/value.js.map +1 -1
- package/package.json +4 -4
- package/src/descriptors.ts +7 -0
- package/src/index.ts +2 -2
- package/src/internal.ts +42 -0
- package/src/listeners.ts +21 -26
- package/src/mixin.ts +55 -9
- package/src/object.ts +57 -7
- package/src/properties.ts +94 -17
- package/src/property-brand.ts +5 -0
- package/src/register-class.ts +296 -95
- package/src/registry.ts +4 -4
- package/src/signal-brand.ts +29 -0
- package/src/signal.ts +177 -6
- package/src/type.ts +1 -1
- package/src/value.ts +40 -5
package/src/register-class.ts
CHANGED
|
@@ -19,6 +19,11 @@ import {
|
|
|
19
19
|
SET_PROPERTY_VFUNC,
|
|
20
20
|
toNativeProperties,
|
|
21
21
|
} from "./properties.js";
|
|
22
|
+
import {
|
|
23
|
+
descriptorFreePropertySpec,
|
|
24
|
+
propertyMapOverride,
|
|
25
|
+
writablePropertyMapOverride,
|
|
26
|
+
} from "./property-brand.js";
|
|
22
27
|
import {
|
|
23
28
|
getClassStructClass,
|
|
24
29
|
getClassType,
|
|
@@ -30,13 +35,19 @@ import {
|
|
|
30
35
|
wrapHandle,
|
|
31
36
|
} from "./registry.js";
|
|
32
37
|
import {
|
|
38
|
+
classSignalMember,
|
|
39
|
+
naturalSignalMember,
|
|
40
|
+
signalEmitMapOverride,
|
|
41
|
+
signalMapOverride,
|
|
42
|
+
} from "./signal-brand.js";
|
|
43
|
+
import {
|
|
44
|
+
canonicalSignalName,
|
|
33
45
|
connectClosureSignal,
|
|
34
46
|
type DeclaredSignalTypes,
|
|
35
47
|
emitDeclaredSignal,
|
|
36
|
-
|
|
48
|
+
installSignalDispatch,
|
|
37
49
|
overrideSignalClassClosure,
|
|
38
50
|
signalForHandlerName,
|
|
39
|
-
type SignalHandler,
|
|
40
51
|
signalIdFor,
|
|
41
52
|
} from "./signal.js";
|
|
42
53
|
import {
|
|
@@ -53,9 +64,9 @@ import {
|
|
|
53
64
|
import { findClassVfuncDescriptor, findInterfaceVfuncDescriptor } from "./vfunc.js";
|
|
54
65
|
|
|
55
66
|
/** A generated interface value, such as `Gio.ListModel`, accepted by {@link registerClass}. */
|
|
56
|
-
type Interface<TImpl> = AnyClass & {
|
|
67
|
+
type Interface<TImpl, TInstance = object> = AnyClass & {
|
|
57
68
|
/** Type-level slot holding the interface's `Impl` type; no value ever carries it. */
|
|
58
|
-
__impl__: (impl: Partial<TImpl> & object) =>
|
|
69
|
+
__impl__: (impl: Partial<TImpl> & object) => TInstance;
|
|
59
70
|
};
|
|
60
71
|
|
|
61
72
|
/** Converts underscores in a property name to canonical dashes. */
|
|
@@ -79,31 +90,255 @@ type DeclaredSignalBase<TSignals> = (keyof TSignals & string) | Dashed<keyof TSi
|
|
|
79
90
|
type DeclaredSignalName<TSignals> = DeclaredSignalBase<TSignals> | `${DeclaredSignalBase<TSignals>}::${string}`;
|
|
80
91
|
|
|
81
92
|
/** Signal methods added for declared names. */
|
|
82
|
-
type DeclaredSignalMethods<TSignals> = {
|
|
93
|
+
type DeclaredSignalMethods<TSignals, TBlockedMembers extends PropertyKey> = {
|
|
83
94
|
/** Type-level map used by signal hooks. */
|
|
84
|
-
__signals__?: Record<
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
95
|
+
__signals__?: Record<DeclaredSignalName<TSignals>, (...args: never[]) => unknown>;
|
|
96
|
+
} &
|
|
97
|
+
Pick<
|
|
98
|
+
{
|
|
99
|
+
connect(
|
|
100
|
+
signal: DeclaredSignalName<TSignals>,
|
|
101
|
+
handler: (...args: never[]) => unknown,
|
|
102
|
+
isAfter?: boolean,
|
|
103
|
+
): number;
|
|
104
|
+
emit(sigName: DeclaredSignalName<TSignals>, ...args: unknown[]): unknown;
|
|
105
|
+
on(sigName: DeclaredSignalName<TSignals>, callback: (...args: never[]) => unknown, isAfter?: boolean): unknown;
|
|
106
|
+
once(
|
|
107
|
+
sigName: DeclaredSignalName<TSignals>,
|
|
108
|
+
callback: (...args: never[]) => unknown,
|
|
109
|
+
isAfter?: boolean,
|
|
110
|
+
): unknown;
|
|
111
|
+
off(sigName: DeclaredSignalName<TSignals>, callback: (...args: never[]) => unknown): unknown;
|
|
112
|
+
},
|
|
113
|
+
Exclude<"connect" | "emit" | "off" | "on" | "once", TBlockedMembers>
|
|
114
|
+
>;
|
|
100
115
|
|
|
101
116
|
/** A registered instance with declared signal methods and property metadata. */
|
|
102
|
-
type RegisteredInstance<
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
117
|
+
type RegisteredInstance<
|
|
118
|
+
TInstance,
|
|
119
|
+
TProperties,
|
|
120
|
+
TSignals,
|
|
121
|
+
TInterfaces extends readonly Interface<TInstance>[],
|
|
122
|
+
TRemainingInterfaces extends readonly Interface<TInstance>[] = TInterfaces,
|
|
123
|
+
TMemberSurface = object,
|
|
124
|
+
TSignalSurface = TInstance extends { [signalMapOverride]?: infer TResolver }
|
|
125
|
+
? TResolver extends () => infer TMap
|
|
126
|
+
? NonNullable<TMap>
|
|
127
|
+
: TInstance extends { __signals__?: infer TMap }
|
|
128
|
+
? NonNullable<TMap>
|
|
129
|
+
: object
|
|
130
|
+
: TInstance extends { __signals__?: infer TMap }
|
|
131
|
+
? NonNullable<TMap>
|
|
132
|
+
: object,
|
|
133
|
+
TSignalEmitSurface = TInstance extends { [signalEmitMapOverride]?: infer TResolver }
|
|
134
|
+
? TResolver extends () => infer TMap
|
|
135
|
+
? NonNullable<TMap>
|
|
136
|
+
: TInstance extends { __signalEmit__?: infer TMap }
|
|
137
|
+
? NonNullable<TMap>
|
|
138
|
+
: object
|
|
139
|
+
: TInstance extends { __signalEmit__?: infer TMap }
|
|
140
|
+
? NonNullable<TMap>
|
|
141
|
+
: object,
|
|
142
|
+
TPropertySurface = TInstance extends { [propertyMapOverride]?: infer TResolver }
|
|
143
|
+
? TResolver extends () => infer TMap
|
|
144
|
+
? NonNullable<TMap>
|
|
145
|
+
: TInstance extends { __properties__?: infer TMap }
|
|
146
|
+
? NonNullable<TMap>
|
|
147
|
+
: object
|
|
148
|
+
: TInstance extends { __properties__?: infer TMap }
|
|
149
|
+
? NonNullable<TMap>
|
|
150
|
+
: object,
|
|
151
|
+
TWritablePropertySurface = TInstance extends { [writablePropertyMapOverride]?: infer TResolver }
|
|
152
|
+
? TResolver extends () => infer TMap
|
|
153
|
+
? NonNullable<TMap>
|
|
154
|
+
: TInstance extends { __writableProperties__?: infer TMap }
|
|
155
|
+
? NonNullable<TMap>
|
|
156
|
+
: object
|
|
157
|
+
: TInstance extends { __writableProperties__?: infer TMap }
|
|
158
|
+
? NonNullable<TMap>
|
|
159
|
+
: object,
|
|
160
|
+
TNaturalInstanceMembers extends PropertyKey = TInstance extends {
|
|
161
|
+
[naturalSignalMember]?: infer TMembers;
|
|
162
|
+
}
|
|
163
|
+
? keyof NonNullable<TMembers>
|
|
164
|
+
: never,
|
|
165
|
+
TClassInstanceSignals extends PropertyKey = TInstance extends {
|
|
166
|
+
[classSignalMember]?: infer TMembers;
|
|
167
|
+
}
|
|
168
|
+
? keyof NonNullable<TMembers>
|
|
169
|
+
: never,
|
|
170
|
+
TLegacySignalMembers extends PropertyKey = "connect" | "disconnect" | "emit" | "off" | "on" | "once",
|
|
171
|
+
TInstalledPropertyCandidate = TInstance & TMemberSurface,
|
|
172
|
+
TRegisteredPropertySurface = Omit<TPropertySurface, InstalledNames<TProperties>> &
|
|
173
|
+
Pick<
|
|
174
|
+
TInstalledPropertyCandidate,
|
|
175
|
+
(string extends keyof TProperties
|
|
176
|
+
? never
|
|
177
|
+
: {
|
|
178
|
+
[K in keyof TProperties & string]: TProperties[K] extends {
|
|
179
|
+
readonly [descriptorFreePropertySpec]: true;
|
|
180
|
+
}
|
|
181
|
+
? Camelized<Dashed<K>>
|
|
182
|
+
: never;
|
|
183
|
+
}[keyof TProperties & string]) & {
|
|
184
|
+
[K in keyof TInstalledPropertyCandidate]-?: Extract<
|
|
185
|
+
TInstalledPropertyCandidate[K],
|
|
186
|
+
(...args: never[]) => unknown
|
|
187
|
+
> extends never
|
|
188
|
+
? K
|
|
189
|
+
: never;
|
|
190
|
+
}[keyof TInstalledPropertyCandidate]
|
|
191
|
+
>,
|
|
192
|
+
TRegisteredWritablePropertySurface = Omit<TWritablePropertySurface, InstalledNames<TProperties>> &
|
|
193
|
+
Pick<
|
|
194
|
+
TInstalledPropertyCandidate,
|
|
195
|
+
(string extends keyof TProperties
|
|
196
|
+
? never
|
|
197
|
+
: {
|
|
198
|
+
[K in keyof TProperties & string]: TProperties[K] extends {
|
|
199
|
+
readonly [descriptorFreePropertySpec]: true;
|
|
200
|
+
}
|
|
201
|
+
? Camelized<Dashed<K>>
|
|
202
|
+
: never;
|
|
203
|
+
}[keyof TProperties & string]) & {
|
|
204
|
+
[K in keyof TInstalledPropertyCandidate]-?: Extract<
|
|
205
|
+
TInstalledPropertyCandidate[K],
|
|
206
|
+
(...args: never[]) => unknown
|
|
207
|
+
> extends never
|
|
208
|
+
? (<U>(probe: U) => U extends { [P in K]: TInstalledPropertyCandidate[P] } ? 1 : 2) extends
|
|
209
|
+
(<U>(probe: U) =>
|
|
210
|
+
U extends { -readonly [P in K]: TInstalledPropertyCandidate[P] } ? 1 : 2)
|
|
211
|
+
? K
|
|
212
|
+
: never
|
|
213
|
+
: never;
|
|
214
|
+
}[keyof TInstalledPropertyCandidate]
|
|
215
|
+
>,
|
|
216
|
+
> = TRemainingInterfaces extends readonly [
|
|
217
|
+
infer TInterface extends Interface<TInstance>,
|
|
218
|
+
...infer TRest extends readonly Interface<TInstance>[],
|
|
219
|
+
]
|
|
220
|
+
? (ReturnType<TInterface["__impl__"]> extends infer TInterfaceInstance extends object
|
|
221
|
+
? RegisteredInstance<
|
|
222
|
+
TInstance,
|
|
223
|
+
TProperties,
|
|
224
|
+
TSignals,
|
|
225
|
+
TInterfaces,
|
|
226
|
+
TRest,
|
|
227
|
+
TMemberSurface &
|
|
228
|
+
Omit<
|
|
229
|
+
TInterfaceInstance,
|
|
230
|
+
| keyof TInstance |
|
|
231
|
+
keyof TMemberSurface |
|
|
232
|
+
"__properties__" |
|
|
233
|
+
"__writableProperties__" |
|
|
234
|
+
"__signalEmit__" |
|
|
235
|
+
"__signals__" |
|
|
236
|
+
TLegacySignalMembers
|
|
237
|
+
> & {
|
|
238
|
+
[K in Extract<
|
|
239
|
+
TInterfaceInstance extends { [naturalSignalMember]?: infer TMembers }
|
|
240
|
+
? keyof NonNullable<TMembers>
|
|
241
|
+
: never,
|
|
242
|
+
TLegacySignalMembers
|
|
243
|
+
> as K extends TNaturalInstanceMembers | keyof TMemberSurface
|
|
244
|
+
? never
|
|
245
|
+
: K]: K extends keyof TInterfaceInstance ? TInterfaceInstance[K] : never;
|
|
246
|
+
},
|
|
247
|
+
TInterfaceInstance extends { __signals__?: infer TNextSignalMap } ? Omit<
|
|
248
|
+
TSignalSurface,
|
|
249
|
+
keyof {
|
|
250
|
+
[K in keyof NonNullable<TNextSignalMap> as K extends string
|
|
251
|
+
? Dashed<
|
|
252
|
+
K extends `${infer TBase}::${string}` ? TBase : K
|
|
253
|
+
> extends TClassInstanceSignals | Dashed<keyof TSignals & string>
|
|
254
|
+
? never
|
|
255
|
+
: K
|
|
256
|
+
: K]: NonNullable<TNextSignalMap>[K];
|
|
257
|
+
}
|
|
258
|
+
> & {
|
|
259
|
+
[K in keyof NonNullable<TNextSignalMap> as K extends string
|
|
260
|
+
? Dashed<
|
|
261
|
+
K extends `${infer TBase}::${string}` ? TBase : K
|
|
262
|
+
> extends TClassInstanceSignals | Dashed<keyof TSignals & string>
|
|
263
|
+
? never
|
|
264
|
+
: K
|
|
265
|
+
: K]: NonNullable<TNextSignalMap>[K];
|
|
266
|
+
}
|
|
267
|
+
: TSignalSurface,
|
|
268
|
+
TInterfaceInstance extends { __signalEmit__?: infer TNextSignalEmitMap } ? Omit<
|
|
269
|
+
TSignalEmitSurface,
|
|
270
|
+
keyof {
|
|
271
|
+
[K in keyof NonNullable<TNextSignalEmitMap> as K extends string
|
|
272
|
+
? Dashed<
|
|
273
|
+
K extends `${infer TBase}::${string}` ? TBase : K
|
|
274
|
+
> extends TClassInstanceSignals | Dashed<keyof TSignals & string>
|
|
275
|
+
? never
|
|
276
|
+
: K
|
|
277
|
+
: K]: NonNullable<TNextSignalEmitMap>[K];
|
|
278
|
+
}
|
|
279
|
+
> & {
|
|
280
|
+
[K in keyof NonNullable<TNextSignalEmitMap> as K extends string
|
|
281
|
+
? Dashed<
|
|
282
|
+
K extends `${infer TBase}::${string}` ? TBase : K
|
|
283
|
+
> extends TClassInstanceSignals | Dashed<keyof TSignals & string>
|
|
284
|
+
? never
|
|
285
|
+
: K
|
|
286
|
+
: K]: NonNullable<TNextSignalEmitMap>[K];
|
|
287
|
+
}
|
|
288
|
+
: TSignalEmitSurface,
|
|
289
|
+
TPropertySurface &
|
|
290
|
+
Omit<
|
|
291
|
+
TInterfaceInstance extends { [propertyMapOverride]?: infer TResolver }
|
|
292
|
+
? TResolver extends () => infer TMap
|
|
293
|
+
? NonNullable<TMap>
|
|
294
|
+
: TInterfaceInstance extends { __properties__?: infer TMap }
|
|
295
|
+
? NonNullable<TMap>
|
|
296
|
+
: object
|
|
297
|
+
: TInterfaceInstance extends { __properties__?: infer TMap }
|
|
298
|
+
? NonNullable<TMap>
|
|
299
|
+
: object,
|
|
300
|
+
keyof TPropertySurface
|
|
301
|
+
>,
|
|
302
|
+
TWritablePropertySurface &
|
|
303
|
+
Omit<
|
|
304
|
+
TInterfaceInstance extends { [writablePropertyMapOverride]?: infer TResolver }
|
|
305
|
+
? TResolver extends () => infer TMap
|
|
306
|
+
? NonNullable<TMap>
|
|
307
|
+
: TInterfaceInstance extends { __writableProperties__?: infer TMap }
|
|
308
|
+
? NonNullable<TMap>
|
|
309
|
+
: object
|
|
310
|
+
: TInterfaceInstance extends { __writableProperties__?: infer TMap }
|
|
311
|
+
? NonNullable<TMap>
|
|
312
|
+
: object,
|
|
313
|
+
keyof TWritablePropertySurface
|
|
314
|
+
>,
|
|
315
|
+
TNaturalInstanceMembers,
|
|
316
|
+
TClassInstanceSignals,
|
|
317
|
+
TLegacySignalMembers
|
|
318
|
+
>
|
|
319
|
+
: never) : TInstance &
|
|
320
|
+
TMemberSurface &
|
|
321
|
+
DeclaredSignalMethods<
|
|
322
|
+
TSignals,
|
|
323
|
+
TNaturalInstanceMembers | Extract<keyof TMemberSurface, TLegacySignalMembers>
|
|
324
|
+
> & {
|
|
325
|
+
[naturalSignalMember]?: Record<
|
|
326
|
+
TNaturalInstanceMembers | Extract<keyof TMemberSurface, TLegacySignalMembers>,
|
|
327
|
+
true
|
|
328
|
+
>;
|
|
329
|
+
[classSignalMember]?: Record<
|
|
330
|
+
TClassInstanceSignals | Dashed<keyof TSignals & string>,
|
|
331
|
+
true
|
|
332
|
+
>;
|
|
333
|
+
[signalMapOverride]?: () => Omit<TSignalSurface, DeclaredSignalName<TSignals>> &
|
|
334
|
+
Record<DeclaredSignalName<TSignals>, (...args: never[]) => unknown>;
|
|
335
|
+
[signalEmitMapOverride]?: () => Omit<TSignalEmitSurface, DeclaredSignalName<TSignals>> &
|
|
336
|
+
Record<DeclaredSignalName<TSignals>, { args: unknown[]; result: unknown }>;
|
|
337
|
+
[propertyMapOverride]?: () => TRegisteredPropertySurface;
|
|
338
|
+
[writablePropertyMapOverride]?: () => TRegisteredWritablePropertySurface;
|
|
339
|
+
__properties__: TRegisteredPropertySurface;
|
|
340
|
+
__writableProperties__: TRegisteredWritablePropertySurface;
|
|
341
|
+
};
|
|
107
342
|
|
|
108
343
|
/** A registered class's construct signature and prototype. */
|
|
109
344
|
type RegisteredConstructor<TClass, TArgs extends unknown[], TInstance> = {
|
|
@@ -118,9 +353,14 @@ type RegisteredParts<TClass, TArgs extends unknown[], TInstance> = Omit<TClass,
|
|
|
118
353
|
RegisteredConstructor<TClass, TArgs, TInstance>;
|
|
119
354
|
|
|
120
355
|
/** The registered class with its declared properties and signals. */
|
|
121
|
-
type RegisteredClass<
|
|
356
|
+
type RegisteredClass<
|
|
357
|
+
TClass extends AnyClass,
|
|
358
|
+
TProperties,
|
|
359
|
+
TSignals,
|
|
360
|
+
TInterfaces extends readonly Interface<TClass["prototype"]>[],
|
|
361
|
+
> =
|
|
122
362
|
TClass extends abstract new (...args: infer TArgs) => infer TInstance
|
|
123
|
-
? RegisteredParts<TClass, TArgs, RegisteredInstance<TInstance, TProperties, TSignals>>
|
|
363
|
+
? RegisteredParts<TClass, TArgs, RegisteredInstance<TInstance, TProperties, TSignals, TInterfaces>>
|
|
124
364
|
: never;
|
|
125
365
|
|
|
126
366
|
/** A numeric GType or a generated or registered wrapper class. */
|
|
@@ -143,6 +383,7 @@ type RegisterClassOptions<
|
|
|
143
383
|
TInstance extends object,
|
|
144
384
|
TProperties extends Record<string, PropertySpec>,
|
|
145
385
|
TSignals extends Record<string, SignalSpec>,
|
|
386
|
+
TInterfaces extends readonly Interface<TInstance>[],
|
|
146
387
|
> = {
|
|
147
388
|
/** Registered GType name, defaulting to the class name. */
|
|
148
389
|
typeName?: string;
|
|
@@ -156,7 +397,7 @@ type RegisterClassOptions<
|
|
|
156
397
|
*/
|
|
157
398
|
classInit?(typeStruct: object): void;
|
|
158
399
|
/** Interfaces implemented through matching `vfunc` methods. */
|
|
159
|
-
implements?:
|
|
400
|
+
implements?: TInterfaces;
|
|
160
401
|
/**
|
|
161
402
|
* ParamSpecs keyed by their JavaScript property names. Keys and ParamSpec names must canonicalize
|
|
162
403
|
* to the same member. Writes validate flags, types, and ranges and notify only on changes.
|
|
@@ -172,7 +413,12 @@ type RegisterClassOptions<
|
|
|
172
413
|
};
|
|
173
414
|
|
|
174
415
|
/** {@link RegisterClassOptions} with the widest instance and property types {@link registerClass} accepts. */
|
|
175
|
-
type AnyRegisterClassOptions = RegisterClassOptions<
|
|
416
|
+
type AnyRegisterClassOptions = RegisterClassOptions<
|
|
417
|
+
object,
|
|
418
|
+
Record<string, PropertySpec>,
|
|
419
|
+
Record<string, SignalSpec>,
|
|
420
|
+
Interface<object>[]
|
|
421
|
+
>;
|
|
176
422
|
type VfuncFn = NativeRegisterClassVfunc["fn"];
|
|
177
423
|
type DiscoveredVfunc = VfuncDescriptor & { methodName: string; fn: VfuncFn };
|
|
178
424
|
type MethodTable = Map<string, VfuncFn>;
|
|
@@ -199,11 +445,6 @@ type PropertyVfuncSpec = {
|
|
|
199
445
|
type ArgPatch = { isCallerAllocated: true } | { isCallScoped: true };
|
|
200
446
|
type DeclaredSignals = { native: NativeRegisterClassSignal[]; table: Map<string, DeclaredSignalTypes> };
|
|
201
447
|
|
|
202
|
-
type SignalMethodHost = {
|
|
203
|
-
connect?: (signal: string, handler: SignalHandler, isAfter?: boolean) => number;
|
|
204
|
-
emit?: (sigName: string, ...args: unknown[]) => unknown;
|
|
205
|
-
};
|
|
206
|
-
|
|
207
448
|
const INSTANCE_ARG_INDEX = 0;
|
|
208
449
|
const VALUE_ARG_INDEX = 2;
|
|
209
450
|
const TEARDOWN_VFUNC_NAMES: Set<string> = new Set(["dispose", "finalize"]);
|
|
@@ -240,10 +481,11 @@ function registerClass<
|
|
|
240
481
|
T extends AnyClass,
|
|
241
482
|
TProperties extends Record<string, PropertySpec> = Record<never, PropertySpec>,
|
|
242
483
|
TSignals extends Record<string, SignalSpec> = Record<never, SignalSpec>,
|
|
484
|
+
const TInterfaces extends readonly Interface<T["prototype"]>[] = readonly Interface<T["prototype"]>[],
|
|
243
485
|
>(
|
|
244
486
|
klass: T,
|
|
245
|
-
options?: RegisterClassOptions<T["prototype"], TProperties, TSignals>,
|
|
246
|
-
): RegisteredClass<T, TProperties, TSignals>;
|
|
487
|
+
options?: RegisterClassOptions<T["prototype"], TProperties, TSignals, TInterfaces>,
|
|
488
|
+
): RegisteredClass<T, TProperties, TSignals, TInterfaces>;
|
|
247
489
|
|
|
248
490
|
function registerClass(klass: AnyClass, options: AnyRegisterClassOptions = {}): AnyClass {
|
|
249
491
|
const parentType = resolveParentType(klass);
|
|
@@ -282,7 +524,7 @@ function registerClass(klass: AnyClass, options: AnyRegisterClassOptions = {}):
|
|
|
282
524
|
markDerivedClass(klass);
|
|
283
525
|
installSignalOverrides(newType, methods);
|
|
284
526
|
applyInterfaceMixins(klass, adoptedTypes, inheritedNames);
|
|
285
|
-
installDeclaredSignalMethods(klass, signals.table
|
|
527
|
+
installDeclaredSignalMethods(klass, signals.table);
|
|
286
528
|
invokeClassInit(options, newType);
|
|
287
529
|
|
|
288
530
|
return klass;
|
|
@@ -632,8 +874,6 @@ function buildPropertyVfunc(
|
|
|
632
874
|
};
|
|
633
875
|
}
|
|
634
876
|
|
|
635
|
-
const canonicalSignalName = (name: string): string => name.replaceAll("_", "-");
|
|
636
|
-
|
|
637
877
|
function assertLowerCaseSignalName(klass: AnyClass, name: string): void {
|
|
638
878
|
if (!UPPER_CASE_PATTERN.test(name)) {
|
|
639
879
|
return;
|
|
@@ -742,72 +982,33 @@ function resolveDeclaredSignals(klass: AnyClass, signals: Record<string, SignalS
|
|
|
742
982
|
return { native, table };
|
|
743
983
|
}
|
|
744
984
|
|
|
745
|
-
function inheritedSignalMethod<T>(inherited: T | undefined, signal: string): T {
|
|
746
|
-
if (inherited === undefined) {
|
|
747
|
-
throw new Error(`Unknown signal '${signal}'`);
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
return inherited;
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
function installDeclaredConnect(
|
|
754
|
-
proto: SignalMethodHost,
|
|
755
|
-
findDeclared: (signal: string) => DeclaredSignalTypes | undefined,
|
|
756
|
-
): void {
|
|
757
|
-
const inheritedConnect = proto.connect;
|
|
758
|
-
|
|
759
|
-
proto.connect = function connect(
|
|
760
|
-
this: object,
|
|
761
|
-
signal: string,
|
|
762
|
-
handler: SignalHandler,
|
|
763
|
-
isAfter?: boolean,
|
|
764
|
-
): number {
|
|
765
|
-
if (findDeclared(signal) === undefined) {
|
|
766
|
-
return inheritedSignalMethod(inheritedConnect, signal).call(this, signal, handler, isAfter);
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
return connectClosureSignal(this, signal, handler, isAfter ?? false);
|
|
770
|
-
};
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
function installDeclaredEmit(
|
|
774
|
-
proto: SignalMethodHost,
|
|
775
|
-
findDeclared: (signal: string) => DeclaredSignalTypes | undefined,
|
|
776
|
-
): void {
|
|
777
|
-
const inheritedEmit = proto.emit;
|
|
778
|
-
|
|
779
|
-
proto.emit = function emit(this: object, sigName: string, ...args: unknown[]): unknown {
|
|
780
|
-
const declared = findDeclared(sigName);
|
|
781
|
-
|
|
782
|
-
if (declared === undefined) {
|
|
783
|
-
return inheritedSignalMethod(inheritedEmit, sigName).call(this, sigName, ...args);
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
return emitDeclaredSignal(this, sigName, declared, args);
|
|
787
|
-
};
|
|
788
|
-
}
|
|
789
|
-
|
|
790
985
|
function installDeclaredSignalMethods(
|
|
791
986
|
klass: AnyClass,
|
|
792
987
|
table: Map<string, DeclaredSignalTypes>,
|
|
793
|
-
definedNames: Set<string>,
|
|
794
988
|
): void {
|
|
795
989
|
if (table.size === 0) {
|
|
796
990
|
return;
|
|
797
991
|
}
|
|
798
992
|
|
|
799
|
-
const proto = klass.prototype as SignalMethodHost;
|
|
800
|
-
|
|
801
993
|
const findDeclared = (signal: string): DeclaredSignalTypes | undefined =>
|
|
802
|
-
table.get(canonicalSignalName(
|
|
994
|
+
table.get(canonicalSignalName(signal));
|
|
803
995
|
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
996
|
+
installSignalDispatch(klass, table.keys().toArray(), {
|
|
997
|
+
connect(instance, signal, handler, isAfter): number {
|
|
998
|
+
findDeclared(signal);
|
|
807
999
|
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
1000
|
+
return connectClosureSignal(instance, signal, handler, isAfter ?? false);
|
|
1001
|
+
},
|
|
1002
|
+
emit(instance, signal, args): unknown {
|
|
1003
|
+
const declared = findDeclared(signal);
|
|
1004
|
+
|
|
1005
|
+
if (declared === undefined) {
|
|
1006
|
+
throw new Error(`Unknown signal '${signal}'`);
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
return emitDeclaredSignal(instance, signal, declared, args);
|
|
1010
|
+
},
|
|
1011
|
+
});
|
|
811
1012
|
}
|
|
812
1013
|
|
|
813
1014
|
function toNativeInterface(binding: InterfaceVfuncBinding): NativeRegisterClassInterface {
|
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
|
+
};
|