@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.
Files changed (156) hide show
  1. package/README.md +5 -5
  2. package/dist/application-class.d.ts +37 -0
  3. package/dist/application-class.d.ts.map +1 -0
  4. package/dist/application-class.js +78 -0
  5. package/dist/application-class.js.map +1 -0
  6. package/dist/arg.d.ts +2 -1
  7. package/dist/arg.d.ts.map +1 -1
  8. package/dist/arg.js +2 -1
  9. package/dist/arg.js.map +1 -1
  10. package/dist/bind.d.ts +11 -0
  11. package/dist/bind.d.ts.map +1 -1
  12. package/dist/bind.js +11 -0
  13. package/dist/bind.js.map +1 -1
  14. package/dist/callback.d.ts +4 -3
  15. package/dist/callback.d.ts.map +1 -1
  16. package/dist/callback.js +124 -29
  17. package/dist/callback.js.map +1 -1
  18. package/dist/closure.d.ts +26 -0
  19. package/dist/closure.d.ts.map +1 -0
  20. package/dist/closure.js +99 -0
  21. package/dist/closure.js.map +1 -0
  22. package/dist/default-application.d.ts +4 -0
  23. package/dist/default-application.d.ts.map +1 -0
  24. package/dist/default-application.js +17 -0
  25. package/dist/default-application.js.map +1 -0
  26. package/dist/descriptors.d.ts +98 -4
  27. package/dist/descriptors.d.ts.map +1 -1
  28. package/dist/descriptors.js +72 -6
  29. package/dist/descriptors.js.map +1 -1
  30. package/dist/error.d.ts +1 -0
  31. package/dist/error.d.ts.map +1 -1
  32. package/dist/error.js.map +1 -1
  33. package/dist/exit-hook.js +13 -0
  34. package/dist/exit-hook.js.map +1 -1
  35. package/dist/fn.d.ts +24 -2
  36. package/dist/fn.d.ts.map +1 -1
  37. package/dist/fn.js +67 -32
  38. package/dist/fn.js.map +1 -1
  39. package/dist/folded-lengths.d.ts +16 -0
  40. package/dist/folded-lengths.d.ts.map +1 -0
  41. package/dist/folded-lengths.js +38 -0
  42. package/dist/folded-lengths.js.map +1 -0
  43. package/dist/index.d.ts +14 -6
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +12 -4
  46. package/dist/index.js.map +1 -1
  47. package/dist/internal.d.ts +2 -0
  48. package/dist/internal.d.ts.map +1 -1
  49. package/dist/internal.js +2 -0
  50. package/dist/internal.js.map +1 -1
  51. package/dist/library.d.ts +3 -1
  52. package/dist/library.d.ts.map +1 -1
  53. package/dist/library.js +3 -1
  54. package/dist/library.js.map +1 -1
  55. package/dist/lifecycle.d.ts +58 -11
  56. package/dist/lifecycle.d.ts.map +1 -1
  57. package/dist/lifecycle.js +95 -22
  58. package/dist/lifecycle.js.map +1 -1
  59. package/dist/listeners.d.ts.map +1 -1
  60. package/dist/listeners.js +19 -5
  61. package/dist/listeners.js.map +1 -1
  62. package/dist/mixin.d.ts +3 -2
  63. package/dist/mixin.d.ts.map +1 -1
  64. package/dist/mixin.js +13 -1
  65. package/dist/mixin.js.map +1 -1
  66. package/dist/native-value.d.ts.map +1 -1
  67. package/dist/native-value.js +4 -3
  68. package/dist/native-value.js.map +1 -1
  69. package/dist/object.d.ts +40 -7
  70. package/dist/object.d.ts.map +1 -1
  71. package/dist/object.js +95 -26
  72. package/dist/object.js.map +1 -1
  73. package/dist/param-spec.d.ts +11 -0
  74. package/dist/param-spec.d.ts.map +1 -0
  75. package/dist/param-spec.js +147 -0
  76. package/dist/param-spec.js.map +1 -0
  77. package/dist/promisify.d.ts.map +1 -1
  78. package/dist/promisify.js +3 -2
  79. package/dist/promisify.js.map +1 -1
  80. package/dist/properties.d.ts +39 -7
  81. package/dist/properties.d.ts.map +1 -1
  82. package/dist/properties.js +310 -43
  83. package/dist/properties.js.map +1 -1
  84. package/dist/register-class.d.ts +147 -12
  85. package/dist/register-class.d.ts.map +1 -1
  86. package/dist/register-class.js +129 -83
  87. package/dist/register-class.js.map +1 -1
  88. package/dist/registry.d.ts +80 -21
  89. package/dist/registry.d.ts.map +1 -1
  90. package/dist/registry.js +86 -33
  91. package/dist/registry.js.map +1 -1
  92. package/dist/signal.d.ts +11 -4
  93. package/dist/signal.d.ts.map +1 -1
  94. package/dist/signal.js +85 -25
  95. package/dist/signal.js.map +1 -1
  96. package/dist/t.d.ts +2 -0
  97. package/dist/t.d.ts.map +1 -1
  98. package/dist/t.js +1 -0
  99. package/dist/t.js.map +1 -1
  100. package/dist/tuple.d.ts +6 -3
  101. package/dist/tuple.d.ts.map +1 -1
  102. package/dist/tuple.js +9 -7
  103. package/dist/tuple.js.map +1 -1
  104. package/dist/type.d.ts +2 -1
  105. package/dist/type.d.ts.map +1 -1
  106. package/dist/type.js +2 -0
  107. package/dist/type.js.map +1 -1
  108. package/dist/value.d.ts +10 -1
  109. package/dist/value.d.ts.map +1 -1
  110. package/dist/value.js +99 -24
  111. package/dist/value.js.map +1 -1
  112. package/dist/vfunc-call.d.ts +37 -0
  113. package/dist/vfunc-call.d.ts.map +1 -0
  114. package/dist/vfunc-call.js +172 -0
  115. package/dist/vfunc-call.js.map +1 -0
  116. package/dist/vfunc-seeds.d.ts +12 -0
  117. package/dist/vfunc-seeds.d.ts.map +1 -0
  118. package/dist/vfunc-seeds.js +19 -0
  119. package/dist/vfunc-seeds.js.map +1 -0
  120. package/dist/vfunc.d.ts +8 -0
  121. package/dist/vfunc.d.ts.map +1 -0
  122. package/dist/vfunc.js +29 -0
  123. package/dist/vfunc.js.map +1 -0
  124. package/package.json +14 -4
  125. package/src/application-class.ts +126 -0
  126. package/src/arg.ts +2 -1
  127. package/src/bind.ts +11 -0
  128. package/src/callback.ts +178 -34
  129. package/src/closure.ts +136 -0
  130. package/src/default-application.ts +21 -0
  131. package/src/descriptors.ts +150 -34
  132. package/src/error.ts +1 -0
  133. package/src/exit-hook.ts +18 -0
  134. package/src/fn.ts +107 -36
  135. package/src/folded-lengths.ts +64 -0
  136. package/src/index.ts +21 -6
  137. package/src/internal.ts +2 -0
  138. package/src/library.ts +3 -1
  139. package/src/lifecycle.ts +138 -25
  140. package/src/listeners.ts +25 -6
  141. package/src/mixin.ts +15 -2
  142. package/src/native-value.ts +5 -3
  143. package/src/object.ts +134 -35
  144. package/src/param-spec.ts +234 -0
  145. package/src/promisify.ts +4 -2
  146. package/src/properties.ts +473 -46
  147. package/src/register-class.ts +386 -114
  148. package/src/registry.ts +169 -49
  149. package/src/signal.ts +116 -42
  150. package/src/t.ts +3 -0
  151. package/src/tuple.ts +18 -12
  152. package/src/type.ts +3 -1
  153. package/src/value.ts +143 -23
  154. package/src/vfunc-call.ts +247 -0
  155. package/src/vfunc-seeds.ts +36 -0
  156. package/src/vfunc.ts +38 -0
