@gtkx/runtime 1.2.2 → 1.4.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 (101) hide show
  1. package/README.md +6 -4
  2. package/dist/arg.d.ts +6 -1
  3. package/dist/arg.d.ts.map +1 -1
  4. package/dist/arg.js +2 -1
  5. package/dist/arg.js.map +1 -1
  6. package/dist/closure.d.ts.map +1 -1
  7. package/dist/closure.js +2 -11
  8. package/dist/closure.js.map +1 -1
  9. package/dist/descriptors.d.ts +21 -3
  10. package/dist/descriptors.d.ts.map +1 -1
  11. package/dist/descriptors.js +50 -21
  12. package/dist/descriptors.js.map +1 -1
  13. package/dist/field.d.ts +42 -0
  14. package/dist/field.d.ts.map +1 -0
  15. package/dist/field.js +41 -0
  16. package/dist/field.js.map +1 -0
  17. package/dist/fn.d.ts +2 -0
  18. package/dist/fn.d.ts.map +1 -1
  19. package/dist/fn.js +50 -10
  20. package/dist/fn.js.map +1 -1
  21. package/dist/index.d.ts +14 -6
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +13 -5
  24. package/dist/index.js.map +1 -1
  25. package/dist/mixin.d.ts +2 -1
  26. package/dist/mixin.d.ts.map +1 -1
  27. package/dist/mixin.js +1 -1
  28. package/dist/mixin.js.map +1 -1
  29. package/dist/native-value.d.ts +9 -3
  30. package/dist/native-value.d.ts.map +1 -1
  31. package/dist/native-value.js +86 -9
  32. package/dist/native-value.js.map +1 -1
  33. package/dist/object.d.ts +14 -6
  34. package/dist/object.d.ts.map +1 -1
  35. package/dist/object.js +21 -10
  36. package/dist/object.js.map +1 -1
  37. package/dist/param-spec.d.ts +32 -1
  38. package/dist/param-spec.d.ts.map +1 -1
  39. package/dist/param-spec.js +67 -5
  40. package/dist/param-spec.js.map +1 -1
  41. package/dist/promisify.d.ts +13 -1
  42. package/dist/promisify.d.ts.map +1 -1
  43. package/dist/promisify.js +14 -1
  44. package/dist/promisify.js.map +1 -1
  45. package/dist/properties.d.ts +48 -5
  46. package/dist/properties.d.ts.map +1 -1
  47. package/dist/properties.js +191 -20
  48. package/dist/properties.js.map +1 -1
  49. package/dist/regex.d.ts +25 -0
  50. package/dist/regex.d.ts.map +1 -0
  51. package/dist/regex.js +59 -0
  52. package/dist/regex.js.map +1 -0
  53. package/dist/register-class.d.ts +165 -15
  54. package/dist/register-class.d.ts.map +1 -1
  55. package/dist/register-class.js +175 -19
  56. package/dist/register-class.js.map +1 -1
  57. package/dist/registry.d.ts +48 -4
  58. package/dist/registry.d.ts.map +1 -1
  59. package/dist/registry.js +147 -3
  60. package/dist/registry.js.map +1 -1
  61. package/dist/signal.d.ts +11 -1
  62. package/dist/signal.d.ts.map +1 -1
  63. package/dist/signal.js +66 -6
  64. package/dist/signal.js.map +1 -1
  65. package/dist/t.d.ts +11 -0
  66. package/dist/t.d.ts.map +1 -1
  67. package/dist/t.js +3 -0
  68. package/dist/t.js.map +1 -1
  69. package/dist/type.d.ts +2 -1
  70. package/dist/type.d.ts.map +1 -1
  71. package/dist/type.js +5 -1
  72. package/dist/type.js.map +1 -1
  73. package/dist/value.d.ts +48 -4
  74. package/dist/value.d.ts.map +1 -1
  75. package/dist/value.js +172 -16
  76. package/dist/value.js.map +1 -1
  77. package/dist/variant.d.ts +75 -26
  78. package/dist/variant.d.ts.map +1 -1
  79. package/dist/variant.js +44 -29
  80. package/dist/variant.js.map +1 -1
  81. package/package.json +5 -5
  82. package/src/arg.ts +6 -1
  83. package/src/closure.ts +2 -14
  84. package/src/descriptors.ts +74 -21
  85. package/src/field.ts +76 -0
  86. package/src/fn.ts +73 -17
  87. package/src/index.ts +46 -5
  88. package/src/mixin.ts +1 -1
  89. package/src/native-value.ts +146 -14
  90. package/src/object.ts +23 -11
  91. package/src/param-spec.ts +96 -8
  92. package/src/promisify.ts +27 -1
  93. package/src/properties.ts +280 -32
  94. package/src/regex.ts +92 -0
  95. package/src/register-class.ts +485 -42
  96. package/src/registry.ts +219 -4
  97. package/src/signal.ts +117 -4
  98. package/src/t.ts +13 -0
  99. package/src/type.ts +7 -0
  100. package/src/value.ts +268 -14
  101. package/src/variant.ts +184 -53
