@gtkx/runtime 0.0.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/LICENSE +373 -0
- package/README.md +171 -3
- package/dist/arg.d.ts +13 -0
- package/dist/arg.d.ts.map +1 -0
- package/dist/arg.js +6 -0
- package/dist/arg.js.map +1 -0
- package/dist/bind.d.ts +5 -0
- package/dist/bind.d.ts.map +1 -0
- package/dist/bind.js +19 -0
- package/dist/bind.js.map +1 -0
- package/dist/callback.d.ts +13 -0
- package/dist/callback.d.ts.map +1 -0
- package/dist/callback.js +86 -0
- package/dist/callback.js.map +1 -0
- package/dist/descriptors.d.ts +158 -0
- package/dist/descriptors.d.ts.map +1 -0
- package/dist/descriptors.js +135 -0
- package/dist/descriptors.js.map +1 -0
- package/dist/error.d.ts +24 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +33 -0
- package/dist/error.js.map +1 -0
- 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 +10 -0
- package/dist/fn.d.ts.map +1 -0
- package/dist/fn.js +90 -0
- package/dist/fn.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +5 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +5 -0
- package/dist/internal.js.map +1 -0
- package/dist/library.d.ts +8 -0
- package/dist/library.d.ts.map +1 -0
- package/dist/library.js +14 -0
- package/dist/library.js.map +1 -0
- package/dist/lifecycle.d.ts +42 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +70 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/listeners.d.ts +36 -0
- package/dist/listeners.d.ts.map +1 -0
- package/dist/listeners.js +85 -0
- package/dist/listeners.js.map +1 -0
- package/dist/mixin.d.ts +13 -0
- package/dist/mixin.d.ts.map +1 -0
- package/dist/mixin.js +49 -0
- package/dist/mixin.js.map +1 -0
- package/dist/native-value.d.ts +13 -0
- package/dist/native-value.d.ts.map +1 -0
- package/dist/native-value.js +105 -0
- package/dist/native-value.js.map +1 -0
- package/dist/object.d.ts +32 -0
- package/dist/object.d.ts.map +1 -0
- package/dist/object.js +66 -0
- package/dist/object.js.map +1 -0
- package/dist/promisify.d.ts +21 -0
- package/dist/promisify.d.ts.map +1 -0
- package/dist/promisify.js +39 -0
- package/dist/promisify.js.map +1 -0
- 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 +25 -0
- package/dist/register-class.d.ts.map +1 -0
- package/dist/register-class.js +178 -0
- package/dist/register-class.js.map +1 -0
- package/dist/registry.d.ts +69 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +186 -0
- package/dist/registry.js.map +1 -0
- package/dist/signal.d.ts +35 -0
- package/dist/signal.d.ts.map +1 -0
- package/dist/signal.js +95 -0
- package/dist/signal.js.map +1 -0
- package/dist/t.d.ts +50 -0
- package/dist/t.d.ts.map +1 -0
- package/dist/t.js +49 -0
- package/dist/t.js.map +1 -0
- package/dist/tuple.d.ts +7 -0
- package/dist/tuple.d.ts.map +1 -0
- package/dist/tuple.js +26 -0
- package/dist/tuple.js.map +1 -0
- package/dist/type.d.ts +88 -0
- package/dist/type.d.ts.map +1 -0
- package/dist/type.js +194 -0
- package/dist/type.js.map +1 -0
- package/dist/value.d.ts +29 -0
- package/dist/value.d.ts.map +1 -0
- package/dist/value.js +292 -0
- package/dist/value.js.map +1 -0
- package/package.json +54 -13
- package/src/arg.ts +15 -0
- package/src/bind.ts +31 -0
- package/src/callback.ts +149 -0
- package/src/descriptors.ts +350 -0
- package/src/error.ts +58 -0
- package/src/exit-hook.ts +3 -0
- package/src/fn.ts +139 -0
- package/src/index.ts +59 -0
- package/src/internal.ts +12 -0
- package/src/library.ts +17 -0
- package/src/lifecycle.ts +101 -0
- package/src/listeners.ts +112 -0
- package/src/mixin.ts +73 -0
- package/src/native-value.ts +135 -0
- package/src/object.ts +95 -0
- package/src/promisify.ts +67 -0
- package/src/properties.ts +115 -0
- package/src/register-class.ts +305 -0
- package/src/registry.ts +311 -0
- package/src/signal.ts +192 -0
- package/src/t.ts +90 -0
- package/src/tuple.ts +37 -0
- package/src/type.ts +290 -0
- package/src/value.ts +430 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { getWrapperClass, tryGetHandle, wrapHandle } from "./registry.js";
|
|
2
|
+
import { resolveDescriptorType } from "./type.js";
|
|
3
|
+
const MARSHALLED_KINDS = new Set([
|
|
4
|
+
"object",
|
|
5
|
+
"struct",
|
|
6
|
+
"boxed",
|
|
7
|
+
"fundamental",
|
|
8
|
+
"array",
|
|
9
|
+
"hashtable",
|
|
10
|
+
]);
|
|
11
|
+
function isMarshalledDescriptor(descriptor) {
|
|
12
|
+
return MARSHALLED_KINDS.has(descriptor.kind);
|
|
13
|
+
}
|
|
14
|
+
function mapCollection(descriptor, value, convert) {
|
|
15
|
+
return value.map((item) => convert(descriptor.itemDescriptor, item));
|
|
16
|
+
}
|
|
17
|
+
function collectionFromNative(descriptor, value) {
|
|
18
|
+
return value === null ? null : mapCollection(descriptor, value, fromNative);
|
|
19
|
+
}
|
|
20
|
+
function boxedFromNative(descriptor, value) {
|
|
21
|
+
return value == null
|
|
22
|
+
? null
|
|
23
|
+
: wrapHandle(value, getWrapperClass(resolveDescriptorType(descriptor)));
|
|
24
|
+
}
|
|
25
|
+
function fundamentalFromNative(descriptor, value) {
|
|
26
|
+
return value == null
|
|
27
|
+
? null
|
|
28
|
+
: wrapHandle(value, descriptor.wrapperClass ?? getWrapperClass(resolveDescriptorType(descriptor)));
|
|
29
|
+
}
|
|
30
|
+
function hashTableFromNative(descriptor, value) {
|
|
31
|
+
if (value === null) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
const entries = value;
|
|
35
|
+
return new Map(entries.map(([key, val]) => [
|
|
36
|
+
fromNative(descriptor.keyDescriptor, key),
|
|
37
|
+
fromNative(descriptor.valueDescriptor, val),
|
|
38
|
+
]));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Converts a raw value returned from native code into its JavaScript form,
|
|
42
|
+
* wrapping object, struct, boxed, and fundamental handles and recursively
|
|
43
|
+
* converting arrays and hash tables according to the descriptor.
|
|
44
|
+
*
|
|
45
|
+
* @param descriptor Describes the native type of the value.
|
|
46
|
+
* @param value The raw native value to convert.
|
|
47
|
+
*/
|
|
48
|
+
function fromNative(descriptor, value) {
|
|
49
|
+
if (!isMarshalledDescriptor(descriptor)) {
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
switch (descriptor.kind) {
|
|
53
|
+
case "object": {
|
|
54
|
+
return wrapHandle(value);
|
|
55
|
+
}
|
|
56
|
+
case "struct": {
|
|
57
|
+
return wrapHandle(value, descriptor.wrapperClass);
|
|
58
|
+
}
|
|
59
|
+
case "boxed": {
|
|
60
|
+
return boxedFromNative(descriptor, value);
|
|
61
|
+
}
|
|
62
|
+
case "fundamental": {
|
|
63
|
+
return fundamentalFromNative(descriptor, value);
|
|
64
|
+
}
|
|
65
|
+
case "array": {
|
|
66
|
+
return collectionFromNative(descriptor, value);
|
|
67
|
+
}
|
|
68
|
+
case "hashtable": {
|
|
69
|
+
return hashTableFromNative(descriptor, value);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function collectionToNative(descriptor, value) {
|
|
74
|
+
return value == null ? null : mapCollection(descriptor, value, toNative);
|
|
75
|
+
}
|
|
76
|
+
function hashTableToNative(descriptor, value) {
|
|
77
|
+
if (value == null) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
return [...value].map(([key, val]) => [
|
|
81
|
+
toNative(descriptor.keyDescriptor, key),
|
|
82
|
+
toNative(descriptor.valueDescriptor, val),
|
|
83
|
+
]);
|
|
84
|
+
}
|
|
85
|
+
function toNative(descriptor, value) {
|
|
86
|
+
if (!isMarshalledDescriptor(descriptor)) {
|
|
87
|
+
return value;
|
|
88
|
+
}
|
|
89
|
+
switch (descriptor.kind) {
|
|
90
|
+
case "object":
|
|
91
|
+
case "struct":
|
|
92
|
+
case "boxed":
|
|
93
|
+
case "fundamental": {
|
|
94
|
+
return tryGetHandle(value) ?? null;
|
|
95
|
+
}
|
|
96
|
+
case "array": {
|
|
97
|
+
return collectionToNative(descriptor, value);
|
|
98
|
+
}
|
|
99
|
+
case "hashtable": {
|
|
100
|
+
return hashTableToNative(descriptor, value);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export { fromNative, toNative };
|
|
105
|
+
//# sourceMappingURL=native-value.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-value.js","sourceRoot":"","sources":["../src/native-value.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Descriptor, ExternalObject, Handle } from \"@gtkx/native\";\nimport type { ArrayDescriptor, FundamentalDescriptor, HashTableDescriptor, StructDescriptor } from \"./descriptors.js\";\nimport { getWrapperClass, tryGetHandle, wrapHandle } from \"./registry.js\";\nimport { resolveDescriptorType } from \"./type.js\";\n\ntype MarshalledKind = \"object\" | \"struct\" | \"boxed\" | \"fundamental\" | \"array\" | \"hashtable\";\ntype MarshalledDescriptor = Extract<Descriptor, { kind: MarshalledKind }>;\n\nconst MARSHALLED_KINDS: Set<Descriptor[\"kind\"]> = new Set<MarshalledKind>([\n \"object\",\n \"struct\",\n \"boxed\",\n \"fundamental\",\n \"array\",\n \"hashtable\",\n]);\n\nfunction isMarshalledDescriptor(descriptor: Descriptor): descriptor is MarshalledDescriptor {\n return MARSHALLED_KINDS.has(descriptor.kind);\n}\n\nfunction mapCollection(\n descriptor: ArrayDescriptor,\n value: unknown,\n convert: (itemDescriptor: Descriptor, item: unknown) => unknown,\n): unknown[] {\n return (value as unknown[]).map((item) => convert(descriptor.itemDescriptor, item));\n}\n\nfunction collectionFromNative(descriptor: ArrayDescriptor, value: unknown): unknown {\n return value === null ? null : mapCollection(descriptor, value, fromNative);\n}\n\nfunction boxedFromNative(descriptor: Descriptor, value: unknown): unknown {\n return value == null\n ? null\n : wrapHandle(value as ExternalObject<Handle>, getWrapperClass(resolveDescriptorType(descriptor)));\n}\n\nfunction fundamentalFromNative(descriptor: FundamentalDescriptor, value: unknown): unknown {\n return value == null\n ? null\n : wrapHandle(\n value as ExternalObject<Handle>,\n descriptor.wrapperClass ?? getWrapperClass(resolveDescriptorType(descriptor)),\n );\n}\n\nfunction hashTableFromNative(descriptor: HashTableDescriptor, value: unknown): unknown {\n if (value === null) {\n return null;\n }\n\n const entries = value as [unknown, unknown][];\n\n return new Map(\n entries.map(([key, val]): [unknown, unknown] => [\n fromNative(descriptor.keyDescriptor, key),\n fromNative(descriptor.valueDescriptor, val),\n ]),\n );\n}\n\n/**\n * Converts a raw value returned from native code into its JavaScript form,\n * wrapping object, struct, boxed, and fundamental handles and recursively\n * converting arrays and hash tables according to the descriptor.\n *\n * @param descriptor Describes the native type of the value.\n * @param value The raw native value to convert.\n */\nfunction fromNative(descriptor: Descriptor, value: unknown): unknown {\n if (!isMarshalledDescriptor(descriptor)) {\n return value;\n }\n\n switch (descriptor.kind) {\n case \"object\": {\n return wrapHandle(value as ExternalObject<Handle> | null);\n }\n case \"struct\": {\n return wrapHandle(value as ExternalObject<Handle> | null, (descriptor as StructDescriptor).wrapperClass);\n }\n case \"boxed\": {\n return boxedFromNative(descriptor, value);\n }\n case \"fundamental\": {\n return fundamentalFromNative(descriptor, value);\n }\n case \"array\": {\n return collectionFromNative(descriptor, value);\n }\n case \"hashtable\": {\n return hashTableFromNative(descriptor, value);\n }\n }\n}\n\nfunction collectionToNative(descriptor: ArrayDescriptor, value: unknown): unknown {\n return value == null ? null : mapCollection(descriptor, value, toNative);\n}\n\nfunction hashTableToNative(descriptor: HashTableDescriptor, value: unknown): unknown {\n if (value == null) {\n return null;\n }\n\n return [...(value as Map<unknown, unknown>)].map(([key, val]): [unknown, unknown] => [\n toNative(descriptor.keyDescriptor, key),\n toNative(descriptor.valueDescriptor, val),\n ]);\n}\n\nfunction toNative(descriptor: Descriptor, value: unknown): unknown {\n if (!isMarshalledDescriptor(descriptor)) {\n return value;\n }\n\n switch (descriptor.kind) {\n case \"object\":\n case \"struct\":\n case \"boxed\":\n case \"fundamental\": {\n return tryGetHandle(value as object | null | undefined) ?? null;\n }\n case \"array\": {\n return collectionToNative(descriptor, value);\n }\n case \"hashtable\": {\n return hashTableToNative(descriptor, value);\n }\n }\n}\n\nexport { fromNative, toNative };\n"]}
|
package/dist/object.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Descriptor, ExternalObject, Handle } from "@gtkx/native";
|
|
2
|
+
/**
|
|
3
|
+
* Constructs a new GObject of the given type, setting the supplied construct
|
|
4
|
+
* properties. Entries whose value is `undefined` or not a `[descriptor, value]`
|
|
5
|
+
* pair are skipped.
|
|
6
|
+
*
|
|
7
|
+
* @param gtype The GType of the object to construct.
|
|
8
|
+
* @param props Property names mapped to `[descriptor, value]` pairs.
|
|
9
|
+
* @returns The handle of the newly created object.
|
|
10
|
+
*/
|
|
11
|
+
declare function newObjectWithProperties(gtype: bigint, props: Record<string, unknown>): ExternalObject<Handle>;
|
|
12
|
+
/**
|
|
13
|
+
* Reads a GObject property and converts it to its JavaScript value using the
|
|
14
|
+
* descriptor.
|
|
15
|
+
*
|
|
16
|
+
* @param obj The object to read from.
|
|
17
|
+
* @param propertyName The property name.
|
|
18
|
+
* @param descriptor Describes the property's type.
|
|
19
|
+
*/
|
|
20
|
+
declare function getObjectProperty(obj: object, propertyName: string, descriptor: Descriptor): unknown;
|
|
21
|
+
/**
|
|
22
|
+
* Writes a JavaScript value to a GObject property, converting it to native form
|
|
23
|
+
* using the descriptor.
|
|
24
|
+
*
|
|
25
|
+
* @param obj The object to write to.
|
|
26
|
+
* @param propertyName The property name.
|
|
27
|
+
* @param descriptor Describes the property's type.
|
|
28
|
+
* @param jsValue The value to set.
|
|
29
|
+
*/
|
|
30
|
+
declare function setObjectProperty(obj: object, propertyName: string, descriptor: Descriptor, jsValue: unknown): void;
|
|
31
|
+
export { newObjectWithProperties, getObjectProperty, setObjectProperty };
|
|
32
|
+
//# sourceMappingURL=object.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../src/object.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAiCvE;;;;;;;;GAQG;AACH,iBAAS,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CAsBtG;AAED;;;;;;;GAOG;AACH,iBAAS,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAK7F;AAED;;;;;;;;GAQG;AACH,iBAAS,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAE5G;AAED,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,CAAC"}
|
package/dist/object.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { bind } from "./bind.js";
|
|
2
|
+
import { biguint64T, objectT, sizedArrayT, stringT, uint32T, voidT } from "./descriptors.js";
|
|
3
|
+
import { LIB, VALUE_SIZE, VALUE_T } from "./library.js";
|
|
4
|
+
import { getHandle } from "./registry.js";
|
|
5
|
+
import { fromValue, newValueForDescriptor, toValue } from "./value.js";
|
|
6
|
+
const gObjectNewWithProperties = bind(LIB, "g_object_new_with_properties", [
|
|
7
|
+
biguint64T,
|
|
8
|
+
uint32T,
|
|
9
|
+
sizedArrayT(stringT("borrowed"), 1, "borrowed"),
|
|
10
|
+
sizedArrayT(VALUE_T, 1, "borrowed", VALUE_SIZE),
|
|
11
|
+
], objectT("full"));
|
|
12
|
+
const gObjectGetProperty = bind(LIB, "g_object_get_property", [objectT("borrowed"), stringT("borrowed"), VALUE_T], voidT);
|
|
13
|
+
const gObjectSetProperty = bind(LIB, "g_object_set_property", [objectT("borrowed"), stringT("borrowed"), VALUE_T], voidT);
|
|
14
|
+
/**
|
|
15
|
+
* Constructs a new GObject of the given type, setting the supplied construct
|
|
16
|
+
* properties. Entries whose value is `undefined` or not a `[descriptor, value]`
|
|
17
|
+
* pair are skipped.
|
|
18
|
+
*
|
|
19
|
+
* @param gtype The GType of the object to construct.
|
|
20
|
+
* @param props Property names mapped to `[descriptor, value]` pairs.
|
|
21
|
+
* @returns The handle of the newly created object.
|
|
22
|
+
*/
|
|
23
|
+
function newObjectWithProperties(gtype, props) {
|
|
24
|
+
const names = [];
|
|
25
|
+
const values = [];
|
|
26
|
+
for (const name in props) {
|
|
27
|
+
const entry = props[name];
|
|
28
|
+
if (!Array.isArray(entry)) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
const [descriptor, value] = entry;
|
|
32
|
+
if (value === undefined) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
names.push(name);
|
|
36
|
+
values.push(toValue(descriptor, value));
|
|
37
|
+
}
|
|
38
|
+
return gObjectNewWithProperties(gtype, names.length, names, values);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Reads a GObject property and converts it to its JavaScript value using the
|
|
42
|
+
* descriptor.
|
|
43
|
+
*
|
|
44
|
+
* @param obj The object to read from.
|
|
45
|
+
* @param propertyName The property name.
|
|
46
|
+
* @param descriptor Describes the property's type.
|
|
47
|
+
*/
|
|
48
|
+
function getObjectProperty(obj, propertyName, descriptor) {
|
|
49
|
+
const value = newValueForDescriptor(descriptor);
|
|
50
|
+
gObjectGetProperty(getHandle(obj), propertyName, value);
|
|
51
|
+
return fromValue(value);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Writes a JavaScript value to a GObject property, converting it to native form
|
|
55
|
+
* using the descriptor.
|
|
56
|
+
*
|
|
57
|
+
* @param obj The object to write to.
|
|
58
|
+
* @param propertyName The property name.
|
|
59
|
+
* @param descriptor Describes the property's type.
|
|
60
|
+
* @param jsValue The value to set.
|
|
61
|
+
*/
|
|
62
|
+
function setObjectProperty(obj, propertyName, descriptor, jsValue) {
|
|
63
|
+
gObjectSetProperty(getHandle(obj), propertyName, toValue(descriptor, jsValue));
|
|
64
|
+
}
|
|
65
|
+
export { newObjectWithProperties, getObjectProperty, setObjectProperty };
|
|
66
|
+
//# sourceMappingURL=object.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"object.js","sourceRoot":"","sources":["../src/object.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC7F,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAEvE,MAAM,wBAAwB,GAAG,IAAI,CACjC,GAAG,EACH,8BAA8B,EAC9B;IACI,UAAU;IACV,OAAO;IACP,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC;IAC/C,WAAW,CAAC,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC;CAClD,EACD,OAAO,CAAC,MAAM,CAAC,CAClB,CAAC;AAEF,MAAM,kBAAkB,GAAG,IAAI,CAC3B,GAAG,EACH,uBAAuB,EACvB,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,EACnD,KAAK,CACR,CAAC;AAEF,MAAM,kBAAkB,GAAG,IAAI,CAC3B,GAAG,EACH,uBAAuB,EACvB,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,EACnD,KAAK,CACR,CAAC;AAEF;;;;;;;;GAQG;AACH,SAAS,uBAAuB,CAAC,KAAa,EAAE,KAA8B;IAC1E,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,MAAM,GAA6B,EAAE,CAAC;IAE5C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,MAAM,KAAK,GAAY,KAAK,CAAC,IAAI,CAAC,CAAC;QAEnC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACxB,SAAS;QACb,CAAC;QAED,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,GAAG,KAA8B,CAAC;QAE3D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACtB,SAAS;QACb,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO,wBAAwB,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAA2B,CAAC;AAClG,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,iBAAiB,CAAC,GAAW,EAAE,YAAoB,EAAE,UAAsB;IAChF,MAAM,KAAK,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAC;IAChD,kBAAkB,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC;IAExD,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,iBAAiB,CAAC,GAAW,EAAE,YAAoB,EAAE,UAAsB,EAAE,OAAgB;IAClG,kBAAkB,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;AACnF,CAAC;AAED,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,CAAC","sourcesContent":["import type { Descriptor, ExternalObject, Handle } from \"@gtkx/native\";\nimport { bind } from \"./bind.js\";\nimport { biguint64T, objectT, sizedArrayT, stringT, uint32T, voidT } from \"./descriptors.js\";\nimport { LIB, VALUE_SIZE, VALUE_T } from \"./library.js\";\nimport { getHandle } from \"./registry.js\";\nimport { fromValue, newValueForDescriptor, toValue } from \"./value.js\";\n\nconst gObjectNewWithProperties = bind(\n LIB,\n \"g_object_new_with_properties\",\n [\n biguint64T,\n uint32T,\n sizedArrayT(stringT(\"borrowed\"), 1, \"borrowed\"),\n sizedArrayT(VALUE_T, 1, \"borrowed\", VALUE_SIZE),\n ],\n objectT(\"full\"),\n);\n\nconst gObjectGetProperty = bind(\n LIB,\n \"g_object_get_property\",\n [objectT(\"borrowed\"), stringT(\"borrowed\"), VALUE_T],\n voidT,\n);\n\nconst gObjectSetProperty = bind(\n LIB,\n \"g_object_set_property\",\n [objectT(\"borrowed\"), stringT(\"borrowed\"), VALUE_T],\n voidT,\n);\n\n/**\n * Constructs a new GObject of the given type, setting the supplied construct\n * properties. Entries whose value is `undefined` or not a `[descriptor, value]`\n * pair are skipped.\n *\n * @param gtype The GType of the object to construct.\n * @param props Property names mapped to `[descriptor, value]` pairs.\n * @returns The handle of the newly created object.\n */\nfunction newObjectWithProperties(gtype: bigint, props: Record<string, unknown>): ExternalObject<Handle> {\n const names: string[] = [];\n const values: ExternalObject<Handle>[] = [];\n\n for (const name in props) {\n const entry: unknown = props[name];\n\n if (!Array.isArray(entry)) {\n continue;\n }\n\n const [descriptor, value] = entry as [Descriptor, unknown];\n\n if (value === undefined) {\n continue;\n }\n\n names.push(name);\n values.push(toValue(descriptor, value));\n }\n\n return gObjectNewWithProperties(gtype, names.length, names, values) as ExternalObject<Handle>;\n}\n\n/**\n * Reads a GObject property and converts it to its JavaScript value using the\n * descriptor.\n *\n * @param obj The object to read from.\n * @param propertyName The property name.\n * @param descriptor Describes the property's type.\n */\nfunction getObjectProperty(obj: object, propertyName: string, descriptor: Descriptor): unknown {\n const value = newValueForDescriptor(descriptor);\n gObjectGetProperty(getHandle(obj), propertyName, value);\n\n return fromValue(value);\n}\n\n/**\n * Writes a JavaScript value to a GObject property, converting it to native form\n * using the descriptor.\n *\n * @param obj The object to write to.\n * @param propertyName The property name.\n * @param descriptor Describes the property's type.\n * @param jsValue The value to set.\n */\nfunction setObjectProperty(obj: object, propertyName: string, descriptor: Descriptor, jsValue: unknown): void {\n gObjectSetProperty(getHandle(obj), propertyName, toValue(descriptor, jsValue));\n}\n\nexport { newObjectWithProperties, getObjectProperty, setObjectProperty };\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts the finished value from the async result a GIO-style operation completes with.
|
|
3
|
+
*
|
|
4
|
+
* @template R - The async result type passed to the completion callback.
|
|
5
|
+
* @template T - The finished value type.
|
|
6
|
+
*/
|
|
7
|
+
type FinishResult<R extends object, T> = (result: R) => T;
|
|
8
|
+
/**
|
|
9
|
+
* Wraps a GIO-style asynchronous function that takes a completion callback into a
|
|
10
|
+
* promise, invoking the finish function to extract the result. Outside production,
|
|
11
|
+
* the call site's stack is captured and attached as the rejection error's cause.
|
|
12
|
+
*
|
|
13
|
+
* @param asyncFn The async function, called with the leading arguments, the cancellable, and a completion callback.
|
|
14
|
+
* @param finish Extracts the result from the async result passed to the completion callback.
|
|
15
|
+
* @param cancellable A cancellable object, or null/undefined for none.
|
|
16
|
+
* @param leading Arguments passed to `asyncFn` before the cancellable and callback.
|
|
17
|
+
* @returns A promise resolving to the finished result, or rejecting if `finish` throws.
|
|
18
|
+
*/
|
|
19
|
+
declare const promisify: <R extends object, T>(asyncFn: (...args: unknown[]) => void, finish: FinishResult<R, T>, cancellable: object | null | undefined, ...leading: unknown[]) => Promise<T>;
|
|
20
|
+
export { promisify, type FinishResult };
|
|
21
|
+
//# sourceMappingURL=promisify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promisify.d.ts","sourceRoot":"","sources":["../src/promisify.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,KAAK,YAAY,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC;AAgC1D;;;;;;;;;;GAUG;AACH,QAAA,MAAM,SAAS,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,EAClC,SAAS,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,EACrC,QAAQ,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,EAC1B,aAAa,MAAM,GAAG,IAAI,GAAG,SAAS,EACtC,GAAG,SAAS,OAAO,EAAE,KACtB,OAAO,CAAC,CAAC,CAQN,CAAC;AAEP,OAAO,EAAE,SAAS,EAAE,KAAK,YAAY,EAAE,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { tryGetHandle } from "./registry.js";
|
|
2
|
+
const attachCreationStack = (error, creationStack) => {
|
|
3
|
+
if (creationStack === undefined || !(error instanceof Error)) {
|
|
4
|
+
return;
|
|
5
|
+
}
|
|
6
|
+
if (error.cause !== undefined || !Object.isExtensible(error)) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
error.cause = creationStack;
|
|
10
|
+
};
|
|
11
|
+
const settle = (settlement, asyncResult) => {
|
|
12
|
+
const { finish, creationStack, resolve, reject } = settlement;
|
|
13
|
+
try {
|
|
14
|
+
resolve(finish(asyncResult));
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
attachCreationStack(error, creationStack);
|
|
18
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Wraps a GIO-style asynchronous function that takes a completion callback into a
|
|
23
|
+
* promise, invoking the finish function to extract the result. Outside production,
|
|
24
|
+
* the call site's stack is captured and attached as the rejection error's cause.
|
|
25
|
+
*
|
|
26
|
+
* @param asyncFn The async function, called with the leading arguments, the cancellable, and a completion callback.
|
|
27
|
+
* @param finish Extracts the result from the async result passed to the completion callback.
|
|
28
|
+
* @param cancellable A cancellable object, or null/undefined for none.
|
|
29
|
+
* @param leading Arguments passed to `asyncFn` before the cancellable and callback.
|
|
30
|
+
* @returns A promise resolving to the finished result, or rejecting if `finish` throws.
|
|
31
|
+
*/
|
|
32
|
+
const promisify = (asyncFn, finish, cancellable, ...leading) => new Promise((resolve, reject) => {
|
|
33
|
+
const creationStack = process.env.NODE_ENV === "production" ? undefined : new Error("gtkx async operation started here");
|
|
34
|
+
asyncFn(...leading, tryGetHandle(cancellable), (_source, asyncResult) => {
|
|
35
|
+
settle({ finish, creationStack, resolve, reject }, asyncResult);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
export { promisify };
|
|
39
|
+
//# sourceMappingURL=promisify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promisify.js","sourceRoot":"","sources":["../src/promisify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAiB7C,MAAM,mBAAmB,GAAG,CAAC,KAAc,EAAE,aAAgC,EAAQ,EAAE;IACnF,IAAI,aAAa,KAAK,SAAS,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,EAAE,CAAC;QAC3D,OAAO;IACX,CAAC;IAED,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3D,OAAO;IACX,CAAC;IAED,KAAK,CAAC,KAAK,GAAG,aAAa,CAAC;AAChC,CAAC,CAAC;AAEF,MAAM,MAAM,GAAG,CAAsB,UAA4B,EAAE,WAAmB,EAAQ,EAAE;IAC5F,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC;IAE9D,IAAI,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,WAAgB,CAAC,CAAC,CAAC;IACtC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,mBAAmB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACtE,CAAC;AACL,CAAC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,SAAS,GAAG,CACd,OAAqC,EACrC,MAA0B,EAC1B,WAAsC,EACtC,GAAG,OAAkB,EACX,EAAE,CACZ,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IAC/B,MAAM,aAAa,GACf,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IAEvG,OAAO,CAAC,GAAG,OAAO,EAAE,YAAY,CAAC,WAAW,CAAC,EAAE,CAAC,OAAsB,EAAE,WAAmB,EAAE,EAAE;QAC3F,MAAM,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,WAAW,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEP,OAAO,EAAE,SAAS,EAAqB,CAAC","sourcesContent":["import { tryGetHandle } from \"./registry.js\";\n\n/**\n * Extracts the finished value from the async result a GIO-style operation completes with.\n *\n * @template R - The async result type passed to the completion callback.\n * @template T - The finished value type.\n */\ntype FinishResult<R extends object, T> = (result: R) => T;\n\ntype Settlement<R extends object, T> = {\n finish: FinishResult<R, T>;\n creationStack: Error | undefined;\n resolve: (value: T) => void;\n reject: (reason: Error) => void;\n};\n\nconst attachCreationStack = (error: unknown, creationStack: Error | undefined): void => {\n if (creationStack === undefined || !(error instanceof Error)) {\n return;\n }\n\n if (error.cause !== undefined || !Object.isExtensible(error)) {\n return;\n }\n\n error.cause = creationStack;\n};\n\nconst settle = <R extends object, T>(settlement: Settlement<R, T>, asyncResult: object): void => {\n const { finish, creationStack, resolve, reject } = settlement;\n\n try {\n resolve(finish(asyncResult as R));\n } catch (error) {\n attachCreationStack(error, creationStack);\n reject(error instanceof Error ? error : new Error(String(error)));\n }\n};\n\n/**\n * Wraps a GIO-style asynchronous function that takes a completion callback into a\n * promise, invoking the finish function to extract the result. Outside production,\n * the call site's stack is captured and attached as the rejection error's cause.\n *\n * @param asyncFn The async function, called with the leading arguments, the cancellable, and a completion callback.\n * @param finish Extracts the result from the async result passed to the completion callback.\n * @param cancellable A cancellable object, or null/undefined for none.\n * @param leading Arguments passed to `asyncFn` before the cancellable and callback.\n * @returns A promise resolving to the finished result, or rejecting if `finish` throws.\n */\nconst promisify = <R extends object, T>(\n asyncFn: (...args: unknown[]) => void,\n finish: FinishResult<R, T>,\n cancellable: object | null | undefined,\n ...leading: unknown[]\n): Promise<T> =>\n new Promise<T>((resolve, reject) => {\n const creationStack =\n process.env.NODE_ENV === \"production\" ? undefined : new Error(\"gtkx async operation started here\");\n\n asyncFn(...leading, tryGetHandle(cancellable), (_source: object | null, asyncResult: object) => {\n settle({ finish, creationStack, resolve, reject }, asyncResult);\n });\n });\n\nexport { promisify, type FinishResult };\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { RegisterClassProperty } from "@gtkx/native";
|
|
2
|
+
import type { AnyClass } from "@gtkx/utils";
|
|
3
|
+
type PropertyAccessor = {
|
|
4
|
+
name: string;
|
|
5
|
+
storage: symbol;
|
|
6
|
+
pspec: object;
|
|
7
|
+
};
|
|
8
|
+
type PropertySpec = object;
|
|
9
|
+
declare function makeGetProperty(accessors: PropertyAccessor[]): (this: object, propertyId: number, value: object) => void;
|
|
10
|
+
declare function makeSetProperty(accessors: PropertyAccessor[]): (this: object, propertyId: number, value: object) => void;
|
|
11
|
+
declare function buildAccessors(klass: AnyClass, properties: Record<string, PropertySpec>): PropertyAccessor[];
|
|
12
|
+
declare function toNativeProperties(properties: Record<string, PropertySpec>): RegisterClassProperty[];
|
|
13
|
+
export { buildAccessors, makeGetProperty, makeSetProperty, toNativeProperties, type PropertyAccessor, type PropertySpec, };
|
|
14
|
+
//# sourceMappingURL=properties.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"properties.d.ts","sourceRoot":"","sources":["../src/properties.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA0B,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAO5C,KAAK,gBAAgB,GAAG;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,YAAY,GAAG,MAAM,CAAC;AA0D3B,iBAAS,eAAe,CAAC,SAAS,EAAE,gBAAgB,EAAE,IACtB,MAAM,MAAM,EAAE,YAAY,MAAM,EAAE,OAAO,MAAM,KAAG,IAAI,CAKrF;AAED,iBAAS,eAAe,CAAC,SAAS,EAAE,gBAAgB,EAAE,IACtB,MAAM,MAAM,EAAE,YAAY,MAAM,EAAE,OAAO,MAAM,KAAG,IAAI,CAKrF;AAED,iBAAS,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,gBAAgB,EAAE,CAUrG;AAED,iBAAS,kBAAkB,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,qBAAqB,EAAE,CAK7F;AAED,OAAO,EACH,cAAc,EACd,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,KAAK,gBAAgB,EACrB,KAAK,YAAY,GACpB,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { camelCase } from "@gtkx/utils";
|
|
2
|
+
import { bind } from "./bind.js";
|
|
3
|
+
import { LIB, PARAM_T, VALUE_T } from "./library.js";
|
|
4
|
+
import { getHandle } from "./registry.js";
|
|
5
|
+
import { fromValue, intoValue } from "./value.js";
|
|
6
|
+
const FIRST_PROPERTY_ID = 1;
|
|
7
|
+
const paramSpecDefaultValue = bind(LIB, "g_param_spec_get_default_value", [PARAM_T], VALUE_T);
|
|
8
|
+
const underscoreCase = (name) => name.replaceAll("-", "_");
|
|
9
|
+
const accessorNames = (name) => [...new Set([name, underscoreCase(name), camelCase(name)])];
|
|
10
|
+
function readStored(instance, accessor) {
|
|
11
|
+
if (!Object.hasOwn(instance, accessor.storage)) {
|
|
12
|
+
const defaults = paramSpecDefaultValue(getHandle(accessor.pspec));
|
|
13
|
+
instance[accessor.storage] = fromValue(defaults);
|
|
14
|
+
}
|
|
15
|
+
return instance[accessor.storage];
|
|
16
|
+
}
|
|
17
|
+
function defineAccessor(prototype, accessor, alias) {
|
|
18
|
+
if (Object.getOwnPropertyDescriptor(prototype, alias) !== undefined) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
Object.defineProperty(prototype, alias, {
|
|
22
|
+
configurable: true,
|
|
23
|
+
enumerable: true,
|
|
24
|
+
get() {
|
|
25
|
+
return readStored(this, accessor);
|
|
26
|
+
},
|
|
27
|
+
set(value) {
|
|
28
|
+
if (readStored(this, accessor) === value) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
this[accessor.storage] = value;
|
|
32
|
+
this.notify?.(accessor.name);
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
function installAccessors(klass, accessor) {
|
|
37
|
+
const prototype = klass.prototype;
|
|
38
|
+
for (const alias of accessorNames(accessor.name)) {
|
|
39
|
+
defineAccessor(prototype, accessor, alias);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function resolveAccessor(accessors, propertyId) {
|
|
43
|
+
const accessor = accessors[propertyId - FIRST_PROPERTY_ID];
|
|
44
|
+
if (accessor === undefined) {
|
|
45
|
+
throw new RangeError(`registerClass: no property registered for id ${String(propertyId)}`);
|
|
46
|
+
}
|
|
47
|
+
return accessor;
|
|
48
|
+
}
|
|
49
|
+
function makeGetProperty(accessors) {
|
|
50
|
+
return function getProperty(propertyId, value) {
|
|
51
|
+
const accessor = resolveAccessor(accessors, propertyId);
|
|
52
|
+
const current = this[camelCase(accessor.name)];
|
|
53
|
+
intoValue(getHandle(value), current);
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function makeSetProperty(accessors) {
|
|
57
|
+
return function setProperty(propertyId, value) {
|
|
58
|
+
const accessor = resolveAccessor(accessors, propertyId);
|
|
59
|
+
const jsValue = fromValue(getHandle(value));
|
|
60
|
+
this[camelCase(accessor.name)] = jsValue;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function buildAccessors(klass, properties) {
|
|
64
|
+
const accessors = [];
|
|
65
|
+
for (const [name, pspec] of Object.entries(properties)) {
|
|
66
|
+
const accessor = { name, storage: Symbol(`gtkx:property:${name}`), pspec };
|
|
67
|
+
installAccessors(klass, accessor);
|
|
68
|
+
accessors.push(accessor);
|
|
69
|
+
}
|
|
70
|
+
return accessors;
|
|
71
|
+
}
|
|
72
|
+
function toNativeProperties(properties) {
|
|
73
|
+
return Object.values(properties).map((pspec, index) => ({
|
|
74
|
+
id: index + FIRST_PROPERTY_ID,
|
|
75
|
+
pspec: getHandle(pspec),
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
export { buildAccessors, makeGetProperty, makeSetProperty, toNativeProperties, };
|
|
79
|
+
//# sourceMappingURL=properties.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"properties.js","sourceRoot":"","sources":["../src/properties.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExternalObject, Handle, RegisterClassProperty } from \"@gtkx/native\";\nimport type { AnyClass } from \"@gtkx/utils\";\nimport { camelCase } from \"@gtkx/utils\";\nimport { bind } from \"./bind.js\";\nimport { LIB, PARAM_T, VALUE_T } from \"./library.js\";\nimport { getHandle } from \"./registry.js\";\nimport { fromValue, intoValue } from \"./value.js\";\n\ntype PropertyAccessor = {\n name: string;\n storage: symbol;\n pspec: object;\n};\n\ntype PropertySpec = object;\ntype NotifyingObject = { notify?: (propertyName: string) => void };\n\nconst FIRST_PROPERTY_ID = 1;\nconst paramSpecDefaultValue = bind(LIB, \"g_param_spec_get_default_value\", [PARAM_T], VALUE_T);\n\nconst underscoreCase = (name: string): string => name.replaceAll(\"-\", \"_\");\nconst accessorNames = (name: string): string[] => [...new Set([name, underscoreCase(name), camelCase(name)])];\n\nfunction readStored(instance: Record<symbol, unknown>, accessor: PropertyAccessor): unknown {\n if (!Object.hasOwn(instance, accessor.storage)) {\n const defaults = paramSpecDefaultValue(getHandle(accessor.pspec)) as ExternalObject<Handle>;\n instance[accessor.storage] = fromValue(defaults);\n }\n\n return instance[accessor.storage];\n}\n\nfunction defineAccessor(prototype: object, accessor: PropertyAccessor, alias: string): void {\n if (Object.getOwnPropertyDescriptor(prototype, alias) !== undefined) {\n return;\n }\n\n Object.defineProperty(prototype, alias, {\n configurable: true,\n enumerable: true,\n get(this: Record<symbol, unknown>) {\n return readStored(this, accessor);\n },\n set(this: Record<symbol, unknown>, value: unknown) {\n if (readStored(this, accessor) === value) {\n return;\n }\n\n this[accessor.storage] = value;\n (this as NotifyingObject).notify?.(accessor.name);\n },\n });\n}\n\nfunction installAccessors(klass: AnyClass, accessor: PropertyAccessor): void {\n const prototype = (klass as { prototype: object }).prototype;\n\n for (const alias of accessorNames(accessor.name)) {\n defineAccessor(prototype, accessor, alias);\n }\n}\n\nfunction resolveAccessor(accessors: PropertyAccessor[], propertyId: number): PropertyAccessor {\n const accessor = accessors[propertyId - FIRST_PROPERTY_ID];\n\n if (accessor === undefined) {\n throw new RangeError(`registerClass: no property registered for id ${String(propertyId)}`);\n }\n\n return accessor;\n}\n\nfunction makeGetProperty(accessors: PropertyAccessor[]) {\n return function getProperty(this: object, propertyId: number, value: object): void {\n const accessor = resolveAccessor(accessors, propertyId);\n const current = (this as Record<string, unknown>)[camelCase(accessor.name)];\n intoValue(getHandle(value), current);\n };\n}\n\nfunction makeSetProperty(accessors: PropertyAccessor[]) {\n return function setProperty(this: object, propertyId: number, value: object): void {\n const accessor = resolveAccessor(accessors, propertyId);\n const jsValue = fromValue(getHandle(value));\n (this as Record<string, unknown>)[camelCase(accessor.name)] = jsValue;\n };\n}\n\nfunction buildAccessors(klass: AnyClass, properties: Record<string, PropertySpec>): PropertyAccessor[] {\n const accessors: PropertyAccessor[] = [];\n\n for (const [name, pspec] of Object.entries(properties)) {\n const accessor: PropertyAccessor = { name, storage: Symbol(`gtkx:property:${name}`), pspec };\n installAccessors(klass, accessor);\n accessors.push(accessor);\n }\n\n return accessors;\n}\n\nfunction toNativeProperties(properties: Record<string, PropertySpec>): RegisterClassProperty[] {\n return Object.values(properties).map((pspec, index) => ({\n id: index + FIRST_PROPERTY_ID,\n pspec: getHandle(pspec),\n }));\n}\n\nexport {\n buildAccessors,\n makeGetProperty,\n makeSetProperty,\n toNativeProperties,\n type PropertyAccessor,\n type PropertySpec,\n};\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type AnyClass } from "@gtkx/utils";
|
|
2
|
+
import { type PropertySpec } from "./properties.js";
|
|
3
|
+
type RegisterClassOptions = {
|
|
4
|
+
typeName?: string;
|
|
5
|
+
/**
|
|
6
|
+
* Properties to install on the new type, keyed by canonical property name. Each value is the
|
|
7
|
+
* `GObject.ParamSpec` describing it, for example `GObject.paramSpecString(...)`. Accessors are
|
|
8
|
+
* generated on the prototype for the dashed, underscored and camelCased spellings of the name
|
|
9
|
+
* unless the class already defines one, and writing through them emits `notify`.
|
|
10
|
+
*/
|
|
11
|
+
properties?: Record<string, PropertySpec>;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Registers a subclass of a wrapper class as a new GType, wiring up any class and
|
|
15
|
+
* inherited-interface virtual functions it overrides. Throws if the class does not
|
|
16
|
+
* extend a registered wrapper class, has no derivable type name, or overrides an
|
|
17
|
+
* unsupported construct-time vtable slot.
|
|
18
|
+
*
|
|
19
|
+
* @param klass The subclass to register.
|
|
20
|
+
* @param options Registration options, such as an explicit type name.
|
|
21
|
+
* @returns The same class, now registered.
|
|
22
|
+
*/
|
|
23
|
+
declare function registerClass<T extends AnyClass>(klass: T, options?: RegisterClassOptions): T;
|
|
24
|
+
export { registerClass };
|
|
25
|
+
//# sourceMappingURL=register-class.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-class.d.ts","sourceRoot":"","sources":["../src/register-class.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,QAAQ,EAAkC,MAAM,aAAa,CAAC;AAE5E,OAAO,EAKH,KAAK,YAAY,EAEpB,MAAM,iBAAiB,CAAC;AAUzB,KAAK,oBAAoB,GAAG;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CAC7C,CAAC;AAWF;;;;;;;;;GASG;AACH,iBAAS,aAAa,CAAC,CAAC,SAAS,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,GAAE,oBAAyB,GAAG,CAAC,CAuB1F;AAkOD,OAAO,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { registerClass as nativeRegisterClass, } from "@gtkx/native";
|
|
2
|
+
import { getParentClass, walkClassChain } from "@gtkx/utils";
|
|
3
|
+
import { wrapCallback } from "./callback.js";
|
|
4
|
+
import { buildAccessors, makeGetProperty, makeSetProperty, toNativeProperties, } from "./properties.js";
|
|
5
|
+
import { getClassType, getInterfaceVfuncRegistry, getVfuncRegistry, registerClassType, } from "./registry.js";
|
|
6
|
+
import { TYPE_INVALID, typeInterfaces } from "./type.js";
|
|
7
|
+
const UNSUPPORTED_CONSTRUCT_VFUNCS = new Set(["constructed", "setProperty", "getProperty"]);
|
|
8
|
+
const VALUE_ARG_INDEX = 2;
|
|
9
|
+
/**
|
|
10
|
+
* Registers a subclass of a wrapper class as a new GType, wiring up any class and
|
|
11
|
+
* inherited-interface virtual functions it overrides. Throws if the class does not
|
|
12
|
+
* extend a registered wrapper class, has no derivable type name, or overrides an
|
|
13
|
+
* unsupported construct-time vtable slot.
|
|
14
|
+
*
|
|
15
|
+
* @param klass The subclass to register.
|
|
16
|
+
* @param options Registration options, such as an explicit type name.
|
|
17
|
+
* @returns The same class, now registered.
|
|
18
|
+
*/
|
|
19
|
+
function registerClass(klass, options = {}) {
|
|
20
|
+
const parentType = resolveParentType(klass);
|
|
21
|
+
if (parentType === TYPE_INVALID) {
|
|
22
|
+
throw new TypeError(`registerClass: ${klass.name} must extend a registered wrapper class`);
|
|
23
|
+
}
|
|
24
|
+
const name = options.typeName ?? klass.name;
|
|
25
|
+
if (!name) {
|
|
26
|
+
throw new Error("registerClass: cannot derive a GType name (anonymous class with no typeName option)");
|
|
27
|
+
}
|
|
28
|
+
const properties = options.properties ?? {};
|
|
29
|
+
const accessors = buildAccessors(klass, properties);
|
|
30
|
+
const classVfuncs = [...discoverClassVfuncs(klass), ...propertyVfuncs(klass, accessors)];
|
|
31
|
+
const claimedMethodNames = new Set(classVfuncs.map((vfunc) => vfunc.methodName));
|
|
32
|
+
const interfaceBindings = discoverInheritedInterfaceVfuncs(klass, parentType, claimedMethodNames);
|
|
33
|
+
const nativeOptions = toNativeOptions(classVfuncs, interfaceBindings, properties);
|
|
34
|
+
const newType = nativeRegisterClass(name, parentType, nativeOptions);
|
|
35
|
+
registerClassType(klass, newType);
|
|
36
|
+
return klass;
|
|
37
|
+
}
|
|
38
|
+
function resolveParentType(klass) {
|
|
39
|
+
return (walkClassChain(getParentClass(klass), (cls) => {
|
|
40
|
+
const gtype = getClassType(cls);
|
|
41
|
+
return gtype === TYPE_INVALID ? undefined : gtype;
|
|
42
|
+
}) ?? TYPE_INVALID);
|
|
43
|
+
}
|
|
44
|
+
function ownInstanceMethodNames(klass) {
|
|
45
|
+
const proto = klass.prototype;
|
|
46
|
+
if (!proto) {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
return Object.getOwnPropertyNames(proto).filter((name) => {
|
|
50
|
+
if (name === "constructor") {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
return typeof Object.getOwnPropertyDescriptor(proto, name)?.value === "function";
|
|
54
|
+
});
|
|
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
|
+
}
|
|
74
|
+
function collectDiscoveredVfuncs(klass, resolveDescriptor, skip) {
|
|
75
|
+
const proto = klass.prototype;
|
|
76
|
+
const result = [];
|
|
77
|
+
for (const methodName of ownInstanceMethodNames(klass)) {
|
|
78
|
+
const discovered = buildDiscoveredVfunc(proto, methodName, resolveDescriptor, skip);
|
|
79
|
+
if (discovered) {
|
|
80
|
+
result.push(discovered);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
function discoverClassVfuncs(klass) {
|
|
86
|
+
return collectDiscoveredVfuncs(klass, (methodName) => {
|
|
87
|
+
const descriptor = findClassVfuncDescriptor(klass, methodName);
|
|
88
|
+
if (descriptor && UNSUPPORTED_CONSTRUCT_VFUNCS.has(methodName)) {
|
|
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");
|
|
92
|
+
}
|
|
93
|
+
return descriptor ?? undefined;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
function wrapVfunc(fn, argDescriptors, returnDescriptor) {
|
|
97
|
+
return wrapCallback(fn, { argDescriptors, returnDescriptor }, "this");
|
|
98
|
+
}
|
|
99
|
+
function discoverInheritedInterfaceVfuncs(klass, parentGtype, claimedMethodNames) {
|
|
100
|
+
const bindings = [];
|
|
101
|
+
for (const interfaceGtype of typeInterfaces(parentGtype)) {
|
|
102
|
+
const [first, ...rest] = discoverInterfaceVfuncs(klass, interfaceGtype, claimedMethodNames);
|
|
103
|
+
if (first !== undefined) {
|
|
104
|
+
bindings.push({ gtype: interfaceGtype, vtableSize: first.vtableSize, vfuncs: [first, ...rest] });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return bindings;
|
|
108
|
+
}
|
|
109
|
+
function discoverInterfaceVfuncs(klass, interfaceGtype, claimedMethodNames) {
|
|
110
|
+
const vfuncRegistry = getInterfaceVfuncRegistry(interfaceGtype);
|
|
111
|
+
if (!vfuncRegistry) {
|
|
112
|
+
return [];
|
|
113
|
+
}
|
|
114
|
+
return collectDiscoveredVfuncs(klass, (methodName) => {
|
|
115
|
+
const entry = vfuncRegistry[methodName];
|
|
116
|
+
return entry?.kind === "interface" ? entry : undefined;
|
|
117
|
+
}, claimedMethodNames);
|
|
118
|
+
}
|
|
119
|
+
function findClassVfuncDescriptor(klass, methodName) {
|
|
120
|
+
return (walkClassChain(getParentClass(klass), (cls) => {
|
|
121
|
+
const entry = getVfuncRegistry(cls)?.[methodName];
|
|
122
|
+
return entry?.kind === "class" ? entry : undefined;
|
|
123
|
+
}) ?? null);
|
|
124
|
+
}
|
|
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) {
|
|
155
|
+
const hasInterfaces = interfaceBindings.length > 0;
|
|
156
|
+
const hasClassVfuncs = classVfuncs.length > 0;
|
|
157
|
+
const hasProperties = Object.keys(properties).length > 0;
|
|
158
|
+
if (!hasClassVfuncs && !hasInterfaces && !hasProperties) {
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
const options = {};
|
|
162
|
+
if (hasProperties) {
|
|
163
|
+
options.properties = toNativeProperties(properties);
|
|
164
|
+
}
|
|
165
|
+
if (hasClassVfuncs) {
|
|
166
|
+
options.vfuncs = [...classVfuncs];
|
|
167
|
+
}
|
|
168
|
+
if (hasInterfaces) {
|
|
169
|
+
options.interfaces = interfaceBindings.map((binding) => ({
|
|
170
|
+
type: binding.gtype,
|
|
171
|
+
vtableSize: binding.vtableSize,
|
|
172
|
+
vfuncs: [...binding.vfuncs],
|
|
173
|
+
}));
|
|
174
|
+
}
|
|
175
|
+
return options;
|
|
176
|
+
}
|
|
177
|
+
export { registerClass };
|
|
178
|
+
//# sourceMappingURL=register-class.js.map
|