@gtkx/runtime 0.0.1 → 1.0.0-rc.1

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.
Files changed (113) hide show
  1. package/LICENSE +373 -0
  2. package/README.md +171 -3
  3. package/dist/arg.d.ts +12 -0
  4. package/dist/arg.d.ts.map +1 -0
  5. package/dist/arg.js +5 -0
  6. package/dist/arg.js.map +1 -0
  7. package/dist/bind.d.ts +4 -0
  8. package/dist/bind.d.ts.map +1 -0
  9. package/dist/bind.js +17 -0
  10. package/dist/bind.js.map +1 -0
  11. package/dist/callback.d.ts +13 -0
  12. package/dist/callback.d.ts.map +1 -0
  13. package/dist/callback.js +68 -0
  14. package/dist/callback.js.map +1 -0
  15. package/dist/descriptors.d.ts +155 -0
  16. package/dist/descriptors.d.ts.map +1 -0
  17. package/dist/descriptors.js +103 -0
  18. package/dist/descriptors.js.map +1 -0
  19. package/dist/error.d.ts +25 -0
  20. package/dist/error.d.ts.map +1 -0
  21. package/dist/error.js +29 -0
  22. package/dist/error.js.map +1 -0
  23. package/dist/fn.d.ts +10 -0
  24. package/dist/fn.d.ts.map +1 -0
  25. package/dist/fn.js +79 -0
  26. package/dist/fn.js.map +1 -0
  27. package/dist/index.d.ts +15 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +15 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/internal.d.ts +5 -0
  32. package/dist/internal.d.ts.map +1 -0
  33. package/dist/internal.js +5 -0
  34. package/dist/internal.js.map +1 -0
  35. package/dist/library.d.ts +7 -0
  36. package/dist/library.d.ts.map +1 -0
  37. package/dist/library.js +13 -0
  38. package/dist/library.js.map +1 -0
  39. package/dist/lifecycle.d.ts +41 -0
  40. package/dist/lifecycle.d.ts.map +1 -0
  41. package/dist/lifecycle.js +55 -0
  42. package/dist/lifecycle.js.map +1 -0
  43. package/dist/listeners.d.ts +36 -0
  44. package/dist/listeners.d.ts.map +1 -0
  45. package/dist/listeners.js +72 -0
  46. package/dist/listeners.js.map +1 -0
  47. package/dist/mixin.d.ts +19 -0
  48. package/dist/mixin.d.ts.map +1 -0
  49. package/dist/mixin.js +39 -0
  50. package/dist/mixin.js.map +1 -0
  51. package/dist/native-value.d.ts +12 -0
  52. package/dist/native-value.d.ts.map +1 -0
  53. package/dist/native-value.js +72 -0
  54. package/dist/native-value.js.map +1 -0
  55. package/dist/object.d.ts +31 -0
  56. package/dist/object.d.ts.map +1 -0
  57. package/dist/object.js +63 -0
  58. package/dist/object.js.map +1 -0
  59. package/dist/promisify.d.ts +13 -0
  60. package/dist/promisify.d.ts.map +1 -0
  61. package/dist/promisify.js +36 -0
  62. package/dist/promisify.js.map +1 -0
  63. package/dist/register-class.d.ts +17 -0
  64. package/dist/register-class.d.ts.map +1 -0
  65. package/dist/register-class.js +124 -0
  66. package/dist/register-class.js.map +1 -0
  67. package/dist/registry.d.ts +67 -0
  68. package/dist/registry.d.ts.map +1 -0
  69. package/dist/registry.js +167 -0
  70. package/dist/registry.js.map +1 -0
  71. package/dist/signal.d.ts +34 -0
  72. package/dist/signal.d.ts.map +1 -0
  73. package/dist/signal.js +88 -0
  74. package/dist/signal.js.map +1 -0
  75. package/dist/t.d.ts +50 -0
  76. package/dist/t.d.ts.map +1 -0
  77. package/dist/t.js +48 -0
  78. package/dist/t.js.map +1 -0
  79. package/dist/tuple.d.ts +6 -0
  80. package/dist/tuple.d.ts.map +1 -0
  81. package/dist/tuple.js +23 -0
  82. package/dist/tuple.js.map +1 -0
  83. package/dist/type.d.ts +81 -0
  84. package/dist/type.d.ts.map +1 -0
  85. package/dist/type.js +174 -0
  86. package/dist/type.js.map +1 -0
  87. package/dist/value.d.ts +20 -0
  88. package/dist/value.d.ts.map +1 -0
  89. package/dist/value.js +227 -0
  90. package/dist/value.js.map +1 -0
  91. package/package.json +56 -13
  92. package/src/arg.ts +13 -0
  93. package/src/bind.ts +22 -0
  94. package/src/callback.ts +87 -0
  95. package/src/descriptors.ts +208 -0
  96. package/src/error.ts +49 -0
  97. package/src/fn.ts +108 -0
  98. package/src/index.ts +57 -0
  99. package/src/internal.ts +12 -0
  100. package/src/library.ts +15 -0
  101. package/src/lifecycle.ts +73 -0
  102. package/src/listeners.ts +84 -0
  103. package/src/mixin.ts +48 -0
  104. package/src/native-value.ts +78 -0
  105. package/src/object.ts +83 -0
  106. package/src/promisify.ts +40 -0
  107. package/src/register-class.ts +178 -0
  108. package/src/registry.ts +221 -0
  109. package/src/signal.ts +152 -0
  110. package/src/t.ts +88 -0
  111. package/src/tuple.ts +25 -0
  112. package/src/type.ts +200 -0
  113. package/src/value.ts +307 -0
