@gtkx/runtime 1.0.0-rc.4 → 1.1.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 +5 -5
- package/dist/application-class.d.ts +37 -0
- package/dist/application-class.d.ts.map +1 -0
- package/dist/application-class.js +78 -0
- package/dist/application-class.js.map +1 -0
- package/dist/arg.d.ts +2 -1
- package/dist/arg.d.ts.map +1 -1
- package/dist/arg.js +2 -1
- 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 +4 -3
- package/dist/callback.d.ts.map +1 -1
- package/dist/callback.js +124 -29
- 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/default-application.d.ts +4 -0
- package/dist/default-application.d.ts.map +1 -0
- package/dist/default-application.js +17 -0
- package/dist/default-application.js.map +1 -0
- package/dist/descriptors.d.ts +98 -4
- package/dist/descriptors.d.ts.map +1 -1
- package/dist/descriptors.js +72 -6
- package/dist/descriptors.js.map +1 -1
- package/dist/error.d.ts +1 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js.map +1 -1
- package/dist/exit-hook.js +13 -0
- package/dist/exit-hook.js.map +1 -1
- package/dist/fn.d.ts +24 -2
- package/dist/fn.d.ts.map +1 -1
- package/dist/fn.js +67 -32
- package/dist/fn.js.map +1 -1
- package/dist/folded-lengths.d.ts +16 -0
- package/dist/folded-lengths.d.ts.map +1 -0
- package/dist/folded-lengths.js +38 -0
- package/dist/folded-lengths.js.map +1 -0
- package/dist/index.d.ts +14 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -4
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +2 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +2 -0
- package/dist/internal.js.map +1 -1
- package/dist/library.d.ts +3 -1
- package/dist/library.d.ts.map +1 -1
- package/dist/library.js +3 -1
- package/dist/library.js.map +1 -1
- package/dist/lifecycle.d.ts +58 -11
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/lifecycle.js +95 -22
- package/dist/lifecycle.js.map +1 -1
- package/dist/listeners.d.ts.map +1 -1
- package/dist/listeners.js +19 -5
- package/dist/listeners.js.map +1 -1
- package/dist/mixin.d.ts +3 -2
- package/dist/mixin.d.ts.map +1 -1
- package/dist/mixin.js +13 -1
- package/dist/mixin.js.map +1 -1
- package/dist/native-value.d.ts.map +1 -1
- package/dist/native-value.js +4 -3
- package/dist/native-value.js.map +1 -1
- package/dist/object.d.ts +40 -7
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +95 -26
- 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 +147 -0
- package/dist/param-spec.js.map +1 -0
- package/dist/promisify.d.ts.map +1 -1
- package/dist/promisify.js +3 -2
- 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 +310 -43
- package/dist/properties.js.map +1 -1
- package/dist/register-class.d.ts +147 -12
- package/dist/register-class.d.ts.map +1 -1
- package/dist/register-class.js +129 -83
- package/dist/register-class.js.map +1 -1
- package/dist/registry.d.ts +80 -21
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +86 -33
- package/dist/registry.js.map +1 -1
- package/dist/signal.d.ts +11 -4
- package/dist/signal.d.ts.map +1 -1
- package/dist/signal.js +85 -25
- package/dist/signal.js.map +1 -1
- package/dist/t.d.ts +2 -0
- package/dist/t.d.ts.map +1 -1
- package/dist/t.js +1 -0
- package/dist/t.js.map +1 -1
- package/dist/tuple.d.ts +6 -3
- package/dist/tuple.d.ts.map +1 -1
- package/dist/tuple.js +9 -7
- package/dist/tuple.js.map +1 -1
- package/dist/type.d.ts +2 -1
- 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 -1
- package/dist/value.d.ts.map +1 -1
- package/dist/value.js +99 -24
- 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 +172 -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 +29 -0
- package/dist/vfunc.js.map +1 -0
- package/package.json +14 -4
- package/src/application-class.ts +126 -0
- package/src/arg.ts +2 -1
- package/src/bind.ts +11 -0
- package/src/callback.ts +178 -34
- package/src/closure.ts +136 -0
- package/src/default-application.ts +21 -0
- package/src/descriptors.ts +150 -34
- package/src/error.ts +1 -0
- package/src/exit-hook.ts +18 -0
- package/src/fn.ts +107 -36
- package/src/folded-lengths.ts +64 -0
- package/src/index.ts +21 -6
- package/src/internal.ts +2 -0
- package/src/library.ts +3 -1
- package/src/lifecycle.ts +138 -25
- package/src/listeners.ts +25 -6
- package/src/mixin.ts +15 -2
- package/src/native-value.ts +5 -3
- package/src/object.ts +134 -35
- package/src/param-spec.ts +234 -0
- package/src/promisify.ts +4 -2
- package/src/properties.ts +473 -46
- package/src/register-class.ts +386 -114
- package/src/registry.ts +169 -49
- package/src/signal.ts +116 -42
- package/src/t.ts +3 -0
- package/src/tuple.ts +18 -12
- package/src/type.ts +3 -1
- package/src/value.ts +143 -23
- package/src/vfunc-call.ts +247 -0
- package/src/vfunc-seeds.ts +36 -0
- package/src/vfunc.ts +38 -0
package/src/mixin.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AnyClass, getParentClass } from "@gtkx/utils";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* The signal plumbing every base class passed to a {@link Mixin} provides, so mixed-in interface
|
|
@@ -76,4 +76,17 @@ function installMixins(target: AnyClass, mixins: Mixin[]): void {
|
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
function dropLayerMembers(layer: AnyClass, names: Set<string>): void {
|
|
80
|
+
for (const name of names) {
|
|
81
|
+
Reflect.deleteProperty(layer.prototype, name);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function insertMixinLayer(target: AnyClass, mixin: Mixin, inheritedNames: Set<string>): void {
|
|
86
|
+
const layer = mixin(getParentClass(target) as AnyClass<MixinReceiver>);
|
|
87
|
+
dropLayerMembers(layer, inheritedNames);
|
|
88
|
+
Object.setPrototypeOf(target.prototype, layer.prototype);
|
|
89
|
+
Object.setPrototypeOf(target, layer);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export { insertMixinLayer, installMixins, type MixinReceiver, type Mixin };
|
package/src/native-value.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Descriptor, ExternalObject, Handle } from "@gtkx/native";
|
|
2
2
|
import type { ArrayDescriptor, FundamentalDescriptor, HashTableDescriptor, StructDescriptor } from "./descriptors.js";
|
|
3
|
-
import { getWrapperClass,
|
|
3
|
+
import { getHandle, getWrapperClass, wrapCallScopedObject, wrapHandle, wrapObject } from "./registry.js";
|
|
4
4
|
import { resolveDescriptorType } from "./type.js";
|
|
5
5
|
|
|
6
6
|
type MarshalledKind = "object" | "struct" | "boxed" | "fundamental" | "array" | "hashtable";
|
|
@@ -76,7 +76,7 @@ function fromNative(descriptor: Descriptor, value: unknown): unknown {
|
|
|
76
76
|
|
|
77
77
|
switch (descriptor.kind) {
|
|
78
78
|
case "object": {
|
|
79
|
-
return
|
|
79
|
+
return descriptor.isCallScoped === true ? wrapCallScopedObject(value) : wrapObject(value);
|
|
80
80
|
}
|
|
81
81
|
case "struct": {
|
|
82
82
|
return wrapHandle(value as ExternalObject<Handle> | null, (descriptor as StructDescriptor).wrapperClass);
|
|
@@ -129,7 +129,9 @@ function toNative(descriptor: Descriptor, value: unknown): unknown {
|
|
|
129
129
|
case "struct":
|
|
130
130
|
case "boxed":
|
|
131
131
|
case "fundamental": {
|
|
132
|
-
|
|
132
|
+
const instance = value as object | null | undefined;
|
|
133
|
+
|
|
134
|
+
return instance == null ? null : getHandle(instance);
|
|
133
135
|
}
|
|
134
136
|
case "array": {
|
|
135
137
|
return collectionToNative(descriptor, value);
|
package/src/object.ts
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Descriptor, type ExternalObject, type Handle, newObject } from "@gtkx/native";
|
|
2
|
+
import { type AnyClass, getParentClass } from "@gtkx/utils";
|
|
2
3
|
import { bind } from "./bind.js";
|
|
3
|
-
import {
|
|
4
|
-
import { LIB,
|
|
5
|
-
import {
|
|
4
|
+
import { objectT, stringT, voidT } from "./descriptors.js";
|
|
5
|
+
import { LIB, VALUE_T } from "./library.js";
|
|
6
|
+
import { type ConstructProperty, constructPropertyFor } from "./properties.js";
|
|
7
|
+
import { getHandle, registerWrapper } from "./registry.js";
|
|
6
8
|
import { fromValue, newValueForDescriptor, toValue } from "./value.js";
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
);
|
|
10
|
+
/**
|
|
11
|
+
* One construct property a wrapper class accepts: the canonical `GObject` name it is set under,
|
|
12
|
+
* and the descriptor its value is marshalled through.
|
|
13
|
+
*/
|
|
14
|
+
type ConstructBinding = [name: string, descriptor: Descriptor];
|
|
15
|
+
/** The construct properties a wrapper class accepts, keyed by the camelCased name callers give them. */
|
|
16
|
+
type ConstructBindings = Record<string, ConstructBinding>;
|
|
17
|
+
type ResolvedBindings = { generation: number; bindings: ConstructBindings };
|
|
18
|
+
|
|
19
|
+
const declaredBindings: WeakMap<AnyClass, ConstructBindings> = new WeakMap();
|
|
20
|
+
const resolvedBindings: WeakMap<AnyClass, ResolvedBindings> = new WeakMap();
|
|
21
|
+
const declarations = { generation: 0 };
|
|
22
|
+
const NO_BINDINGS: ConstructBindings = Object.create(null) as ConstructBindings;
|
|
19
23
|
|
|
20
24
|
const gObjectGetProperty = bind(
|
|
21
25
|
LIB,
|
|
@@ -31,37 +35,122 @@ const gObjectSetProperty = bind(
|
|
|
31
35
|
voidT,
|
|
32
36
|
);
|
|
33
37
|
|
|
38
|
+
function collectDeclaredBindings(cls: AnyClass): ConstructBindings[] {
|
|
39
|
+
const declared: ConstructBindings[] = [];
|
|
40
|
+
let current: AnyClass | null = cls;
|
|
41
|
+
|
|
42
|
+
while (current !== null) {
|
|
43
|
+
const own = declaredBindings.get(current);
|
|
44
|
+
|
|
45
|
+
if (own !== undefined) {
|
|
46
|
+
declared.push(own);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
current = getParentClass(current);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return declared;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function mergeDeclaredBindings(cls: AnyClass): ConstructBindings {
|
|
56
|
+
const declared = collectDeclaredBindings(cls);
|
|
57
|
+
const merged: ConstructBindings = Object.create(null) as ConstructBindings;
|
|
58
|
+
|
|
59
|
+
for (let index = declared.length - 1; index >= 0; index--) {
|
|
60
|
+
Object.assign(merged, declared[index]);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return merged;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function constructBindingsFor(cls: AnyClass | undefined): ConstructBindings {
|
|
67
|
+
if (cls === undefined) {
|
|
68
|
+
return NO_BINDINGS;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const cached = resolvedBindings.get(cls);
|
|
72
|
+
|
|
73
|
+
if (cached?.generation === declarations.generation) {
|
|
74
|
+
return cached.bindings;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const bindings = mergeDeclaredBindings(cls);
|
|
78
|
+
resolvedBindings.set(cls, { generation: declarations.generation, bindings });
|
|
79
|
+
|
|
80
|
+
return bindings;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Declares the construct properties a wrapper class accepts, so `newObjectWithProperties`
|
|
85
|
+
* marshals each one through its descriptor rather than resolving it from the
|
|
86
|
+
* `GObject.ParamSpec` the type installs. A class inherits the declarations of its ancestors.
|
|
87
|
+
* Registering takes effect immediately, including for classes already constructed from and for
|
|
88
|
+
* subclasses that already inherited an earlier declaration.
|
|
89
|
+
*
|
|
90
|
+
* @param cls The wrapper class the properties are declared on.
|
|
91
|
+
* @param bindings CamelCased property names mapped to their canonical name and descriptor.
|
|
92
|
+
*/
|
|
93
|
+
function registerConstructProperties(cls: AnyClass, bindings: ConstructBindings): void {
|
|
94
|
+
declaredBindings.set(cls, bindings);
|
|
95
|
+
declarations.generation += 1;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function constructPropertyForEntry(
|
|
99
|
+
source: { gtype: bigint; bindings: ConstructBindings; wrapper: object },
|
|
100
|
+
name: string,
|
|
101
|
+
value: unknown,
|
|
102
|
+
): ConstructProperty | undefined {
|
|
103
|
+
if (value === undefined) {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const binding = source.bindings[name];
|
|
108
|
+
|
|
109
|
+
if (binding === undefined) {
|
|
110
|
+
return constructPropertyFor(source.gtype, name, value, source.wrapper);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return { name: binding[0], value: toValue(binding[1], value) };
|
|
114
|
+
}
|
|
115
|
+
|
|
34
116
|
/**
|
|
35
117
|
* Constructs a new GObject of the given type, setting the supplied construct
|
|
36
|
-
* properties
|
|
37
|
-
*
|
|
118
|
+
* properties, and binds `wrapper` to it. A property the wrapper's class declares
|
|
119
|
+
* through `registerConstructProperties` is marshalled through its descriptor; any
|
|
120
|
+
* other one is marshalled through the `GObject.ParamSpec` the type installs under
|
|
121
|
+
* that name, dashed or camelCased, and is skipped when the type installs none.
|
|
122
|
+
* A value that ParamSpec would refuse throws before GObject sees it: a `TypeError`
|
|
123
|
+
* for a read-only property and for a value of a type the property cannot hold, and
|
|
124
|
+
* a `RangeError` for a value the ParamSpec rejects. A value marshalled through a
|
|
125
|
+
* declared descriptor is converted rather than checked, so a `null` handed to a
|
|
126
|
+
* numeric one of those lands 0 rather than being refused.
|
|
127
|
+
* Properties whose value is `undefined` are skipped. A type registered with
|
|
128
|
+
* `registerClass` binds the wrapper before its `constructed` slot runs, so an
|
|
129
|
+
* override of that slot already sees a usable instance.
|
|
38
130
|
*
|
|
39
131
|
* @param gtype The GType of the object to construct.
|
|
40
|
-
* @param props Property names mapped to
|
|
132
|
+
* @param props Property names mapped to the values to set them to.
|
|
133
|
+
* @param wrapper The wrapper instance to bind to the new object.
|
|
41
134
|
* @returns The handle of the newly created object.
|
|
42
135
|
*/
|
|
43
|
-
function newObjectWithProperties(gtype: bigint, props:
|
|
136
|
+
function newObjectWithProperties(gtype: bigint, props: object, wrapper: object): ExternalObject<Handle> {
|
|
44
137
|
const names: string[] = [];
|
|
45
138
|
const values: ExternalObject<Handle>[] = [];
|
|
139
|
+
const bindings = constructBindingsFor(wrapper.constructor as AnyClass | undefined);
|
|
140
|
+
const source = { gtype, bindings, wrapper };
|
|
46
141
|
|
|
47
|
-
for (const name
|
|
48
|
-
const
|
|
142
|
+
for (const name of Object.keys(props)) {
|
|
143
|
+
const property = constructPropertyForEntry(source, name, Reflect.get(props, name));
|
|
49
144
|
|
|
50
|
-
if (
|
|
51
|
-
|
|
145
|
+
if (property !== undefined) {
|
|
146
|
+
names.push(property.name);
|
|
147
|
+
values.push(property.value);
|
|
52
148
|
}
|
|
53
|
-
|
|
54
|
-
const [descriptor, value] = entry as [Descriptor, unknown];
|
|
55
|
-
|
|
56
|
-
if (value === undefined) {
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
names.push(name);
|
|
61
|
-
values.push(toValue(descriptor, value));
|
|
62
149
|
}
|
|
63
150
|
|
|
64
|
-
|
|
151
|
+
newObject(gtype, names, values, wrapper, registerWrapper);
|
|
152
|
+
|
|
153
|
+
return getHandle(wrapper);
|
|
65
154
|
}
|
|
66
155
|
|
|
67
156
|
/**
|
|
@@ -81,7 +170,10 @@ function getObjectProperty(obj: object, propertyName: string, descriptor: Descri
|
|
|
81
170
|
|
|
82
171
|
/**
|
|
83
172
|
* Writes a JavaScript value to a GObject property, converting it to native form
|
|
84
|
-
* using the descriptor.
|
|
173
|
+
* using the descriptor. The descriptor converts what it is given rather than checking it against
|
|
174
|
+
* the property's `GObject.ParamSpec`, so `null` and `undefined` written to a numeric or enum
|
|
175
|
+
* property land 0, where the same write to a property installed through `registerClass` is
|
|
176
|
+
* refused with a `TypeError`.
|
|
85
177
|
*
|
|
86
178
|
* @param obj The object to write to.
|
|
87
179
|
* @param propertyName The property name.
|
|
@@ -92,4 +184,11 @@ function setObjectProperty(obj: object, propertyName: string, descriptor: Descri
|
|
|
92
184
|
gObjectSetProperty(getHandle(obj), propertyName, toValue(descriptor, jsValue));
|
|
93
185
|
}
|
|
94
186
|
|
|
95
|
-
export {
|
|
187
|
+
export {
|
|
188
|
+
newObjectWithProperties,
|
|
189
|
+
getObjectProperty,
|
|
190
|
+
registerConstructProperties,
|
|
191
|
+
setObjectProperty,
|
|
192
|
+
type ConstructBinding,
|
|
193
|
+
type ConstructBindings,
|
|
194
|
+
};
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { type ExternalObject, type Handle, read } from "@gtkx/native";
|
|
2
|
+
import { bind } from "./bind.js";
|
|
3
|
+
import { biguint64T, booleanT, stringT, uint32T, voidT } from "./descriptors.js";
|
|
4
|
+
import { LIB, PARAM_T, VALUE_T } from "./library.js";
|
|
5
|
+
import { getInstanceType } from "./registry.js";
|
|
6
|
+
import {
|
|
7
|
+
getStrvType,
|
|
8
|
+
isTypedClass,
|
|
9
|
+
TYPE_BOOLEAN,
|
|
10
|
+
TYPE_BOXED,
|
|
11
|
+
TYPE_CHAR,
|
|
12
|
+
TYPE_DOUBLE,
|
|
13
|
+
TYPE_ENUM,
|
|
14
|
+
TYPE_FLAGS,
|
|
15
|
+
TYPE_FLOAT,
|
|
16
|
+
TYPE_GTYPE,
|
|
17
|
+
TYPE_INT,
|
|
18
|
+
TYPE_INT64,
|
|
19
|
+
TYPE_INTERFACE,
|
|
20
|
+
TYPE_INVALID,
|
|
21
|
+
TYPE_LONG,
|
|
22
|
+
TYPE_OBJECT,
|
|
23
|
+
TYPE_PARAM,
|
|
24
|
+
TYPE_POINTER,
|
|
25
|
+
TYPE_STRING,
|
|
26
|
+
TYPE_UCHAR,
|
|
27
|
+
TYPE_UINT,
|
|
28
|
+
TYPE_UINT64,
|
|
29
|
+
TYPE_ULONG,
|
|
30
|
+
TYPE_VARIANT,
|
|
31
|
+
typeFundamental,
|
|
32
|
+
typeIsA,
|
|
33
|
+
} from "./type.js";
|
|
34
|
+
|
|
35
|
+
type ValueGuard = (value: unknown) => boolean;
|
|
36
|
+
type ParamLayout = { flags: number; valueType: bigint };
|
|
37
|
+
|
|
38
|
+
const PARAM_READABLE = 1;
|
|
39
|
+
const PARAM_WRITABLE = 2;
|
|
40
|
+
const PARAM_CONSTRUCT_ONLY = 8;
|
|
41
|
+
const PARAM_LAX_VALIDATION = 16;
|
|
42
|
+
const READ_FLAGS = PARAM_READABLE | PARAM_WRITABLE | PARAM_CONSTRUCT_ONLY | PARAM_LAX_VALIDATION;
|
|
43
|
+
const FLAGS_BYTE_OFFSET = 16;
|
|
44
|
+
const VALUE_TYPE_BYTE_OFFSET = 24;
|
|
45
|
+
const LAYOUT_PROBE_NAME = "gtkx-param-layout";
|
|
46
|
+
const INT8_MINIMUM = -128;
|
|
47
|
+
const INT8_MAXIMUM = 127;
|
|
48
|
+
const UINT8_MAXIMUM = 255;
|
|
49
|
+
const INT32_MINIMUM = -2_147_483_648;
|
|
50
|
+
const INT32_MAXIMUM = 2_147_483_647;
|
|
51
|
+
const UINT32_MAXIMUM = 4_294_967_295;
|
|
52
|
+
const INT64_MINIMUM = -(2n ** 63n);
|
|
53
|
+
const INT64_MAXIMUM = 2n ** 63n - 1n;
|
|
54
|
+
const UINT64_MAXIMUM = 2n ** 64n - 1n;
|
|
55
|
+
|
|
56
|
+
const WRAPPED_FUNDAMENTALS: Set<bigint> = new Set([
|
|
57
|
+
TYPE_BOXED,
|
|
58
|
+
TYPE_INTERFACE,
|
|
59
|
+
TYPE_OBJECT,
|
|
60
|
+
TYPE_PARAM,
|
|
61
|
+
TYPE_VARIANT,
|
|
62
|
+
]);
|
|
63
|
+
|
|
64
|
+
const isWideUnsignedValue: ValueGuard = wideIntegerGuardFor(0n, UINT64_MAXIMUM);
|
|
65
|
+
|
|
66
|
+
const SCALAR_GUARDS: Map<bigint, ValueGuard> = new Map([
|
|
67
|
+
[TYPE_BOOLEAN, isBooleanValue],
|
|
68
|
+
[TYPE_STRING, isStringValue],
|
|
69
|
+
[TYPE_CHAR, integerGuardFor(INT8_MINIMUM, INT8_MAXIMUM)],
|
|
70
|
+
[TYPE_UCHAR, integerGuardFor(0, UINT8_MAXIMUM)],
|
|
71
|
+
[TYPE_INT, integerGuardFor(INT32_MINIMUM, INT32_MAXIMUM)],
|
|
72
|
+
[TYPE_UINT, integerGuardFor(0, UINT32_MAXIMUM)],
|
|
73
|
+
[TYPE_ENUM, integerGuardFor(INT32_MINIMUM, INT32_MAXIMUM)],
|
|
74
|
+
[TYPE_FLAGS, integerGuardFor(0, UINT32_MAXIMUM)],
|
|
75
|
+
[TYPE_LONG, wideIntegerGuardFor(INT64_MINIMUM, INT64_MAXIMUM)],
|
|
76
|
+
[TYPE_ULONG, isWideUnsignedValue],
|
|
77
|
+
[TYPE_INT64, wideIntegerGuardFor(INT64_MINIMUM, INT64_MAXIMUM)],
|
|
78
|
+
[TYPE_UINT64, isWideUnsignedValue],
|
|
79
|
+
[TYPE_FLOAT, isNumberValue],
|
|
80
|
+
[TYPE_DOUBLE, isNumberValue],
|
|
81
|
+
[TYPE_POINTER, isNullValue],
|
|
82
|
+
]);
|
|
83
|
+
|
|
84
|
+
const layout = { wasChecked: false };
|
|
85
|
+
const paramValueValidate = bind(LIB, "g_param_value_validate", [PARAM_T, VALUE_T], booleanT);
|
|
86
|
+
const paramSpecUnref = bind(LIB, "g_param_spec_unref", [PARAM_T], voidT);
|
|
87
|
+
const paramSpecRefSink = bind(LIB, "g_param_spec_ref_sink", [PARAM_T], PARAM_T);
|
|
88
|
+
|
|
89
|
+
const newParamSpecBoolean = bind(
|
|
90
|
+
LIB,
|
|
91
|
+
"g_param_spec_boolean",
|
|
92
|
+
[stringT("borrowed"), stringT("borrowed"), stringT("borrowed"), booleanT, uint32T],
|
|
93
|
+
PARAM_T,
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
const getParamFlags = (pspec: ExternalObject<Handle>): number => read(pspec, uint32T, FLAGS_BYTE_OFFSET) as number;
|
|
97
|
+
|
|
98
|
+
const getParamValueType = (pspec: ExternalObject<Handle>): bigint =>
|
|
99
|
+
read(pspec, biguint64T, VALUE_TYPE_BYTE_OFFSET) as bigint;
|
|
100
|
+
|
|
101
|
+
const isParamWritable = (flags: number): boolean => (flags & PARAM_WRITABLE) !== 0;
|
|
102
|
+
const isParamConstructOnly = (flags: number): boolean => (flags & PARAM_CONSTRUCT_ONLY) !== 0;
|
|
103
|
+
const isParamLaxlyValidated = (flags: number): boolean => (flags & PARAM_LAX_VALIDATION) !== 0;
|
|
104
|
+
|
|
105
|
+
const wasParamValueModified = (pspec: ExternalObject<Handle>, value: ExternalObject<Handle>): boolean =>
|
|
106
|
+
paramValueValidate(pspec, value) as boolean;
|
|
107
|
+
|
|
108
|
+
function isBooleanValue(value: unknown): boolean {
|
|
109
|
+
return typeof value === "boolean";
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function isStringValue(value: unknown): boolean {
|
|
113
|
+
return value == null || typeof value === "string";
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function isStrvValue(value: unknown): boolean {
|
|
117
|
+
return value == null || (Array.isArray(value) && value.every((item) => typeof item === "string"));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function isNumberValue(value: unknown): boolean {
|
|
121
|
+
return typeof value === "number";
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function isAnyValue(): boolean {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function isNullValue(value: unknown): boolean {
|
|
129
|
+
return value == null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function integerGuardFor(minimum: number, maximum: number): ValueGuard {
|
|
133
|
+
return (value) => Number.isSafeInteger(value) && (value as number) >= minimum && (value as number) <= maximum;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function toWideInteger(value: unknown): bigint | undefined {
|
|
137
|
+
if (typeof value === "bigint") {
|
|
138
|
+
return value;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return Number.isSafeInteger(value) ? BigInt(value as number) : undefined;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function wideIntegerGuardFor(minimum: bigint, maximum: bigint): ValueGuard {
|
|
145
|
+
return (value) => {
|
|
146
|
+
const wide = toWideInteger(value);
|
|
147
|
+
|
|
148
|
+
return wide !== undefined && wide >= minimum && wide <= maximum;
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function resolveGtype(value: unknown): bigint {
|
|
153
|
+
const instanceType = getInstanceType(value as object);
|
|
154
|
+
|
|
155
|
+
if (instanceType !== TYPE_INVALID) {
|
|
156
|
+
return instanceType;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return isTypedClass(value) ? value.__type__ : TYPE_INVALID;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function wrappedGuardFor(valueType: bigint): ValueGuard {
|
|
163
|
+
return (value) => value == null || typeIsA(resolveGtype(value), valueType);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function exactGuardFor(valueType: bigint): ValueGuard | undefined {
|
|
167
|
+
if (valueType === TYPE_GTYPE) {
|
|
168
|
+
return isWideUnsignedValue;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return valueType === getStrvType() ? isStrvValue : undefined;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function valueGuardFor(valueType: bigint): ValueGuard {
|
|
175
|
+
assertParamLayout();
|
|
176
|
+
const exact = exactGuardFor(valueType);
|
|
177
|
+
|
|
178
|
+
if (exact !== undefined) {
|
|
179
|
+
return exact;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const fundamental = typeFundamental(valueType);
|
|
183
|
+
|
|
184
|
+
if (WRAPPED_FUNDAMENTALS.has(fundamental)) {
|
|
185
|
+
return wrappedGuardFor(valueType);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return SCALAR_GUARDS.get(fundamental) ?? isAnyValue;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function readProbeLayout(flags: number): ParamLayout {
|
|
192
|
+
const probe = newParamSpecBoolean(LAYOUT_PROBE_NAME, null, null, false, flags) as ExternalObject<Handle>;
|
|
193
|
+
paramSpecRefSink(probe);
|
|
194
|
+
|
|
195
|
+
try {
|
|
196
|
+
return { flags: getParamFlags(probe), valueType: getParamValueType(probe) };
|
|
197
|
+
} finally {
|
|
198
|
+
paramSpecUnref(probe);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function isLayoutIntact(flags: number): boolean {
|
|
203
|
+
const layout = readProbeLayout(flags);
|
|
204
|
+
|
|
205
|
+
return (layout.flags & READ_FLAGS) === flags && layout.valueType === TYPE_BOOLEAN;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function assertParamLayout(): void {
|
|
209
|
+
if (layout.wasChecked) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
layout.wasChecked = true;
|
|
214
|
+
const readWrite = PARAM_READABLE | PARAM_WRITABLE;
|
|
215
|
+
|
|
216
|
+
if (isLayoutIntact(readWrite) && isLayoutIntact(readWrite | PARAM_CONSTRUCT_ONLY | PARAM_LAX_VALIDATION)) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
throw new Error(
|
|
221
|
+
"GParamSpec does not match the memory layout this build reads a property's flags and value type at",
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export {
|
|
226
|
+
getParamFlags,
|
|
227
|
+
getParamValueType,
|
|
228
|
+
isParamConstructOnly,
|
|
229
|
+
isParamLaxlyValidated,
|
|
230
|
+
isParamWritable,
|
|
231
|
+
type ValueGuard,
|
|
232
|
+
valueGuardFor,
|
|
233
|
+
wasParamValueModified,
|
|
234
|
+
};
|
package/src/promisify.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getHandle } from "./registry.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Extracts the value of a completed asynchronous operation from its `GAsyncResult`, throwing when
|
|
@@ -57,7 +57,9 @@ const promisify = <R extends object, T>(
|
|
|
57
57
|
const creationStack =
|
|
58
58
|
process.env.NODE_ENV === "production" ? undefined : new Error("GTKX async operation started here");
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
const cancellableHandle = cancellable == null ? null : getHandle(cancellable);
|
|
61
|
+
|
|
62
|
+
asyncFn(...leading, cancellableHandle, (_source: object | null, asyncResult: object) => {
|
|
61
63
|
settle({ finish, creationStack, resolve, reject }, asyncResult);
|
|
62
64
|
});
|
|
63
65
|
});
|