package/src/param-spec.ts CHANGED
@@ -2,7 +2,7 @@ import { type ExternalObject, type Handle, read } from "@gtkx/native";
2
2
  import { bind } from "./bind.js";
3
3
  import { biguint64T, booleanT, stringT, uint32T, voidT } from "./descriptors.js";
4
4
  import { LIB, PARAM_T, VALUE_T } from "./library.js";
5
- import { getInstanceType } from "./registry.js";
5
+ import { getHandle, getInstanceType } from "./registry.js";
6
6
  import {
7
7
  getStrvType,
8
8
  isTypedClass,
@@ -33,15 +33,17 @@ import {
33
33
  } from "./type.js";
34
34
 
35
35
  type ValueGuard = (value: unknown) => boolean;
36
- type ParamLayout = { flags: number; valueType: bigint };
36
+ type ParamLayout = { flags: number; valueType: bigint; ownerType: bigint };
37
37
 
38
38
  const PARAM_READABLE = 1;
39
39
  const PARAM_WRITABLE = 2;
40
40
  const PARAM_CONSTRUCT_ONLY = 8;
41
41
  const PARAM_LAX_VALIDATION = 16;
42
+ const PARAM_EXPLICIT_NOTIFY = 1 << 30;
42
43
  const READ_FLAGS = PARAM_READABLE | PARAM_WRITABLE | PARAM_CONSTRUCT_ONLY | PARAM_LAX_VALIDATION;
43
44
  const FLAGS_BYTE_OFFSET = 16;
44
45
  const VALUE_TYPE_BYTE_OFFSET = 24;
46
+ const OWNER_TYPE_BYTE_OFFSET = 32;
45
47
  const LAYOUT_PROBE_NAME = "gtkx-param-layout";
46
48
  const INT8_MINIMUM = -128;
47
49
  const INT8_MAXIMUM = 127;
@@ -49,9 +51,9 @@ const UINT8_MAXIMUM = 255;
49
51
  const INT32_MINIMUM = -2_147_483_648;
50
52
  const INT32_MAXIMUM = 2_147_483_647;
51
53
  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;
54
+ const INT64_MINIMUM: bigint = -(2n ** 63n);
55
+ const INT64_MAXIMUM: bigint = 2n ** 63n - 1n;
56
+ const UINT64_MAXIMUM: bigint = 2n ** 64n - 1n;
55
57
 
56
58
  const WRAPPED_FUNDAMENTALS: Set<bigint> = new Set([
57
59
  TYPE_BOXED,
@@ -62,6 +64,20 @@ const WRAPPED_FUNDAMENTALS: Set<bigint> = new Set([
62
64
  ]);
63
65
 
64
66
  const isWideUnsignedValue: ValueGuard = wideIntegerGuardFor(0n, UINT64_MAXIMUM);
67
+ const MAX_SAFE: number = Number.MAX_SAFE_INTEGER;
68
+
69
+ const WHOLE_NUMBER_RANGES: Map<bigint, [minimum: number, maximum: number]> = new Map([
70
+ [TYPE_CHAR, [INT8_MINIMUM, INT8_MAXIMUM]],
71
+ [TYPE_UCHAR, [0, UINT8_MAXIMUM]],
72
+ [TYPE_INT, [INT32_MINIMUM, INT32_MAXIMUM]],
73
+ [TYPE_UINT, [0, UINT32_MAXIMUM]],
74
+ [TYPE_ENUM, [INT32_MINIMUM, INT32_MAXIMUM]],
75
+ [TYPE_FLAGS, [0, UINT32_MAXIMUM]],
76
+ [TYPE_LONG, [-MAX_SAFE, MAX_SAFE]],
77
+ [TYPE_ULONG, [0, MAX_SAFE]],
78
+ [TYPE_INT64, [-MAX_SAFE, MAX_SAFE]],
79
+ [TYPE_UINT64, [0, MAX_SAFE]],
80
+ ]);
65
81
 
66
82
  const SCALAR_GUARDS: Map<bigint, ValueGuard> = new Map([
67
83
  [TYPE_BOOLEAN, isBooleanValue],
@@ -98,9 +114,50 @@ const getParamFlags = (pspec: ExternalObject<Handle>): number => read(pspec, uin
98
114
  const getParamValueType = (pspec: ExternalObject<Handle>): bigint =>
99
115
  read(pspec, biguint64T, VALUE_TYPE_BYTE_OFFSET) as bigint;
100
116
 
117
+ const getParamOwnerType = (pspec: ExternalObject<Handle>): bigint =>
118
+ read(pspec, biguint64T, OWNER_TYPE_BYTE_OFFSET) as bigint;
119
+
120
+ /**
121
+ * Reads the `GParamFlags` bitfield of a `GObject.ParamSpec`.
122
+ *
123
+ * @param spec The param spec wrapper to read.
124
+ * @returns The spec's flags.
125
+ */
126
+ const getParamSpecFlags = (spec: object): number => {
127
+ assertParamLayout();
128
+
129
+ return getParamFlags(getHandle(spec));
130
+ };
131
+
132
+ /**
133
+ * Reads the GType of the values a `GObject.ParamSpec` describes.
134
+ *
135
+ * @param spec The param spec wrapper to read.
136
+ * @returns The GType of the spec's values.
137
+ */
138
+ const getParamSpecValueType = (spec: object): bigint => {
139
+ assertParamLayout();
140
+
141
+ return getParamValueType(getHandle(spec));
142
+ };
143
+
144
+ /**
145
+ * Reads the GType a `GObject.ParamSpec` is installed on.
146
+ *
147
+ * @param spec The param spec wrapper to read.
148
+ * @returns The owning GType, or `TYPE_INVALID` while the spec is not installed on any type.
149
+ */
150
+ const getParamSpecOwnerType = (spec: object): bigint => {
151
+ assertParamLayout();
152
+
153
+ return getParamOwnerType(getHandle(spec));
154
+ };
155
+
101
156
  const isParamWritable = (flags: number): boolean => (flags & PARAM_WRITABLE) !== 0;
157
+ const isParamReadable = (flags: number): boolean => (flags & PARAM_READABLE) !== 0;
102
158
  const isParamConstructOnly = (flags: number): boolean => (flags & PARAM_CONSTRUCT_ONLY) !== 0;
103
159
  const isParamLaxlyValidated = (flags: number): boolean => (flags & PARAM_LAX_VALIDATION) !== 0;
160
+ const isParamExplicitlyNotified = (flags: number): boolean => (flags & PARAM_EXPLICIT_NOTIFY) !== 0;
104
161
 
105
162
  const wasParamValueModified = (pspec: ExternalObject<Handle>, value: ExternalObject<Handle>): boolean =>
106
163
  paramValueValidate(pspec, value) as boolean;
@@ -113,8 +170,18 @@ function isStringValue(value: unknown): boolean {
113
170
  return value == null || typeof value === "string";
114
171
  }
115
172
 
173
+ function isStringArray(value: unknown[]): boolean {
174
+ for (const item of value) {
175
+ if (typeof item !== "string") {
176
+ return false;
177
+ }
178
+ }
179
+
180
+ return true;
181
+ }
182
+
116
183
  function isStrvValue(value: unknown): boolean {
117
- return value == null || (Array.isArray(value) && value.every((item) => typeof item === "string"));
184
+ return value == null || (Array.isArray(value) && isStringArray(value));
118
185
  }
119
186
 
120
187
  function isNumberValue(value: unknown): boolean {
@@ -193,7 +260,11 @@ function readProbeLayout(flags: number): ParamLayout {
193
260
  paramSpecRefSink(probe);
194
261
 
195
262
  try {
196
- return { flags: getParamFlags(probe), valueType: getParamValueType(probe) };
263
+ return {
264
+ flags: getParamFlags(probe),
265
+ valueType: getParamValueType(probe),
266
+ ownerType: getParamOwnerType(probe),
267
+ };
197
268
  } finally {
198
269
  paramSpecUnref(probe);
199
270
  }
@@ -202,7 +273,11 @@ function readProbeLayout(flags: number): ParamLayout {
202
273
  function isLayoutIntact(flags: number): boolean {
203
274
  const layout = readProbeLayout(flags);
204
275
 
205
- return (layout.flags & READ_FLAGS) === flags && layout.valueType === TYPE_BOOLEAN;
276
+ return (
277
+ (layout.flags & READ_FLAGS) === flags &&
278
+ layout.valueType === TYPE_BOOLEAN &&
279
+ layout.ownerType === TYPE_INVALID
280
+ );
206
281
  }
207
282
 
208
283
  function assertParamLayout(): void {
@@ -223,11 +298,24 @@ function assertParamLayout(): void {
223
298
  }
224
299
 
225
300
  export {
301
+ WHOLE_NUMBER_RANGES,
226
302
  getParamFlags,
303
+ getParamSpecFlags,
304
+ getParamSpecOwnerType,
305
+ getParamSpecValueType,
227
306
  getParamValueType,
307
+ INT32_MAXIMUM,
308
+ INT32_MINIMUM,
309
+ INT64_MAXIMUM,
310
+ INT64_MINIMUM,
228
311
  isParamConstructOnly,
312
+ isParamReadable,
313
+ isStringArray,
314
+ isParamExplicitlyNotified,
229
315
  isParamLaxlyValidated,
230
316
  isParamWritable,
317
+ resolveGtype,
318
+ UINT64_MAXIMUM,
231
319
  type ValueGuard,
232
320
  valueGuardFor,
233
321
  wasParamValueModified,
package/src/promisify.ts CHANGED
@@ -13,6 +13,13 @@ type Settlement<R extends object, T> = {
13
13
  reject: (reason: Error) => void;
14
14
  };
15
15
 
16
+ /** A finish result with its leading success boolean dropped: bare when one value remains, a tuple otherwise. */
17
+ type TrimmedFinish<T> = T extends readonly [boolean, infer Only]
18
+ ? Only
19
+ : T extends readonly [boolean, ...infer Rest]
20
+ ? Rest
21
+ : never;
22
+
16
23
  const attachCreationStack = (error: unknown, creationStack: Error | undefined): void => {
17
24
  if (creationStack === undefined || !(error instanceof Error)) {
18
25
  return;
@@ -36,6 +43,25 @@ const settle = <R extends object, T>(settlement: Settlement<R, T>, asyncResult:
36
43
  }
37
44
  };
38
45
 
46
+ /**
47
+ * Wraps a finish function whose result leads with the success boolean of a throwing C call,
48
+ * dropping that boolean: failure already surfaces as a thrown error, so the boolean is always
49
+ * `true`. A single remaining value is handed back bare, several stay a tuple. The finish result
50
+ * must carry at least one value beyond the boolean; a boolean-only finish needs no trimming.
51
+ *
52
+ * @param finish Extracts the boolean-led result from the async result passed to the completion callback.
53
+ * @returns A finish function resolving to the result without its leading boolean.
54
+ */
55
+ const trimFinish =
56
+ <R extends object, T extends readonly [boolean, unknown, ...unknown[]]>(
57
+ finish: FinishResult<R, T>,
58
+ ): FinishResult<R, TrimmedFinish<T>> =>
59
+ (result: R): TrimmedFinish<T> => {
60
+ const [, ...rest] = finish(result);
61
+
62
+ return (rest.length === 1 ? rest[0] : rest) as TrimmedFinish<T>;
63
+ };
64
+
39
65
  /**
40
66
  * Wraps a GIO-style asynchronous function that takes a completion callback into a
41
67
  * promise, invoking the finish function to extract the result. Outside production,
@@ -64,4 +90,4 @@ const promisify = <R extends object, T>(
64
90
  });
65
91
  });
66
92
 
67
- export { promisify };
93
+ export { promisify, trimFinish };