package/src/closure.ts ADDED
@@ -0,0 +1,136 @@
1
+ import { type ExternalObject, type Handle, read } from "@gtkx/native";
2
+ import { type AnyClass } from "@gtkx/utils";
3
+ import { bind } from "./bind.js";
4
+ import { boxedT, callbackT, sizedArrayT, structT, uint32T, uint64T, voidT } from "./descriptors.js";
5
+ import { CLOSURE_SIZE, LIB, VALUE_SIZE, VALUE_T } from "./library.js";
6
+ import { getClassType, getHandle, getWrapperClass, instanceClassName, wrapHandle } from "./registry.js";
7
+ import { resolveBoxedType, typeIsA } from "./type.js";
8
+ import { fromValue, getValueType, intoValue } from "./value.js";
9
+
10
+ /**
11
+ * Handler backing a `GClosure`. It receives the closure's parameters already converted from their
12
+ * `GValue`s, and its result is written back into the closure's return `GValue` when it has one.
13
+ *
14
+ * A parameter that is itself a `GValue`, such as the target a property binding transform fills in,
15
+ * arrives as the caller's own `GObject.Value` rather than a copy, so writing to it is how the
16
+ * handler produces that parameter's value. It stops being valid once the handler returns.
17
+ */
18
+ type ClosureCallback = (...args: never[]) => unknown;
19
+
20
+ const CCLOSURE_CALLBACK_OFFSET = CLOSURE_SIZE;
21
+ const N_PARAM_VALUES_INDEX = 2;
22
+ const MARSHAL_DATA_INDEX = 5;
23
+ const CLOSURE_T = boxedT("GClosure", { sharedLibrary: LIB, getTypeFnName: "g_closure_get_type" });
24
+
25
+ const OWNED_CLOSURE_T = boxedT("GClosure", {
26
+ ownership: "full",
27
+ sharedLibrary: LIB,
28
+ getTypeFnName: "g_closure_get_type",
29
+ });
30
+
31
+ const MARSHAL_VALUE_T = boxedT("GValue", {
32
+ sharedLibrary: LIB,
33
+ getTypeFnName: "g_value_get_type",
34
+ size: VALUE_SIZE,
35
+ isCallerAllocated: true,
36
+ });
37
+
38
+ const MARSHAL_T = callbackT(
39
+ [
40
+ CLOSURE_T,
41
+ MARSHAL_VALUE_T,
42
+ uint32T,
43
+ sizedArrayT(MARSHAL_VALUE_T, N_PARAM_VALUES_INDEX, "borrowed", VALUE_SIZE),
44
+ uint64T,
45
+ uint64T,
46
+ ],
47
+ voidT,
48
+ {
49
+ hasUserData: true,
50
+ userDataIndex: MARSHAL_DATA_INDEX,
51
+ hasDestroy: true,
52
+ destroyKind: "closureNotify",
53
+ scope: "notified",
54
+ },
55
+ );
56
+
57
+ const NESTED_VALUE_T = structT("borrowed");
58
+ const gCclosureNew = bind(LIB, "g_cclosure_new", [MARSHAL_T], OWNED_CLOSURE_T);
59
+ const gValueGetBoxed = bind(LIB, "g_value_get_boxed", [VALUE_T], NESTED_VALUE_T);
60
+ const gClosureRef = bind(LIB, "g_closure_ref", [CLOSURE_T], uint64T);
61
+ const gClosureSink = bind(LIB, "g_closure_sink", [CLOSURE_T], voidT);
62
+ const gClosureSetMarshal = bind(LIB, "g_closure_set_marshal", [CLOSURE_T, uint64T], voidT);
63
+
64
+ const isClosureInstance = (value: object): boolean =>
65
+ typeIsA(getClassType(value.constructor as AnyClass), resolveBoxedType(CLOSURE_T));
66
+
67
+ const getNestedValue = (param: ExternalObject<Handle>): object | null =>
68
+ wrapHandle(gValueGetBoxed(param) as ExternalObject<Handle> | null, getWrapperClass(resolveBoxedType(VALUE_T)));
69
+
70
+ const fromParamValue = (param: ExternalObject<Handle>): unknown =>
71
+ getValueType(param) === resolveBoxedType(VALUE_T) ? getNestedValue(param) : fromValue(param);
72
+
73
+ function describeValue(value: unknown): string {
74
+ if (value === null) {
75
+ return "null";
76
+ }
77
+
78
+ if (typeof value !== "object") {
79
+ return typeof value;
80
+ }
81
+
82
+ return instanceClassName(value);
83
+ }
84
+
85
+ function marshalFor(callback: ClosureCallback): (...args: unknown[]) => void {
86
+ return (_closure: unknown, returnValue: unknown, _count: unknown, paramValues: unknown): void => {
87
+ const values = paramValues as ExternalObject<Handle>[];
88
+ const args = values.map((value) => fromParamValue(value));
89
+ const result = (callback as (...values: unknown[]) => unknown)(...(args as never[]));
90
+
91
+ if (returnValue !== null) {
92
+ intoValue(returnValue as ExternalObject<Handle>, result);
93
+ }
94
+ };
95
+ }
96
+
97
+ function newClosure(callback: ClosureCallback): ExternalObject<Handle> {
98
+ const handle = gCclosureNew(marshalFor(callback)) as ExternalObject<Handle>;
99
+ const marshal = read(handle, uint64T, CCLOSURE_CALLBACK_OFFSET);
100
+ gClosureRef(handle);
101
+ gClosureSink(handle);
102
+ gClosureSetMarshal(handle, marshal);
103
+
104
+ return handle;
105
+ }
106
+
107
+ /**
108
+ * Marshals a value passed where a `GObject.Closure` is expected into a closure handle: a function
109
+ * becomes a new `GClosure` dispatching into it, and an existing closure yields its own handle.
110
+ * @param value Function to wrap, or an already-built closure.
111
+ * @throws {ClosureMarshalError} When the value is neither.
112
+ */
113
+ function toClosure(value: unknown): ExternalObject<Handle> {
114
+ if (typeof value === "function") {
115
+ return newClosure(value as ClosureCallback);
116
+ }
117
+
118
+ if (typeof value === "object" && value !== null && isClosureInstance(value)) {
119
+ return getHandle(value);
120
+ }
121
+
122
+ throw new ClosureMarshalError(`Cannot marshal ${describeValue(value)} into a GObject.Closure`);
123
+ }
124
+
125
+ /** Same as {@link toClosure}, but passes a null or undefined value through as no closure at all. */
126
+ function tryToClosure(value: unknown): ExternalObject<Handle> | undefined {
127
+ return value == null ? undefined : toClosure(value);
128
+ }
129
+
130
+ /** Thrown when a value passed where a `GObject.Closure` is expected cannot be marshalled into one. */
131
+ class ClosureMarshalError extends TypeError {
132
+ /** Name callers match on when the error is caught as a plain `TypeError`. */
133
+ public override name = "ClosureMarshalError";
134
+ }
135
+
136
+ export { type ClosureCallback, ClosureMarshalError, toClosure, tryToClosure };
@@ -0,0 +1,21 @@
1
+ import { bind } from "./bind.js";
2
+ import { objectT, voidT } from "./descriptors.js";
3
+ import { GIO_LIB } from "./library.js";
4
+ import { getHandle } from "./registry.js";
5
+
6
+ const readDefaultApplication = bind(GIO_LIB, "g_application_get_default", [], objectT("borrowed"));
7
+ const writeDefaultApplication = bind(GIO_LIB, "g_application_set_default", [objectT("borrowed")], voidT);
8
+
9
+ const claimDefaultApplication = (application: object): void => {
10
+ writeDefaultApplication(getHandle(application));
11
+ };
12
+
13
+ const releaseDefaultApplication = (application: object): void => {
14
+ if (readDefaultApplication() !== application) {
15
+ return;
16
+ }
17
+
18
+ writeDefaultApplication(null);
19
+ };
20
+
21
+ export { claimDefaultApplication, releaseDefaultApplication };
@@ -1,43 +1,75 @@
1
1
  import type { ArrayKind, Descriptor, Ownership } from "@gtkx/native";
