@gtkx/runtime 1.0.0-rc.3 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -9
- package/dist/application-class.d.ts +32 -0
- package/dist/application-class.d.ts.map +1 -0
- package/dist/application-class.js +68 -0
- package/dist/application-class.js.map +1 -0
- package/dist/arg.d.ts +9 -3
- package/dist/arg.d.ts.map +1 -1
- package/dist/arg.js +4 -3
- package/dist/arg.js.map +1 -1
- package/dist/bind.d.ts +11 -0
- package/dist/bind.d.ts.map +1 -1
- package/dist/bind.js +11 -0
- package/dist/bind.js.map +1 -1
- package/dist/callback.d.ts +2 -1
- package/dist/callback.d.ts.map +1 -1
- package/dist/callback.js +119 -21
- package/dist/callback.js.map +1 -1
- package/dist/closure.d.ts +26 -0
- package/dist/closure.d.ts.map +1 -0
- package/dist/closure.js +99 -0
- package/dist/closure.js.map +1 -0
- package/dist/descriptors.d.ts +105 -6
- package/dist/descriptors.d.ts.map +1 -1
- package/dist/descriptors.js +56 -12
- package/dist/descriptors.js.map +1 -1
- package/dist/error.d.ts +7 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +1 -1
- package/dist/error.js.map +1 -1
- package/dist/fn.d.ts +24 -3
- package/dist/fn.d.ts.map +1 -1
- package/dist/fn.js +70 -33
- package/dist/fn.js.map +1 -1
- package/dist/index.d.ts +29 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -4
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +1 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +1 -0
- package/dist/internal.js.map +1 -1
- package/dist/library.d.ts +2 -1
- package/dist/library.d.ts.map +1 -1
- package/dist/library.js +2 -1
- package/dist/library.js.map +1 -1
- package/dist/lifecycle.d.ts +52 -10
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/lifecycle.js +62 -18
- package/dist/lifecycle.js.map +1 -1
- package/dist/listeners.d.ts +6 -0
- package/dist/listeners.d.ts.map +1 -1
- package/dist/listeners.js +3 -1
- package/dist/listeners.js.map +1 -1
- package/dist/mixin.d.ts +16 -2
- package/dist/mixin.d.ts.map +1 -1
- package/dist/mixin.js +18 -6
- package/dist/mixin.js.map +1 -1
- package/dist/native-value.d.ts +8 -0
- package/dist/native-value.d.ts.map +1 -1
- package/dist/native-value.js +12 -3
- package/dist/native-value.js.map +1 -1
- package/dist/object.d.ts +34 -6
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +89 -25
- package/dist/object.js.map +1 -1
- package/dist/param-spec.d.ts +11 -0
- package/dist/param-spec.d.ts.map +1 -0
- package/dist/param-spec.js +149 -0
- package/dist/param-spec.js.map +1 -0
- package/dist/promisify.d.ts +3 -5
- package/dist/promisify.d.ts.map +1 -1
- package/dist/promisify.js +4 -3
- package/dist/promisify.js.map +1 -1
- package/dist/properties.d.ts +39 -7
- package/dist/properties.d.ts.map +1 -1
- package/dist/properties.js +305 -42
- package/dist/properties.js.map +1 -1
- package/dist/register-class.d.ts +119 -14
- package/dist/register-class.d.ts.map +1 -1
- package/dist/register-class.js +109 -80
- package/dist/register-class.js.map +1 -1
- package/dist/registry.d.ts +81 -17
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +72 -26
- package/dist/registry.js.map +1 -1
- package/dist/signal.d.ts +22 -3
- package/dist/signal.d.ts.map +1 -1
- package/dist/signal.js +64 -8
- package/dist/signal.js.map +1 -1
- package/dist/t.d.ts +44 -0
- package/dist/t.d.ts.map +1 -1
- package/dist/t.js.map +1 -1
- package/dist/type.d.ts +2 -2
- package/dist/type.d.ts.map +1 -1
- package/dist/type.js +2 -0
- package/dist/type.js.map +1 -1
- package/dist/value.d.ts +10 -10
- package/dist/value.d.ts.map +1 -1
- package/dist/value.js +44 -22
- package/dist/value.js.map +1 -1
- package/dist/vfunc-call.d.ts +37 -0
- package/dist/vfunc-call.d.ts.map +1 -0
- package/dist/vfunc-call.js +168 -0
- package/dist/vfunc-call.js.map +1 -0
- package/dist/vfunc-seeds.d.ts +12 -0
- package/dist/vfunc-seeds.d.ts.map +1 -0
- package/dist/vfunc-seeds.js +19 -0
- package/dist/vfunc-seeds.js.map +1 -0
- package/dist/vfunc.d.ts +8 -0
- package/dist/vfunc.d.ts.map +1 -0
- package/dist/vfunc.js +23 -0
- package/dist/vfunc.js.map +1 -0
- package/package.json +4 -4
- package/src/application-class.ts +116 -0
- package/src/arg.ts +11 -5
- package/src/bind.ts +11 -0
- package/src/callback.ts +163 -23
- package/src/closure.ts +136 -0
- package/src/descriptors.ts +137 -41
- package/src/error.ts +8 -1
- package/src/fn.ts +104 -39
- package/src/index.ts +36 -7
- package/src/internal.ts +1 -0
- package/src/library.ts +2 -1
- package/src/lifecycle.ts +99 -22
- package/src/listeners.ts +9 -1
- package/src/mixin.ts +27 -8
- package/src/native-value.ts +13 -3
- package/src/object.ts +128 -34
- package/src/param-spec.ts +235 -0
- package/src/promisify.ts +8 -8
- package/src/properties.ts +459 -45
- package/src/register-class.ts +329 -114
- package/src/registry.ts +150 -38
- package/src/signal.ts +101 -17
- package/src/t.ts +44 -0
- package/src/type.ts +3 -2
- package/src/value.ts +57 -19
- package/src/vfunc-call.ts +243 -0
- package/src/vfunc-seeds.ts +36 -0
- package/src/vfunc.ts +31 -0
package/src/descriptors.ts
CHANGED
|
@@ -1,97 +1,192 @@
|
|
|
1
1
|
import type { ArrayKind, Descriptor, Ownership } from "@gtkx/native";
|
|
2
2
|
import type { AnyClass } from "@gtkx/utils";
|
|
3
3
|
|
|
4
|
+
/** Descriptor variant for a `gint8`. */
|
|
4
5
|
type Int8Descriptor = Extract<Descriptor, { kind: "int8" }>;
|
|
6
|
+
/** Descriptor variant for a `guint8`. */
|
|
5
7
|
type Uint8Descriptor = Extract<Descriptor, { kind: "uint8" }>;
|
|
8
|
+
/** Descriptor variant for a `gint16`. */
|
|
6
9
|
type Int16Descriptor = Extract<Descriptor, { kind: "int16" }>;
|
|
10
|
+
/** Descriptor variant for a `guint16`. */
|
|
7
11
|
type Uint16Descriptor = Extract<Descriptor, { kind: "uint16" }>;
|
|
12
|
+
/** Descriptor variant for a `gint32`. */
|
|
8
13
|
type Int32Descriptor = Extract<Descriptor, { kind: "int32" }>;
|
|
14
|
+
/** Descriptor variant for a `guint32`. */
|
|
9
15
|
type Uint32Descriptor = Extract<Descriptor, { kind: "uint32" }>;
|
|
16
|
+
/** Descriptor variant for a `gint64` marshalled as a number. */
|
|
10
17
|
type Int64Descriptor = Extract<Descriptor, { kind: "int64" }>;
|
|
18
|
+
/** Descriptor variant for a `guint64` marshalled as a number. */
|
|
11
19
|
type Uint64Descriptor = Extract<Descriptor, { kind: "uint64" }>;
|
|
20
|
+
/** Descriptor variant for a `gint64` marshalled as a bigint. */
|
|
12
21
|
type BigInt64Descriptor = Extract<Descriptor, { kind: "bigint64" }>;
|
|
22
|
+
/** Descriptor variant for a `guint64` marshalled as a bigint. */
|
|
13
23
|
type BigUint64Descriptor = Extract<Descriptor, { kind: "biguint64" }>;
|
|
24
|
+
/** Descriptor variant for a `gfloat`. */
|
|
14
25
|
type Float32Descriptor = Extract<Descriptor, { kind: "float32" }>;
|
|
26
|
+
/** Descriptor variant for a `gdouble`. */
|
|
15
27
|
type Float64Descriptor = Extract<Descriptor, { kind: "float64" }>;
|
|
28
|
+
/** Descriptor variant for an enumeration, carrying the library and `get_type` symbol its GType comes from. */
|
|
16
29
|
type EnumDescriptor = Extract<Descriptor, { kind: "enum" }>;
|
|
30
|
+
/** Descriptor variant for a flags type, carrying the library and `get_type` symbol its GType comes from. */
|
|
17
31
|
type FlagsDescriptor = Extract<Descriptor, { kind: "flags" }>;
|
|
32
|
+
/** Descriptor variant for a `gboolean`. */
|
|
18
33
|
type BooleanDescriptor = Extract<Descriptor, { kind: "boolean" }>;
|
|
34
|
+
/** Descriptor variant for a C string. */
|
|
19
35
|
type StringDescriptor = Extract<Descriptor, { kind: "string" }>;
|
|
36
|
+
/** Descriptor variant for a `GObject`. */
|
|
20
37
|
type ObjectDescriptor = Extract<Descriptor, { kind: "object" }>;
|
|
38
|
+
/** Descriptor variant for a `gunichar`. */
|
|
21
39
|
type UnicharDescriptor = Extract<Descriptor, { kind: "unichar" }>;
|
|
40
|
+
/** Descriptor variant for the absence of a value. */
|
|
22
41
|
type VoidDescriptor = Extract<Descriptor, { kind: "void" }>;
|
|
42
|
+
/** Descriptor variant for an opaque `gpointer`. */
|
|
23
43
|
type BufferDescriptor = Extract<Descriptor, { kind: "buffer" }>;
|
|
44
|
+
/** Descriptor variant for a `GBoxed` value. */
|
|
24
45
|
type BoxedDescriptor = Extract<Descriptor, { kind: "boxed" }>;
|
|
25
|
-
|
|
26
|
-
|
|
46
|
+
|
|
47
|
+
/** Descriptor variant for a plain C struct, extended with the class its decoded value is wrapped in. */
|
|
48
|
+
type StructDescriptor = Extract<Descriptor, { kind: "struct" }> & {
|
|
49
|
+
/** Class a decoded value is wrapped in; without it the wrapper comes from the value's own GType. */
|
|
50
|
+
wrapperClass?: AnyClass;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/** Descriptor variant for a ref-counted fundamental type, extended with the class its decoded value is wrapped in. */
|
|
54
|
+
type FundamentalDescriptor = Extract<Descriptor, { kind: "fundamental" }> & {
|
|
55
|
+
/** Class a decoded value is wrapped in; without it the wrapper comes from the type named by `typeName`. */
|
|
56
|
+
wrapperClass?: AnyClass;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/** Descriptor variant for an array of items in one of the supported container layouts. */
|
|
27
60
|
type ArrayDescriptor = Extract<Descriptor, { kind: "array" }>;
|
|
61
|
+
/** Descriptor variant for a `GHashTable`, marshalled as an array of key/value pairs. */
|
|
28
62
|
type HashTableDescriptor = Extract<Descriptor, { kind: "hashtable" }>;
|
|
63
|
+
/** Descriptor variant for a function pointer a JavaScript function is marshalled into. */
|
|
29
64
|
type CallbackDescriptor = Extract<Descriptor, { kind: "callback" }>;
|
|
65
|
+
/** Descriptor variant for a pointer to another descriptor's value, for an output or inout argument. */
|
|
30
66
|
type RefDescriptor = Extract<Descriptor, { kind: "ref" }>;
|
|
31
|
-
type TypeDescriptor = BigUint64Descriptor & { type: true };
|
|
32
67
|
|
|
68
|
+
/** Descriptor for a `GType`: a `guint64` marked so it resolves to `G_TYPE_GTYPE` rather than an integer. */
|
|
69
|
+
type TypeDescriptor = BigUint64Descriptor & {
|
|
70
|
+
/** Distinguishes a GType from a plain `guint64` when the GLib type and the GValue type are resolved. */
|
|
71
|
+
type: true;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/** How a boxed value is stored, and where its GType and free function are resolved from. */
|
|
33
75
|
type BoxedOptions = {
|
|
34
|
-
|
|
35
|
-
|
|
76
|
+
/** The caller owns the storage the callee fills, so a decoded value is borrowed instead of copied. */
|
|
77
|
+
isCallerAllocated?: boolean;
|
|
78
|
+
/** The value is embedded in the containing struct rather than reached through a pointer. */
|
|
79
|
+
isInline?: boolean;
|
|
80
|
+
/** Whether a decoded value is owned by the caller; defaults to `"borrowed"`. */
|
|
36
81
|
ownership?: Ownership;
|
|
82
|
+
/** Library `getTypeFnName` and `freeFnName` are resolved in. */
|
|
37
83
|
sharedLibrary?: string;
|
|
84
|
+
/** Symbol returning the boxed GType, used when the type is not already registered under its name. */
|
|
38
85
|
getTypeFnName?: string;
|
|
86
|
+
/** Symbol that frees the value, for a boxed type with no GType of its own. */
|
|
39
87
|
freeFnName?: string;
|
|
88
|
+
/** Byte size of the value, needed to copy it into an inline field. */
|
|
40
89
|
size?: number;
|
|
41
90
|
};
|
|
42
91
|
|
|
92
|
+
/** How the callee takes a callback's closure, and how long that closure has to stay alive. */
|
|
43
93
|
type CallbackOptions = {
|
|
94
|
+
/** The callee also takes a destroy notify, which frees the closure once it is done with it. */
|
|
44
95
|
hasDestroy?: boolean;
|
|
96
|
+
/** Signature of that destroy notify; defaults to `destroyNotify`, a one-argument `GDestroyNotify`. */
|
|
97
|
+
destroyKind?: CallbackDescriptor["destroyKind"];
|
|
98
|
+
/** The callee also takes a `user_data` pointer; without one the closure can never be freed. */
|
|
99
|
+
hasUserData?: boolean;
|
|
100
|
+
/** Position of `user_data` among the callback's own arguments, dropped before the closure is called. */
|
|
45
101
|
userDataIndex?: number;
|
|
102
|
+
/** Lifetime of the closure; defaults to `notified` when `hasDestroy` is set and `call` otherwise. */
|
|
46
103
|
scope?: CallbackDescriptor["scope"];
|
|
47
104
|
};
|
|
48
105
|
|
|
106
|
+
/** The lengths and strides a C array layout needs beyond its element type. */
|
|
49
107
|
type ArrayOptions = {
|
|
108
|
+
/** Stride in bytes between elements stored inline in the array. */
|
|
50
109
|
elementSize?: number | undefined;
|
|
110
|
+
/** Position of the argument carrying the element count, for a length-bounded array. */
|
|
51
111
|
sizeParamIndex?: number | undefined;
|
|
112
|
+
/** Element count of a fixed-length array. */
|
|
52
113
|
fixedSize?: number | undefined;
|
|
53
114
|
};
|
|
54
115
|
|
|
116
|
+
/** How a ref-counted fundamental value is named, wrapped and stored. */
|
|
55
117
|
type FundamentalOptions = {
|
|
118
|
+
/** Whether a decoded value is owned by the caller; defaults to `"borrowed"`. */
|
|
56
119
|
ownership?: Ownership;
|
|
120
|
+
/** GLib type name the wrapper class is looked up by. */
|
|
57
121
|
typeName?: string;
|
|
122
|
+
/** Class a decoded value is wrapped in, instead of the one registered for `typeName`. */
|
|
58
123
|
wrapperClass?: AnyClass;
|
|
59
|
-
|
|
124
|
+
/** The value is embedded in the containing struct rather than reached through a pointer. */
|
|
125
|
+
isInline?: boolean;
|
|
60
126
|
};
|
|
61
127
|
|
|
128
|
+
/** How a plain C struct is stored and wrapped. */
|
|
62
129
|
type StructOptions = {
|
|
63
|
-
|
|
64
|
-
|
|
130
|
+
/** The caller owns the storage the callee fills, so a decoded value is borrowed instead of copied. */
|
|
131
|
+
isCallerAllocated?: boolean;
|
|
132
|
+
/** The value is embedded in the containing struct rather than reached through a pointer. */
|
|
133
|
+
isInline?: boolean;
|
|
134
|
+
/** Byte size of the struct, needed to copy it rather than borrow the pointer. */
|
|
65
135
|
size?: number;
|
|
136
|
+
/** Class a decoded value is wrapped in, instead of the one registered for its GType. */
|
|
66
137
|
wrapperClass?: AnyClass;
|
|
67
138
|
};
|
|
68
139
|
|
|
140
|
+
/** Descriptor for a `gint8`, marshalled as a number. */
|
|
69
141
|
const int8T: Int8Descriptor = { kind: "int8" };
|
|
142
|
+
/** Descriptor for a `guint8`, marshalled as a number. */
|
|
70
143
|
const uint8T: Uint8Descriptor = { kind: "uint8" };
|
|
144
|
+
/** Descriptor for a `gint16`, marshalled as a number. */
|
|
71
145
|
const int16T: Int16Descriptor = { kind: "int16" };
|
|
146
|
+
/** Descriptor for a `guint16`, marshalled as a number. */
|
|
72
147
|
const uint16T: Uint16Descriptor = { kind: "uint16" };
|
|
148
|
+
/** Descriptor for a `gint32`, marshalled as a number. */
|
|
73
149
|
const int32T: Int32Descriptor = { kind: "int32" };
|
|
150
|
+
/** Descriptor for a `guint32`, marshalled as a number. */
|
|
74
151
|
const uint32T: Uint32Descriptor = { kind: "uint32" };
|
|
152
|
+
/** Descriptor for a `gint64`, marshalled as a number and rejected outside the 2^53 safe range. */
|
|
75
153
|
const int64T: Int64Descriptor = { kind: "int64" };
|
|
154
|
+
/** Descriptor for a `guint64`, marshalled as a number and rejected outside the 2^53 safe range. */
|
|
76
155
|
const uint64T: Uint64Descriptor = { kind: "uint64" };
|
|
156
|
+
/** Descriptor for a `gint64`, marshalled as a bigint so the full 64-bit range survives. */
|
|
77
157
|
const bigint64T: BigInt64Descriptor = { kind: "bigint64" };
|
|
158
|
+
/** Descriptor for a `guint64`, marshalled as a bigint so the full 64-bit range survives. */
|
|
78
159
|
const biguint64T: BigUint64Descriptor = { kind: "biguint64" };
|
|
160
|
+
/** Descriptor for a `GType`, marshalled as a bigint and recognized as a GType by GValue conversion. */
|
|
79
161
|
const gtypeT: TypeDescriptor = { kind: "biguint64", type: true };
|
|
162
|
+
/** Descriptor for a `gfloat`. */
|
|
80
163
|
const float32T: Float32Descriptor = { kind: "float32" };
|
|
164
|
+
/** Descriptor for a `gdouble`. */
|
|
81
165
|
const float64T: Float64Descriptor = { kind: "float64" };
|
|
166
|
+
/** Descriptor for a `gboolean`, marshalled as a JavaScript boolean. */
|
|
82
167
|
const booleanT: BooleanDescriptor = { kind: "boolean" };
|
|
168
|
+
/** Descriptor for the absence of a value, used as the return descriptor of a `void` function. */
|
|
83
169
|
const voidT: VoidDescriptor = { kind: "void" };
|
|
170
|
+
/** Descriptor for a `gunichar`, marshalled as a single-character string or a codepoint number. */
|
|
84
171
|
const unicharT: UnicharDescriptor = { kind: "unichar" };
|
|
172
|
+
/** Descriptor for an opaque `gpointer`, taken from a typed array's memory or a numeric address. */
|
|
85
173
|
const bufferT: BufferDescriptor = { kind: "buffer" };
|
|
86
174
|
|
|
175
|
+
/**
|
|
176
|
+
* Builds a descriptor for a C string, whose optional length sizes the caller-allocated buffer
|
|
177
|
+
* used when the string is passed by reference.
|
|
178
|
+
*/
|
|
87
179
|
const stringT = (ownership: Ownership = "borrowed", length?: number): StringDescriptor =>
|
|
88
180
|
length === undefined ? { kind: "string", ownership } : { kind: "string", ownership, length };
|
|
89
181
|
|
|
182
|
+
/** Builds a descriptor for a `GObject`, wrapped in the class registered for its runtime GType. */
|
|
90
183
|
const objectT = (ownership: Ownership = "borrowed"): ObjectDescriptor => ({ kind: "object", ownership });
|
|
91
184
|
|
|
185
|
+
/** Wraps a descriptor in a pointer to it, for an output or inout argument. */
|
|
92
186
|
const refT = (innerDescriptor: Descriptor, isInout = false): RefDescriptor =>
|
|
93
187
|
isInout ? { kind: "ref", innerDescriptor, inout: true } : { kind: "ref", innerDescriptor };
|
|
94
188
|
|
|
189
|
+
/** Builds a descriptor for a `GHashTable`, marshalled as an array of key/value pairs. */
|
|
95
190
|
const hashTableT = (
|
|
96
191
|
keyDescriptor: Descriptor,
|
|
97
192
|
valueDescriptor: Descriptor,
|
|
@@ -103,18 +198,20 @@ const hashTableT = (
|
|
|
103
198
|
ownership,
|
|
104
199
|
});
|
|
105
200
|
|
|
201
|
+
/** Builds a descriptor for an enumeration, resolving its GType from the named `get_type` function. */
|
|
106
202
|
const enumT = (sharedLibrary: string, typeFnName: string, isSigned: boolean): EnumDescriptor => ({
|
|
107
203
|
kind: "enum",
|
|
108
204
|
sharedLibrary,
|
|
109
205
|
getTypeFnName: typeFnName,
|
|
110
|
-
|
|
206
|
+
isSigned,
|
|
111
207
|
});
|
|
112
208
|
|
|
209
|
+
/** Builds a descriptor for a flags type, resolving its GType from the named `get_type` function. */
|
|
113
210
|
const flagsT = (sharedLibrary: string, typeFnName: string, isSigned: boolean): FlagsDescriptor => ({
|
|
114
211
|
kind: "flags",
|
|
115
212
|
sharedLibrary,
|
|
116
213
|
getTypeFnName: typeFnName,
|
|
117
|
-
|
|
214
|
+
isSigned,
|
|
118
215
|
});
|
|
119
216
|
|
|
120
217
|
const applyBoxedNames = (result: BoxedDescriptor, options: BoxedOptions): void => {
|
|
@@ -134,12 +231,12 @@ const applyBoxedNames = (result: BoxedDescriptor, options: BoxedOptions): void =
|
|
|
134
231
|
const applyBoxedOptions = (result: BoxedDescriptor, options: BoxedOptions): void => {
|
|
135
232
|
applyBoxedNames(result, options);
|
|
136
233
|
|
|
137
|
-
if (options.
|
|
138
|
-
result.
|
|
234
|
+
if (options.isCallerAllocated) {
|
|
235
|
+
result.isCallerAllocated = true;
|
|
139
236
|
}
|
|
140
237
|
|
|
141
|
-
if (options.
|
|
142
|
-
result.
|
|
238
|
+
if (options.isInline) {
|
|
239
|
+
result.isInline = true;
|
|
143
240
|
}
|
|
144
241
|
|
|
145
242
|
if (options.size !== undefined) {
|
|
@@ -147,6 +244,7 @@ const applyBoxedOptions = (result: BoxedDescriptor, options: BoxedOptions): void
|
|
|
147
244
|
}
|
|
148
245
|
};
|
|
149
246
|
|
|
247
|
+
/** Builds a descriptor for a `GBoxed` value of the named type. */
|
|
150
248
|
const boxedT = (typeName: string, options: BoxedOptions = {}): BoxedDescriptor => {
|
|
151
249
|
const result: BoxedDescriptor = {
|
|
152
250
|
kind: "boxed",
|
|
@@ -159,6 +257,7 @@ const boxedT = (typeName: string, options: BoxedOptions = {}): BoxedDescriptor =
|
|
|
159
257
|
return result;
|
|
160
258
|
};
|
|
161
259
|
|
|
260
|
+
/** Builds a descriptor for a plain C struct. */
|
|
162
261
|
const structT = (ownership: Ownership = "borrowed", options: StructOptions = {}): StructDescriptor => {
|
|
163
262
|
const result: StructDescriptor = { kind: "struct", ownership };
|
|
164
263
|
|
|
@@ -170,17 +269,18 @@ const structT = (ownership: Ownership = "borrowed", options: StructOptions = {})
|
|
|
170
269
|
result.wrapperClass = options.wrapperClass;
|
|
171
270
|
}
|
|
172
271
|
|
|
173
|
-
if (options.
|
|
174
|
-
result.
|
|
272
|
+
if (options.isCallerAllocated) {
|
|
273
|
+
result.isCallerAllocated = true;
|
|
175
274
|
}
|
|
176
275
|
|
|
177
|
-
if (options.
|
|
178
|
-
result.
|
|
276
|
+
if (options.isInline) {
|
|
277
|
+
result.isInline = true;
|
|
179
278
|
}
|
|
180
279
|
|
|
181
280
|
return result;
|
|
182
281
|
};
|
|
183
282
|
|
|
283
|
+
/** Builds a descriptor for a fundamental type whose lifetime is managed by named ref and unref functions. */
|
|
184
284
|
const fundamentalT = (
|
|
185
285
|
sharedLibrary: string,
|
|
186
286
|
refFnName: string,
|
|
@@ -198,13 +298,14 @@ const fundamentalT = (
|
|
|
198
298
|
result.wrapperClass = options.wrapperClass;
|
|
199
299
|
}
|
|
200
300
|
|
|
201
|
-
if (options.
|
|
202
|
-
result.
|
|
301
|
+
if (options.isInline) {
|
|
302
|
+
result.isInline = true;
|
|
203
303
|
}
|
|
204
304
|
|
|
205
305
|
return result;
|
|
206
306
|
};
|
|
207
307
|
|
|
308
|
+
/** Builds a descriptor for an array of items in one of the supported container layouts. */
|
|
208
309
|
const arrayT = (
|
|
209
310
|
itemDescriptor: Descriptor,
|
|
210
311
|
arrayKind: ArrayKind = "array",
|
|
@@ -228,15 +329,19 @@ const arrayT = (
|
|
|
228
329
|
return result;
|
|
229
330
|
};
|
|
230
331
|
|
|
332
|
+
/** Builds a descriptor for a `GList` of items. */
|
|
231
333
|
const listT = (itemDescriptor: Descriptor, ownership: Ownership = "borrowed"): ArrayDescriptor =>
|
|
232
334
|
arrayT(itemDescriptor, "glist", ownership);
|
|
233
335
|
|
|
336
|
+
/** Builds a descriptor for a `GSList` of items. */
|
|
234
337
|
const slistT = (itemDescriptor: Descriptor, ownership: Ownership = "borrowed"): ArrayDescriptor =>
|
|
235
338
|
arrayT(itemDescriptor, "gslist", ownership);
|
|
236
339
|
|
|
340
|
+
/** Builds a descriptor for a `GPtrArray` of items. */
|
|
237
341
|
const ptrArrayT = (itemDescriptor: Descriptor, ownership: Ownership = "borrowed"): ArrayDescriptor =>
|
|
238
342
|
arrayT(itemDescriptor, "gptrarray", ownership);
|
|
239
343
|
|
|
344
|
+
/** Builds a descriptor for a `GArray` of items, optionally with an explicit element size. */
|
|
240
345
|
const gArrayT = (
|
|
241
346
|
itemDescriptor: Descriptor,
|
|
242
347
|
ownership: Ownership = "borrowed",
|
|
@@ -244,9 +349,11 @@ const gArrayT = (
|
|
|
244
349
|
): ArrayDescriptor =>
|
|
245
350
|
arrayT(itemDescriptor, "garray", ownership, elementSize === undefined ? undefined : { elementSize });
|
|
246
351
|
|
|
352
|
+
/** Builds a descriptor for a `GByteArray`. */
|
|
247
353
|
const byteArrayT = (ownership: Ownership = "borrowed"): ArrayDescriptor =>
|
|
248
354
|
arrayT(uint8T, "gbytearray", ownership);
|
|
249
355
|
|
|
356
|
+
/** Builds a descriptor for a C array whose length is carried by another argument. */
|
|
250
357
|
const sizedArrayT = (
|
|
251
358
|
itemDescriptor: Descriptor,
|
|
252
359
|
sizeParamIndex: number,
|
|
@@ -254,6 +361,7 @@ const sizedArrayT = (
|
|
|
254
361
|
elementSize?: number,
|
|
255
362
|
): ArrayDescriptor => arrayT(itemDescriptor, "sized", ownership, { sizeParamIndex, elementSize });
|
|
256
363
|
|
|
364
|
+
/** Builds a descriptor for a C array of a fixed length. */
|
|
257
365
|
const fixedArrayT = (
|
|
258
366
|
itemDescriptor: Descriptor,
|
|
259
367
|
fixedSize: number,
|
|
@@ -261,6 +369,7 @@ const fixedArrayT = (
|
|
|
261
369
|
elementSize?: number,
|
|
262
370
|
): ArrayDescriptor => arrayT(itemDescriptor, "fixed", ownership, { fixedSize, elementSize });
|
|
263
371
|
|
|
372
|
+
/** Builds a descriptor for a function pointer, marshalling a JavaScript function into a native closure. */
|
|
264
373
|
const callbackT = (
|
|
265
374
|
argDescriptors: Descriptor[],
|
|
266
375
|
returnDescriptor: Descriptor,
|
|
@@ -272,6 +381,14 @@ const callbackT = (
|
|
|
272
381
|
result.hasDestroy = options.hasDestroy;
|
|
273
382
|
}
|
|
274
383
|
|
|
384
|
+
if (options?.destroyKind !== undefined) {
|
|
385
|
+
result.destroyKind = options.destroyKind;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
if (options?.hasUserData !== undefined) {
|
|
389
|
+
result.hasUserData = options.hasUserData;
|
|
390
|
+
}
|
|
391
|
+
|
|
275
392
|
if (options?.userDataIndex !== undefined) {
|
|
276
393
|
result.userDataIndex = options.userDataIndex;
|
|
277
394
|
}
|
|
@@ -319,26 +436,6 @@ export {
|
|
|
319
436
|
sizedArrayT,
|
|
320
437
|
fixedArrayT,
|
|
321
438
|
callbackT,
|
|
322
|
-
type Int8Descriptor,
|
|
323
|
-
type Uint8Descriptor,
|
|
324
|
-
type Int16Descriptor,
|
|
325
|
-
type Uint16Descriptor,
|
|
326
|
-
type Int32Descriptor,
|
|
327
|
-
type Uint32Descriptor,
|
|
328
|
-
type Int64Descriptor,
|
|
329
|
-
type Uint64Descriptor,
|
|
330
|
-
type BigInt64Descriptor,
|
|
331
|
-
type BigUint64Descriptor,
|
|
332
|
-
type Float32Descriptor,
|
|
333
|
-
type Float64Descriptor,
|
|
334
|
-
type EnumDescriptor,
|
|
335
|
-
type FlagsDescriptor,
|
|
336
|
-
type BooleanDescriptor,
|
|
337
|
-
type StringDescriptor,
|
|
338
|
-
type ObjectDescriptor,
|
|
339
|
-
type UnicharDescriptor,
|
|
340
|
-
type VoidDescriptor,
|
|
341
|
-
type BufferDescriptor,
|
|
342
439
|
type BoxedDescriptor,
|
|
343
440
|
type StructDescriptor,
|
|
344
441
|
type FundamentalDescriptor,
|
|
@@ -346,5 +443,4 @@ export {
|
|
|
346
443
|
type HashTableDescriptor,
|
|
347
444
|
type CallbackDescriptor,
|
|
348
445
|
type RefDescriptor,
|
|
349
|
-
type TypeDescriptor,
|
|
350
446
|
};
|
package/src/error.ts
CHANGED
|
@@ -2,8 +2,14 @@ import type { ExternalObject, Handle, Ref } from "@gtkx/native";
|
|
|
2
2
|
import { getWrapperClass, wrapHandle } from "./registry.js";
|
|
3
3
|
import { getErrorType, isTypedClass } from "./type.js";
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* A wrapped `GError` thrown across the FFI boundary: a JavaScript `Error` that also identifies its
|
|
7
|
+
* GLib domain and code.
|
|
8
|
+
*/
|
|
5
9
|
type ErrorLike = Error & {
|
|
10
|
+
/** Quark of the error domain the code belongs to. */
|
|
6
11
|
domain: number;
|
|
12
|
+
/** Error code, meaningful only within `ErrorLike.domain`. */
|
|
7
13
|
code: number;
|
|
8
14
|
};
|
|
9
15
|
|
|
@@ -12,6 +18,7 @@ type ErrorLike = Error & {
|
|
|
12
18
|
* matches wrapped GLib errors belonging to a specific error domain.
|
|
13
19
|
*/
|
|
14
20
|
type ErrorDomain<T extends Record<string, number>> = T & {
|
|
21
|
+
/** Backs `instanceof`, matching a wrapped GLib error whose domain is this one. */
|
|
15
22
|
[Symbol.hasInstance]: (value: unknown) => value is ErrorLike;
|
|
16
23
|
};
|
|
17
24
|
|
|
@@ -21,7 +28,7 @@ function checkError(error: Ref): void {
|
|
|
21
28
|
}
|
|
22
29
|
|
|
23
30
|
const gerror = wrapHandle(error.value as ExternalObject<Handle>, getWrapperClass(getErrorType())) as ErrorLike;
|
|
24
|
-
const callSite = new Error("
|
|
31
|
+
const callSite = new Error("GTKX call site");
|
|
25
32
|
const callerFrames = (callSite.stack ?? "").split("\n").slice(2);
|
|
26
33
|
gerror.stack = [`${gerror.name}: ${gerror.message}`, ...callerFrames].join("\n");
|
|
27
34
|
throw gerror;
|
package/src/fn.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { Descriptor, Ref } from "@gtkx/native";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import type { CallDescriptor, Descriptor, ExternalObject, Ref } from "@gtkx/native";
|
|
2
|
+
import { call, bind as nativeBind } from "@gtkx/native";
|
|
3
|
+
import type { RefSeeds } from "./vfunc-seeds.js";
|
|
4
|
+
import { type Arg, isCallerAllocatedArg, isOutputArg, isRefArg, requiresInputArg } from "./arg.js";
|
|
4
5
|
import { wrapCallbackValue } from "./callback.js";
|
|
5
6
|
import { boxedT, refT } from "./descriptors.js";
|
|
6
7
|
import { checkError } from "./error.js";
|
|
@@ -9,24 +10,37 @@ import { fromNative } from "./native-value.js";
|
|
|
9
10
|
import { getHandle } from "./registry.js";
|
|
10
11
|
import { packTupleResult } from "./tuple.js";
|
|
11
12
|
|
|
13
|
+
/** The signature a native function is bound against. */
|
|
12
14
|
type FnSpec = {
|
|
15
|
+
/** The C arguments in declaration order, including the ones the callee writes into. */
|
|
13
16
|
args: Arg[];
|
|
17
|
+
/** Descriptor for the C return value, packed first when output arguments are also returned. */
|
|
14
18
|
returns: Descriptor;
|
|
15
|
-
|
|
19
|
+
/** The function takes a trailing `GError**`, whose contents are thrown as an error on return. */
|
|
20
|
+
canThrow?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* How many of `args` precede the callee's ellipsis, marking it variadic. Omitting it binds a
|
|
23
|
+
* fixed-arity call, which passes the wrong argument classes to a variadic callee on some
|
|
24
|
+
* architectures.
|
|
25
|
+
*/
|
|
26
|
+
fixedArgCount?: number;
|
|
16
27
|
};
|
|
17
28
|
|
|
18
29
|
type ArgSpec = {
|
|
19
30
|
arg: Arg;
|
|
31
|
+
index: number;
|
|
20
32
|
isRef: boolean;
|
|
21
33
|
isCallerAllocated: boolean;
|
|
22
|
-
|
|
34
|
+
requiresInput: boolean;
|
|
23
35
|
inputIndex: number;
|
|
24
36
|
isOutParam: boolean;
|
|
25
37
|
};
|
|
26
38
|
|
|
39
|
+
const NO_OUT_PARAMS: unknown[] = [];
|
|
40
|
+
|
|
27
41
|
const buildNativeArgTypes = (args: Arg[], canThrow: boolean): Descriptor[] => {
|
|
28
42
|
const nativeArgTypes = args.map((argSpec) =>
|
|
29
|
-
argSpec.direction !== undefined && argSpec.
|
|
43
|
+
argSpec.direction !== undefined && argSpec.isCallerAllocated !== true ? refT(argSpec.type) : argSpec.type,
|
|
30
44
|
);
|
|
31
45
|
|
|
32
46
|
if (canThrow) {
|
|
@@ -41,17 +55,18 @@ const buildNativeArgTypes = (args: Arg[], canThrow: boolean): Descriptor[] => {
|
|
|
41
55
|
const buildArgSpecs = (args: Arg[]): ArgSpec[] => {
|
|
42
56
|
let inputCursor = 0;
|
|
43
57
|
|
|
44
|
-
return args.map((arg) => {
|
|
58
|
+
return args.map((arg, index) => {
|
|
45
59
|
const isRef = isRefArg(arg);
|
|
46
|
-
const
|
|
47
|
-
const isOutParam = isOutputArg(arg) && arg.
|
|
60
|
+
const requiresInput = requiresInputArg(arg);
|
|
61
|
+
const isOutParam = isOutputArg(arg) && arg.isConsumed !== true;
|
|
48
62
|
|
|
49
63
|
return {
|
|
50
64
|
arg,
|
|
65
|
+
index,
|
|
51
66
|
isRef,
|
|
52
67
|
isCallerAllocated: isCallerAllocatedArg(arg),
|
|
53
|
-
|
|
54
|
-
inputIndex:
|
|
68
|
+
requiresInput,
|
|
69
|
+
inputIndex: requiresInput ? inputCursor++ : -1,
|
|
55
70
|
isOutParam,
|
|
56
71
|
};
|
|
57
72
|
});
|
|
@@ -63,19 +78,19 @@ const resolveCallerAllocated = (inputs: unknown[], inputIndex: number): unknown
|
|
|
63
78
|
return wrapper == null ? wrapper : getHandle(wrapper);
|
|
64
79
|
};
|
|
65
80
|
|
|
66
|
-
const buildRefValue = (
|
|
67
|
-
value:
|
|
81
|
+
const buildRefValue = (spec: ArgSpec, inputs: unknown[], seeds: RefSeeds | undefined): Ref => ({
|
|
82
|
+
value: spec.requiresInput ? inputs[spec.inputIndex] : (seeds?.get(spec.index) ?? null),
|
|
68
83
|
});
|
|
69
84
|
|
|
70
|
-
const buildNativeValue = (spec: ArgSpec, inputs: unknown[]): unknown => {
|
|
71
|
-
const { arg, isRef, isCallerAllocated,
|
|
85
|
+
const buildNativeValue = (spec: ArgSpec, inputs: unknown[], seeds: RefSeeds | undefined): unknown => {
|
|
86
|
+
const { arg, isRef, isCallerAllocated, inputIndex } = spec;
|
|
72
87
|
|
|
73
88
|
if (isCallerAllocated) {
|
|
74
89
|
return resolveCallerAllocated(inputs, inputIndex);
|
|
75
90
|
}
|
|
76
91
|
|
|
77
92
|
if (isRef) {
|
|
78
|
-
return buildRefValue(
|
|
93
|
+
return buildRefValue(spec, inputs, seeds);
|
|
79
94
|
}
|
|
80
95
|
|
|
81
96
|
if (arg.type.kind === "callback") {
|
|
@@ -85,44 +100,79 @@ const buildNativeValue = (spec: ArgSpec, inputs: unknown[]): unknown => {
|
|
|
85
100
|
return inputs[inputIndex];
|
|
86
101
|
};
|
|
87
102
|
|
|
88
|
-
const buildNativeValues = (plans: ArgSpec[], inputs: unknown[]): unknown[] =>
|
|
89
|
-
plans.map((plan) => buildNativeValue(plan, inputs));
|
|
103
|
+
const buildNativeValues = (plans: ArgSpec[], inputs: unknown[], seeds: RefSeeds | undefined): unknown[] =>
|
|
104
|
+
plans.map((plan) => buildNativeValue(plan, inputs, seeds));
|
|
105
|
+
|
|
106
|
+
const readOutParams = (outPlans: ArgSpec[], inputs: unknown[], nativeValues: unknown[]): unknown[] => {
|
|
107
|
+
if (outPlans.length === 0) {
|
|
108
|
+
return NO_OUT_PARAMS;
|
|
109
|
+
}
|
|
90
110
|
|
|
91
|
-
|
|
92
|
-
|
|
111
|
+
return Array.from(outPlans, (plan) =>
|
|
112
|
+
plan.isCallerAllocated
|
|
113
|
+
? inputs[plan.inputIndex]
|
|
114
|
+
: fromNative(plan.arg.type, (nativeValues[plan.index] as Ref).value));
|
|
115
|
+
};
|
|
93
116
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
117
|
+
const isPassThroughPlan = (plan: ArgSpec, index: number): boolean =>
|
|
118
|
+
plan.inputIndex === index &&
|
|
119
|
+
!plan.isRef &&
|
|
120
|
+
!plan.isCallerAllocated &&
|
|
121
|
+
plan.arg.type.kind !== "callback";
|
|
98
122
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
);
|
|
123
|
+
const resizeInputs = (inputs: unknown[], argCount: number): unknown[] => {
|
|
124
|
+
while (inputs.length < argCount) {
|
|
125
|
+
inputs.push(undefined);
|
|
102
126
|
}
|
|
103
127
|
|
|
104
|
-
|
|
128
|
+
if (inputs.length > argCount) {
|
|
129
|
+
inputs.length = argCount;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return inputs;
|
|
105
133
|
};
|
|
106
134
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
135
|
+
const directCallable = (
|
|
136
|
+
descriptor: ExternalObject<CallDescriptor>,
|
|
137
|
+
returnDescriptor: Descriptor,
|
|
138
|
+
argCount: number,
|
|
139
|
+
): ((...inputs: unknown[]) => unknown) => {
|
|
140
|
+
if (returnDescriptor.kind === "void") {
|
|
141
|
+
return (...inputs) => {
|
|
142
|
+
call(descriptor, resizeInputs(inputs, argCount));
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return (...inputs) => fromNative(returnDescriptor, call(descriptor, resizeInputs(inputs, argCount)));
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
function fromNativeCallable(
|
|
150
|
+
descriptor: ExternalObject<CallDescriptor>,
|
|
151
|
+
spec: FnSpec,
|
|
152
|
+
getRefSeeds?: () => RefSeeds | undefined,
|
|
153
|
+
): (...inputs: unknown[]) => unknown {
|
|
154
|
+
const { args, returns: returnDescriptor, canThrow = false } = spec;
|
|
111
155
|
const hasPrimary = returnDescriptor.kind !== "void";
|
|
112
156
|
const plans = buildArgSpecs(args);
|
|
157
|
+
const outPlans = plans.filter((plan) => plan.isOutParam);
|
|
158
|
+
const arePassThrough = plans.every((plan, index) => isPassThroughPlan(plan, index));
|
|
159
|
+
|
|
160
|
+
if (!canThrow && arePassThrough) {
|
|
161
|
+
return directCallable(descriptor, returnDescriptor, plans.length);
|
|
162
|
+
}
|
|
113
163
|
|
|
114
164
|
const shape = (inputs: unknown[], nativeValues: unknown[], nativeResult: unknown): unknown => {
|
|
115
165
|
const primary = hasPrimary ? fromNative(returnDescriptor, nativeResult) : undefined;
|
|
116
166
|
|
|
117
|
-
return packTupleResult(readOutParams(
|
|
167
|
+
return packTupleResult(readOutParams(outPlans, inputs, nativeValues), primary, hasPrimary);
|
|
118
168
|
};
|
|
119
169
|
|
|
120
|
-
if (
|
|
170
|
+
if (canThrow) {
|
|
121
171
|
return (...inputs) => {
|
|
122
|
-
const nativeValues = buildNativeValues(plans, inputs);
|
|
172
|
+
const nativeValues = buildNativeValues(plans, inputs, getRefSeeds?.());
|
|
123
173
|
const errorRef: Ref = { value: null };
|
|
124
174
|
nativeValues.push(errorRef);
|
|
125
|
-
const nativeResult =
|
|
175
|
+
const nativeResult = call(descriptor, nativeValues);
|
|
126
176
|
checkError(errorRef);
|
|
127
177
|
|
|
128
178
|
return shape(inputs, nativeValues, nativeResult);
|
|
@@ -130,10 +180,25 @@ function fn(sharedLibrary: string, symbol: string, spec: FnSpec): (...inputs: un
|
|
|
130
180
|
}
|
|
131
181
|
|
|
132
182
|
return (...inputs) => {
|
|
133
|
-
const nativeValues = buildNativeValues(plans, inputs);
|
|
183
|
+
const nativeValues = buildNativeValues(plans, inputs, getRefSeeds?.());
|
|
134
184
|
|
|
135
|
-
return shape(inputs, nativeValues,
|
|
185
|
+
return shape(inputs, nativeValues, call(descriptor, nativeValues));
|
|
136
186
|
};
|
|
137
187
|
}
|
|
138
188
|
|
|
139
|
-
|
|
189
|
+
/**
|
|
190
|
+
* Binds a symbol in a shared library to a callable that marshals its inputs and packs output
|
|
191
|
+
* arguments into the result. When the spec sets `canThrow`, the reported `GError` is thrown.
|
|
192
|
+
*
|
|
193
|
+
* @param sharedLibrary Shared library the symbol is looked up in.
|
|
194
|
+
* @param symbol Name of the C symbol to bind.
|
|
195
|
+
* @param spec Argument and return descriptors the call is marshalled through.
|
|
196
|
+
*/
|
|
197
|
+
function fn(sharedLibrary: string, symbol: string, spec: FnSpec): (...inputs: unknown[]) => unknown {
|
|
198
|
+
const nativeArgTypes = buildNativeArgTypes(spec.args, spec.canThrow ?? false);
|
|
199
|
+
const descriptor = nativeBind(sharedLibrary, symbol, nativeArgTypes, spec.returns, spec.fixedArgCount);
|
|
200
|
+
|
|
201
|
+
return fromNativeCallable(descriptor, spec);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export { buildNativeArgTypes, fn, fromNativeCallable };
|