package/src/value.ts ADDED
@@ -0,0 +1,307 @@
1
+ import { alloc, type Descriptor, type ExternalObject, getType, type Handle, read, write } from "@gtkx/native";
2
+ import { bind, createBindCache } from "./bind.js";
3
+ import {
4
+ arrayT,
5
+ bigint64T,
6
+ biguint64T,
7
+ booleanT,
8
+ boxedT,
9
+ float32T,
10
+ float64T,
11
+ int32T,
12
+ objectT,
13
+ stringT,
14
+ uint32T,
15
+ uint64T,
16
+ voidT,
17
+ } from "./descriptors.js";
18
+ import { LIB, PARAM_T, VALUE_SIZE, VALUE_T, VARIANT_T } from "./library.js";
19
+ import { toNative } from "./native-value.js";
20
+ import { getHandle, getWrapperClass, wrapHandle } from "./registry.js";
21
+ import {
22
+ getStrvType,
23
+ resolveBoxedType,
24
+ resolveDescriptorType,
25
+ resolveFundamentalType,
26
+ resolveType,
27
+ TYPE_BOOLEAN,
28
+ TYPE_BOXED,
29
+ TYPE_DOUBLE,
30
+ TYPE_ENUM,
31
+ TYPE_FLAGS,
32
+ TYPE_FLOAT,
33
+ TYPE_GTYPE,
34
+ TYPE_INT,
35
+ TYPE_INT64,
36
+ TYPE_INVALID,
37
+ TYPE_OBJECT,
38
+ TYPE_PARAM,
39
+ TYPE_POINTER,
40
+ TYPE_STRING,
41
+ TYPE_UINT,
42
+ TYPE_UINT64,
43
+ TYPE_VARIANT,
44
+ typeFundamental,
45
+ typeName,
46
+ } from "./type.js";
47
+
48
+ type ValueType = {
49
+ set: (value: ExternalObject<Handle>, nativeValue: unknown) => void;
50
+ get: (value: ExternalObject<Handle>) => unknown;
51
+ };
52
+
53
+ const getBoxedTypeName = (type: bigint): string => typeName(type) ?? "GBoxed";
54
+ const newValue = (): ExternalObject<Handle> => alloc(VALUE_SIZE, "GValue");
55
+
56
+ const setBoxedCache = createBindCache();
57
+ const setStaticBoxedCache = createBindCache();
58
+ const dupBoxedCache = createBindCache();
59
+
60
+ const gValueInit = bind(LIB, "g_value_init", [VALUE_T, biguint64T], voidT);
61
+ const gValueCopy = bind(LIB, "g_value_copy", [VALUE_T, VALUE_T], voidT);
62
+
63
+ const bindValueType = (symbol: string, descriptor: Descriptor): ValueType => ({
64
+ set: bind(LIB, `g_value_set_${symbol}`, [VALUE_T, descriptor], voidT),
65
+ get: bind(LIB, `g_value_get_${symbol}`, [VALUE_T], descriptor),
66
+ });
67
+
68
+ const setBoxedBind = (name: string) =>
69
+ setBoxedCache(name, LIB, "g_value_set_boxed", [VALUE_T, boxedT(name, { sharedLibrary: LIB })], voidT);
70
+
71
+ const setStaticBoxedBind = (name: string) =>
72
+ setStaticBoxedCache(name, LIB, "g_value_set_static_boxed", [VALUE_T, boxedT(name, { sharedLibrary: LIB })], voidT);
73
+
74
+ const dupBoxedBind = (name: string) =>
75
+ dupBoxedCache(name, LIB, "g_value_dup_boxed", [VALUE_T], boxedT(name, { ownership: "full", sharedLibrary: LIB }));
76
+
77
+ const booleanValueType = bindValueType("boolean", booleanT);
78
+ const typeValueType = bindValueType("gtype", biguint64T);
79
+ const intValueType = bindValueType("int", int32T);
80
+ const uintValueType = bindValueType("uint", uint32T);
81
+ const int64ValueType = bindValueType("int64", bigint64T);
82
+ const uint64ValueType = bindValueType("uint64", biguint64T);
83
+ const floatValueType = bindValueType("float", float32T);
84
+ const doubleValueType = bindValueType("double", float64T);
85
+ const stringValueType = bindValueType("string", stringT("borrowed"));
86
+ const enumValueType = bindValueType("enum", int32T);
87
+ const flagsValueType = bindValueType("flags", uint32T);
88
+ const objectValueType = bindValueType("object", objectT("borrowed"));
89
+ const paramValueType = bindValueType("param", PARAM_T);
90
+ const variantValueType = bindValueType("variant", VARIANT_T);
91
+ const pointerValueType = bindValueType("pointer", uint64T);
92
+
93
+ const strvValueType: ValueType = {
94
+ set: bind(LIB, "g_value_set_boxed", [VALUE_T, arrayT(stringT("borrowed"))], voidT),
95
+ get: bind(LIB, "g_value_get_boxed", [VALUE_T], arrayT(stringT("borrowed"))),
96
+ };
97
+
98
+ const boxedValueType = (type: bigint): ValueType => {
99
+ const name = getBoxedTypeName(type);
100
+ return { set: setBoxedBind(name), get: dupBoxedBind(name) };
101
+ };
102
+
103
+ const enumOrFlagsValueType = (type: bigint): ValueType =>
104
+ typeFundamental(type) === TYPE_FLAGS ? flagsValueType : enumValueType;
105
+
106
+ const fundamentalValueType = (type: bigint): ValueType => {
107
+ switch (typeFundamental(type)) {
108
+ case TYPE_PARAM:
109
+ return paramValueType;
110
+ case TYPE_VARIANT:
111
+ return variantValueType;
112
+ case TYPE_BOXED:
113
+ return boxedValueType(type);
114
+ default:
115
+ throw new Error(`Unsupported fundamental type '${typeName(type) ?? String(type)}' for value`);
116
+ }
117
+ };
118
+
119
+ export function getValueType(value: ExternalObject<Handle>): bigint {
120
+ return read(value, biguint64T, 0) as bigint;
121
+ }
122
+
123
+ export function copyValue(dest: ExternalObject<Handle>, src: ExternalObject<Handle>): void {
124
+ if (getValueType(dest) === TYPE_INVALID) {
125
+ gValueInit(dest, getValueType(src));
126
+ }
127
+ gValueCopy(src, dest);
128
+ }
129
+
130
+ const newTypedValue = (type: bigint): ExternalObject<Handle> => {
131
+ const value = newValue();
132
+ gValueInit(value, type);
133
+ return value;
134
+ };
135
+
136
+ const newBoxedValue = (
137
+ descriptor: Descriptor,
138
+ boxed: object,
139
+ resolveSetBind: (name: string) => ValueType["set"],
140
+ ): ExternalObject<Handle> => {
141
+ const type = resolveDescriptorType(descriptor);
142
+ const value = newTypedValue(type);
143
+ resolveSetBind(getBoxedTypeName(type))(value, getHandle(boxed));
144
+ return value;
145
+ };
146
+
147
+ /**
148
+ * Reads the boxed pointer out of a GValue and returns it wrapped in its registered
149
+ * class, or null when the value does not hold a boxed type.
150
+ */
151
+ export function getBoxedValue(value: ExternalObject<Handle>): object | null {
152
+ const type = getValueType(value);
153
+ if (typeFundamental(type) !== TYPE_BOXED) return null;
154
+ const cls = getWrapperClass(type);
155
+ const boxed = dupBoxedBind(getBoxedTypeName(type))(value) as ExternalObject<Handle> | null;
156
+ return wrapHandle(boxed, cls);
157
+ }
158
+
159
+ /** Stores a boxed object, or null, into a GValue that holds a boxed type. */
160
+ export function setBoxedValue(value: ExternalObject<Handle>, boxed: object | null): void {
161
+ const name = getBoxedTypeName(getValueType(value));
162
+ setBoxedBind(name)(value, boxed === null ? null : getHandle(boxed));
163
+ }
164
+
165
+ const resolveValueType = (descriptor: Descriptor): ValueType => {
166
+ if (descriptor.kind === "biguint64" && "type" in descriptor) {
167
+ return typeValueType;
168
+ }
169
+ switch (descriptor.kind) {
170
+ case "boolean":
171
+ return booleanValueType;
172
+ case "string":
173
+ return stringValueType;
174
+ case "int8":
175
+ case "int16":
176
+ case "int32":
177
+ return intValueType;
178
+ case "uint8":
179
+ case "uint16":
180
+ case "uint32":
181
+ return uintValueType;
182
+ case "int64":
183
+ case "bigint64":
184
+ return int64ValueType;
185
+ case "uint64":
186
+ case "biguint64":
187
+ return uint64ValueType;
188
+ case "float32":
189
+ return floatValueType;
190
+ case "float64":
191
+ return doubleValueType;
192
+ case "object":
193
+ return objectValueType;
194
+ case "enum":
195
+ case "flags":
196
+ return enumOrFlagsValueType(resolveType(descriptor.sharedLibrary, descriptor.getTypeFnName));
197
+ case "boxed":
198
+ return boxedValueType(resolveBoxedType(descriptor));
199
+ case "fundamental":
200
+ return fundamentalValueType(resolveFundamentalType(descriptor));
201
+ case "array":
202
+ if (descriptor.itemDescriptor.kind === "string" && descriptor.arrayKind === "array") {
203
+ return strvValueType;
204
+ }
205
+ throw new Error(`Unsupported array type ${descriptor.arrayKind} of ${descriptor.itemDescriptor.kind}`);
206
+ default:
207
+ throw new Error(`Unsupported type descriptor '${descriptor.kind}'`);
208
+ }
209
+ };
210
+
211
+ const resolveValueGetter = (fundamental: bigint): ((value: ExternalObject<Handle>) => unknown) | undefined => {
212
+ switch (fundamental) {
213
+ case TYPE_BOOLEAN:
214
+ return booleanValueType.get;
215
+ case TYPE_GTYPE:
216
+ return typeValueType.get;
217
+ case TYPE_INT:
218
+ return intValueType.get;
219
+ case TYPE_UINT:
220
+ return uintValueType.get;
221
+ case TYPE_INT64:
222
+ return int64ValueType.get;
223
+ case TYPE_UINT64:
224
+ return uint64ValueType.get;
225
+ case TYPE_FLOAT:
226
+ return floatValueType.get;
227
+ case TYPE_DOUBLE:
228
+ return doubleValueType.get;
229
+ case TYPE_ENUM:
230
+ return enumValueType.get;
231
+ case TYPE_FLAGS:
232
+ return flagsValueType.get;
233
+ case TYPE_STRING:
234
+ return (value) => stringValueType.get(value) ?? null;
235
+ case TYPE_OBJECT:
236
+ return (value) => wrapHandle(objectValueType.get(value) as ExternalObject<Handle> | null);
237
+ case TYPE_PARAM:
238
+ return (value) =>
239
+ wrapHandle(paramValueType.get(value) as ExternalObject<Handle> | null, getWrapperClass(TYPE_PARAM));
240
+ case TYPE_VARIANT:
241
+ return (value) =>
242
+ wrapHandle(variantValueType.get(value) as ExternalObject<Handle> | null, getWrapperClass(TYPE_VARIANT));
243
+ case TYPE_BOXED:
244
+ return getBoxedValue;
245
+ case TYPE_POINTER:
246
+ return (value) => {
247
+ if (pointerValueType.get(value)) {
248
+ throw new Error("G_TYPE_POINTER non-null values cannot be marshalled to JS");
249
+ }
250
+ return null;
251
+ };
252
+ default:
253
+ return undefined;
254
+ }
255
+ };
256
+
257
+ export function toValue(descriptor: Descriptor, value: unknown): ExternalObject<Handle> {
258
+ const isHandleKind = descriptor.kind === "object" || descriptor.kind === "boxed";
259
+ const nativeValue = isHandleKind
260
+ ? value == null
261
+ ? null
262
+ : getHandle(value as object)
263
+ : toNative(descriptor, value);
264
+ const type =
265
+ descriptor.kind === "object"
266
+ ? nativeValue == null
267
+ ? TYPE_OBJECT
268
+ : getType(nativeValue as ExternalObject<Handle>)
269
+ : resolveDescriptorType(descriptor);
270
+ const gValue = newTypedValue(type);
271
+ resolveValueType(descriptor).set(gValue, nativeValue);
272
+ return gValue;
273
+ }
274
+
275
+ export function fromValue(value: ExternalObject<Handle>): unknown {
276
+ const type = getValueType(value);
277
+ if (type === getStrvType()) return strvValueType.get(value);
278
+ const get = resolveValueGetter(typeFundamental(type));
279
+ if (get === undefined) {
280
+ throw new Error(`Unsupported type for fromValue: ${typeName(type) ?? String(type)}`);
281
+ }
282
+ return get(value);
283
+ }
284
+
285
+ export function newValueForDescriptor(descriptor: Descriptor): ExternalObject<Handle> {
286
+ return newTypedValue(resolveDescriptorType(descriptor));
287
+ }
288
+
289
+ export function outValueForDescriptor(
290
+ descriptor: Descriptor,
291
+ initial?: unknown,
292
+ ): { value: ExternalObject<Handle>; read: () => unknown } {
293
+ const storage = alloc(8);
294
+ write(storage, uint64T, 0, 0);
295
+ if (initial !== undefined) write(storage, descriptor, 0, initial);
296
+ const value = newTypedValue(TYPE_POINTER);
297
+ pointerValueType.set(value, storage);
298
+ return { value, read: () => read(storage, descriptor, 0) };
299
+ }
300
+
301
+ export function outValueForBoxedDescriptor(descriptor: Descriptor, boxed: object): ExternalObject<Handle> {
302
+ return newBoxedValue(descriptor, boxed, setBoxedBind);
303
+ }
304
+
305
+ export function inoutValueForBoxedDescriptor(descriptor: Descriptor, boxed: object): ExternalObject<Handle> {
306
+ return newBoxedValue(descriptor, boxed, setStaticBoxedBind);
307
+ }