2
2
  import type { AnyClass } from "@gtkx/utils";
3
3
 
4
+ /** Descriptor variant for a `gint8`. */
4
5
  type Int8Descriptor = Extract<Descriptor, { kind: "int8" }>;
6
+ /** Descriptor variant for a `guint8`. */
5
7
  type Uint8Descriptor = Extract<Descriptor, { kind: "uint8" }>;
8
+ /** Descriptor variant for a `gint16`. */
6
9
  type Int16Descriptor = Extract<Descriptor, { kind: "int16" }>;
10
+ /** Descriptor variant for a `guint16`. */
7
11
  type Uint16Descriptor = Extract<Descriptor, { kind: "uint16" }>;
12
+ /** Descriptor variant for a `gint32`. */
8
13
  type Int32Descriptor = Extract<Descriptor, { kind: "int32" }>;
14
+ /** Descriptor variant for a `guint32`. */
9
15
  type Uint32Descriptor = Extract<Descriptor, { kind: "uint32" }>;
16
+ /** Descriptor variant for a `gint64` marshalled as a number. */
10
17
  type Int64Descriptor = Extract<Descriptor, { kind: "int64" }>;
18
+ /** Descriptor variant for a `guint64` marshalled as a number. */
11
19
  type Uint64Descriptor = Extract<Descriptor, { kind: "uint64" }>;
