@gtkx/codegen 1.2.1 → 1.3.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 (213) hide show
  1. package/README.md +2 -1
  2. package/dist/analysis/descriptor-render.d.ts +7 -1
  3. package/dist/analysis/descriptor-render.d.ts.map +1 -1
  4. package/dist/analysis/descriptor-render.js +36 -15
  5. package/dist/analysis/descriptor-render.js.map +1 -1
  6. package/dist/analysis/descriptor.d.ts +4 -1
  7. package/dist/analysis/descriptor.d.ts.map +1 -1
  8. package/dist/analysis/descriptor.js +11 -2
  9. package/dist/analysis/descriptor.js.map +1 -1
  10. package/dist/analysis/param-capability.d.ts +5 -2
  11. package/dist/analysis/param-capability.d.ts.map +1 -1
  12. package/dist/analysis/param-capability.js +36 -4
  13. package/dist/analysis/param-capability.js.map +1 -1
  14. package/dist/analysis/param-structure.d.ts +1 -1
  15. package/dist/analysis/param-structure.d.ts.map +1 -1
  16. package/dist/analysis/param-structure.js.map +1 -1
  17. package/dist/analysis/ts-type.d.ts +1 -1
  18. package/dist/analysis/ts-type.d.ts.map +1 -1
  19. package/dist/analysis/ts-type.js +28 -10
  20. package/dist/analysis/ts-type.js.map +1 -1
  21. package/dist/compile.js +1 -1
  22. package/dist/compile.js.map +1 -1
  23. package/dist/docs/api-reference.d.ts +6 -0
  24. package/dist/docs/api-reference.d.ts.map +1 -1
  25. package/dist/docs/api-reference.js +11 -2
  26. package/dist/docs/api-reference.js.map +1 -1
  27. package/dist/docs/pipeline.d.ts +3 -0
  28. package/dist/docs/pipeline.d.ts.map +1 -1
  29. package/dist/docs/pipeline.js +10 -1
  30. package/dist/docs/pipeline.js.map +1 -1
  31. package/dist/fingerprint.d.ts +5 -0
  32. package/dist/fingerprint.d.ts.map +1 -1
  33. package/dist/fingerprint.js +107 -15
  34. package/dist/fingerprint.js.map +1 -1
  35. package/dist/gi.d.ts +3 -0
  36. package/dist/gi.d.ts.map +1 -1
  37. package/dist/gi.js +29 -7
  38. package/dist/gi.js.map +1 -1
  39. package/dist/gir/external-namespaces.d.ts +8 -0
  40. package/dist/gir/external-namespaces.d.ts.map +1 -0
  41. package/dist/gir/external-namespaces.js +4 -0
  42. package/dist/gir/external-namespaces.js.map +1 -0
  43. package/dist/gir/finish-overrides.d.ts +3 -0
  44. package/dist/gir/finish-overrides.d.ts.map +1 -0
  45. package/dist/gir/finish-overrides.js +5 -0
  46. package/dist/gir/finish-overrides.js.map +1 -0
  47. package/dist/gir/function.d.ts +5 -2
  48. package/dist/gir/function.d.ts.map +1 -1
  49. package/dist/gir/function.js +34 -5
  50. package/dist/gir/function.js.map +1 -1
  51. package/dist/gir/hidden-symbols.d.ts +3 -0
  52. package/dist/gir/hidden-symbols.d.ts.map +1 -0
  53. package/dist/gir/hidden-symbols.js +39 -0
  54. package/dist/gir/hidden-symbols.js.map +1 -0
  55. package/dist/gir/library.d.ts +22 -2
  56. package/dist/gir/library.d.ts.map +1 -1
  57. package/dist/gir/library.js +21 -3
  58. package/dist/gir/library.js.map +1 -1
  59. package/dist/gir/ucs4-overrides.d.ts +3 -0
  60. package/dist/gir/ucs4-overrides.d.ts.map +1 -0
  61. package/dist/gir/ucs4-overrides.js +7 -0
  62. package/dist/gir/ucs4-overrides.js.map +1 -0
  63. package/dist/jsx.d.ts.map +1 -1
  64. package/dist/jsx.js +27 -8
  65. package/dist/jsx.js.map +1 -1
  66. package/dist/runner.d.ts +8 -0
  67. package/dist/runner.d.ts.map +1 -1
  68. package/dist/runner.js +9 -3
  69. package/dist/runner.js.map +1 -1
  70. package/dist/store/external-package-links.d.ts +6 -0
  71. package/dist/store/external-package-links.d.ts.map +1 -0
  72. package/dist/store/external-package-links.js +158 -0
  73. package/dist/store/external-package-links.js.map +1 -0
  74. package/dist/store/gi/callable-doc.d.ts.map +1 -1
  75. package/dist/store/gi/callable-doc.js +4 -4
  76. package/dist/store/gi/callable-doc.js.map +1 -1
  77. package/dist/store/gi/callables.d.ts +1 -1
  78. package/dist/store/gi/callables.d.ts.map +1 -1
  79. package/dist/store/gi/callables.js +4 -4
  80. package/dist/store/gi/callables.js.map +1 -1
  81. package/dist/store/gi/class.d.ts.map +1 -1
  82. package/dist/store/gi/class.js +25 -15
  83. package/dist/store/gi/class.js.map +1 -1
  84. package/dist/store/gi/constructor-props.js +1 -1
  85. package/dist/store/gi/constructor-props.js.map +1 -1
  86. package/dist/store/gi/function.d.ts.map +1 -1
  87. package/dist/store/gi/function.js +2 -1
  88. package/dist/store/gi/function.js.map +1 -1
  89. package/dist/store/gi/gtype-binding.d.ts +2 -2
  90. package/dist/store/gi/gtype-binding.d.ts.map +1 -1
  91. package/dist/store/gi/gtype-binding.js +6 -13
  92. package/dist/store/gi/gtype-binding.js.map +1 -1
  93. package/dist/store/gi/interface.js +2 -2
  94. package/dist/store/gi/interface.js.map +1 -1
  95. package/dist/store/gi/method.d.ts +7 -2
  96. package/dist/store/gi/method.d.ts.map +1 -1
  97. package/dist/store/gi/method.js +126 -30
  98. package/dist/store/gi/method.js.map +1 -1
  99. package/dist/store/gi/param-marshal.d.ts +8 -1
  100. package/dist/store/gi/param-marshal.d.ts.map +1 -1
  101. package/dist/store/gi/param-marshal.js +52 -4
  102. package/dist/store/gi/param-marshal.js.map +1 -1
  103. package/dist/store/gi/record-constructor.d.ts.map +1 -1
  104. package/dist/store/gi/record-constructor.js +2 -3
  105. package/dist/store/gi/record-constructor.js.map +1 -1
  106. package/dist/store/gi/record-field-accessor.d.ts +2 -1
  107. package/dist/store/gi/record-field-accessor.d.ts.map +1 -1
  108. package/dist/store/gi/record-field-accessor.js +142 -16
  109. package/dist/store/gi/record-field-accessor.js.map +1 -1
  110. package/dist/store/gi/record-layout.d.ts +5 -2
  111. package/dist/store/gi/record-layout.d.ts.map +1 -1
  112. package/dist/store/gi/record-layout.js +2 -1
  113. package/dist/store/gi/record-layout.js.map +1 -1
  114. package/dist/store/gi/record.d.ts.map +1 -1
  115. package/dist/store/gi/record.js +9 -5
  116. package/dist/store/gi/record.js.map +1 -1
  117. package/dist/store/gi/runtime-override.js +1 -1
  118. package/dist/store/gi/runtime-override.js.map +1 -1
  119. package/dist/store/gi/signal.js +2 -2
  120. package/dist/store/gi/signal.js.map +1 -1
  121. package/dist/store/gi/vtable.d.ts.map +1 -1
  122. package/dist/store/gi/vtable.js +82 -12
  123. package/dist/store/gi/vtable.js.map +1 -1
  124. package/dist/store/gi-store.d.ts +7 -2
  125. package/dist/store/gi-store.d.ts.map +1 -1
  126. package/dist/store/gi-store.js +19 -4
  127. package/dist/store/gi-store.js.map +1 -1
  128. package/dist/store/jsx/jsx.d.ts.map +1 -1
  129. package/dist/store/jsx/jsx.js +3 -1
  130. package/dist/store/jsx/jsx.js.map +1 -1
  131. package/dist/store/jsx-store.d.ts +8 -1
  132. package/dist/store/jsx-store.d.ts.map +1 -1
  133. package/dist/store/jsx-store.js +9 -2
  134. package/dist/store/jsx-store.js.map +1 -1
  135. package/dist/store/resolve-store.d.ts +2 -1
  136. package/dist/store/resolve-store.d.ts.map +1 -1
  137. package/dist/store/resolve-store.js +2 -1
  138. package/dist/store/resolve-store.js.map +1 -1
  139. package/dist/store/store-fs.d.ts +2 -1
  140. package/dist/store/store-fs.d.ts.map +1 -1
  141. package/dist/store/store-fs.js +8 -3
  142. package/dist/store/store-fs.js.map +1 -1
  143. package/dist/writer/context.d.ts.map +1 -1
  144. package/dist/writer/context.js +8 -0
  145. package/dist/writer/context.js.map +1 -1
  146. package/dist/writer/gtk-doc.d.ts.map +1 -1
  147. package/dist/writer/gtk-doc.js +27 -1
  148. package/dist/writer/gtk-doc.js.map +1 -1
  149. package/overrides/gdk/rgba.ts.ejs +15 -1
  150. package/overrides/glib/index.ts.ejs +3 -0
  151. package/overrides/glib/regex.ts.ejs +66 -0
  152. package/overrides/gobject/index.ts.ejs +3 -0
  153. package/overrides/gobject/object-class.ts.ejs +27 -0
  154. package/overrides/gobject/param-spec-getters.ts.ejs +57 -0
  155. package/overrides/gobject/param-spec.ts.ejs +21 -0
  156. package/overrides/gobject/value.ts.ejs +6 -1
  157. package/overrides/graphene/structs.ts.ejs +38 -3
  158. package/overrides/gtk/index.ts.ejs +2 -0
  159. package/overrides/gtk/widget-class.ts.ejs +28 -0
  160. package/package.json +6 -5
  161. package/src/analysis/descriptor-render.ts +59 -16
  162. package/src/analysis/descriptor.ts +15 -3
  163. package/src/analysis/param-capability.ts +68 -5
  164. package/src/analysis/param-structure.ts +1 -1
  165. package/src/analysis/ts-type.ts +45 -11
  166. package/src/compile.ts +1 -1
  167. package/src/docs/api-reference.ts +20 -2
  168. package/src/docs/pipeline.ts +15 -1
  169. package/src/fingerprint.ts +144 -16
  170. package/src/gi.ts +44 -9
  171. package/src/gir/external-namespaces.ts +8 -0
  172. package/src/gir/finish-overrides.ts +5 -0
  173. package/src/gir/function.ts +52 -14
  174. package/src/gir/hidden-symbols.ts +39 -0
  175. package/src/gir/library.ts +36 -3
  176. package/src/gir/ucs4-overrides.ts +7 -0
  177. package/src/jsx.ts +33 -8
  178. package/src/runner.ts +17 -3
  179. package/src/store/external-package-links.ts +226 -0
  180. package/src/store/gi/callable-doc.ts +8 -4
  181. package/src/store/gi/callables.ts +5 -5
  182. package/src/store/gi/class.ts +42 -32
  183. package/src/store/gi/constructor-props.ts +1 -1
  184. package/src/store/gi/function.ts +2 -1
  185. package/src/store/gi/gtype-binding.ts +7 -15
  186. package/src/store/gi/interface.ts +2 -2
  187. package/src/store/gi/method.ts +189 -36
  188. package/src/store/gi/param-marshal.ts +67 -4
  189. package/src/store/gi/record-constructor.ts +8 -3
  190. package/src/store/gi/record-field-accessor.ts +209 -16
  191. package/src/store/gi/record-layout.ts +11 -1
  192. package/src/store/gi/record.ts +17 -13
  193. package/src/store/gi/runtime-override.ts +1 -1
  194. package/src/store/gi/signal.ts +2 -2
  195. package/src/store/gi/vtable.ts +118 -11
  196. package/src/store/gi-store.ts +33 -3
  197. package/src/store/jsx/jsx.ts +3 -1
  198. package/src/store/jsx-store.ts +23 -7
  199. package/src/store/resolve-store.ts +2 -1
  200. package/src/store/store-fs.ts +10 -2
  201. package/src/writer/context.ts +11 -0
  202. package/src/writer/gtk-doc.ts +38 -1
  203. package/overrides/cairo/context.ts.ejs +0 -1269
  204. package/overrides/cairo/font-face.ts.ejs +0 -151
  205. package/overrides/cairo/font-options.ts.ejs +0 -199
  206. package/overrides/cairo/image-surface.ts.ejs +0 -132
  207. package/overrides/cairo/index.ts.ejs +0 -22
  208. package/overrides/cairo/matrix.ts.ejs +0 -171
  209. package/overrides/cairo/pattern.ts.ejs +0 -476
  210. package/overrides/cairo/recording-surface.ts.ejs +0 -102
  211. package/overrides/cairo/region.ts.ejs +0 -237
  212. package/overrides/cairo/scaled-font.ts.ejs +0 -330
  213. package/overrides/cairo/surface.ts.ejs +0 -296
