@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.
- package/dist/arg.d.ts +6 -5
- package/dist/arg.d.ts.map +1 -1
- package/dist/arg.js +5 -4
- package/dist/arg.js.map +1 -1
- package/dist/bind.d.ts +3 -2
- package/dist/bind.d.ts.map +1 -1
- package/dist/bind.js +5 -3
- package/dist/bind.js.map +1 -1
- package/dist/callback.d.ts +3 -3
- package/dist/callback.d.ts.map +1 -1
- package/dist/callback.js +51 -33
- package/dist/callback.js.map +1 -1
- package/dist/descriptors.d.ts +67 -64
- package/dist/descriptors.d.ts.map +1 -1
- package/dist/descriptors.js +92 -60
- package/dist/descriptors.js.map +1 -1
- package/dist/error.d.ts +5 -6
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +10 -6
- package/dist/error.js.map +1 -1
- package/dist/exit-hook.d.ts +2 -0
- package/dist/exit-hook.d.ts.map +1 -0
- package/dist/exit-hook.js +3 -0
- package/dist/exit-hook.js.map +1 -0
- package/dist/fn.d.ts +2 -2
- package/dist/fn.d.ts.map +1 -1
- package/dist/fn.js +26 -15
- package/dist/fn.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/library.d.ts +6 -5
- package/dist/library.d.ts.map +1 -1
- package/dist/library.js +6 -5
- package/dist/library.js.map +1 -1
- package/dist/lifecycle.d.ts +10 -9
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/lifecycle.js +38 -23
- package/dist/lifecycle.js.map +1 -1
- package/dist/listeners.d.ts +8 -8
- package/dist/listeners.d.ts.map +1 -1
- package/dist/listeners.js +28 -15
- package/dist/listeners.js.map +1 -1
- package/dist/mixin.d.ts +5 -11
- package/dist/mixin.d.ts.map +1 -1
- package/dist/mixin.js +24 -14
- package/dist/mixin.js.map +1 -1
- package/dist/native-value.d.ts +3 -2
- package/dist/native-value.d.ts.map +1 -1
- package/dist/native-value.js +75 -42
- package/dist/native-value.js.map +1 -1
- package/dist/object.d.ts +4 -3
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +8 -5
- package/dist/object.js.map +1 -1
- package/dist/promisify.d.ts +9 -1
- package/dist/promisify.d.ts.map +1 -1
- package/dist/promisify.js +18 -15
- package/dist/promisify.js.map +1 -1
- package/dist/properties.d.ts +14 -0
- package/dist/properties.d.ts.map +1 -0
- package/dist/properties.js +79 -0
- package/dist/properties.js.map +1 -0
- package/dist/register-class.d.ts +10 -2
- package/dist/register-class.d.ts.map +1 -1
- package/dist/register-class.js +83 -29
- package/dist/register-class.js.map +1 -1
- package/dist/registry.d.ts +23 -21
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +54 -35
- package/dist/registry.js.map +1 -1
- package/dist/signal.d.ts +7 -6
- package/dist/signal.d.ts.map +1 -1
- package/dist/signal.js +19 -12
- package/dist/signal.js.map +1 -1
- package/dist/t.d.ts +2 -2
- package/dist/t.d.ts.map +1 -1
- package/dist/t.js +2 -1
- package/dist/t.js.map +1 -1
- package/dist/tuple.d.ts +3 -2
- package/dist/tuple.d.ts.map +1 -1
- package/dist/tuple.js +7 -4
- package/dist/tuple.js.map +1 -1
- package/dist/type.d.ts +48 -41
- package/dist/type.d.ts.map +1 -1
- package/dist/type.js +107 -87
- package/dist/type.js.map +1 -1
- package/dist/value.d.ts +19 -10
- package/dist/value.d.ts.map +1 -1
- package/dist/value.js +164 -99
- package/dist/value.js.map +1 -1
- package/package.json +4 -6
- package/src/arg.ts +7 -5
- package/src/bind.ts +13 -4
- package/src/callback.ts +97 -35
- package/src/descriptors.ts +227 -85
- package/src/error.ts +18 -9
- package/src/exit-hook.ts +3 -0
- package/src/fn.ts +53 -22
- package/src/index.ts +4 -2
- package/src/library.ts +7 -5
- package/src/lifecycle.ts +54 -26
- package/src/listeners.ts +46 -18
- package/src/mixin.ts +39 -14
- package/src/native-value.ts +103 -46
- package/src/object.ts +19 -7
- package/src/promisify.ts +42 -15
- package/src/properties.ts +115 -0
- package/src/register-class.ts +157 -30
- package/src/registry.ts +144 -54
- package/src/signal.ts +53 -13
- package/src/t.ts +3 -1
- package/src/tuple.ts +16 -4
- package/src/type.ts +183 -93
- package/src/value.ts +231 -108
package/dist/register-class.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { registerClass as nativeRegisterClass, } from "@gtkx/native";
|
|
2
2
|
import { getParentClass, walkClassChain } from "@gtkx/utils";
|
|
3
3
|
import { wrapCallback } from "./callback.js";
|
|
4
|
+
import { buildAccessors, makeGetProperty, makeSetProperty, toNativeProperties, } from "./properties.js";
|
|
4
5
|
import { getClassType, getInterfaceVfuncRegistry, getVfuncRegistry, registerClassType, } from "./registry.js";
|
|
5
6
|
import { TYPE_INVALID, typeInterfaces } from "./type.js";
|
|
7
|
+
const UNSUPPORTED_CONSTRUCT_VFUNCS = new Set(["constructed", "setProperty", "getProperty"]);
|
|
8
|
+
const VALUE_ARG_INDEX = 2;
|
|
6
9
|
/**
|
|
7
10
|
* Registers a subclass of a wrapper class as a new GType, wiring up any class and
|
|
8
11
|
* inherited-interface virtual functions it overrides. Throws if the class does not
|
|
@@ -13,7 +16,7 @@ import { TYPE_INVALID, typeInterfaces } from "./type.js";
|
|
|
13
16
|
* @param options Registration options, such as an explicit type name.
|
|
14
17
|
* @returns The same class, now registered.
|
|
15
18
|
*/
|
|
16
|
-
|
|
19
|
+
function registerClass(klass, options = {}) {
|
|
17
20
|
const parentType = resolveParentType(klass);
|
|
18
21
|
if (parentType === TYPE_INVALID) {
|
|
19
22
|
throw new TypeError(`registerClass: ${klass.name} must extend a registered wrapper class`);
|
|
@@ -22,10 +25,12 @@ export function registerClass(klass, options = {}) {
|
|
|
22
25
|
if (!name) {
|
|
23
26
|
throw new Error("registerClass: cannot derive a GType name (anonymous class with no typeName option)");
|
|
24
27
|
}
|
|
25
|
-
const
|
|
28
|
+
const properties = options.properties ?? {};
|
|
29
|
+
const accessors = buildAccessors(klass, properties);
|
|
30
|
+
const classVfuncs = [...discoverClassVfuncs(klass), ...propertyVfuncs(klass, accessors)];
|
|
26
31
|
const claimedMethodNames = new Set(classVfuncs.map((vfunc) => vfunc.methodName));
|
|
27
32
|
const interfaceBindings = discoverInheritedInterfaceVfuncs(klass, parentType, claimedMethodNames);
|
|
28
|
-
const nativeOptions = toNativeOptions(classVfuncs, interfaceBindings);
|
|
33
|
+
const nativeOptions = toNativeOptions(classVfuncs, interfaceBindings, properties);
|
|
29
34
|
const newType = nativeRegisterClass(name, parentType, nativeOptions);
|
|
30
35
|
registerClassType(klass, newType);
|
|
31
36
|
return klass;
|
|
@@ -33,45 +38,57 @@ export function registerClass(klass, options = {}) {
|
|
|
33
38
|
function resolveParentType(klass) {
|
|
34
39
|
return (walkClassChain(getParentClass(klass), (cls) => {
|
|
35
40
|
const gtype = getClassType(cls);
|
|
36
|
-
return gtype
|
|
41
|
+
return gtype === TYPE_INVALID ? undefined : gtype;
|
|
37
42
|
}) ?? TYPE_INVALID);
|
|
38
43
|
}
|
|
39
44
|
function ownInstanceMethodNames(klass) {
|
|
40
45
|
const proto = klass.prototype;
|
|
41
|
-
if (!proto)
|
|
46
|
+
if (!proto) {
|
|
42
47
|
return [];
|
|
48
|
+
}
|
|
43
49
|
return Object.getOwnPropertyNames(proto).filter((name) => {
|
|
44
|
-
if (name === "constructor")
|
|
50
|
+
if (name === "constructor") {
|
|
45
51
|
return false;
|
|
46
|
-
|
|
52
|
+
}
|
|
53
|
+
return typeof Object.getOwnPropertyDescriptor(proto, name)?.value === "function";
|
|
47
54
|
});
|
|
48
55
|
}
|
|
56
|
+
function buildDiscoveredVfunc(proto, methodName, resolveDescriptor, skip) {
|
|
57
|
+
if (skip?.has(methodName)) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
const descriptor = resolveDescriptor(methodName);
|
|
61
|
+
if (!descriptor) {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
const fn = proto[methodName];
|
|
65
|
+
if (!fn) {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
...descriptor,
|
|
70
|
+
methodName,
|
|
71
|
+
fn: wrapVfunc(fn, descriptor.argDescriptors, descriptor.returnDescriptor),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
49
74
|
function collectDiscoveredVfuncs(klass, resolveDescriptor, skip) {
|
|
50
75
|
const proto = klass.prototype;
|
|
51
76
|
const result = [];
|
|
52
77
|
for (const methodName of ownInstanceMethodNames(klass)) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
continue;
|
|
58
|
-
const fn = proto[methodName];
|
|
59
|
-
if (!fn)
|
|
60
|
-
continue;
|
|
61
|
-
result.push({
|
|
62
|
-
...descriptor,
|
|
63
|
-
methodName,
|
|
64
|
-
fn: wrapVfunc(fn, descriptor.argDescriptors, descriptor.returnDescriptor),
|
|
65
|
-
});
|
|
78
|
+
const discovered = buildDiscoveredVfunc(proto, methodName, resolveDescriptor, skip);
|
|
79
|
+
if (discovered) {
|
|
80
|
+
result.push(discovered);
|
|
81
|
+
}
|
|
66
82
|
}
|
|
67
83
|
return result;
|
|
68
84
|
}
|
|
69
|
-
const UNSUPPORTED_CONSTRUCT_VFUNCS = new Set(["constructed", "setProperty", "getProperty"]);
|
|
70
85
|
function discoverClassVfuncs(klass) {
|
|
71
86
|
return collectDiscoveredVfuncs(klass, (methodName) => {
|
|
72
87
|
const descriptor = findClassVfuncDescriptor(klass, methodName);
|
|
73
88
|
if (descriptor && UNSUPPORTED_CONSTRUCT_VFUNCS.has(methodName)) {
|
|
74
|
-
throw new Error(`registerClass: overriding the GObject construct-time vtable slot '${methodName}' is not
|
|
89
|
+
throw new Error(`registerClass: overriding the GObject construct-time vtable slot '${methodName}' is not ` +
|
|
90
|
+
"supported; run construct-time initialization in the subclass constructor, after " +
|
|
91
|
+
"super(...), instead");
|
|
75
92
|
}
|
|
76
93
|
return descriptor ?? undefined;
|
|
77
94
|
});
|
|
@@ -82,17 +99,18 @@ function wrapVfunc(fn, argDescriptors, returnDescriptor) {
|
|
|
82
99
|
function discoverInheritedInterfaceVfuncs(klass, parentGtype, claimedMethodNames) {
|
|
83
100
|
const bindings = [];
|
|
84
101
|
for (const interfaceGtype of typeInterfaces(parentGtype)) {
|
|
85
|
-
const
|
|
86
|
-
if (
|
|
87
|
-
bindings.push({ gtype: interfaceGtype, vfuncs });
|
|
102
|
+
const [first, ...rest] = discoverInterfaceVfuncs(klass, interfaceGtype, claimedMethodNames);
|
|
103
|
+
if (first !== undefined) {
|
|
104
|
+
bindings.push({ gtype: interfaceGtype, vtableSize: first.vtableSize, vfuncs: [first, ...rest] });
|
|
88
105
|
}
|
|
89
106
|
}
|
|
90
107
|
return bindings;
|
|
91
108
|
}
|
|
92
109
|
function discoverInterfaceVfuncs(klass, interfaceGtype, claimedMethodNames) {
|
|
93
110
|
const vfuncRegistry = getInterfaceVfuncRegistry(interfaceGtype);
|
|
94
|
-
if (!vfuncRegistry)
|
|
111
|
+
if (!vfuncRegistry) {
|
|
95
112
|
return [];
|
|
113
|
+
}
|
|
96
114
|
return collectDiscoveredVfuncs(klass, (methodName) => {
|
|
97
115
|
const entry = vfuncRegistry[methodName];
|
|
98
116
|
return entry?.kind === "interface" ? entry : undefined;
|
|
@@ -104,21 +122,57 @@ function findClassVfuncDescriptor(klass, methodName) {
|
|
|
104
122
|
return entry?.kind === "class" ? entry : undefined;
|
|
105
123
|
}) ?? null);
|
|
106
124
|
}
|
|
107
|
-
function
|
|
125
|
+
function propertyVfuncs(klass, accessors) {
|
|
126
|
+
if (accessors.length === 0) {
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
return [
|
|
130
|
+
buildPropertyVfunc(klass, "getProperty", makeGetProperty(accessors), true),
|
|
131
|
+
buildPropertyVfunc(klass, "setProperty", makeSetProperty(accessors), false),
|
|
132
|
+
];
|
|
133
|
+
}
|
|
134
|
+
// `get_property` fills a GValue the caller owns, so the marshalled copy handed to JavaScript has to
|
|
135
|
+
// be written back into it; `set_property` only reads its GValue and needs no copy back.
|
|
136
|
+
function markValueCallerAllocated(argDescriptors) {
|
|
137
|
+
return argDescriptors.map((arg, index) => index === VALUE_ARG_INDEX ? { ...arg, callerAllocated: true } : arg);
|
|
138
|
+
}
|
|
139
|
+
function buildPropertyVfunc(klass, methodName, fn, isValueOut) {
|
|
140
|
+
const descriptor = findClassVfuncDescriptor(klass, methodName);
|
|
141
|
+
if (!descriptor) {
|
|
142
|
+
throw new Error(`registerClass: the parent class exposes no '${methodName}' vtable slot`);
|
|
143
|
+
}
|
|
144
|
+
const argDescriptors = isValueOut
|
|
145
|
+
? markValueCallerAllocated(descriptor.argDescriptors)
|
|
146
|
+
: descriptor.argDescriptors;
|
|
147
|
+
return {
|
|
148
|
+
...descriptor,
|
|
149
|
+
methodName,
|
|
150
|
+
argDescriptors,
|
|
151
|
+
fn: wrapVfunc(fn, argDescriptors, descriptor.returnDescriptor),
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
function toNativeOptions(classVfuncs, interfaceBindings, properties) {
|
|
108
155
|
const hasInterfaces = interfaceBindings.length > 0;
|
|
109
156
|
const hasClassVfuncs = classVfuncs.length > 0;
|
|
110
|
-
|
|
157
|
+
const hasProperties = Object.keys(properties).length > 0;
|
|
158
|
+
if (!hasClassVfuncs && !hasInterfaces && !hasProperties) {
|
|
111
159
|
return undefined;
|
|
112
160
|
}
|
|
113
161
|
const options = {};
|
|
114
|
-
if (
|
|
162
|
+
if (hasProperties) {
|
|
163
|
+
options.properties = toNativeProperties(properties);
|
|
164
|
+
}
|
|
165
|
+
if (hasClassVfuncs) {
|
|
115
166
|
options.vfuncs = [...classVfuncs];
|
|
167
|
+
}
|
|
116
168
|
if (hasInterfaces) {
|
|
117
169
|
options.interfaces = interfaceBindings.map((binding) => ({
|
|
118
170
|
type: binding.gtype,
|
|
171
|
+
vtableSize: binding.vtableSize,
|
|
119
172
|
vfuncs: [...binding.vfuncs],
|
|
120
173
|
}));
|
|
121
174
|
}
|
|
122
175
|
return options;
|
|
123
176
|
}
|
|
177
|
+
export { registerClass };
|
|
124
178
|
//# sourceMappingURL=register-class.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register-class.js","sourceRoot":"","sources":["../src/register-class.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,aAAa,IAAI,mBAAmB,GACvC,MAAM,cAAc,CAAC;AACtB,OAAO,EAAiB,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EACH,YAAY,EACZ,yBAAyB,EACzB,gBAAgB,EAChB,iBAAiB,GAEpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AASzD;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAAqB,KAAQ,EAAE,OAAO,GAAyB,EAAE;IAC1F,MAAM,UAAU,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAC5C,IAAI,UAAU,KAAK,YAAY,EAAE,CAAC;QAC9B,MAAM,IAAI,SAAS,CAAC,kBAAkB,KAAK,CAAC,IAAI,yCAAyC,CAAC,CAAC;IAC/F,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC;IAE5C,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,MAAM,IAAI,KAAK,CAAC,qFAAqF,CAAC,CAAC;IAC3G,CAAC;IAED,MAAM,WAAW,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAC/C,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;IACjF,MAAM,iBAAiB,GAAG,gCAAgC,CAAC,KAAK,EAAE,UAAU,EAAE,kBAAkB,CAAC,CAAC;IAElG,MAAM,aAAa,GAAG,eAAe,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;IACtE,MAAM,OAAO,GAAW,mBAAmB,CAAC,IAAI,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;IAC7E,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAElC,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAe;IACtC,OAAO,CACH,cAAc,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE;QAC1C,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAChC,OAAO,KAAK,KAAK,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACtD,CAAC,CAAC,IAAI,YAAY,CACrB,CAAC;AACN,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAe;IAC3C,MAAM,KAAK,GAAI,KAAgC,CAAC,SAAS,CAAC;IAC1D,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,OAAO,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;QACrD,IAAI,IAAI,KAAK,aAAa;YAAE,OAAO,KAAK,CAAC;QACzC,OAAO,OAAQ,KAAiC,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC;IAC1E,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,uBAAuB,CAC5B,KAAe,EACf,iBAAyE,EACzE,IAAkB;IAElB,MAAM,KAAK,GAAI,KAAgD,CAAC,SAAS,CAAC;IAC1E,MAAM,MAAM,GAAyB,EAAE,CAAC;IACxC,KAAK,MAAM,UAAU,IAAI,sBAAsB,CAAC,KAAK,CAAC,EAAE,CAAC;QACrD,IAAI,IAAI,EAAE,GAAG,CAAC,UAAU,CAAC;YAAE,SAAS;QACpC,MAAM,UAAU,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC;QACjD,IAAI,CAAC,UAAU;YAAE,SAAS;QAC1B,MAAM,EAAE,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC;QAC7B,IAAI,CAAC,EAAE;YAAE,SAAS;QAClB,MAAM,CAAC,IAAI,CAAC;YACR,GAAG,UAAU;YACb,UAAU;YACV,EAAE,EAAE,SAAS,CAAC,EAAE,EAAE,UAAU,CAAC,cAAc,EAAE,UAAU,CAAC,gBAAgB,CAAC;SAC5E,CAAC,CAAC;IACP,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,MAAM,4BAA4B,GAAgB,IAAI,GAAG,CAAC,CAAC,aAAa,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC,CAAC;AAEzG,SAAS,mBAAmB,CAAC,KAAe;IACxC,OAAO,uBAAuB,CAAC,KAAK,EAAE,CAAC,UAAU,EAAE,EAAE;QACjD,MAAM,UAAU,GAAG,wBAAwB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAC/D,IAAI,UAAU,IAAI,4BAA4B,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YAC7D,MAAM,IAAI,KAAK,CACX,qEAAqE,UAAU,8GAA8G,CAChM,CAAC;QACN,CAAC;QACD,OAAO,UAAU,IAAI,SAAS,CAAC;IACnC,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,SAAS,CACd,EAAW,EACX,cAA0D,EAC1D,gBAA8D;IAE9D,OAAO,YAAY,CAAC,EAAqC,EAAE,EAAE,cAAc,EAAE,gBAAgB,EAAE,EAAE,MAAM,CAAC,CAAC;AAC7G,CAAC;AAED,SAAS,gCAAgC,CACrC,KAAe,EACf,WAAmB,EACnB,kBAA+B;IAE/B,MAAM,QAAQ,GAA4B,EAAE,CAAC;IAC7C,KAAK,MAAM,cAAc,IAAI,cAAc,CAAC,WAAW,CAAC,EAAE,CAAC;QACvD,MAAM,MAAM,GAAG,uBAAuB,CAAC,KAAK,EAAE,cAAc,EAAE,kBAAkB,CAAC,CAAC;QAClF,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;QACrD,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED,SAAS,uBAAuB,CAC5B,KAAe,EACf,cAAsB,EACtB,kBAA+B;IAE/B,MAAM,aAAa,GAAG,yBAAyB,CAAC,cAAc,CAAC,CAAC;IAChE,IAAI,CAAC,aAAa;QAAE,OAAO,EAAE,CAAC;IAC9B,OAAO,uBAAuB,CAC1B,KAAK,EACL,CAAC,UAAU,EAAE,EAAE;QACX,MAAM,KAAK,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;QACxC,OAAO,KAAK,EAAE,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3D,CAAC,EACD,kBAAkB,CACrB,CAAC;AACN,CAAC;AAED,SAAS,wBAAwB,CAAC,KAAe,EAAE,UAAkB;IACjE,OAAO,CACH,cAAc,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE;QAC1C,MAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;QAClD,OAAO,KAAK,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACvD,CAAC,CAAC,IAAI,IAAI,CACb,CAAC;AACN,CAAC;AAED,SAAS,eAAe,CACpB,WAAmC,EACnC,iBAA0C;IAE1C,MAAM,aAAa,GAAG,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC;IACnD,MAAM,cAAc,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;IAC9C,IAAI,CAAC,cAAc,IAAI,CAAC,aAAa,EAAE,CAAC;QACpC,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,MAAM,OAAO,GAA+B,EAAE,CAAC;IAC/C,IAAI,cAAc;QAAE,OAAO,CAAC,MAAM,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC;IACtD,IAAI,aAAa,EAAE,CAAC;QAChB,OAAO,CAAC,UAAU,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACrD,IAAI,EAAE,OAAO,CAAC,KAAK;YACnB,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;SAC9B,CAAC,CAAC,CAAC;IACR,CAAC;IACD,OAAO,OAAO,CAAC;AACnB,CAAC","sourcesContent":["import {\n type RegisterClassOptions as NativeRegisterClassOptions,\n type RegisterClassVfunc as NativeRegisterClassVfunc,\n registerClass as nativeRegisterClass,\n} from \"@gtkx/native\";\nimport { type AnyClass, getParentClass, walkClassChain } from \"@gtkx/utils\";\nimport { wrapCallback } from \"./callback.js\";\nimport {\n getClassType,\n getInterfaceVfuncRegistry,\n getVfuncRegistry,\n registerClassType,\n type VfuncDescriptor,\n} from \"./registry.js\";\nimport { TYPE_INVALID, typeInterfaces } from \"./type.js\";\n\ntype RegisterClassOptions = { typeName?: string };\ntype VfuncFn = NativeRegisterClassVfunc[\"fn\"];\ntype DiscoveredVfunc<K extends \"class\" | \"interface\"> = VfuncDescriptor<K> & { methodName: string; fn: VfuncFn };\ntype DiscoveredClassVfunc = DiscoveredVfunc<\"class\">;\ntype DiscoveredInterfaceVfunc = DiscoveredVfunc<\"interface\">;\ntype InterfaceVfuncBinding = { gtype: bigint; vfuncs: DiscoveredInterfaceVfunc[] };\n\n/**\n * Registers a subclass of a wrapper class as a new GType, wiring up any class and\n * inherited-interface virtual functions it overrides. Throws if the class does not\n * extend a registered wrapper class, has no derivable type name, or overrides an\n * unsupported construct-time vtable slot.\n *\n * @param klass The subclass to register.\n * @param options Registration options, such as an explicit type name.\n * @returns The same class, now registered.\n */\nexport function registerClass<T extends AnyClass>(klass: T, options: RegisterClassOptions = {}): T {\n const parentType = resolveParentType(klass);\n if (parentType === TYPE_INVALID) {\n throw new TypeError(`registerClass: ${klass.name} must extend a registered wrapper class`);\n }\n\n const name = options.typeName ?? klass.name;\n\n if (!name) {\n throw new Error(\"registerClass: cannot derive a GType name (anonymous class with no typeName option)\");\n }\n\n const classVfuncs = discoverClassVfuncs(klass);\n const claimedMethodNames = new Set(classVfuncs.map((vfunc) => vfunc.methodName));\n const interfaceBindings = discoverInheritedInterfaceVfuncs(klass, parentType, claimedMethodNames);\n\n const nativeOptions = toNativeOptions(classVfuncs, interfaceBindings);\n const newType: bigint = nativeRegisterClass(name, parentType, nativeOptions);\n registerClassType(klass, newType);\n\n return klass;\n}\n\nfunction resolveParentType(klass: AnyClass): bigint {\n return (\n walkClassChain(getParentClass(klass), (cls) => {\n const gtype = getClassType(cls);\n return gtype !== TYPE_INVALID ? gtype : undefined;\n }) ?? TYPE_INVALID\n );\n}\n\nfunction ownInstanceMethodNames(klass: AnyClass): string[] {\n const proto = (klass as { prototype?: object }).prototype;\n if (!proto) return [];\n return Object.getOwnPropertyNames(proto).filter((name) => {\n if (name === \"constructor\") return false;\n return typeof (proto as Record<string, unknown>)[name] === \"function\";\n });\n}\n\nfunction collectDiscoveredVfuncs<K extends \"class\" | \"interface\">(\n klass: AnyClass,\n resolveDescriptor: (methodName: string) => VfuncDescriptor<K> | undefined,\n skip?: Set<string>,\n): DiscoveredVfunc<K>[] {\n const proto = (klass as { prototype: Record<string, VfuncFn> }).prototype;\n const result: DiscoveredVfunc<K>[] = [];\n for (const methodName of ownInstanceMethodNames(klass)) {\n if (skip?.has(methodName)) continue;\n const descriptor = resolveDescriptor(methodName);\n if (!descriptor) continue;\n const fn = proto[methodName];\n if (!fn) continue;\n result.push({\n ...descriptor,\n methodName,\n fn: wrapVfunc(fn, descriptor.argDescriptors, descriptor.returnDescriptor),\n });\n }\n return result;\n}\n\nconst UNSUPPORTED_CONSTRUCT_VFUNCS: Set<string> = new Set([\"constructed\", \"setProperty\", \"getProperty\"]);\n\nfunction discoverClassVfuncs(klass: AnyClass): DiscoveredClassVfunc[] {\n return collectDiscoveredVfuncs(klass, (methodName) => {\n const descriptor = findClassVfuncDescriptor(klass, methodName);\n if (descriptor && UNSUPPORTED_CONSTRUCT_VFUNCS.has(methodName)) {\n throw new Error(\n `registerClass: overriding the GObject construct-time vtable slot '${methodName}' is not supported; run construct-time initialization in the subclass constructor, after super(...), instead`,\n );\n }\n return descriptor ?? undefined;\n });\n}\n\nfunction wrapVfunc(\n fn: VfuncFn,\n argDescriptors: NativeRegisterClassVfunc[\"argDescriptors\"],\n returnDescriptor: NativeRegisterClassVfunc[\"returnDescriptor\"],\n): VfuncFn {\n return wrapCallback(fn as (...args: unknown[]) => unknown, { argDescriptors, returnDescriptor }, \"this\");\n}\n\nfunction discoverInheritedInterfaceVfuncs(\n klass: AnyClass,\n parentGtype: bigint,\n claimedMethodNames: Set<string>,\n): InterfaceVfuncBinding[] {\n const bindings: InterfaceVfuncBinding[] = [];\n for (const interfaceGtype of typeInterfaces(parentGtype)) {\n const vfuncs = discoverInterfaceVfuncs(klass, interfaceGtype, claimedMethodNames);\n if (vfuncs.length > 0) {\n bindings.push({ gtype: interfaceGtype, vfuncs });\n }\n }\n return bindings;\n}\n\nfunction discoverInterfaceVfuncs(\n klass: AnyClass,\n interfaceGtype: bigint,\n claimedMethodNames: Set<string>,\n): DiscoveredInterfaceVfunc[] {\n const vfuncRegistry = getInterfaceVfuncRegistry(interfaceGtype);\n if (!vfuncRegistry) return [];\n return collectDiscoveredVfuncs(\n klass,\n (methodName) => {\n const entry = vfuncRegistry[methodName];\n return entry?.kind === \"interface\" ? entry : undefined;\n },\n claimedMethodNames,\n );\n}\n\nfunction findClassVfuncDescriptor(klass: AnyClass, methodName: string): VfuncDescriptor<\"class\"> | null {\n return (\n walkClassChain(getParentClass(klass), (cls) => {\n const entry = getVfuncRegistry(cls)?.[methodName];\n return entry?.kind === \"class\" ? entry : undefined;\n }) ?? null\n );\n}\n\nfunction toNativeOptions(\n classVfuncs: DiscoveredClassVfunc[],\n interfaceBindings: InterfaceVfuncBinding[],\n): NativeRegisterClassOptions | undefined {\n const hasInterfaces = interfaceBindings.length > 0;\n const hasClassVfuncs = classVfuncs.length > 0;\n if (!hasClassVfuncs && !hasInterfaces) {\n return undefined;\n }\n const options: NativeRegisterClassOptions = {};\n if (hasClassVfuncs) options.vfuncs = [...classVfuncs];\n if (hasInterfaces) {\n options.interfaces = interfaceBindings.map((binding) => ({\n type: binding.gtype,\n vfuncs: [...binding.vfuncs],\n }));\n }\n return options;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"register-class.js","sourceRoot":"","sources":["../src/register-class.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Descriptor } from \"@gtkx/native\";\nimport {\n registerClass as nativeRegisterClass,\n type RegisterClassOptions as NativeRegisterClassOptions,\n type RegisterClassVfunc as NativeRegisterClassVfunc,\n} from \"@gtkx/native\";\nimport { type AnyClass, getParentClass, walkClassChain } from \"@gtkx/utils\";\nimport { wrapCallback } from \"./callback.js\";\nimport {\n buildAccessors,\n makeGetProperty,\n makeSetProperty,\n type PropertyAccessor,\n type PropertySpec,\n toNativeProperties,\n} from \"./properties.js\";\nimport {\n getClassType,\n getInterfaceVfuncRegistry,\n getVfuncRegistry,\n registerClassType,\n type VfuncDescriptor,\n} from \"./registry.js\";\nimport { TYPE_INVALID, typeInterfaces } from \"./type.js\";\n\ntype RegisterClassOptions = {\n typeName?: string;\n /**\n * Properties to install on the new type, keyed by canonical property name. Each value is the\n * `GObject.ParamSpec` describing it, for example `GObject.paramSpecString(...)`. Accessors are\n * generated on the prototype for the dashed, underscored and camelCased spellings of the name\n * unless the class already defines one, and writing through them emits `notify`.\n */\n properties?: Record<string, PropertySpec>;\n};\n\ntype VfuncFn = NativeRegisterClassVfunc[\"fn\"];\ntype DiscoveredVfunc<K extends \"class\" | \"interface\"> = VfuncDescriptor<K> & { methodName: string; fn: VfuncFn };\ntype DiscoveredClassVfunc = DiscoveredVfunc<\"class\">;\ntype DiscoveredInterfaceVfunc = DiscoveredVfunc<\"interface\">;\ntype InterfaceVfuncBinding = { gtype: bigint; vtableSize: number; vfuncs: DiscoveredInterfaceVfunc[] };\n\nconst UNSUPPORTED_CONSTRUCT_VFUNCS: Set<string> = new Set([\"constructed\", \"setProperty\", \"getProperty\"]);\nconst VALUE_ARG_INDEX = 2;\n\n/**\n * Registers a subclass of a wrapper class as a new GType, wiring up any class and\n * inherited-interface virtual functions it overrides. Throws if the class does not\n * extend a registered wrapper class, has no derivable type name, or overrides an\n * unsupported construct-time vtable slot.\n *\n * @param klass The subclass to register.\n * @param options Registration options, such as an explicit type name.\n * @returns The same class, now registered.\n */\nfunction registerClass<T extends AnyClass>(klass: T, options: RegisterClassOptions = {}): T {\n const parentType = resolveParentType(klass);\n\n if (parentType === TYPE_INVALID) {\n throw new TypeError(`registerClass: ${klass.name} must extend a registered wrapper class`);\n }\n\n const name = options.typeName ?? klass.name;\n\n if (!name) {\n throw new Error(\"registerClass: cannot derive a GType name (anonymous class with no typeName option)\");\n }\n\n const properties = options.properties ?? {};\n const accessors = buildAccessors(klass, properties);\n const classVfuncs = [...discoverClassVfuncs(klass), ...propertyVfuncs(klass, accessors)];\n const claimedMethodNames = new Set(classVfuncs.map((vfunc) => vfunc.methodName));\n const interfaceBindings = discoverInheritedInterfaceVfuncs(klass, parentType, claimedMethodNames);\n const nativeOptions = toNativeOptions(classVfuncs, interfaceBindings, properties);\n const newType: bigint = nativeRegisterClass(name, parentType, nativeOptions);\n registerClassType(klass, newType);\n\n return klass;\n}\n\nfunction resolveParentType(klass: AnyClass): bigint {\n return (\n walkClassChain(getParentClass(klass), (cls) => {\n const gtype = getClassType(cls);\n\n return gtype === TYPE_INVALID ? undefined : gtype;\n }) ?? TYPE_INVALID\n );\n}\n\nfunction ownInstanceMethodNames(klass: AnyClass): string[] {\n const proto = (klass as { prototype?: object }).prototype;\n\n if (!proto) {\n return [];\n }\n\n return Object.getOwnPropertyNames(proto).filter((name) => {\n if (name === \"constructor\") {\n return false;\n }\n\n return typeof Object.getOwnPropertyDescriptor(proto, name)?.value === \"function\";\n });\n}\n\nfunction buildDiscoveredVfunc<K extends \"class\" | \"interface\">(\n proto: Record<string, VfuncFn>,\n methodName: string,\n resolveDescriptor: (methodName: string) => VfuncDescriptor<K> | undefined,\n skip: Set<string> | undefined,\n): DiscoveredVfunc<K> | undefined {\n if (skip?.has(methodName)) {\n return undefined;\n }\n\n const descriptor = resolveDescriptor(methodName);\n\n if (!descriptor) {\n return undefined;\n }\n\n const fn = proto[methodName];\n\n if (!fn) {\n return undefined;\n }\n\n return {\n ...descriptor,\n methodName,\n fn: wrapVfunc(fn, descriptor.argDescriptors, descriptor.returnDescriptor),\n };\n}\n\nfunction collectDiscoveredVfuncs<K extends \"class\" | \"interface\">(\n klass: AnyClass,\n resolveDescriptor: (methodName: string) => VfuncDescriptor<K> | undefined,\n skip?: Set<string>,\n): DiscoveredVfunc<K>[] {\n const proto = (klass as { prototype: Record<string, VfuncFn> }).prototype;\n const result: DiscoveredVfunc<K>[] = [];\n\n for (const methodName of ownInstanceMethodNames(klass)) {\n const discovered = buildDiscoveredVfunc(proto, methodName, resolveDescriptor, skip);\n\n if (discovered) {\n result.push(discovered);\n }\n }\n\n return result;\n}\n\nfunction discoverClassVfuncs(klass: AnyClass): DiscoveredClassVfunc[] {\n return collectDiscoveredVfuncs(klass, (methodName) => {\n const descriptor = findClassVfuncDescriptor(klass, methodName);\n\n if (descriptor && UNSUPPORTED_CONSTRUCT_VFUNCS.has(methodName)) {\n throw new Error(\n `registerClass: overriding the GObject construct-time vtable slot '${methodName}' is not ` +\n \"supported; run construct-time initialization in the subclass constructor, after \" +\n \"super(...), instead\",\n );\n }\n\n return descriptor ?? undefined;\n });\n}\n\nfunction wrapVfunc(\n fn: VfuncFn,\n argDescriptors: NativeRegisterClassVfunc[\"argDescriptors\"],\n returnDescriptor: NativeRegisterClassVfunc[\"returnDescriptor\"],\n): VfuncFn {\n return wrapCallback(fn as (...args: unknown[]) => unknown, { argDescriptors, returnDescriptor }, \"this\");\n}\n\nfunction discoverInheritedInterfaceVfuncs(\n klass: AnyClass,\n parentGtype: bigint,\n claimedMethodNames: Set<string>,\n): InterfaceVfuncBinding[] {\n const bindings: InterfaceVfuncBinding[] = [];\n\n for (const interfaceGtype of typeInterfaces(parentGtype)) {\n const [first, ...rest] = discoverInterfaceVfuncs(klass, interfaceGtype, claimedMethodNames);\n\n if (first !== undefined) {\n bindings.push({ gtype: interfaceGtype, vtableSize: first.vtableSize, vfuncs: [first, ...rest] });\n }\n }\n\n return bindings;\n}\n\nfunction discoverInterfaceVfuncs(\n klass: AnyClass,\n interfaceGtype: bigint,\n claimedMethodNames: Set<string>,\n): DiscoveredInterfaceVfunc[] {\n const vfuncRegistry = getInterfaceVfuncRegistry(interfaceGtype);\n\n if (!vfuncRegistry) {\n return [];\n }\n\n return collectDiscoveredVfuncs(\n klass,\n (methodName) => {\n const entry = vfuncRegistry[methodName];\n\n return entry?.kind === \"interface\" ? entry : undefined;\n },\n claimedMethodNames,\n );\n}\n\nfunction findClassVfuncDescriptor(klass: AnyClass, methodName: string): VfuncDescriptor<\"class\"> | null {\n return (\n walkClassChain(getParentClass(klass), (cls) => {\n const entry = getVfuncRegistry(cls)?.[methodName];\n\n return entry?.kind === \"class\" ? entry : undefined;\n }) ?? null\n );\n}\n\nfunction propertyVfuncs(klass: AnyClass, accessors: PropertyAccessor[]): DiscoveredClassVfunc[] {\n if (accessors.length === 0) {\n return [];\n }\n\n return [\n buildPropertyVfunc(klass, \"getProperty\", makeGetProperty(accessors), true),\n buildPropertyVfunc(klass, \"setProperty\", makeSetProperty(accessors), false),\n ];\n}\n\n// `get_property` fills a GValue the caller owns, so the marshalled copy handed to JavaScript has to\n// be written back into it; `set_property` only reads its GValue and needs no copy back.\nfunction markValueCallerAllocated(argDescriptors: Descriptor[]): Descriptor[] {\n return argDescriptors.map((arg, index) =>\n index === VALUE_ARG_INDEX ? { ...arg, callerAllocated: true } : arg);\n}\n\nfunction buildPropertyVfunc(\n klass: AnyClass,\n methodName: string,\n fn: VfuncFn,\n isValueOut: boolean,\n): DiscoveredClassVfunc {\n const descriptor = findClassVfuncDescriptor(klass, methodName);\n\n if (!descriptor) {\n throw new Error(`registerClass: the parent class exposes no '${methodName}' vtable slot`);\n }\n\n const argDescriptors = isValueOut\n ? markValueCallerAllocated(descriptor.argDescriptors)\n : descriptor.argDescriptors;\n\n return {\n ...descriptor,\n methodName,\n argDescriptors,\n fn: wrapVfunc(fn, argDescriptors, descriptor.returnDescriptor),\n };\n}\n\nfunction toNativeOptions(\n classVfuncs: DiscoveredClassVfunc[],\n interfaceBindings: InterfaceVfuncBinding[],\n properties: Record<string, PropertySpec>,\n): NativeRegisterClassOptions | undefined {\n const hasInterfaces = interfaceBindings.length > 0;\n const hasClassVfuncs = classVfuncs.length > 0;\n const hasProperties = Object.keys(properties).length > 0;\n\n if (!hasClassVfuncs && !hasInterfaces && !hasProperties) {\n return undefined;\n }\n\n const options: NativeRegisterClassOptions = {};\n\n if (hasProperties) {\n options.properties = toNativeProperties(properties);\n }\n\n if (hasClassVfuncs) {\n options.vfuncs = [...classVfuncs];\n }\n\n if (hasInterfaces) {\n options.interfaces = interfaceBindings.map((binding) => ({\n type: binding.gtype,\n vtableSize: binding.vtableSize,\n vfuncs: [...binding.vfuncs],\n }));\n }\n\n return options;\n}\n\nexport { registerClass };\n"]}
|
package/dist/registry.d.ts
CHANGED
|
@@ -1,25 +1,26 @@
|
|
|
1
|
-
import { type ExternalObject, type Handle, type RegisterClassVfunc as NativeRegisterClassVfunc } from "@gtkx/native";
|
|
2
1
|
import type { AnyClass } from "@gtkx/utils";
|
|
2
|
+
import { type ExternalObject, type Handle, type RegisterClassVfunc as NativeRegisterClassVfunc } from "@gtkx/native";
|
|
3
3
|
import type { Mixin } from "./mixin.js";
|
|
4
4
|
import { type TypedClass } from "./type.js";
|
|
5
5
|
/**
|
|
6
6
|
* Static side of class `C` with its construct signature preserved but the member
|
|
7
7
|
* named `K` (default `"new"`) removed.
|
|
8
8
|
*/
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
type StaticBase<C, K extends PropertyKey = "new"> = Omit<C, K> & (C extends new (...args: infer A) => infer R ? new (...args: A) => R : never);
|
|
10
|
+
type VfuncDescriptor<K extends "class" | "interface"> = {
|
|
11
11
|
kind: K;
|
|
12
12
|
className: string;
|
|
13
13
|
vfuncName: string;
|
|
14
14
|
byteOffset: number;
|
|
15
|
+
vtableSize: number;
|
|
15
16
|
argDescriptors: NativeRegisterClassVfunc["argDescriptors"];
|
|
16
17
|
returnDescriptor: NativeRegisterClassVfunc["returnDescriptor"];
|
|
17
18
|
};
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
type VfuncRegistry = Record<string, VfuncDescriptor<"class"> | VfuncDescriptor<"interface">>;
|
|
20
|
+
declare function getClassType(cls: AnyClass): bigint;
|
|
20
21
|
/** Returns the GType tag of the given wrapper instance. */
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
declare function getInstanceType(instance: object): bigint;
|
|
23
|
+
declare function registerClassType(cls: AnyClass, type: bigint): void;
|
|
23
24
|
/**
|
|
24
25
|
* Registers a wrapper class as the JS representation of a GType, optionally
|
|
25
26
|
* installing a registry of virtual functions.
|
|
@@ -27,7 +28,7 @@ export declare function registerClassType(cls: AnyClass, type: bigint): void;
|
|
|
27
28
|
* @param type GType the class wraps.
|
|
28
29
|
* @param vfuncs Virtual functions the class overrides.
|
|
29
30
|
*/
|
|
30
|
-
|
|
31
|
+
declare function registerWrapperClass(cls: AnyClass, type: bigint, vfuncs?: VfuncRegistry): void;
|
|
31
32
|
/**
|
|
32
33
|
* Registers a GInterface, associating its GType with a mixin used to compose the
|
|
33
34
|
* interface onto wrapper classes and an optional virtual function registry.
|
|
@@ -36,7 +37,7 @@ export declare function registerWrapperClass(cls: AnyClass, type: bigint, vfuncs
|
|
|
36
37
|
* @param mixin Mixin that applies the interface to a wrapper class.
|
|
37
38
|
* @param vfuncs Virtual functions the interface exposes.
|
|
38
39
|
*/
|
|
39
|
-
|
|
40
|
+
declare function registerInterface(cls: AnyClass, type: bigint, mixin: Mixin, vfuncs?: VfuncRegistry): void;
|
|
40
41
|
/**
|
|
41
42
|
* Wraps a native handle in a JS wrapper instance. With no class, resolves and
|
|
42
43
|
* reuses the wrapper for the handle's runtime GType (composing interface mixins);
|
|
@@ -45,23 +46,24 @@ export declare function registerInterface(cls: AnyClass, type: bigint, mixin: Mi
|
|
|
45
46
|
* @param handle Native handle to wrap.
|
|
46
47
|
* @param cls Wrapper class to instantiate, or omitted to resolve it from the runtime type.
|
|
47
48
|
*/
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
declare function wrapHandle(handle: null | undefined, cls?: AnyClass): null;
|
|
50
|
+
declare function wrapHandle<T extends object>(handle: ExternalObject<Handle>, cls: AnyClass<T>): T;
|
|
51
|
+
declare function wrapHandle<T extends object>(handle: ExternalObject<Handle> | null | undefined, cls: AnyClass<T>): T | null;
|
|
52
|
+
declare function wrapHandle(handle: ExternalObject<Handle>, cls?: AnyClass): TypedClass;
|
|
53
|
+
declare function wrapHandle(handle: ExternalObject<Handle> | null | undefined, cls?: AnyClass): TypedClass | null;
|
|
53
54
|
/**
|
|
54
55
|
* Returns the wrapper class registered for a GType, walking up to ancestor types,
|
|
55
56
|
* and throws if none is registered.
|
|
56
57
|
*/
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
declare function getWrapperClass(type: bigint): AnyClass;
|
|
59
|
+
declare function resolveWrapperClass(type: bigint): AnyClass | null;
|
|
59
60
|
/** Returns the native handle bound to a wrapper instance, throwing if none is set. */
|
|
60
|
-
|
|
61
|
+
declare function getHandle(instance: object): ExternalObject<Handle>;
|
|
61
62
|
/** Returns the native handle bound to an instance, or undefined when there is none or the instance is null. */
|
|
62
|
-
|
|
63
|
+
declare function tryGetHandle(instance: object | null | undefined): ExternalObject<Handle> | undefined;
|
|
63
64
|
/** Associates a native handle with a wrapper instance. */
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
declare function setHandle(instance: object, handle: ExternalObject<Handle>): void;
|
|
66
|
+
declare function getVfuncRegistry(cls: object): VfuncRegistry | undefined;
|
|
67
|
+
declare function getInterfaceVfuncRegistry(type: bigint): VfuncRegistry | undefined;
|
|
68
|
+
export { getClassType, getInstanceType, registerClassType, registerWrapperClass, registerInterface, wrapHandle, getWrapperClass, resolveWrapperClass, getHandle, tryGetHandle, setHandle, getVfuncRegistry, getInterfaceVfuncRegistry, type StaticBase, type VfuncDescriptor, type VfuncRegistry, };
|
|
67
69
|
//# sourceMappingURL=registry.d.ts.map
|
package/dist/registry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,KAAK,cAAc,EAGnB,KAAK,MAAM,EACX,KAAK,kBAAkB,IAAI,wBAAwB,EAEtD,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
|
package/dist/registry.js
CHANGED
|
@@ -9,19 +9,20 @@ const interfaceVfuncRegistry = new Map();
|
|
|
9
9
|
function setClassType(cls, type) {
|
|
10
10
|
cls.prototype.__type__ = type;
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
function getClassType(cls) {
|
|
13
13
|
const proto = cls.prototype;
|
|
14
14
|
return Object.hasOwn(proto, "__type__") ? proto.__type__ : TYPE_INVALID;
|
|
15
15
|
}
|
|
16
16
|
/** Returns the GType tag of the given wrapper instance. */
|
|
17
|
-
|
|
17
|
+
function getInstanceType(instance) {
|
|
18
18
|
return getClassType(instance.constructor);
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
if (type
|
|
22
|
-
|
|
23
|
-
setClassType(cls, type);
|
|
20
|
+
function registerClassType(cls, type) {
|
|
21
|
+
if (type === TYPE_INVALID) {
|
|
22
|
+
return;
|
|
24
23
|
}
|
|
24
|
+
classRegistry.set(type, cls);
|
|
25
|
+
setClassType(cls, type);
|
|
25
26
|
}
|
|
26
27
|
/**
|
|
27
28
|
* Registers a wrapper class as the JS representation of a GType, optionally
|
|
@@ -30,10 +31,11 @@ export function registerClassType(cls, type) {
|
|
|
30
31
|
* @param type GType the class wraps.
|
|
31
32
|
* @param vfuncs Virtual functions the class overrides.
|
|
32
33
|
*/
|
|
33
|
-
|
|
34
|
+
function registerWrapperClass(cls, type, vfuncs) {
|
|
34
35
|
registerClassType(cls, type);
|
|
35
|
-
if (vfuncs)
|
|
36
|
+
if (vfuncs) {
|
|
36
37
|
registerVfuncRegistry(cls, vfuncs);
|
|
38
|
+
}
|
|
37
39
|
}
|
|
38
40
|
/**
|
|
39
41
|
* Registers a GInterface, associating its GType with a mixin used to compose the
|
|
@@ -43,17 +45,20 @@ export function registerWrapperClass(cls, type, vfuncs) {
|
|
|
43
45
|
* @param mixin Mixin that applies the interface to a wrapper class.
|
|
44
46
|
* @param vfuncs Virtual functions the interface exposes.
|
|
45
47
|
*/
|
|
46
|
-
|
|
47
|
-
if (type === TYPE_INVALID)
|
|
48
|
+
function registerInterface(cls, type, mixin, vfuncs) {
|
|
49
|
+
if (type === TYPE_INVALID) {
|
|
48
50
|
return;
|
|
51
|
+
}
|
|
49
52
|
setClassType(cls, type);
|
|
50
53
|
interfaceMixinRegistry.set(type, mixin);
|
|
51
|
-
if (vfuncs)
|
|
54
|
+
if (vfuncs) {
|
|
52
55
|
registerInterfaceVfuncRegistry(type, vfuncs);
|
|
56
|
+
}
|
|
53
57
|
}
|
|
54
|
-
|
|
55
|
-
if (handle === null || handle === undefined)
|
|
58
|
+
function wrapHandle(handle, cls) {
|
|
59
|
+
if (handle === null || handle === undefined) {
|
|
56
60
|
return null;
|
|
61
|
+
}
|
|
57
62
|
if (cls === undefined) {
|
|
58
63
|
return getOrCreateWrapper(handle);
|
|
59
64
|
}
|
|
@@ -65,72 +70,84 @@ export function wrapHandle(handle, cls) {
|
|
|
65
70
|
* Returns the wrapper class registered for a GType, walking up to ancestor types,
|
|
66
71
|
* and throws if none is registered.
|
|
67
72
|
*/
|
|
68
|
-
|
|
73
|
+
function getWrapperClass(type) {
|
|
69
74
|
const cls = resolveWrapperClass(type);
|
|
70
75
|
if (!cls) {
|
|
71
76
|
throw new Error(`No registered wrapper class for type '${typeName(type) ?? String(type)}'`);
|
|
72
77
|
}
|
|
73
78
|
return cls;
|
|
74
79
|
}
|
|
75
|
-
|
|
80
|
+
function resolveWrapperClass(type) {
|
|
76
81
|
let currentType = type;
|
|
77
82
|
while (currentType !== TYPE_INVALID) {
|
|
78
83
|
const cls = classRegistry.get(currentType);
|
|
79
|
-
if (cls)
|
|
84
|
+
if (cls) {
|
|
80
85
|
return cls;
|
|
86
|
+
}
|
|
81
87
|
currentType = typeParent(currentType);
|
|
82
88
|
}
|
|
83
89
|
return null;
|
|
84
90
|
}
|
|
91
|
+
function applyInterfaceMixin(cls, type, baseType, applied) {
|
|
92
|
+
if (applied.has(type) || typeIsA(baseType, type)) {
|
|
93
|
+
return cls;
|
|
94
|
+
}
|
|
95
|
+
const mixin = interfaceMixinRegistry.get(type);
|
|
96
|
+
if (mixin === undefined) {
|
|
97
|
+
return cls;
|
|
98
|
+
}
|
|
99
|
+
applied.add(type);
|
|
100
|
+
return mixin(cls);
|
|
101
|
+
}
|
|
85
102
|
function createComposedClass(base, runtimeType) {
|
|
86
103
|
const baseType = getClassType(base);
|
|
87
104
|
const applied = new Set();
|
|
88
105
|
let cls = base;
|
|
89
106
|
for (const type of typeInterfaces(runtimeType)) {
|
|
90
|
-
|
|
91
|
-
continue;
|
|
92
|
-
const mixin = interfaceMixinRegistry.get(type);
|
|
93
|
-
if (mixin === undefined)
|
|
94
|
-
continue;
|
|
95
|
-
applied.add(type);
|
|
96
|
-
cls = mixin(cls);
|
|
107
|
+
cls = applyInterfaceMixin(cls, type, baseType, applied);
|
|
97
108
|
}
|
|
98
109
|
return applied.size === 0 ? base : cls;
|
|
99
110
|
}
|
|
100
111
|
function resolveComposedClass(runtimeType) {
|
|
101
112
|
const exact = classRegistry.get(runtimeType);
|
|
102
|
-
if (exact)
|
|
113
|
+
if (exact) {
|
|
103
114
|
return exact;
|
|
115
|
+
}
|
|
104
116
|
const cached = composedClassRegistry.get(runtimeType);
|
|
105
|
-
if (cached)
|
|
117
|
+
if (cached) {
|
|
106
118
|
return cached;
|
|
119
|
+
}
|
|
107
120
|
const base = resolveWrapperClass(runtimeType);
|
|
108
|
-
if (base === null)
|
|
121
|
+
if (base === null) {
|
|
109
122
|
return null;
|
|
123
|
+
}
|
|
110
124
|
const composed = createComposedClass(base, runtimeType);
|
|
111
|
-
if (composed === base)
|
|
125
|
+
if (composed === base) {
|
|
112
126
|
return base;
|
|
127
|
+
}
|
|
113
128
|
setClassType(composed, runtimeType);
|
|
114
129
|
composedClassRegistry.set(runtimeType, composed);
|
|
115
130
|
return composed;
|
|
116
131
|
}
|
|
117
132
|
function getOrCreateWrapper(handle) {
|
|
118
133
|
const existing = getWrapper(handle);
|
|
119
|
-
if (existing)
|
|
134
|
+
if (existing) {
|
|
120
135
|
return existing;
|
|
136
|
+
}
|
|
121
137
|
const runtimeType = getType(handle);
|
|
122
138
|
if (runtimeType === TYPE_INVALID) {
|
|
123
139
|
throw new Error("Cannot resolve runtime GLib type from handle");
|
|
124
140
|
}
|
|
125
141
|
const cls = resolveComposedClass(runtimeType);
|
|
126
|
-
if (!cls)
|
|
142
|
+
if (!cls) {
|
|
127
143
|
throw new Error(`Expected registered GLib type, got type ${String(runtimeType)}`);
|
|
144
|
+
}
|
|
128
145
|
const instance = Object.create(cls.prototype);
|
|
129
146
|
registerWrapper(handle, instance);
|
|
130
147
|
return instance;
|
|
131
148
|
}
|
|
132
149
|
/** Returns the native handle bound to a wrapper instance, throwing if none is set. */
|
|
133
|
-
|
|
150
|
+
function getHandle(instance) {
|
|
134
151
|
const handle = handleMap.get(instance);
|
|
135
152
|
if (handle === undefined) {
|
|
136
153
|
const name = instance.constructor?.name ?? "object";
|
|
@@ -139,11 +156,11 @@ export function getHandle(instance) {
|
|
|
139
156
|
return handle;
|
|
140
157
|
}
|
|
141
158
|
/** Returns the native handle bound to an instance, or undefined when there is none or the instance is null. */
|
|
142
|
-
|
|
159
|
+
function tryGetHandle(instance) {
|
|
143
160
|
return instance == null ? undefined : handleMap.get(instance);
|
|
144
161
|
}
|
|
145
162
|
/** Associates a native handle with a wrapper instance. */
|
|
146
|
-
|
|
163
|
+
function setHandle(instance, handle) {
|
|
147
164
|
handleMap.set(instance, handle);
|
|
148
165
|
}
|
|
149
166
|
function registerWrapper(handle, instance) {
|
|
@@ -153,15 +170,17 @@ function registerWrapper(handle, instance) {
|
|
|
153
170
|
function registerVfuncRegistry(cls, registry) {
|
|
154
171
|
vfuncRegistry.set(cls, registry);
|
|
155
172
|
}
|
|
156
|
-
|
|
173
|
+
function getVfuncRegistry(cls) {
|
|
157
174
|
return vfuncRegistry.get(cls);
|
|
158
175
|
}
|
|
159
176
|
function registerInterfaceVfuncRegistry(type, registry) {
|
|
160
|
-
if (type === TYPE_INVALID)
|
|
177
|
+
if (type === TYPE_INVALID) {
|
|
161
178
|
return;
|
|
179
|
+
}
|
|
162
180
|
interfaceVfuncRegistry.set(type, registry);
|
|
163
181
|
}
|
|
164
|
-
|
|
182
|
+
function getInterfaceVfuncRegistry(type) {
|
|
165
183
|
return interfaceVfuncRegistry.get(type);
|
|
166
184
|
}
|
|
185
|
+
export { getClassType, getInstanceType, registerClassType, registerWrapperClass, registerInterface, wrapHandle, getWrapperClass, resolveWrapperClass, getHandle, tryGetHandle, setHandle, getVfuncRegistry, getInterfaceVfuncRegistry, };
|
|
167
186
|
//# sourceMappingURL=registry.js.map
|
package/dist/registry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,OAAO,EACP,UAAU,EAGV,UAAU,GACb,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,YAAY,EAAmB,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAoBzG,MAAM,aAAa,GAAG,IAAI,GAAG,EAAoB,CAAC;AAClD,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAAiB,CAAC;AACxD,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAoB,CAAC;AAC1D,MAAM,SAAS,GAAG,IAAI,OAAO,EAAkC,CAAC;AAChE,MAAM,aAAa,GAAG,IAAI,OAAO,EAAyB,CAAC;AAC3D,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAAyB,CAAC;AAEhE,SAAS,YAAY,CAAC,GAAa,EAAE,IAAY;IAC5C,GAAG,CAAC,SAAwD,CAAC,QAAQ,GAAG,IAAI,CAAC;AAClF,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAa;IACtC,MAAM,KAAK,GAAW,GAAG,CAAC,SAAS,CAAC;IACpC,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,CAAE,KAAoB,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC;AAC5F,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC5C,OAAO,YAAY,CAAC,QAAQ,CAAC,WAAuB,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAa,EAAE,IAAY;IACzD,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;QACxB,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC7B,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAa,EAAE,IAAY,EAAE,MAAsB;IACpF,iBAAiB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC7B,IAAI,MAAM;QAAE,qBAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AACnD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAa,EAAE,IAAY,EAAE,KAAY,EAAE,MAAsB;IAC/F,IAAI,IAAI,KAAK,YAAY;QAAE,OAAO;IAClC,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACxB,sBAAsB,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACxC,IAAI,MAAM;QAAE,8BAA8B,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC7D,CAAC;AAqBD,MAAM,UAAU,UAAU,CAAC,MAAiD,EAAE,GAAc;IACxF,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACzD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACpB,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IACD,MAAM,QAAQ,GAAW,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACtD,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC5B,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IACxC,MAAM,GAAG,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,CAAC,GAAG,EAAE,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,yCAAyC,QAAQ,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChG,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC5C,IAAI,WAAW,GAAG,IAAI,CAAC;IACvB,OAAO,WAAW,KAAK,YAAY,EAAE,CAAC;QAClC,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC3C,IAAI,GAAG;YAAE,OAAO,GAAG,CAAC;QACpB,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAc,EAAE,WAAmB;IAC5D,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,IAAI,GAAG,GAAa,IAAI,CAAC;IACzB,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7C,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC;YAAE,SAAS;QAC3D,MAAM,KAAK,GAAG,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClB,GAAG,GAAG,KAAK,CAAC,GAA8B,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;AAC3C,CAAC;AAED,SAAS,oBAAoB,CAAC,WAAmB;IAC7C,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC7C,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IACxB,MAAM,MAAM,GAAG,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACtD,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,IAAI,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAC9C,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IACxD,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACnC,YAAY,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IACpC,qBAAqB,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IACjD,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED,SAAS,kBAAkB,CAAC,MAA8B;IACtD,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,MAAM,WAAW,GAAW,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,WAAW,KAAK,YAAY,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,GAAG,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAC9C,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IAC5F,MAAM,QAAQ,GAAW,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACtD,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAClC,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,SAAS,CAAC,QAAgB;IACtC,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACvB,MAAM,IAAI,GAAI,QAAgD,CAAC,WAAW,EAAE,IAAI,IAAI,QAAQ,CAAC;QAC7F,MAAM,IAAI,KAAK,CAAC,oCAAoC,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,+GAA+G;AAC/G,MAAM,UAAU,YAAY,CAAC,QAAmC;IAC5D,OAAO,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAClE,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,MAA8B;IACtE,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,eAAe,CAAC,MAA8B,EAAE,QAAgB;IACrE,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC5B,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,qBAAqB,CAAC,GAAW,EAAE,QAAuB;IAC/D,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAW;IACxC,OAAO,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,8BAA8B,CAAC,IAAY,EAAE,QAAuB;IACzE,IAAI,IAAI,KAAK,YAAY;QAAE,OAAO;IAClC,sBAAsB,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,IAAY;IAClD,OAAO,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC5C,CAAC","sourcesContent":["import {\n type ExternalObject,\n getType,\n getWrapper,\n type Handle,\n type RegisterClassVfunc as NativeRegisterClassVfunc,\n setWrapper,\n} from \"@gtkx/native\";\nimport type { AnyClass } from \"@gtkx/utils\";\nimport type { Mixin, MixinReceiver } from \"./mixin.js\";\nimport { TYPE_INVALID, type TypedClass, typeInterfaces, typeIsA, typeName, typeParent } from \"./type.js\";\n\n/**\n * Static side of class `C` with its construct signature preserved but the member\n * named `K` (default `\"new\"`) removed.\n */\nexport type StaticBase<C, K extends PropertyKey = \"new\"> = Omit<C, K> &\n (C extends new (...args: infer A) => infer R ? new (...args: A) => R : never);\n\nexport type VfuncDescriptor<K extends \"class\" | \"interface\"> = {\n kind: K;\n className: string;\n vfuncName: string;\n byteOffset: number;\n argDescriptors: NativeRegisterClassVfunc[\"argDescriptors\"];\n returnDescriptor: NativeRegisterClassVfunc[\"returnDescriptor\"];\n};\n\nexport type VfuncRegistry = Record<string, VfuncDescriptor<\"class\"> | VfuncDescriptor<\"interface\">>;\n\nconst classRegistry = new Map<bigint, AnyClass>();\nconst interfaceMixinRegistry = new Map<bigint, Mixin>();\nconst composedClassRegistry = new Map<bigint, AnyClass>();\nconst handleMap = new WeakMap<object, ExternalObject<Handle>>();\nconst vfuncRegistry = new WeakMap<object, VfuncRegistry>();\nconst interfaceVfuncRegistry = new Map<bigint, VfuncRegistry>();\n\nfunction setClassType(cls: AnyClass, type: bigint): void {\n (cls.prototype as { [K in keyof TypedClass]: TypedClass[K] }).__type__ = type;\n}\n\nexport function getClassType(cls: AnyClass): bigint {\n const proto: object = cls.prototype;\n return Object.hasOwn(proto, \"__type__\") ? (proto as TypedClass).__type__ : TYPE_INVALID;\n}\n\n/** Returns the GType tag of the given wrapper instance. */\nexport function getInstanceType(instance: object): bigint {\n return getClassType(instance.constructor as AnyClass);\n}\n\nexport function registerClassType(cls: AnyClass, type: bigint): void {\n if (type !== TYPE_INVALID) {\n classRegistry.set(type, cls);\n setClassType(cls, type);\n }\n}\n\n/**\n * Registers a wrapper class as the JS representation of a GType, optionally\n * installing a registry of virtual functions.\n * @param cls Wrapper class to associate with the type.\n * @param type GType the class wraps.\n * @param vfuncs Virtual functions the class overrides.\n */\nexport function registerWrapperClass(cls: AnyClass, type: bigint, vfuncs?: VfuncRegistry): void {\n registerClassType(cls, type);\n if (vfuncs) registerVfuncRegistry(cls, vfuncs);\n}\n\n/**\n * Registers a GInterface, associating its GType with a mixin used to compose the\n * interface onto wrapper classes and an optional virtual function registry.\n * @param cls Class carrying the interface's GType tag.\n * @param type GType of the interface.\n * @param mixin Mixin that applies the interface to a wrapper class.\n * @param vfuncs Virtual functions the interface exposes.\n */\nexport function registerInterface(cls: AnyClass, type: bigint, mixin: Mixin, vfuncs?: VfuncRegistry): void {\n if (type === TYPE_INVALID) return;\n setClassType(cls, type);\n interfaceMixinRegistry.set(type, mixin);\n if (vfuncs) registerInterfaceVfuncRegistry(type, vfuncs);\n}\n\n/**\n * Wraps a native handle in a JS wrapper instance. With no class, resolves and\n * reuses the wrapper for the handle's runtime GType (composing interface mixins);\n * with an explicit class, creates a bare instance backed by the handle. Returns\n * null for a null or undefined handle.\n * @param handle Native handle to wrap.\n * @param cls Wrapper class to instantiate, or omitted to resolve it from the runtime type.\n */\nexport function wrapHandle(handle: null | undefined, cls?: AnyClass): null;\nexport function wrapHandle<T extends object>(handle: ExternalObject<Handle>, cls: AnyClass<T>): T;\nexport function wrapHandle<T extends object>(\n handle: ExternalObject<Handle> | null | undefined,\n cls: AnyClass<T>,\n): T | null;\nexport function wrapHandle<T extends object = TypedClass>(handle: ExternalObject<Handle>, cls?: AnyClass): T;\nexport function wrapHandle<T extends object = TypedClass>(\n handle: ExternalObject<Handle> | null | undefined,\n cls?: AnyClass,\n): T | null;\nexport function wrapHandle(handle: ExternalObject<Handle> | null | undefined, cls?: AnyClass): object | null {\n if (handle === null || handle === undefined) return null;\n if (cls === undefined) {\n return getOrCreateWrapper(handle);\n }\n const instance: object = Object.create(cls.prototype);\n setHandle(instance, handle);\n return instance;\n}\n\n/**\n * Returns the wrapper class registered for a GType, walking up to ancestor types,\n * and throws if none is registered.\n */\nexport function getWrapperClass(type: bigint): AnyClass {\n const cls = resolveWrapperClass(type);\n if (!cls) {\n throw new Error(`No registered wrapper class for type '${typeName(type) ?? String(type)}'`);\n }\n return cls;\n}\n\nexport function resolveWrapperClass(type: bigint): AnyClass | null {\n let currentType = type;\n while (currentType !== TYPE_INVALID) {\n const cls = classRegistry.get(currentType);\n if (cls) return cls;\n currentType = typeParent(currentType);\n }\n return null;\n}\n\nfunction createComposedClass(base: AnyClass, runtimeType: bigint): AnyClass {\n const baseType = getClassType(base);\n const applied = new Set<bigint>();\n let cls: AnyClass = base;\n for (const type of typeInterfaces(runtimeType)) {\n if (applied.has(type) || typeIsA(baseType, type)) continue;\n const mixin = interfaceMixinRegistry.get(type);\n if (mixin === undefined) continue;\n applied.add(type);\n cls = mixin(cls as AnyClass<MixinReceiver>);\n }\n return applied.size === 0 ? base : cls;\n}\n\nfunction resolveComposedClass(runtimeType: bigint): AnyClass | null {\n const exact = classRegistry.get(runtimeType);\n if (exact) return exact;\n const cached = composedClassRegistry.get(runtimeType);\n if (cached) return cached;\n const base = resolveWrapperClass(runtimeType);\n if (base === null) return null;\n const composed = createComposedClass(base, runtimeType);\n if (composed === base) return base;\n setClassType(composed, runtimeType);\n composedClassRegistry.set(runtimeType, composed);\n return composed;\n}\n\nfunction getOrCreateWrapper(handle: ExternalObject<Handle>): object {\n const existing = getWrapper(handle);\n if (existing) return existing;\n\n const runtimeType: bigint = getType(handle);\n if (runtimeType === TYPE_INVALID) {\n throw new Error(\"Cannot resolve runtime GLib type from handle\");\n }\n\n const cls = resolveComposedClass(runtimeType);\n if (!cls) throw new Error(`Expected registered GLib type, got type ${String(runtimeType)}`);\n const instance: object = Object.create(cls.prototype);\n registerWrapper(handle, instance);\n return instance;\n}\n\n/** Returns the native handle bound to a wrapper instance, throwing if none is set. */\nexport function getHandle(instance: object): ExternalObject<Handle> {\n const handle = handleMap.get(instance);\n if (handle === undefined) {\n const name = (instance as { constructor?: { name?: string } }).constructor?.name ?? \"object\";\n throw new Error(`No native handle associated with ${name}`);\n }\n return handle;\n}\n\n/** Returns the native handle bound to an instance, or undefined when there is none or the instance is null. */\nexport function tryGetHandle(instance: object | null | undefined): ExternalObject<Handle> | undefined {\n return instance == null ? undefined : handleMap.get(instance);\n}\n\n/** Associates a native handle with a wrapper instance. */\nexport function setHandle(instance: object, handle: ExternalObject<Handle>): void {\n handleMap.set(instance, handle);\n}\n\nfunction registerWrapper(handle: ExternalObject<Handle>, instance: object): void {\n setHandle(instance, handle);\n setWrapper(handle, instance);\n}\n\nfunction registerVfuncRegistry(cls: object, registry: VfuncRegistry): void {\n vfuncRegistry.set(cls, registry);\n}\n\nexport function getVfuncRegistry(cls: object): VfuncRegistry | undefined {\n return vfuncRegistry.get(cls);\n}\n\nfunction registerInterfaceVfuncRegistry(type: bigint, registry: VfuncRegistry): void {\n if (type === TYPE_INVALID) return;\n interfaceVfuncRegistry.set(type, registry);\n}\n\nexport function getInterfaceVfuncRegistry(type: bigint): VfuncRegistry | undefined {\n return interfaceVfuncRegistry.get(type);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AACA,OAAO,EAEH,OAAO,EACP,UAAU,EAGV,UAAU,GACb,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,YAAY,EAAmB,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAqBzG,MAAM,aAAa,GAA0B,IAAI,GAAG,EAAE,CAAC;AACvD,MAAM,sBAAsB,GAAuB,IAAI,GAAG,EAAE,CAAC;AAC7D,MAAM,qBAAqB,GAA0B,IAAI,GAAG,EAAE,CAAC;AAC/D,MAAM,SAAS,GAA4C,IAAI,OAAO,EAAE,CAAC;AACzE,MAAM,aAAa,GAAmC,IAAI,OAAO,EAAE,CAAC;AACpE,MAAM,sBAAsB,GAA+B,IAAI,GAAG,EAAE,CAAC;AAErE,SAAS,YAAY,CAAC,GAAa,EAAE,IAAY;IAC5C,GAAG,CAAC,SAAwD,CAAC,QAAQ,GAAG,IAAI,CAAC;AAClF,CAAC;AAED,SAAS,YAAY,CAAC,GAAa;IAC/B,MAAM,KAAK,GAAW,GAAG,CAAC,SAAS,CAAC;IAEpC,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,CAAE,KAAoB,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC;AAC5F,CAAC;AAED,2DAA2D;AAC3D,SAAS,eAAe,CAAC,QAAgB;IACrC,OAAO,YAAY,CAAC,QAAQ,CAAC,WAAuB,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAa,EAAE,IAAY;IAClD,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;QACxB,OAAO;IACX,CAAC;IAED,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC7B,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED;;;;;;GAMG;AACH,SAAS,oBAAoB,CAAC,GAAa,EAAE,IAAY,EAAE,MAAsB;IAC7E,iBAAiB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAE7B,IAAI,MAAM,EAAE,CAAC;QACT,qBAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,iBAAiB,CAAC,GAAa,EAAE,IAAY,EAAE,KAAY,EAAE,MAAsB;IACxF,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;QACxB,OAAO;IACX,CAAC;IAED,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACxB,sBAAsB,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAExC,IAAI,MAAM,EAAE,CAAC;QACT,8BAA8B,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACjD,CAAC;AACL,CAAC;AAqBD,SAAS,UAAU,CAAC,MAAiD,EAAE,GAAc;IACjF,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QAC1C,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACpB,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,QAAQ,GAAW,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAW,CAAC;IAChE,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAE5B,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe,CAAC,IAAY;IACjC,MAAM,GAAG,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAEtC,IAAI,CAAC,GAAG,EAAE,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,yCAAyC,QAAQ,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChG,CAAC;IAED,OAAO,GAAG,CAAC;AACf,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAY;IACrC,IAAI,WAAW,GAAG,IAAI,CAAC;IAEvB,OAAO,WAAW,KAAK,YAAY,EAAE,CAAC;QAClC,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAE3C,IAAI,GAAG,EAAE,CAAC;YACN,OAAO,GAAG,CAAC;QACf,CAAC;QAED,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IAC1C,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,SAAS,mBAAmB,CAAC,GAAa,EAAE,IAAY,EAAE,QAAgB,EAAE,OAAoB;IAC5F,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC;QAC/C,OAAO,GAAG,CAAC;IACf,CAAC;IAED,MAAM,KAAK,GAAG,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAE/C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,GAAG,CAAC;IACf,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAElB,OAAO,KAAK,CAAC,GAA8B,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAc,EAAE,WAAmB;IAC5D,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,OAAO,GAAgB,IAAI,GAAG,EAAE,CAAC;IACvC,IAAI,GAAG,GAAa,IAAI,CAAC;IAEzB,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7C,GAAG,GAAG,mBAAmB,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;AAC3C,CAAC;AAED,SAAS,oBAAoB,CAAC,WAAmB;IAC7C,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAE7C,IAAI,KAAK,EAAE,CAAC;QACR,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,MAAM,MAAM,GAAG,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAEtD,IAAI,MAAM,EAAE,CAAC;QACT,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAE9C,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAExD,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,YAAY,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IACpC,qBAAqB,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAEjD,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED,SAAS,kBAAkB,CAAC,MAA8B;IACtD,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAEpC,IAAI,QAAQ,EAAE,CAAC;QACX,OAAO,QAAQ,CAAC;IACpB,CAAC;IAED,MAAM,WAAW,GAAW,OAAO,CAAC,MAAM,CAAC,CAAC;IAE5C,IAAI,WAAW,KAAK,YAAY,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,GAAG,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAE9C,IAAI,CAAC,GAAG,EAAE,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,2CAA2C,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IACtF,CAAC;IAED,MAAM,QAAQ,GAAW,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAW,CAAC;IAChE,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAElC,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED,sFAAsF;AACtF,SAAS,SAAS,CAAC,QAAgB;IAC/B,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAEvC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACvB,MAAM,IAAI,GAAI,QAAgD,CAAC,WAAW,EAAE,IAAI,IAAI,QAAQ,CAAC;QAC7F,MAAM,IAAI,KAAK,CAAC,oCAAoC,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,+GAA+G;AAC/G,SAAS,YAAY,CAAC,QAAmC;IACrD,OAAO,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAClE,CAAC;AAED,0DAA0D;AAC1D,SAAS,SAAS,CAAC,QAAgB,EAAE,MAA8B;IAC/D,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,eAAe,CAAC,MAA8B,EAAE,QAAgB;IACrE,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC5B,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,qBAAqB,CAAC,GAAW,EAAE,QAAuB;IAC/D,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAW;IACjC,OAAO,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,8BAA8B,CAAC,IAAY,EAAE,QAAuB;IACzE,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;QACxB,OAAO;IACX,CAAC;IAED,sBAAsB,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,yBAAyB,CAAC,IAAY;IAC3C,OAAO,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED,OAAO,EACH,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,mBAAmB,EACnB,SAAS,EACT,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,yBAAyB,GAI5B,CAAC","sourcesContent":["import type { AnyClass } from \"@gtkx/utils\";\nimport {\n type ExternalObject,\n getType,\n getWrapper,\n type Handle,\n type RegisterClassVfunc as NativeRegisterClassVfunc,\n setWrapper,\n} from \"@gtkx/native\";\nimport type { Mixin, MixinReceiver } from \"./mixin.js\";\nimport { TYPE_INVALID, type TypedClass, typeInterfaces, typeIsA, typeName, typeParent } from \"./type.js\";\n\n/**\n * Static side of class `C` with its construct signature preserved but the member\n * named `K` (default `\"new\"`) removed.\n */\ntype StaticBase<C, K extends PropertyKey = \"new\"> = Omit<C, K> &\n (C extends new (...args: infer A) => infer R ? new (...args: A) => R : never);\n\ntype VfuncDescriptor<K extends \"class\" | \"interface\"> = {\n kind: K;\n className: string;\n vfuncName: string;\n byteOffset: number;\n vtableSize: number;\n argDescriptors: NativeRegisterClassVfunc[\"argDescriptors\"];\n returnDescriptor: NativeRegisterClassVfunc[\"returnDescriptor\"];\n};\n\ntype VfuncRegistry = Record<string, VfuncDescriptor<\"class\"> | VfuncDescriptor<\"interface\">>;\n\nconst classRegistry: Map<bigint, AnyClass> = new Map();\nconst interfaceMixinRegistry: Map<bigint, Mixin> = new Map();\nconst composedClassRegistry: Map<bigint, AnyClass> = new Map();\nconst handleMap: WeakMap<object, ExternalObject<Handle>> = new WeakMap();\nconst vfuncRegistry: WeakMap<object, VfuncRegistry> = new WeakMap();\nconst interfaceVfuncRegistry: Map<bigint, VfuncRegistry> = new Map();\n\nfunction setClassType(cls: AnyClass, type: bigint): void {\n (cls.prototype as { [K in keyof TypedClass]: TypedClass[K] }).__type__ = type;\n}\n\nfunction getClassType(cls: AnyClass): bigint {\n const proto: object = cls.prototype;\n\n return Object.hasOwn(proto, \"__type__\") ? (proto as TypedClass).__type__ : TYPE_INVALID;\n}\n\n/** Returns the GType tag of the given wrapper instance. */\nfunction getInstanceType(instance: object): bigint {\n return getClassType(instance.constructor as AnyClass);\n}\n\nfunction registerClassType(cls: AnyClass, type: bigint): void {\n if (type === TYPE_INVALID) {\n return;\n }\n\n classRegistry.set(type, cls);\n setClassType(cls, type);\n}\n\n/**\n * Registers a wrapper class as the JS representation of a GType, optionally\n * installing a registry of virtual functions.\n * @param cls Wrapper class to associate with the type.\n * @param type GType the class wraps.\n * @param vfuncs Virtual functions the class overrides.\n */\nfunction registerWrapperClass(cls: AnyClass, type: bigint, vfuncs?: VfuncRegistry): void {\n registerClassType(cls, type);\n\n if (vfuncs) {\n registerVfuncRegistry(cls, vfuncs);\n }\n}\n\n/**\n * Registers a GInterface, associating its GType with a mixin used to compose the\n * interface onto wrapper classes and an optional virtual function registry.\n * @param cls Class carrying the interface's GType tag.\n * @param type GType of the interface.\n * @param mixin Mixin that applies the interface to a wrapper class.\n * @param vfuncs Virtual functions the interface exposes.\n */\nfunction registerInterface(cls: AnyClass, type: bigint, mixin: Mixin, vfuncs?: VfuncRegistry): void {\n if (type === TYPE_INVALID) {\n return;\n }\n\n setClassType(cls, type);\n interfaceMixinRegistry.set(type, mixin);\n\n if (vfuncs) {\n registerInterfaceVfuncRegistry(type, vfuncs);\n }\n}\n\n/**\n * Wraps a native handle in a JS wrapper instance. With no class, resolves and\n * reuses the wrapper for the handle's runtime GType (composing interface mixins);\n * with an explicit class, creates a bare instance backed by the handle. Returns\n * null for a null or undefined handle.\n * @param handle Native handle to wrap.\n * @param cls Wrapper class to instantiate, or omitted to resolve it from the runtime type.\n */\nfunction wrapHandle(handle: null | undefined, cls?: AnyClass): null;\nfunction wrapHandle<T extends object>(handle: ExternalObject<Handle>, cls: AnyClass<T>): T;\n\nfunction wrapHandle<T extends object>(\n handle: ExternalObject<Handle> | null | undefined,\n cls: AnyClass<T>,\n): T | null;\n\nfunction wrapHandle(handle: ExternalObject<Handle>, cls?: AnyClass): TypedClass;\nfunction wrapHandle(handle: ExternalObject<Handle> | null | undefined, cls?: AnyClass): TypedClass | null;\n\nfunction wrapHandle(handle: ExternalObject<Handle> | null | undefined, cls?: AnyClass): object | null {\n if (handle === null || handle === undefined) {\n return null;\n }\n\n if (cls === undefined) {\n return getOrCreateWrapper(handle);\n }\n\n const instance: object = Object.create(cls.prototype) as object;\n setHandle(instance, handle);\n\n return instance;\n}\n\n/**\n * Returns the wrapper class registered for a GType, walking up to ancestor types,\n * and throws if none is registered.\n */\nfunction getWrapperClass(type: bigint): AnyClass {\n const cls = resolveWrapperClass(type);\n\n if (!cls) {\n throw new Error(`No registered wrapper class for type '${typeName(type) ?? String(type)}'`);\n }\n\n return cls;\n}\n\nfunction resolveWrapperClass(type: bigint): AnyClass | null {\n let currentType = type;\n\n while (currentType !== TYPE_INVALID) {\n const cls = classRegistry.get(currentType);\n\n if (cls) {\n return cls;\n }\n\n currentType = typeParent(currentType);\n }\n\n return null;\n}\n\nfunction applyInterfaceMixin(cls: AnyClass, type: bigint, baseType: bigint, applied: Set<bigint>): AnyClass {\n if (applied.has(type) || typeIsA(baseType, type)) {\n return cls;\n }\n\n const mixin = interfaceMixinRegistry.get(type);\n\n if (mixin === undefined) {\n return cls;\n }\n\n applied.add(type);\n\n return mixin(cls as AnyClass<MixinReceiver>);\n}\n\nfunction createComposedClass(base: AnyClass, runtimeType: bigint): AnyClass {\n const baseType = getClassType(base);\n const applied: Set<bigint> = new Set();\n let cls: AnyClass = base;\n\n for (const type of typeInterfaces(runtimeType)) {\n cls = applyInterfaceMixin(cls, type, baseType, applied);\n }\n\n return applied.size === 0 ? base : cls;\n}\n\nfunction resolveComposedClass(runtimeType: bigint): AnyClass | null {\n const exact = classRegistry.get(runtimeType);\n\n if (exact) {\n return exact;\n }\n\n const cached = composedClassRegistry.get(runtimeType);\n\n if (cached) {\n return cached;\n }\n\n const base = resolveWrapperClass(runtimeType);\n\n if (base === null) {\n return null;\n }\n\n const composed = createComposedClass(base, runtimeType);\n\n if (composed === base) {\n return base;\n }\n\n setClassType(composed, runtimeType);\n composedClassRegistry.set(runtimeType, composed);\n\n return composed;\n}\n\nfunction getOrCreateWrapper(handle: ExternalObject<Handle>): object {\n const existing = getWrapper(handle);\n\n if (existing) {\n return existing;\n }\n\n const runtimeType: bigint = getType(handle);\n\n if (runtimeType === TYPE_INVALID) {\n throw new Error(\"Cannot resolve runtime GLib type from handle\");\n }\n\n const cls = resolveComposedClass(runtimeType);\n\n if (!cls) {\n throw new Error(`Expected registered GLib type, got type ${String(runtimeType)}`);\n }\n\n const instance: object = Object.create(cls.prototype) as object;\n registerWrapper(handle, instance);\n\n return instance;\n}\n\n/** Returns the native handle bound to a wrapper instance, throwing if none is set. */\nfunction getHandle(instance: object): ExternalObject<Handle> {\n const handle = handleMap.get(instance);\n\n if (handle === undefined) {\n const name = (instance as { constructor?: { name?: string } }).constructor?.name ?? \"object\";\n throw new Error(`No native handle associated with ${name}`);\n }\n\n return handle;\n}\n\n/** Returns the native handle bound to an instance, or undefined when there is none or the instance is null. */\nfunction tryGetHandle(instance: object | null | undefined): ExternalObject<Handle> | undefined {\n return instance == null ? undefined : handleMap.get(instance);\n}\n\n/** Associates a native handle with a wrapper instance. */\nfunction setHandle(instance: object, handle: ExternalObject<Handle>): void {\n handleMap.set(instance, handle);\n}\n\nfunction registerWrapper(handle: ExternalObject<Handle>, instance: object): void {\n setHandle(instance, handle);\n setWrapper(handle, instance);\n}\n\nfunction registerVfuncRegistry(cls: object, registry: VfuncRegistry): void {\n vfuncRegistry.set(cls, registry);\n}\n\nfunction getVfuncRegistry(cls: object): VfuncRegistry | undefined {\n return vfuncRegistry.get(cls);\n}\n\nfunction registerInterfaceVfuncRegistry(type: bigint, registry: VfuncRegistry): void {\n if (type === TYPE_INVALID) {\n return;\n }\n\n interfaceVfuncRegistry.set(type, registry);\n}\n\nfunction getInterfaceVfuncRegistry(type: bigint): VfuncRegistry | undefined {\n return interfaceVfuncRegistry.get(type);\n}\n\nexport {\n getClassType,\n getInstanceType,\n registerClassType,\n registerWrapperClass,\n registerInterface,\n wrapHandle,\n getWrapperClass,\n resolveWrapperClass,\n getHandle,\n tryGetHandle,\n setHandle,\n getVfuncRegistry,\n getInterfaceVfuncRegistry,\n type StaticBase,\n type VfuncDescriptor,\n type VfuncRegistry,\n};\n"]}
|