20
+ /** Descriptor variant for a `gint64` marshalled as a bigint. */
12
21
  type BigInt64Descriptor = Extract<Descriptor, { kind: "bigint64" }>;
22
+ /** Descriptor variant for a `guint64` marshalled as a bigint. */
13
23
  type BigUint64Descriptor = Extract<Descriptor, { kind: "biguint64" }>;
24
+ /** Descriptor variant for a `gfloat`. */
14
25
  type Float32Descriptor = Extract<Descriptor, { kind: "float32" }>;
26
+ /** Descriptor variant for a `gdouble`. */
15
27
  type Float64Descriptor = Extract<Descriptor, { kind: "float64" }>;
28
+ /** Descriptor variant for an enumeration, carrying the library and `get_type` symbol its GType comes from. */
16
29
  type EnumDescriptor = Extract<Descriptor, { kind: "enum" }>;
30
+ /** Descriptor variant for a flags type, carrying the library and `get_type` symbol its GType comes from. */
17
31
  type FlagsDescriptor = Extract<Descriptor, { kind: "flags" }>;
32
+ /** Descriptor variant for a `gboolean`. */
18
33
  type BooleanDescriptor = Extract<Descriptor, { kind: "boolean" }>;
34
+ /** Descriptor variant for a C string. */
19
35
  type StringDescriptor = Extract<Descriptor, { kind: "string" }>;
36
+ /** Descriptor variant for a `GObject`. */
20
37
  type ObjectDescriptor = Extract<Descriptor, { kind: "object" }>;
38
+ /** Descriptor variant for a `gunichar`. */
21
39
  type UnicharDescriptor = Extract<Descriptor, { kind: "unichar" }>;
40
+ /** Descriptor variant for the absence of a value. */
22
41
  type VoidDescriptor = Extract<Descriptor, { kind: "void" }>;
42
+ /** Descriptor variant for an opaque `gpointer`. */
23
43
  type BufferDescriptor = Extract<Descriptor, { kind: "buffer" }>;
44
+ /** Descriptor variant for a `GBoxed` value. */
24
45
  type BoxedDescriptor = Extract<Descriptor, { kind: "boxed" }>;
25
46
 
47
+ /** Descriptor variant for a plain C struct, extended with the class its decoded value is wrapped in. */
26
48
  type StructDescriptor = Extract<Descriptor, { kind: "struct" }> & {
27
49
  /** Class a decoded value is wrapped in; without it the wrapper comes from the value's own GType. */
28
50
  wrapperClass?: AnyClass;
29
51
  };
30
52
 
53
+ /** Descriptor variant for a ref-counted fundamental type, extended with the class its decoded value is wrapped in. */
31
54
  type FundamentalDescriptor = Extract<Descriptor, { kind: "fundamental" }> & {
32
55
  /** Class a decoded value is wrapped in; without it the wrapper comes from the type named by `typeName`. */
33
56
  wrapperClass?: AnyClass;
34
57
  };