@@ -20,6 +20,7 @@ import {
20
20
  parameterIdentifier,
21
21
  } from "../../analysis/param-structure.js";
22
22
  import { renderParameterTsType, renderTsType } from "../../analysis/ts-type.js";
23
+ import { primitiveCategoryFor } from "../../analysis/type-shape.js";
23
24
  import { type GirParameter, isCallerAllocatedOut, isInoutParameter, isOutParameter } from "../../gir/parameter.js";
24
25
  import { hasUnknownArrayLength, type TypeId } from "../../gir/type-id.js";
25
26
  import { areClosuresInvoked } from "./closure-invocation.js";
@@ -27,8 +28,10 @@ import { itemComparatorArgDescriptors, itemComparatorTsType } from "./item-compa
27
28
  import {
28
29
  isClosureType,
29
30
  isCollectibleCallerOut,
31
+ isFixedArrayCallerOut,
30
32
  isHandlePassedInPlace,
31
33
  isHandlePassing,
34
+ isValueType,
32
35
  renderCallerOutInstance,
33
36
  } from "./param-marshal.js";
34
37
 
@@ -44,6 +47,14 @@ type CallExpressionOptions = {
44
47
  isForcedNullable?: boolean | undefined;
45
48
  };
46
49
 
50
+ type MarshalledArgumentOptions = {
51
+ context: ModuleContext;
52
+ ref: TypeId;
53
+ name: string;
54
+ isNullable: boolean;
55
+ isValueMarshalled: boolean;
56
+ };
57
+
47
58
  type PromisifyContext = {
48
59
  context: ModuleContext;
49
60
  asyncFn: GirFunction;
@@ -64,12 +75,15 @@ type CallArgPlan = {
64
75
  type ReturnDescriptorPlan = {
65
76
  descriptor: string;
66
77
  isSkipped: boolean;
78
+ isUnpacked: boolean;
67
79
  };
68
80
 
69
81
  type ParamDescriptorOptions = {
70
82
  direction?: "out" | "inout";
71
83
  isCallerAllocated?: boolean;
72
84
  isConsumed?: boolean;
85
+ isUnpacked?: boolean;
86
+ isRequired?: boolean;
73
87
  };
74
88
 
75
89
  type ArgIndexOptions = {
@@ -113,6 +127,9 @@ const requiresClosureMarshal = (context: ModuleContext, fn: GirFunction, ref: Ty
113
127
  const requiresClosureAnnotation = (context: ModuleContext, fn: GirFunction, parameter: GirParameter): boolean =>
114
128
  parameter.type !== undefined && requiresClosureMarshal(context, fn, parameter.type);
115
129
 
130
+ const isValueRead = (parameter: GirParameter): boolean =>
131
+ !isInoutParameter(parameter) && parameter.cType?.includes("const ") === true;
132
+
116
133
  const parameterAnnotation = (context: ModuleContext, fn: GirFunction, parameter: GirParameter): string => {
117
134
  const comparator = itemComparatorTsType(context, fn, parameter);
118
135
 
@@ -120,7 +137,7 @@ const parameterAnnotation = (context: ModuleContext, fn: GirFunction, parameter:
120
137
  return comparator;
121
138
  }
122
139
 
123
- const base = renderParameterTsType(context, parameter.type, parameter.nullable);
140
+ const base = renderParameterTsType(context, parameter.type, parameter.nullable, isValueRead(parameter));
124
141
 
125
142
  return requiresClosureAnnotation(context, fn, parameter) ? closureAnnotation(context, base) : base;
126
143
  };
@@ -153,10 +170,14 @@ const renderInputParameters = (context: ModuleContext, fn: GirFunction, options:
153
170
  return parts.join(", ");
154
171
  };
155
172
 
173
+ const isInPlaceInout = (context: ModuleContext, parameter: GirParameter): boolean =>
174
+ context.library.isInoutInPlace && isInoutParameter(parameter) && isHandlePassedInPlace(context, parameter);
175
+
156
176
  const isReturnedOutParameter = (context: ModuleContext, parameter: GirParameter): boolean =>
157
177
  isOutParameter(parameter) ||
158
- (isCallerAllocatedOut(parameter) && isCollectibleCallerOut(context, parameter)) ||
159
- isInoutParameter(parameter);
178
+ (isCallerAllocatedOut(parameter) &&
179
+ (isCollectibleCallerOut(context, parameter) || isFixedArrayCallerOut(context, parameter))) ||
180
+ (isInoutParameter(parameter) && !isInPlaceInout(context, parameter));
160
181
 
161
182
  const returnedOutParameters = (context: ModuleContext, fn: GirFunction): InputParameter[] => {
162
183
  const folded = foldedLengthIndices(context.library, fn);
@@ -171,18 +192,34 @@ const returnedOutParameters = (context: ModuleContext, fn: GirFunction): InputPa
171
192
  return result;
172
193
  };
173
194
 
195
+ const isUnwrappedValue = (context: ModuleContext, ref: TypeId | undefined): boolean =>
196
+ context.library.isValueUnwrapped && ref !== undefined && isValueType(context, ref);
197
+
198
+ const renderReturnedTsType = (context: ModuleContext, ref: TypeId | undefined, isNullable: boolean): string =>
199
+ isUnwrappedValue(context, ref) ? "unknown" : renderTsType(context, ref, isNullable);
200
+
201
+ const isUnpackedOutParameter = (context: ModuleContext, parameter: GirParameter): boolean =>
202
+ isCallerAllocatedOut(parameter) &&
203
+ isCollectibleCallerOut(context, parameter) &&
204
+ isUnwrappedValue(context, parameter.type);
205
+
206
+ const renderOutTsType = (context: ModuleContext, parameter: GirParameter): string =>
207
+ isUnpackedOutParameter(context, parameter)
208
+ ? "unknown"
209
+ : renderTsType(context, parameter.type, parameter.nullable);
210
+
174
211
  const renderMethodReturnType = (context: ModuleContext, fn: GirFunction): string => {
175
212
  const outs = returnedOutParameters(context, fn);
176
213
 
177
214
  const primary = shouldOmitPrimaryReturn(context.library, fn.returnValue)
178
215
  ? undefined
179
- : renderTsType(context, fn.returnValue.type, fn.returnValue.nullable);
216
+ : renderReturnedTsType(context, fn.returnValue.type, fn.returnValue.nullable);
180
217
 
181
218
  if (outs.length === 0) {
182
219
  return primary ?? "void";
183
220
  }
184
221
 
185
- const outTypes = outs.map(({ parameter }) => renderTsType(context, parameter.type, parameter.nullable));
222
+ const outTypes = outs.map(({ parameter }) => renderOutTsType(context, parameter));
186
223
 
187
224
  return foldOutParamShape(primary, outTypes);
188
225
  };
@@ -240,13 +277,35 @@ const renderCancellableExpression = (parameters: GirParameter[], cancellableInde
240
277
  return parameter === undefined ? "null" : parameterIdentifier(parameter, cancellableIndex);
241
278
  };
242
279
 
280
+ const shouldTrimFinishBoolean = (context: ModuleContext, finishFn: GirFunction): boolean =>
281
+ context.library.isFinishTrimmed &&
282
+ finishFn.throws &&
283
+ !shouldOmitPrimaryReturn(context.library, finishFn.returnValue) &&
284
+ primitiveCategoryFor(context.library, finishFn.returnValue.type) === "boolean" &&
285
+ returnedOutParameters(context, finishFn).length > 0;
286
+
287
+ const promisifiedFinishExpression = (
288
+ context: ModuleContext,
289
+ finishFn: GirFunction,
290
+ finishExpression: string,
291
+ ): string => {
292
+ if (!shouldTrimFinishBoolean(context, finishFn)) {
293
+ return finishExpression;
294
+ }
295
+
296
+ context.addRuntimeImport("trimFinish");
297
+
298
+ return `trimFinish(${finishExpression})`;
299
+ };
300
+
243
301
  const renderPromisifiedBody = (
244
302
  context: ModuleContext,
245
303
  asyncFn: GirFunction,
246
- finishExpression: string,
304
+ finishTarget: { fn: GirFunction; expression: string },
247
305
  bindingExpression: string,
248
306
  ): string => {
249
307
  context.addRuntimeImport("promisify");
308
+ const finish = promisifiedFinishExpression(context, finishTarget.fn, finishTarget.expression);
250
309
  const cancellableIndex = findCancellableIndex(context, asyncFn.parameters);
251
310
 
252
311
  const promisifyContext: PromisifyContext = {
@@ -267,7 +326,7 @@ const renderPromisifiedBody = (
267
326
  const cancellableExpression = renderCancellableExpression(asyncFn.parameters, cancellableIndex);
268
327
  const leadingArguments = leadingExpressions.length > 0 ? `, ${leadingExpressions.join(", ")}` : "";
269
328
 
270
- return `return promisify(${bindingExpression}, ${finishExpression}, ${cancellableExpression}${leadingArguments});`;
329
+ return `return promisify(${bindingExpression}, ${finish}, ${cancellableExpression}${leadingArguments});`;
271
330
  };
272
331
 
273
332
  const finishCallExpression = (asyncFn: GirFunction, finishFn: GirFunction, ownerName: string): string =>
@@ -310,7 +369,12 @@ const renderPromisifiedSignature = (
310
369
  isOptionalExtra: (parameter) => isCancellable(context, parameter),
311
370
  });
312
371
 
313
- const finishReturn = renderMethodReturnType(context, finishFn);
372
+ const finishReturn = shouldTrimFinishBoolean(context, finishFn)
373
+ ? foldOutParamShape(
374
+ undefined,
375
+ returnedOutParameters(context, finishFn).map(({ parameter }) => renderOutTsType(context, parameter)),
376
+ )
377
+ : renderMethodReturnType(context, finishFn);
314
378
 
315
379
  return { signature, returnType: `Promise<${finishReturn}>` };
316
380
  };
@@ -356,6 +420,14 @@ const paramDescriptorLiteral = (descriptor: string, options: ParamDescriptorOpti
356
420
  parts.push("isConsumed: true");
357
421
  }
358
422
 
423
+ if (options.isUnpacked === true) {
424
+ parts.push("isUnpacked: true");
425
+ }
426
+
427
+ if (options.isRequired === true) {
428
+ parts.push("isRequired: true");
429
+ }
430
+
359
431
  return `{ ${parts.join(", ")} }`;
360
432
  };
361
433
 
@@ -368,7 +440,11 @@ const renderReturnDescriptor = (context: ModuleContext, fn: GirFunction): Return
368
440
  isNewlyCreated: fn.instance === undefined,
369
441
  });
370
442
 
371
- return { descriptor, isSkipped: isSkippedPrimaryReturn(context.library, fn.returnValue) };
443
+ return {
444
+ descriptor,
445
+ isSkipped: isSkippedPrimaryReturn(context.library, fn.returnValue),
446
+ isUnpacked: isUnwrappedValue(context, fn.returnValue.type),
447
+ };
372
448
  };