35
58
 
59
+ /** Descriptor variant for an array of items in one of the supported container layouts. */
36
60
  type ArrayDescriptor = Extract<Descriptor, { kind: "array" }>;
61
+ /** Descriptor variant for a `GHashTable`, marshalled as an array of key/value pairs. */
37
62
  type HashTableDescriptor = Extract<Descriptor, { kind: "hashtable" }>;
63
+ /** Descriptor variant for a function pointer a JavaScript function is marshalled into. */
38
64
  type CallbackDescriptor = Extract<Descriptor, { kind: "callback" }>;
65
+ /** Descriptor variant for a pointer to another descriptor's value, for an output or inout argument. */
39
66
  type RefDescriptor = Extract<Descriptor, { kind: "ref" }>;
40
- type TypeDescriptor = BigUint64Descriptor & { type: true };
67
+
68
+ /** Descriptor for a `GType`: a `guint64` marked so it resolves to `G_TYPE_GTYPE` rather than an integer. */
69
+ type TypeDescriptor = BigUint64Descriptor & {
70
+ /** Distinguishes a GType from a plain `guint64` when the GLib type and the GValue type are resolved. */
71
+ type: true;
72
+ };
41
73
 
42
74
  /** How a boxed value is stored, and where its GType and free function are resolved from. */