373
449
 
374
450
  const planCallArgs = (context: ModuleContext, fn: GirFunction): CallArgPlan[] => {
@@ -408,6 +484,8 @@ const planCallArgs = (context: ModuleContext, fn: GirFunction): CallArgPlan[] =>
408
484
  const isSkippedPlanParameter = (parameter: GirParameter, index: number, closureIndices: Set<number>): boolean =>
409
485
  parameter.isVarargs || closureIndices.has(index);
410
486
 
487
+ const isRequiredParameter = (parameter: GirParameter): boolean => !parameter.nullable && !parameter.optional;
488
+
411
489
  const planParameter = (
412
490
  context: ModuleContext,
413
491
  parameter: GirParameter,
@@ -503,18 +581,35 @@ const planCallerOut = (
503
581
  parameter: GirParameter,
504
582
  argIndex: ArgIndexOptions,
505
583
  ): CallArgPlan => {
506
- const descriptor = renderDescriptor(context, parameter.type, "none", argIndex);
507
-
508
584
  if (isCollectibleCallerOut(context, parameter)) {
509
585
  context.addRuntimeImport("getHandle");
510
586
 
511
587
  return {
512
- paramLiteral: paramDescriptorLiteral(descriptor, { direction: "out", isCallerAllocated: true }),
588
+ paramLiteral: paramDescriptorLiteral(renderDescriptor(context, parameter.type, "none", argIndex), {
589
+ direction: "out",
590
+ isCallerAllocated: true,
591
+ isUnpacked: isUnpackedOutParameter(context, parameter),
592
+ }),
513
593
  inputExpr: renderCallerOutInstance(context, parameter),
514
594
  };
515
595
  }
516
596
 
517
- return { paramLiteral: paramDescriptorLiteral(descriptor, {}), inputExpr: "undefined" };
597
+ if (isFixedArrayCallerOut(context, parameter)) {
598
+ const descriptor = renderDescriptor(context, parameter.type, "none", {
599
+ ...argIndex,
600
+ isCallerAllocated: true,
601
+ });
602
+
603
+ return {
604
+ paramLiteral: paramDescriptorLiteral(descriptor, { direction: "out" }),
605
+ inputExpr: undefined,
606
+ };
607
+ }
608
+
609
+ return {
610
+ paramLiteral: paramDescriptorLiteral(renderDescriptor(context, parameter.type, "none", argIndex), {}),
611
+ inputExpr: "undefined",
612
+ };
518
613
  };
519
614
 
520
615
  const planInoutParam = (
@@ -537,7 +632,8 @@ const planInoutParam = (
537
632
  paramLiteral: paramDescriptorLiteral(descriptor, {
538
633
  direction: "inout",
539
634
  isCallerAllocated: true,
540
- isConsumed,
635
+ isConsumed: isConsumed || context.library.isInoutInPlace,
636
+ isRequired: isRequiredParameter(parameter),
541
637
  }),
542
638
  inputExpr: parameterIdentifier(parameter, index),
543
639
  };
@@ -549,7 +645,11 @@ const planInoutParam = (
549
645
  });
550
646
 
551
647
  return {
552
- paramLiteral: paramDescriptorLiteral(descriptor, { direction: "inout", isConsumed }),
648
+ paramLiteral: paramDescriptorLiteral(descriptor, {
649
+ direction: "inout",
650
+ isConsumed,
651
+ isRequired: lengthSource === undefined && isRequiredParameter(parameter),
652
+ }),
553
653
  inputExpr:
554
654
  lengthSource === undefined
555
655
  ? parameterCallExpression(context, parameter, index, { fn })
@@ -582,7 +682,7 @@ const planInParam = (
582
682
  );
583
683
 
584
684
  return {
585
- paramLiteral: paramDescriptorLiteral(descriptor, {}),
685
+ paramLiteral: paramDescriptorLiteral(descriptor, { isRequired: isRequiredParameter(parameter) }),
586
686
  inputExpr: parameterCallExpression(context, parameter, index, { fn }),
587
687
  };
588
688
  };
@@ -602,7 +702,25 @@ const closureArgument = (context: ModuleContext, name: string, isNullable: boole
602
702
  return `${helper}(${name})`;
603
703
  };
604
704
 
605
- const hashtableArgument = (context: ModuleContext, valueRef: TypeId, name: string): string => {
705
+ const valueArgument = (context: ModuleContext, name: string, isNullable: boolean): string => {
706
+ const helper = isNullable ? "tryToValueHandle" : "toValueHandle";
707
+ context.addRuntimeImport(helper);
708
+
709
+ return `${helper}(${name})`;
710
+ };
711
+
712
+ const hashtableArgument = (
713
+ context: ModuleContext,
714
+ valueRef: TypeId,
715
+ name: string,
716
+ isValueMarshalled: boolean,
717
+ ): string => {
718
+ if (isValueMarshalled && isValueType(context, valueRef)) {
719
+ context.addRuntimeImport("toValueHandle");
720
+
721
+ return `${name} ? globalThis.Array.from(${name}).map(([k, v]) => [k, toValueHandle(v)]) : null`;
722
+ }
723
+
606
724
  if (isHandlePassing(context, valueRef)) {
607
725
  context.addRuntimeImport("getHandle");
608
726
 
@@ -612,36 +730,43 @@ const hashtableArgument = (context: ModuleContext, valueRef: TypeId, name: strin
612
730
  return `${name} ? globalThis.Array.from(${name}) : null`;
613
731
  };
614
732
 
615
- const mapHandleExpression = (name: string, isNullable: boolean): string =>
616
- isNullable ? `${name}?.map((item) => getHandle(item))` : `${name}.map((item) => getHandle(item))`;
733
+ const mapItemExpression = (name: string, isNullable: boolean, helper: string): string =>
734
+ isNullable ? `${name}?.map((item) => ${helper}(item))` : `${name}.map((item) => ${helper}(item))`;
735
+
736
+ const itemHelper = (context: ModuleContext, element: TypeId, isValueMarshalled: boolean): string => {
737
+ const helper = isValueMarshalled && isValueType(context, element) ? "toValueHandle" : "getHandle";
738
+ context.addRuntimeImport(helper);
739
+
740
+ return helper;
741
+ };
742
+
743
+ const collectionArgument = (options: MarshalledArgumentOptions & { type: GirType | undefined }): string | undefined => {
744
+ const { context, type, name, isNullable, isValueMarshalled } = options;
617
745
 
618
- const collectionArgument = (
619
- context: ModuleContext,
620
- type: GirType | undefined,
621
- name: string,
622
- isNullable: boolean,
623
- ): string | undefined => {
624
746
  if (type?.kind === "hashtable") {
625
- return hashtableArgument(context, type.value, name);
747
+ return hashtableArgument(context, type.value, name, isValueMarshalled);
626
748
  }
627
749
 
628
- if (!isMappableSequence(context, type)) {
750
+ const element = mappableElement(context, type);
751
+
752
+ if (element === undefined) {
629
753
  return undefined;
630
754
  }
631
755
 
632
- context.addRuntimeImport("getHandle");
633
-
634
- return mapHandleExpression(name, isNullable);
756
+ return mapItemExpression(name, isNullable, itemHelper(context, element, isValueMarshalled));
635
757
  };
636
758
 
637
- const isMappableSequence = (context: ModuleContext, type: GirType | undefined): boolean => {
759
+ const mappableElement = (context: ModuleContext, type: GirType | undefined): TypeId | undefined => {
638
760
  if (type?.kind === "carray") {
639
- return !hasUnknownArrayLength(type) && isHandlePassing(context, type.element);
761
+ return hasUnknownArrayLength(type) ? undefined : mappableRef(context, type.element);
640
762
  }
641
763
 
642
- return type?.kind === "list" && isHandlePassing(context, type.element);
764
+ return type?.kind === "list" ? mappableRef(context, type.element) : undefined;
643
765
  };
644
766
 
767
+ const mappableRef = (context: ModuleContext, element: TypeId): TypeId | undefined =>
768
+ isHandlePassing(context, element) ? element : undefined;
769
+
645
770
  const parameterCallExpression = (
646
771
  context: ModuleContext,
647
772
  parameter: GirParameter,
@@ -662,13 +787,40 @@ const parameterCallExpression = (
662
787
  return closureArgument(context, name, isNullable);
663
788
  }
664
789
 
665
- if (isHandlePassing(context, ref)) {
666
- return handleArgument(context, name, isNullable);
790
+ const marshalled = marshalledArgument({
791
+ context,
792
+ ref,
793
+ name,
794
+ isNullable,
795
+ isValueMarshalled: isValueRead(parameter),
796
+ });
797
+
798
+ if (marshalled !== undefined) {
799
+ return marshalled;
667
800
  }
668
801
 
669
802
  const type = context.library.typeFor(ref);
670
803
 
671
- return collectionArgument(context, type, name, isNullable) ?? name;
804
+ return (
805
+ collectionArgument({
806
+ context,
807
+ ref,
808
+ type,
809
+ name,
810
+ isNullable,
811
+ isValueMarshalled: isValueRead(parameter),
812
+ }) ?? name
813
+ );
814
+ };
815
+
816
+ const marshalledArgument = (options: MarshalledArgumentOptions): string | undefined => {
817
+ const { context, ref, name, isNullable, isValueMarshalled } = options;
818
+
819
+ if (isValueMarshalled && isValueType(context, ref)) {
820
+ return valueArgument(context, name, isNullable);
821
+ }
822
+
823
+ return isHandlePassing(context, ref) ? handleArgument(context, name, isNullable) : undefined;
672
824
  };
673
825
 
674
826
  export {
@@ -681,6 +833,7 @@ export {
681
833
  renderPromisifiedBody,
682
834
  finishCallExpression,
683
835
  renderPromisifiedSignature,
836
+ shouldTrimFinishBoolean,
684
837
  renderMethodBody,
685
838
  renderReturnDescriptor,
686
839
  planCallArgs,
@@ -1,8 +1,8 @@
1
1
  import { sanitizeTypeIdentifier } from "@gtkx/utils";
2
- import type { TypeId } from "../../gir/type-id.js";
2
+ import type { CArrayType, TypeId } from "../../gir/type-id.js";
3
3
  import type { GirType } from "../../gir/type.js";
4
4
  import type { ModuleContext } from "../../writer/context.js";
5
- import { type GirParameter, isInoutParameter } from "../../gir/parameter.js";
5
+ import { type GirParameter, isCallerAllocatedOut, isInoutParameter } from "../../gir/parameter.js";
6
6
  import { recordInlineSize } from "./record-layout.js";
7
7
  import { isConstructibleRecord } from "./value-marshalable.js";
8
8
 
@@ -104,6 +104,62 @@ const renderCallerOutInstance = (context: ModuleContext, parameter: GirParameter
104
104
  const isCollectibleCallerOut = (context: ModuleContext, parameter: GirParameter): boolean =>
105
105
  callerOutAllocation(context, parameter) !== undefined;
106
106
 
107
+ const hasInlineElementStride = (context: ModuleContext, array: CArrayType): boolean => {
108
+ if (array.elementCType?.includes("*") === true) {
109
+ return false;
110
+ }
111
+
112
+ const element = underlyingType(context, array.element);
113
+
114
+ if (element === undefined) {
115
+ return false;
116
+ }
117
+
118
+ switch (element.kind) {
119
+ case "primitive": {
120
+ return (
121
+ element.category !== "void" &&
122
+ element.category !== "string" &&
123
+ element.category !== "pointer" &&
124
+ element.category !== "unichar" &&
125
+ element.category !== "gtype"
126
+ );
127
+ }
128
+ case "enum": {
129
+ return true;
130
+ }
131
+ case "record": {
132
+ return recordInlineSize(context, element.value) !== undefined;
133
+ }
134
+ case "alias":
135
+ case "callback":
136
+ case "carray":
137
+ case "class":
138
+ case "hashtable":
139
+ case "interface":
140
+ case "list":
141
+ case "varargs": {
142
+ return false;
143
+ }
144
+ }
145
+ };
146
+
147
+ const isFixedArrayCallerOut = (context: ModuleContext, parameter: GirParameter): boolean => {
148
+ if (!isCallerAllocatedOut(parameter)) {
149
+ return false;
150
+ }
151
+
152
+ const type = parameter.type === undefined ? undefined : underlyingType(context, parameter.type);
153
+
154
+ return (
155
+ type?.kind === "carray" &&
156
+ type.fixedSize !== undefined &&
157
+ type.fixedSize > 0 &&
158
+ type.lengthParameterIndex === undefined &&
159
+ hasInlineElementStride(context, type)
160
+ );
161
+ };
162
+
107
163
  const isAllocatableCallerOut = (context: ModuleContext, parameter: GirParameter): boolean =>
108
164
  underlyingParamKind(context, parameter) === "record" && isCollectibleCallerOut(context, parameter);
109
165
 
@@ -138,17 +194,24 @@ const isHandlePassing = (context: ModuleContext, ref: TypeId): boolean => {
138
194
  }
139
195
  };
140
196
 
141
- const isClosureType = (context: ModuleContext, ref: TypeId): boolean => {
197
+ const isGObjectTypeNamed = (context: ModuleContext, ref: TypeId, typeName: string): boolean => {
142
198
  const name = context.library.nameFor(ref);
143
199
 
144
- return name?.namespaceName === "GObject" && name.typeName === "Closure";
200
+ return name?.namespaceName === "GObject" && name.typeName === typeName;
145
201
  };
146
202
 
203
+ const isClosureType = (context: ModuleContext, ref: TypeId): boolean => isGObjectTypeNamed(context, ref, "Closure");
204
+ const isValueType = (context: ModuleContext, ref: TypeId): boolean => isGObjectTypeNamed(context, ref, "Value");
205
+ const isValueTypeName = (name: TypeName): boolean => name.namespaceName === "GObject" && name.typeName === "Value";
206
+
147
207
  export {
148
208
  isAllocatableCallerOut,
149
209
  isClosureType,
210
+ isValueType,
211
+ isValueTypeName,
150
212
  isHandlePassedInPlace,
151
213
  isCollectibleCallerOut,
214
+ isFixedArrayCallerOut,
152
215
  isRecordInout,
153
216
  isHandlePassing,
154
217
  renderCallerOutInstance,
@@ -6,12 +6,17 @@ import type { TypeId } from "../../gir/type-id.js";
6
6
  import type { ModuleContext } from "../../writer/context.js";
7
7
  import { renderDescriptor } from "../../analysis/descriptor-render.js";
8
8
  import { inputParameters, parameterIdentifier } from "../../analysis/param-structure.js";
9
- import { renderTsType } from "../../analysis/ts-type.js";
10
9
  import { renderBlock, renderBracedOrEmpty } from "../../writer/emit.js";
11
10
  import { type Callables, staticMembers } from "./callables.js";
12
11
  import { getDoc } from "./doc-spec.js";
13
12
  import { renderSourceGtype } from "./gtype-binding.js";
14
- import { emitFieldWrite, isEmittableField, isInlineField, isStorableFieldType } from "./record-field-accessor.js";
13
+ import {
14
+ emitFieldWrite,
15
+ fieldTsType,
16
+ isEmittableField,
17
+ isInlineField,
18
+ isStorableFieldType,
19
+ } from "./record-field-accessor.js";
15
20
  import { computeRecordFieldSlots, type RecordFieldSlot } from "./record-layout.js";
16
21
  import { isConstructibleRecord } from "./value-marshalable.js";
17
22
 
@@ -42,7 +47,7 @@ const renderRecordConstructorPropsInterface = (
42
47
  .map(
43
48
  (entry) =>
44
49
  `${getDoc(entry.field)}${toCamelIdentifier(entry.field.name)}?: ` +
45
- `${renderTsType(context, entry.field.type, true)};`,
50
+ `${fieldTsType(context, entry.field.type, true)};`,
46
51
  );
47
52
 
48
53
  return renderBracedOrEmpty(head, lines.join("\n"));