43
75
  type BoxedOptions = {
@@ -57,11 +89,18 @@ type BoxedOptions = {
57
89
  size?: number;
58
90
  };
59
91
 
60
- /** How the callee takes a callback's closure, and how long that closure has to stay alive. */
92
+ /**
93
+ * What the bindings do with a callback's return value, how the callee takes its closure, and how
94
+ * long that closure has to stay alive.
95
+ */
61
96
  type CallbackOptions = {
62
- /** The callee also takes a `GDestroyNotify`, which frees the closure once it is done with it. */
97
+ /** The callee also takes a destroy notify, which frees the closure once it is done with it. */
63
98
  hasDestroy?: boolean;
64
- /** Position of the `user_data` argument carrying the closure; without one it can never be freed. */
99
+ /** Signature of that destroy notify; defaults to `destroyNotify`, a one-argument `GDestroyNotify`. */
100
+ destroyKind?: CallbackDescriptor["destroyKind"];
101
+ /** The callee also takes a `user_data` pointer; without one the closure can never be freed. */
102
+ hasUserData?: boolean;
103
+ /** Position of `user_data` among the callback's own arguments, dropped before the closure is called. */
65
104
  userDataIndex?: number;
66
105
  /** Lifetime of the closure; defaults to `notified` when `hasDestroy` is set and `call` otherwise. */
67
106
  scope?: CallbackDescriptor["scope"];
@@ -71,12 +110,22 @@ type CallbackOptions = {
71
110
  type ArrayOptions = {
72
111
  /** Stride in bytes between elements stored inline in the array. */
73
112
  elementSize?: number | undefined;
113
+ /** Position of the argument whose buffer a cursor array points into. */
114
+ baseParamIndex?: number | undefined;
74
115
  /** Position of the argument carrying the element count, for a length-bounded array. */
75
116
  sizeParamIndex?: number | undefined;
76
117
  /** Element count of a fixed-length array. */
77
118
  fixedSize?: number | undefined;
78
119
  };
79
120
 
121
+ /** Where a cursor array's base buffer and total length come from. */
122
+ type CursorBounds = {
123
+ /** Position of the argument holding the buffer the cursor points into. */
124
+ baseParamIndex: number;
125
+ /** Position of the argument carrying that buffer's element count. */
126
+ sizeParamIndex: number;
127
+ };
128
+
80
129
  /** How a ref-counted fundamental value is named, wrapped and stored. */
81
130
  type FundamentalOptions = {
82
131
  /** Whether a decoded value is owned by the caller; defaults to `"borrowed"`. */
@@ -89,6 +138,12 @@ type FundamentalOptions = {
89
138
  isInline?: boolean;
90
139
  };
91
140
 
141
+ type FundamentalLifecycle = {
142
+ sharedLibrary: string;
143
+ refFnName: string;
144
+ unrefFnName: string;
145
+ };
146
+
92
147
  /** How a plain C struct is stored and wrapped. */
93
148
  type StructOptions = {
94
149
  /** The caller owns the storage the callee fills, so a decoded value is borrowed instead of copied. */
@@ -101,32 +156,57 @@ type StructOptions = {
101
156
  wrapperClass?: AnyClass;
102
157
  };
103
158
 
159
+ /** Descriptor for a `gint8`, marshalled as a number. */
104
160
  const int8T: Int8Descriptor = { kind: "int8" };
161
+ /** Descriptor for a `guint8`, marshalled as a number. */
105
162
  const uint8T: Uint8Descriptor = { kind: "uint8" };
163
+ /** Descriptor for a `gint16`, marshalled as a number. */
106
164
  const int16T: Int16Descriptor = { kind: "int16" };
165
+ /** Descriptor for a `guint16`, marshalled as a number. */
107
166
  const uint16T: Uint16Descriptor = { kind: "uint16" };
167
+ /** Descriptor for a `gint32`, marshalled as a number. */
108
168
  const int32T: Int32Descriptor = { kind: "int32" };
169
+ /** Descriptor for a `guint32`, marshalled as a number. */
109
170
  const uint32T: Uint32Descriptor = { kind: "uint32" };
171
+ /** Descriptor for a `gint64`, marshalled as a number and rejected outside the 2^53 safe range. */
110
172
  const int64T: Int64Descriptor = { kind: "int64" };
173
+ /** Descriptor for a `guint64`, marshalled as a number and rejected outside the 2^53 safe range. */
111
174
  const uint64T: Uint64Descriptor = { kind: "uint64" };
175
+ /** Descriptor for a `gint64`, marshalled as a bigint so the full 64-bit range survives. */
112
176
  const bigint64T: BigInt64Descriptor = { kind: "bigint64" };
177
+ /** Descriptor for a `guint64`, marshalled as a bigint so the full 64-bit range survives. */
113
178
  const biguint64T: BigUint64Descriptor = { kind: "biguint64" };
179
+ /** Descriptor for a `GType`, marshalled as a bigint and recognized as a GType by GValue conversion. */
114
180
  const gtypeT: TypeDescriptor = { kind: "biguint64", type: true };
181
+ /** Descriptor for a `gfloat`. */
115
182
  const float32T: Float32Descriptor = { kind: "float32" };
183
+ /** Descriptor for a `gdouble`. */
116
184
  const float64T: Float64Descriptor = { kind: "float64" };
185
+ /** Descriptor for a `gboolean`, marshalled as a JavaScript boolean. */
117
186
  const booleanT: BooleanDescriptor = { kind: "boolean" };
187
+ /** Descriptor for the absence of a value, used as the return descriptor of a `void` function. */
118
188
  const voidT: VoidDescriptor = { kind: "void" };
189
+ /** Descriptor for a `gunichar`, marshalled as a single-character string or a codepoint number. */
119
190
  const unicharT: UnicharDescriptor = { kind: "unichar" };
191
+ /** Descriptor for an opaque `gpointer`, taken from a typed array's memory or a numeric address. */
120
192
  const bufferT: BufferDescriptor = { kind: "buffer" };
193
+ const fundamentalLifecycles: Map<string, FundamentalLifecycle> = new Map();
121
194
 
195
+ /**
196
+ * Builds a descriptor for a C string, whose optional length sizes the caller-allocated buffer
197
+ * used when the string is passed by reference.
198
+ */
122
199
  const stringT = (ownership: Ownership = "borrowed", length?: number): StringDescriptor =>
123
200
  length === undefined ? { kind: "string", ownership } : { kind: "string", ownership, length };
124
201
 
202
+ /** Builds a descriptor for a `GObject`, wrapped in the class registered for its runtime GType. */
125
203
  const objectT = (ownership: Ownership = "borrowed"): ObjectDescriptor => ({ kind: "object", ownership });
126
204
 
205
+ /** Wraps a descriptor in a pointer to it, for an output or inout argument. */
127
206
  const refT = (innerDescriptor: Descriptor, isInout = false): RefDescriptor =>
128
207
  isInout ? { kind: "ref", innerDescriptor, inout: true } : { kind: "ref", innerDescriptor };
129
208
 
209
+ /** Builds a descriptor for a `GHashTable`, marshalled as an array of key/value pairs. */
130
210
  const hashTableT = (
131
211
  keyDescriptor: Descriptor,
132
212
  valueDescriptor: Descriptor,
@@ -138,6 +218,7 @@ const hashTableT = (
138
218
  ownership,
139
219
  });
140
220
 
221
+ /** Builds a descriptor for an enumeration, resolving its GType from the named `get_type` function. */
141
222
  const enumT = (sharedLibrary: string, typeFnName: string, isSigned: boolean): EnumDescriptor => ({
142
223
  kind: "enum",
143
224
  sharedLibrary,
@@ -145,6 +226,7 @@ const enumT = (sharedLibrary: string, typeFnName: string, isSigned: boolean): En
145
226
  isSigned,
146
227
  });
147
228
 
229
+ /** Builds a descriptor for a flags type, resolving its GType from the named `get_type` function. */
148
230
  const flagsT = (sharedLibrary: string, typeFnName: string, isSigned: boolean): FlagsDescriptor => ({
149
231
  kind: "flags",
150
232
  sharedLibrary,
@@ -182,6 +264,7 @@ const applyBoxedOptions = (result: BoxedDescriptor, options: BoxedOptions): void
182
264
  }
183
265
  };
184
266
 
267
+ /** Builds a descriptor for a `GBoxed` value of the named type. */
185
268
  const boxedT = (typeName: string, options: BoxedOptions = {}): BoxedDescriptor => {
186
269
  const result: BoxedDescriptor = {
187
270
  kind: "boxed",
@@ -194,6 +277,7 @@ const boxedT = (typeName: string, options: BoxedOptions = {}): BoxedDescriptor =
194
277
  return result;
195
278
  };
196
279
 
280
+ /** Builds a descriptor for a plain C struct. */
197
281
  const structT = (ownership: Ownership = "borrowed", options: StructOptions = {}): StructDescriptor => {
198
282
  const result: StructDescriptor = { kind: "struct", ownership };
199
283
 
@@ -216,6 +300,16 @@ const structT = (ownership: Ownership = "borrowed", options: StructOptions = {})
216
300
  return result;
217
301
  };
218
302
 
303
+ const recordFundamentalLifecycle = (typeName: string, lifecycle: FundamentalLifecycle): void => {
304
+ if (!fundamentalLifecycles.has(typeName)) {
305
+ fundamentalLifecycles.set(typeName, lifecycle);
306
+ }
307
+ };
308
+
309
+ const fundamentalLifecycleFor = (typeName: string): FundamentalLifecycle | undefined =>
310
+ fundamentalLifecycles.get(typeName);
311
+
312
+ /** Builds a descriptor for a fundamental type whose lifetime is managed by named ref and unref functions. */
219
313
  const fundamentalT = (
220
314
  sharedLibrary: string,
221
315
  refFnName: string,
@@ -227,6 +321,7 @@ const fundamentalT = (
227
321
 
228
322
  if (options.typeName !== undefined) {
229
323
  result.typeName = options.typeName;
324
+ recordFundamentalLifecycle(options.typeName, { sharedLibrary, refFnName, unrefFnName });
230
325
  }
231
326
 
232
327
  if (options.wrapperClass !== undefined) {
@@ -240,6 +335,7 @@ const fundamentalT = (
240
335
  return result;
241
336
  };
242
337
 
338
+ /** Builds a descriptor for an array of items in one of the supported container layouts. */
243
339
  const arrayT = (
244
340
  itemDescriptor: Descriptor,
245
341
  arrayKind: ArrayKind = "array",
@@ -252,6 +348,10 @@ const arrayT = (
252
348
  result.elementSize = options.elementSize;
253
349
  }
254
350
 
351
+ if (options?.baseParamIndex !== undefined) {
352
+ result.baseParamIndex = options.baseParamIndex;
353
+ }
354
+
255
355
  if (options?.sizeParamIndex !== undefined) {
256
356
  result.sizeParamIndex = options.sizeParamIndex;
257
357
  }
@@ -263,15 +363,19 @@ const arrayT = (
263
363
  return result;
264
364
  };
265
365
 
366
+ /** Builds a descriptor for a `GList` of items. */
266
367
  const listT = (itemDescriptor: Descriptor, ownership: Ownership = "borrowed"): ArrayDescriptor =>
267
368
  arrayT(itemDescriptor, "glist", ownership);
268
369
 
370
+ /** Builds a descriptor for a `GSList` of items. */
269
371
  const slistT = (itemDescriptor: Descriptor, ownership: Ownership = "borrowed"): ArrayDescriptor =>
270
372
  arrayT(itemDescriptor, "gslist", ownership);
271
373
 
374
+ /** Builds a descriptor for a `GPtrArray` of items. */
272
375
  const ptrArrayT = (itemDescriptor: Descriptor, ownership: Ownership = "borrowed"): ArrayDescriptor =>
273
376
  arrayT(itemDescriptor, "gptrarray", ownership);
274
377
 
378
+ /** Builds a descriptor for a `GArray` of items, optionally with an explicit element size. */
275
379
  const gArrayT = (
276
380
  itemDescriptor: Descriptor,
277
381
  ownership: Ownership = "borrowed",
@@ -279,9 +383,11 @@ const gArrayT = (
279
383
  ): ArrayDescriptor =>
280
384
  arrayT(itemDescriptor, "garray", ownership, elementSize === undefined ? undefined : { elementSize });
281
385
 
386
+ /** Builds a descriptor for a `GByteArray`. */
282
387
  const byteArrayT = (ownership: Ownership = "borrowed"): ArrayDescriptor =>
283
388
  arrayT(uint8T, "gbytearray", ownership);
284
389
 
390
+ /** Builds a descriptor for a C array whose length is carried by another argument. */
285
391
  const sizedArrayT = (
286
392
  itemDescriptor: Descriptor,
287
393
  sizeParamIndex: number,
@@ -289,6 +395,18 @@ const sizedArrayT = (
289
395
  elementSize?: number,
290
396
  ): ArrayDescriptor => arrayT(itemDescriptor, "sized", ownership, { sizeParamIndex, elementSize });
291
397
 
398
+ /**
399
+ * Builds a descriptor for an out pointer into the buffer another argument supplied, decoded as the
400
+ * elements from where it points to the end of that buffer.
401
+ */
402
+ const cursorArrayT = (
403
+ itemDescriptor: Descriptor,
404
+ bounds: CursorBounds,
405
+ ownership: Ownership = "borrowed",
406
+ elementSize?: number,
407
+ ): ArrayDescriptor => arrayT(itemDescriptor, "cursor", ownership, { ...bounds, elementSize });
408
+
409
+ /** Builds a descriptor for a C array of a fixed length. */
292
410
  const fixedArrayT = (
293
411
  itemDescriptor: Descriptor,
294
412
  fixedSize: number,
@@ -296,6 +414,29 @@ const fixedArrayT = (
296
414
  elementSize?: number,
297
415
  ): ArrayDescriptor => arrayT(itemDescriptor, "fixed", ownership, { fixedSize, elementSize });
298
416
 
417
+ const applyClosureOptions = (result: CallbackDescriptor, options: CallbackOptions): void => {
418
+ if (options.hasDestroy !== undefined) {
419
+ result.hasDestroy = options.hasDestroy;
420
+ }
421
+
422
+ if (options.destroyKind !== undefined) {
423
+ result.destroyKind = options.destroyKind;
424
+ }
425
+
426
+ if (options.hasUserData !== undefined) {
427
+ result.hasUserData = options.hasUserData;
428
+ }
429
+
430
+ if (options.userDataIndex !== undefined) {
431
+ result.userDataIndex = options.userDataIndex;
432
+ }
433
+
434
+ if (options.scope !== undefined) {
435
+ result.scope = options.scope;
436
+ }
437
+ };
438
+
439
+ /** Builds a descriptor for a function pointer, marshalling a JavaScript function into a native closure. */
299
440
  const callbackT = (
300
441
  argDescriptors: Descriptor[],
301
442
  returnDescriptor: Descriptor,
@@ -303,17 +444,11 @@ const callbackT = (
303
444
  ): CallbackDescriptor => {
304
445
  const result: CallbackDescriptor = { kind: "callback", argDescriptors, returnDescriptor };
305
446
 
306
- if (options?.hasDestroy !== undefined) {
307
- result.hasDestroy = options.hasDestroy;
447
+ if (options === undefined) {
448
+ return result;
308
449
  }
309
450
 
310
- if (options?.userDataIndex !== undefined) {
311
- result.userDataIndex = options.userDataIndex;
312
- }
313
-
314
- if (options?.scope !== undefined) {
315
- result.scope = options.scope;
316
- }
451
+ applyClosureOptions(result, options);
317
452
 
318
453
  return result;
319
454
  };
@@ -344,6 +479,7 @@ export {
344
479
  flagsT,
345
480
  boxedT,
346
481
  structT,
482
+ fundamentalLifecycleFor,
347
483
  fundamentalT,
348
484
  arrayT,
349
485
  listT,
@@ -353,27 +489,8 @@ export {
353
489
  byteArrayT,
354
490
  sizedArrayT,
355
491
  fixedArrayT,
492
+ cursorArrayT,
356
493
  callbackT,
357
- type Int8Descriptor,
358
- type Uint8Descriptor,
359
- type Int16Descriptor,
360
- type Uint16Descriptor,
361
- type Int32Descriptor,
362
- type Uint32Descriptor,
363
- type Int64Descriptor,
364
- type Uint64Descriptor,
365
- type BigInt64Descriptor,
366
- type BigUint64Descriptor,
367
- type Float32Descriptor,
368
- type Float64Descriptor,
369
- type EnumDescriptor,
370
- type FlagsDescriptor,
371
- type BooleanDescriptor,
372
- type StringDescriptor,
373
- type ObjectDescriptor,
374
- type UnicharDescriptor,
375
- type VoidDescriptor,
376
- type BufferDescriptor,
377
494
  type BoxedDescriptor,
378
495
  type StructDescriptor,
379
496
  type FundamentalDescriptor,
@@ -381,5 +498,4 @@ export {
381
498
  type HashTableDescriptor,
382
499
  type CallbackDescriptor,
383
500
  type RefDescriptor,
384
- type TypeDescriptor,
385
501
  };
package/src/error.ts CHANGED
@@ -18,6 +18,7 @@ type ErrorLike = Error & {
18
18
  * matches wrapped GLib errors belonging to a specific error domain.
19
19
  */
20
20
  type ErrorDomain<T extends Record<string, number>> = T & {
21
+ /** Backs `instanceof`, matching a wrapped GLib error whose domain is this one. */
21
22
  [Symbol.hasInstance]: (value: unknown) => value is ErrorLike;
22
23
  };
23
24
 
package/src/exit-hook.ts CHANGED
@@ -1,3 +1,21 @@
1
1
  import { quit } from "./lifecycle.js";
2
2
 
3
+ const TERMINATION_SIGNALS: NodeJS.Signals[] = ["SIGHUP", "SIGINT", "SIGTERM"];
4
+
5
+ const isSoleHandler = (signal: NodeJS.Signals): boolean => process.listenerCount(signal) === 1;
6
+
7
+ const quitOnSignal = (signal: NodeJS.Signals): void => {
8
+ if (!isSoleHandler(signal)) {
9
+ return;
10
+ }
11
+
12
+ quit();
13
+ process.removeAllListeners(signal);
14
+ process.kill(process.pid, signal);
15
+ };
16
+
3
17
  process.on("exit", quit);
18
+
19
+ for (const signal of TERMINATION_SIGNALS) {
20
+ process.on(signal, quitOnSignal);
21
+ }