@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
@@ -65,6 +65,7 @@ type ArgIndexOptions = {
65
65
  };
66
66
 
67
67
  type CursorArgIndexOptions = ArgIndexOptions & { cursor: GirCursorBounds };
68
+ type CArrayExpressionOptions = ArgIndexOptions & { isCallerAllocated: boolean };
68
69
 
69
70
  type RenderDescriptorOptions = Partial<ArgIndexOptions> & {
70
71
  isCallerAllocated?: boolean;
@@ -77,6 +78,11 @@ type RecordPlacement = {
77
78
  isInline?: boolean;
78
79
  };
79
80
 
81
+ type RecordLayout = {
82
+ isCallerAllocated: boolean;
83
+ isInline: boolean;
84
+ };
85
+
80
86
  type FundamentalDescriptor = {
81
87
  lib: string;
82
88
  refFunc: string;
@@ -84,6 +90,7 @@ type FundamentalDescriptor = {
84
90
  typeName: string | undefined;
85
91
  ownership: Ownership;
86
92
  wrapperClass?: string | undefined;
93
+ isCallerAllocated?: boolean | undefined;
87
94
  isInline?: boolean | undefined;
88
95
  };
89
96
 
@@ -103,6 +110,7 @@ type FundamentalRecordOptions = {
103
110
  unrefFunc: string;
104
111
  ownership: Ownership;
105
112
  wrapperClass: string | undefined;
113
+ isCallerAllocated: boolean;
106
114
  isInline: boolean;
107
115
  };
108
116
 
@@ -189,7 +197,7 @@ const renderDescriptor = (
189
197
  return tVoid;
190
198
  }
191
199
  case "callback": {
192
- return tUint64;
200
+ return tBiguint64;
193
201
  }
194
202
  case "class":
195
203
  case "interface":
@@ -199,7 +207,10 @@ const renderDescriptor = (
199
207
  return expressionForResolved(context, type, transfer, options);
200
208
  }
201
209
  case "carray": {
202
- return arrayExpression(context, type, transfer, indexOptions);
210
+ return arrayExpression(context, type, transfer, {
211
+ ...indexOptions,
212
+ isCallerAllocated: options.isCallerAllocated === true,
213
+ });
203
214
  }
204
215
  case "list": {
205
216
  return listExpression(context, type, transfer, indexOptions);
@@ -333,7 +344,11 @@ const findUserDataIndex = (parameters: GirParameter[]): number | undefined => {
333
344
  return declared?.closureIndex ?? userDataIndexByName(parameters);
334
345
  };
335
346
 
336
- const callbackOptionsArg = (owningParameter: GirParameter, userDataIndex: number | undefined): string[] => {
347
+ const callbackOptionsArg = (
348
+ owningParameter: GirParameter,
349
+ userDataIndex: number | undefined,
350
+ canThrow: boolean,
351
+ ): string[] => {
337
352
  const options: string[] = [];
338
353
 
339
354
  if (owningParameter.destroyIndex !== undefined) {
@@ -348,6 +363,10 @@ const callbackOptionsArg = (owningParameter: GirParameter, userDataIndex: number
348
363
  options.push(`userDataIndex: ${String(userDataIndex)}`);
349
364
  }
350
365
 
366
+ if (canThrow) {
367
+ options.push("canThrow: true");
368
+ }
369
+
351
370
  if (owningParameter.scope !== undefined) {
352
371
  options.push(`scope: ${sourceStringLiteral(owningParameter.scope)}`);
353
372
  }
@@ -376,7 +395,7 @@ const renderCallbackType = (
376
395
  return tCallback({
377
396
  argTypes,
378
397
  returns: renderDescriptor(context, returnValue.type, returnValue.transferOwnership),
379
- options: callbackOptionsArg(owningParameter, findUserDataIndex(callback.parameters)),
398
+ options: callbackOptionsArg(owningParameter, findUserDataIndex(callback.parameters), callback.throws),
380
399
  });
381
400
  };
382
401
 
@@ -401,12 +420,13 @@ const primitiveExpression = (category: PrimitiveCategory, ownership: Ownership):
401
420
  };
402
421
 
403
422
  const renderFundamental = (descriptor: FundamentalDescriptor): string => {
404
- const { lib, refFunc, unrefFunc, typeName, ownership, wrapperClass, isInline } = descriptor;
423
+ const { lib, refFunc, unrefFunc, typeName, ownership, wrapperClass, isCallerAllocated, isInline } = descriptor;
405
424
 
406
425
  return tFundamental(lib, refFunc, unrefFunc, {
407
426
  ownership,
408
427
  typeName,
409
428
  wrapperClass,
429
+ isCallerAllocated,
410
430
  isInline,
411
431
  });
412
432
  };
@@ -529,6 +549,11 @@ const renderSelfDescriptor = (context: ModuleContext, instance: GirParameter): s
529
549
  return tObject("borrowed");
530
550
  };
531
551
 
552
+ const recordLayout = (placement: RecordPlacement): RecordLayout => ({
553
+ isCallerAllocated: placement.isCallerAllocated ?? false,
554
+ isInline: placement.isInline ?? false,
555
+ });
556
+
532
557
  const recordRefPair = (record: ResolvedRecord): { refFunc: string | undefined; unrefFunc: string | undefined } => ({
533
558
  refFunc: record.glibRefFunc ?? record.copyFunc,
534
559
  unrefFunc: record.glibUnrefFunc ?? record.freeFunc,
@@ -563,7 +588,7 @@ const structExpression = (
563
588
  };
564
589
 
565
590
  const fundamentalRecordExpression = (options: FundamentalRecordOptions): string => {
566
- const { resolved, lib, refFunc, unrefFunc, ownership, wrapperClass, isInline } = options;
591
+ const { resolved, lib, refFunc, unrefFunc, ownership, wrapperClass, isCallerAllocated, isInline } = options;
567
592
 
568
593
  return renderFundamental({
569
594
  lib,
@@ -572,6 +597,7 @@ const fundamentalRecordExpression = (options: FundamentalRecordOptions): string
572
597
  typeName: resolved.value.glibTypeName,
573
598
  ownership,
574
599
  wrapperClass,
600
+ isCallerAllocated,
575
601
  isInline,
576
602
  });
577
603
  };
@@ -606,11 +632,7 @@ const plainRecordExpression = (
606
632
  placement: RecordPlacement,
607
633
  ): string => {
608
634
  const record = resolved.value;
609
-
610
- const layout = {
611
- isCallerAllocated: placement.isCallerAllocated ?? false,
612
- isInline: placement.isInline ?? false,
613
- };
635
+ const layout = recordLayout(placement);
614
636
 
615
637
  if (record.glibGetType === undefined) {
616
638
  return structExpression(context, resolved, ownership, layout);
@@ -619,6 +641,17 @@ const plainRecordExpression = (
619
641
  return boxedRecordExpression({ context, resolved, ownership, ...layout, typeFnName: record.glibGetType });
620
642
  };
621
643
 
644
+ const isPlainStruct = (resolved: Extract<EntityType, { kind: "record" }>): boolean => {
645
+ const record = resolved.value;
646
+ const { refFunc, unrefFunc } = recordRefPair(record);
647
+
648
+ if (refFunc !== undefined && unrefFunc !== undefined && resolved.namespace.sharedLibrary !== undefined) {
649
+ return false;
650
+ }
651
+
652
+ return record.glibGetType === undefined;
653
+ };
654
+
622
655
  const recordExpression = (
623
656
  context: ModuleContext,
624
657
  resolved: Extract<EntityType, { kind: "record" }>,
@@ -641,7 +674,7 @@ const recordExpression = (
641
674
  unrefFunc,
642
675
  ownership,
643
676
  wrapperClass,
644
- isInline: placement.isInline ?? false,
677
+ ...recordLayout(placement),
645
678
  });
646
679
  }
647
680
 
@@ -650,16 +683,20 @@ const recordExpression = (
650
683
 
651
684
  const rawEnumDescriptor = (isSigned: boolean): string => (isSigned ? tInt32 : tUint32);
652
685
 
686
+ const flagsMask = (resolved: Extract<EntityType, { kind: "enum" }>): number =>
687
+ resolved.value.members.reduce((mask, member) => (mask | Number(member.value)) >>> 0, 0);
688
+
653
689
  const enumExpression = (resolved: Extract<EntityType, { kind: "enum" }>): string => {
654
690
  const getter = resolved.value.glibGetType;
655
691
  const isSigned = resolved.value.members.some((member) => member.value.startsWith("-"));
656
692
  const lib = resolved.namespace.sharedLibrary;
693
+ const isBitfield = resolved.value.kind === "bitfield";
657
694
 
658
695
  if (getter === undefined || getter === "" || lib === undefined) {
659
- return rawEnumDescriptor(isSigned);
696
+ return isBitfield ? tFlags("", "", isSigned, flagsMask(resolved)) : rawEnumDescriptor(isSigned);
660
697
  }
661
698
 
662
- return resolved.value.kind === "bitfield" ? tFlags(lib, getter, isSigned) : tEnum(lib, getter, isSigned);
699
+ return isBitfield ? tFlags(lib, getter, isSigned) : tEnum(lib, getter, isSigned);
663
700
  };
664
701
 
665
702
  const expressionForResolved = (
@@ -700,6 +737,7 @@ const elementExpression = (
700
737
  ...options,
701
738
  cursor: undefined,
702
739
  hasOutIndirection: false,
740
+ isCallerAllocated: false,
703
741
  });
704
742
 
705
743
  const cursorArrayExpression = (
@@ -724,11 +762,14 @@ const arrayLayout = (context: ModuleContext, ref: CArrayType, options: ArgIndexO
724
762
  context.library.isByteArrayTyped && !hasUnknownArrayLength(ref) && isByteSequence(context.library, ref),
725
763
  });
726
764
 
765
+ const fixedArrayLayout = (layout: ArrayLayout, isCallerAllocated: boolean): ArrayLayout =>
766
+ isCallerAllocated ? { ...layout, isCallerAllocated: true } : layout;
767
+
727
768
  const arrayExpression = (
728
769
  context: ModuleContext,
729
770
  ref: CArrayType,
730
771
  transfer: ParameterTransfer,
731
- options: ArgIndexOptions,
772
+ options: CArrayExpressionOptions,
732
773
  ): string => {
733
774
  const { cursor } = options;
734
775
  const layout = arrayLayout(context, ref, options);
@@ -749,7 +790,7 @@ const arrayExpression = (
749
790
  }
750
791
 
751
792
  if (ref.fixedSize !== undefined) {
752
- return tFixedArray(element, ref.fixedSize, ownership, layout);
793
+ return tFixedArray(element, ref.fixedSize, ownership, fixedArrayLayout(layout, options.isCallerAllocated));
753
794
  }
754
795
 
755
796
  return tArray(element, ownership, layout);
@@ -789,6 +830,8 @@ const aliasExpression = (
789
830
  };
790
831
 
791
832
  export {
833
+ isPlainStruct,
834
+ transferOwnership,
792
835
  isInlineCallbackRef,
793
836
  isSkippedPrimaryReturn,
794
837
  isVoidPrimaryReturn,
@@ -82,6 +82,7 @@ type FundamentalOptions = {
82
82
  ownership: Ownership;
83
83
  typeName: string | undefined;
84
84
  wrapperClass: string | undefined;
85
+ isCallerAllocated?: boolean | undefined;
85
86
  isInline?: boolean | undefined;
86
87
  };
87
88
 
@@ -90,6 +91,7 @@ type ListDescriptorName = "list" | "slist" | "ptrArray" | "gArray";
90
91
  type ArrayLayout = {
91
92
  elementSize?: number | undefined;
92
93
  isBytes: boolean;
94
+ isCallerAllocated?: boolean | undefined;
93
95
  };
94
96
 
95
97
  type BindArgs = {
@@ -103,6 +105,7 @@ type FnSpecParts = {
103
105
  args: string;
104
106
  returns: string;
105
107
  isReturnSkipped: boolean;
108
+ isReturnUnpacked: boolean;
106
109
  canThrow: boolean;
107
110
  };
108
111
 
@@ -113,6 +116,7 @@ type CallbackSpecParts = {
113
116
  };
114
117
 
115
118
  const SKIPPED_RETURN_ENTRY = "isReturnSkipped: true";
119
+ const UNPACKED_RETURN_ENTRY = "isReturnUnpacked: true";
116
120
 
117
121
  const T: DescriptorNames = {
118
122
  bind: "t.bind",
@@ -218,6 +222,7 @@ const tFundamental = (lib: string, refFunc: string, unrefFunc: string, options:
218
222
  `ownership: ${sourceStringLiteral(options.ownership)}`,
219
223
  options.typeName === undefined ? undefined : `typeName: ${sourceStringLiteral(options.typeName)}`,
220
224
  options.wrapperClass === undefined ? undefined : `wrapperClass: ${options.wrapperClass}`,
225
+ options.isCallerAllocated === true ? "isCallerAllocated: true" : undefined,
221
226
  options.isInline === true ? "isInline: true" : undefined,
222
227
  ]),
223
228
  ]);
@@ -230,8 +235,13 @@ const tHashTable = (key: string, value: string, ownership: Ownership): string =>
230
235
  const tEnum = (lib: string, typeFnName: string, isSigned: boolean): string =>
231
236
  call("enum", [sourceStringLiteral(lib), sourceStringLiteral(typeFnName), String(isSigned)]);
232
237
 
233
- const tFlags = (lib: string, typeFnName: string, isSigned: boolean): string =>
234
- call("flags", [sourceStringLiteral(lib), sourceStringLiteral(typeFnName), String(isSigned)]);
238
+ const tFlags = (lib: string, typeFnName: string, isSigned: boolean, mask?: number): string =>
239
+ call("flags", [
240
+ sourceStringLiteral(lib),
241
+ sourceStringLiteral(typeFnName),
242
+ String(isSigned),
243
+ mask === undefined ? undefined : `0x${mask.toString(16)}`,
244
+ ]);
235
245
 
236
246
  const tByteArray = (ownership: Ownership): string => call("byteArray", [sourceStringLiteral(ownership)]);
237
247
 
@@ -253,6 +263,7 @@ const arrayLayoutArg = (ownership: Ownership | undefined, layout: ArrayLayout):
253
263
  const entries = [
254
264
  layout.elementSize === undefined ? undefined : `elementSize: ${String(layout.elementSize)}`,
255
265
  layout.isBytes ? "isBytes: true" : undefined,
266
+ layout.isCallerAllocated === true ? "isCallerAllocated: true" : undefined,
256
267
  ].filter((entry): entry is string => entry !== undefined);
257
268
 
258
269
  return entries.length === 0 ? undefined : `{ ${entries.join(", ")} }`;
@@ -311,12 +322,13 @@ const tBind = (args: BindArgs): string =>
311
322
 
312
323
  const tFn = (lib: string, cIdentifier: string, spec: FnSpecParts): string => {
313
324
  const skipEntry = spec.isReturnSkipped ? `, ${SKIPPED_RETURN_ENTRY}` : "";
325
+ const unpackEntry = spec.isReturnUnpacked ? `, ${UNPACKED_RETURN_ENTRY}` : "";
314
326
  const throwsEntry = spec.canThrow ? ", canThrow: true" : "";
315
327
 
316
328
  return call("fn", [
317
329
  sourceStringLiteral(lib),
318
330
  sourceStringLiteral(cIdentifier),
319
- `{ args: ${spec.args}, returns: ${spec.returns}${skipEntry}${throwsEntry} }`,
331
+ `{ args: ${spec.args}, returns: ${spec.returns}${skipEntry}${unpackEntry}${throwsEntry} }`,
320
332
  ]);
321
333
  };
322
334
 
@@ -1,11 +1,20 @@
1
- import type { GirCallable, GirParameter } from "../gir/parameter.js";
1
+ import type { GirCallable, GirParameter, ParameterTransfer } from "../gir/parameter.js";
2
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
5
  import { isCallerAllocatedOut, isInoutParameter } from "../gir/parameter.js";
6
- import { isCollectibleCallerOut, isHandlePassedInPlace, underlyingType } from "../store/gi/param-marshal.js";
6
+ import {
7
+ isCollectibleCallerOut,
8
+ isFixedArrayCallerOut,
9
+ isHandlePassedInPlace,
10
+ isRecordInout,
11
+ underlyingType,
12
+ } from "../store/gi/param-marshal.js";
7
13
  import { recordInlineSize } from "../store/gi/record-layout.js";
8
- import { isScalarRef } from "./descriptor-render.js";
14
+ import { isPlainStruct, isScalarRef, transferOwnership } from "./descriptor-render.js";
15
+ import { closureAndDestroyIndices } from "./param-structure.js";
16
+
17
+ type UnmarshalableSubject = GirCallable & { instance?: GirParameter | undefined };
9
18
 
10
19
  const POINTER_DEPTH = 1;
11
20
 
@@ -119,6 +128,10 @@ const isUnmarshalableCallerOut = (context: ModuleContext, parameter: GirParamete
119
128
  return true;
120
129
  }
121
130
 
131
+ if (isFixedArrayCallerOut(context, parameter)) {
132
+ return false;
133
+ }
134
+
122
135
  return !isCollectibleCallerOut(context, parameter) && !parameter.optional;
123
136
  };
124
137
 
@@ -143,12 +156,59 @@ const isTypeErasedCallback = (context: ModuleContext, parameter: GirParameter):
143
156
  return type?.kind === "callback" && type.value.parameters.length === 0;
144
157
  };
145
158
 
159
+ const isCallbackParam = (context: ModuleContext, parameter: GirParameter): boolean => {
160
+ const type = parameter.type === undefined ? undefined : underlyingType(context, parameter.type);
161
+
162
+ return type?.kind === "callback";
163
+ };
164
+
165
+ const hasDetachedClosure = (parameter: GirParameter, index: number): boolean => {
166
+ const userDataIndex = parameter.closureIndex;
167
+
168
+ if (userDataIndex !== undefined && userDataIndex !== index + 1) {
169
+ return true;
170
+ }
171
+
172
+ const notifyIndex = parameter.destroyIndex;
173
+
174
+ return notifyIndex !== undefined && notifyIndex !== index + (userDataIndex === undefined ? 1 : 2);
175
+ };
176
+
177
+ const hasDetachedCallback = (context: ModuleContext, parameters: GirParameter[]): boolean => {
178
+ const claimed = closureAndDestroyIndices({ parameters });
179
+
180
+ return parameters.some(
181
+ (parameter, index) =>
182
+ !claimed.has(index) && isCallbackParam(context, parameter) && hasDetachedClosure(parameter, index),
183
+ );
184
+ };
185
+
186
+ const isRefusedTransfer = (
187
+ context: ModuleContext,
188
+ ref: TypeId | undefined,
189
+ transfer: ParameterTransfer,
190
+ ): boolean => {
191
+ if (ref === undefined || transferOwnership(transfer) !== "full") {
192
+ return false;
193
+ }
194
+
195
+ const type = underlyingType(context, ref);
196
+
197
+ return type?.kind === "record" && isPlainStruct(type);
198
+ };
199
+
200
+ const isLentInPlace = (context: ModuleContext, parameter: GirParameter): boolean =>
201
+ isCallerAllocatedOut(parameter) || isRecordInout(context, parameter);
202
+
203
+ const isRefusedParamTransfer = (context: ModuleContext, parameter: GirParameter): boolean =>
204
+ !isLentInPlace(context, parameter) && isRefusedTransfer(context, parameter.type, parameter.transferOwnership);
205
+
146
206
  const isUnmarshalableCallParam = (context: ModuleContext, parameter: GirParameter): boolean => {
147
207
  if (parameter.isVarargs) {
148
208
  return false;
149
209
  }
150
210
 
151
- if (isTypeErasedCallback(context, parameter)) {
211
+ if (isTypeErasedCallback(context, parameter) || isRefusedParamTransfer(context, parameter)) {
152
212
  return true;
153
213
  }
154
214
 
@@ -163,7 +223,10 @@ const isUnmarshalableCallParam = (context: ModuleContext, parameter: GirParamete
163
223
  return hasIndirectionMismatch(context, parameter);
164
224
  };
165
225
 
166
- const hasUnmarshalableParam = (context: ModuleContext, callable: GirCallable): boolean =>
226
+ const hasUnmarshalableParam = (context: ModuleContext, callable: UnmarshalableSubject): boolean =>
227
+ (callable.instance !== undefined && isRefusedParamTransfer(context, callable.instance)) ||
228
+ isRefusedTransfer(context, callable.returnValue.type, callable.returnValue.transferOwnership) ||
229
+ hasDetachedCallback(context, callable.parameters) ||
167
230
  callable.parameters.some((parameter) => isUnmarshalableCallParam(context, parameter));
168
231
 
169
232
  export { hasUnmarshalableParam };
@@ -61,7 +61,7 @@ const inputParameters = (library: Library, fn: GirFunction): InputParameter[] =>
61
61
  return result;
62
62
  };
63
63
 
64
- const closureAndDestroyIndices = (fn: GirFunction): Set<number> => {
64
+ const closureAndDestroyIndices = (fn: Pick<GirCallable, "parameters">): Set<number> => {
65
65
  const indices: Set<number> = new Set();
66
66
 
67
67
  for (const parameter of fn.parameters) {
@@ -11,7 +11,8 @@ import {
11
11
  type ListType,
12
12
  type TypeId,
13
13
  } from "../gir/type-id.js";
14
- import { gtypeTsType } from "../store/gi/gtype-binding.js";
14
+ import { gtypeParamTsType, gtypeTsType } from "../store/gi/gtype-binding.js";
15
+ import { isValueTypeName } from "../store/gi/param-marshal.js";
15
16
  import { isByteSequence } from "./type-shape.js";
16
17
 
17
18
  type ReferenceName = {
@@ -27,6 +28,12 @@ type TsTypeTarget = {
27
28
  renderGtype: () => string;
28
29
  };
29
30
 
31
+ type ModuleTypeOptions = {
32
+ byteArrayType: string;
33
+ isValueWidened: boolean;
34
+ isGtypeWidened: boolean;
35
+ };
36
+
30
37
  const BYTE_ARRAY_TYPE = "Uint8Array";
31
38
  const BYTE_ARRAY_INPUT_TYPE = "Uint8Array | number[]";
32
39
  const NUMBER_ARRAY_TYPE = "number[]";
@@ -101,6 +108,8 @@ const renderContainerType = (
101
108
  return renderSequenceType(library, target, type);
102
109
  };
103
110
 
111
+ const parenthesizeUnion = (rendered: string): string => (rendered.includes(" | ") ? `(${rendered})` : rendered);
112
+
104
113
  const renderSequenceType = (library: Library, target: TsTypeTarget, type: CArrayType | ListType): string => {
105
114
  if (type.kind === "carray" && hasUnknownArrayLength(type)) {
106
115
  return "number";
@@ -110,7 +119,7 @@ const renderSequenceType = (library: Library, target: TsTypeTarget, type: CArray
110
119
  return target.byteArrayType;
111
120
  }
112
121
 
113
- return `${renderBaseType(library, target, type.element)}[]`;
122
+ return `${parenthesizeUnion(renderBaseType(library, target, type.element))}[]`;
114
123
  };
115
124
 
116
125
  const renderNamedType = (
@@ -128,30 +137,55 @@ const renderNamedType = (
128
137
  const getByteArrayType = (library: Library): string =>
129
138
  library.isByteArrayTyped ? BYTE_ARRAY_TYPE : NUMBER_ARRAY_TYPE;
130
139
 
131
- const moduleTarget = (context: ModuleContext, byteArrayType: string): TsTypeTarget => ({
140
+ const renderNamedModuleType = (context: ModuleContext, name: ReferenceName, isValueWidened: boolean): string => {
141
+ const qualified = context.qualify(name.namespaceName, name.typeName);
142
+
143
+ if (!isValueWidened || !isValueTypeName(name)) {
144
+ return qualified;
145
+ }
146
+
147
+ context.addRuntimeTypeImport("JsValue");
148
+
149
+ return `${qualified} | JsValue`;
150
+ };
151
+
152
+ const moduleTarget = (context: ModuleContext, options: ModuleTypeOptions): TsTypeTarget => ({
132
153
  containerStyle: "map",
133
154
  callbackType: "((...args: any[]) => any)",
134
- byteArrayType,
135
- renderNamed: (_resolved, name) => context.qualify(name.namespaceName, name.typeName),
136
- renderGtype: () => gtypeTsType(context),
155
+ byteArrayType: options.byteArrayType,
156
+ renderNamed: (_resolved, name) => renderNamedModuleType(context, name, options.isValueWidened),
157
+ renderGtype: () => (options.isGtypeWidened ? gtypeParamTsType(context) : gtypeTsType(context)),
137
158
  });
138
159
 
139
160
  const renderModuleType = (
140
161
  context: ModuleContext,
141
162
  ref: TypeId | undefined,
142
163
  isNullable: boolean,
143
- byteArrayType: string,
164
+ options: ModuleTypeOptions,
144
165
  ): string => {
145
- const base = renderBaseType(context.library, moduleTarget(context, byteArrayType), ref);
166
+ const base = renderBaseType(context.library, moduleTarget(context, options), ref);
146
167
 
147
168
  return isNullable ? `${base} | null` : base;
148
169
  };
149
170
 
150
171
  const renderTsType = (context: ModuleContext, ref: TypeId | undefined, isNullable = false): string =>
151
- renderModuleType(context, ref, isNullable, getByteArrayType(context.library));
172
+ renderModuleType(context, ref, isNullable, {
173
+ byteArrayType: getByteArrayType(context.library),
174
+ isValueWidened: false,
175
+ isGtypeWidened: false,
176
+ });
152
177
 
153
- const renderParameterTsType = (context: ModuleContext, ref: TypeId | undefined, isNullable = false): string =>
154
- renderModuleType(context, ref, isNullable, BYTE_ARRAY_INPUT_TYPE);
178
+ const renderParameterTsType = (
179
+ context: ModuleContext,
180
+ ref: TypeId | undefined,
181
+ isNullable = false,
182
+ isValueWidened = true,
183
+ ): string =>
184
+ renderModuleType(context, ref, isNullable, {
185
+ byteArrayType: BYTE_ARRAY_INPUT_TYPE,
186
+ isValueWidened,
187
+ isGtypeWidened: true,
188
+ });
155
189
 
156
190
  const recordTypeTarget = (
157
191
  library: Library,
package/src/compile.ts CHANGED
@@ -76,7 +76,7 @@ const DECLARATION_EMIT = {
76
76
  };
77
77
 
78
78
  const MODULE_EMIT = {
79
- removeComments: false,
79
+ removeComments: true,
80
80
  };
81
81
 
82
82
  const DECLARATION_OPTIONS = ts.convertCompilerOptionsFromJson(
@@ -3,6 +3,7 @@ import type { GirClass } from "../gir/class.js";
3
3
  import type { GirFunction } from "../gir/function.js";
4
4
  import type { GirRecord } from "../gir/record.js";
5
5
  import { isEmittableEntity } from "../gir/emittable.js";
6
+ import { externalPackageFor } from "../gir/external-namespaces.js";
6
7
  import { Library } from "../gir/library.js";
7
8
  import { type GirNamespace, namespaceDirectory } from "../gir/namespace.js";
8
9
  import { dedupeCallables, isEmittableCallable } from "../store/gi/callables.js";
@@ -26,6 +27,12 @@ type ApiReferenceOptions = {
26
27
  omittedProps?: OmittedProps;
27
28
  /** Describes GIR byte sequences as `Uint8Array` rather than `number[]`; defaults to false. */
28
29
  isByteArrayTyped?: boolean;
30
+ /** Describes what a `GObject.Value` a binding hands back holds, rather than the value itself; off by default. */
31
+ isValueUnwrapped?: boolean;
32
+ /** Describes promisified results of a throwing finish without their leading success boolean; off by default. */
33
+ isFinishTrimmed?: boolean;
34
+ /** Describes a handle-passing inout parameter as mutated in place rather than returned; off by default. */
35
+ isInoutInPlace?: boolean;
29
36
  };
30
37
 
31
38
  /** Narrows an `ApiReference.symbols` enumeration. */
@@ -373,7 +380,14 @@ class ApiReference {
373
380
  this.libraries = options.libraries;
374
381
  this.props = options.props ?? {};
375
382
  this.omittedProps = options.omittedProps ?? {};
376
- this.library = Library.load(options.libraries, options.girPath, options.isByteArrayTyped === true);
383
+
384
+ this.library = Library.load(options.libraries, options.girPath, {
385
+ isByteArrayTyped: options.isByteArrayTyped === true,
386
+ isValueUnwrapped: options.isValueUnwrapped === true,
387
+ isFinishTrimmed: options.isFinishTrimmed === true,
388
+ isInoutInPlace: options.isInoutInPlace === true,
389
+ });
390
+
377
391
  this.elementContext = { library: this.library, linkFor: (): string | undefined => undefined };
378
392
  this.buildIndex();
379
393
  }
@@ -399,6 +413,10 @@ class ApiReference {
399
413
 
400
414
  private buildIndex(): void {
401
415
  for (const namespace of this.library.namespaces.values()) {
416
+ if (externalPackageFor(namespace.name) !== undefined) {
417
+ continue;
418
+ }
419
+
402
420
  this.indexNamespace(namespace);
403
421
  }
404
422
 
@@ -475,7 +493,7 @@ class ApiReference {
475
493
  const lower = name.toLowerCase();
476
494
 
477
495
  for (const namespace of this.library.namespaces.values()) {
478
- if (namespace.name.toLowerCase() === lower) {
496
+ if (namespace.name.toLowerCase() === lower && externalPackageFor(namespace.name) === undefined) {
479
497
  return namespace;
480
498
  }
481
499
  }
@@ -39,6 +39,9 @@ type DocsOptions = {
39
39
  omittedProps?: OmittedProps;
40
40
  isForced?: boolean;
41
41
  isByteArrayTyped?: boolean;
42
+ isValueUnwrapped?: boolean;
43
+ isFinishTrimmed?: boolean;
44
+ isInoutInPlace?: boolean;
42
45
  };
43
46
 
44
47
  type DocsManifest = {
@@ -259,7 +262,11 @@ const giInputs = (options: DocsOptions, girFiles: string[]): GiInputs => ({
259
262
  girFiles,
260
263
  libraries: options.libraries,
261
264
  girPath: options.girPath,
265
+ storeVersion: undefined,
262
266
  isByteArrayTyped: options.isByteArrayTyped === true,
267
+ isValueUnwrapped: options.isValueUnwrapped === true,
268
+ isFinishTrimmed: options.isFinishTrimmed === true,
269
+ isInoutInPlace: options.isInoutInPlace === true,
263
270
  });
264
271
 
265
272
  const assertOwnedOutDir = (options: DocsOptions, manifest: DocsManifest | undefined): void => {
@@ -344,7 +351,14 @@ const writeDocs = (options: DocsOptions): DocsResult => {
344
351
  }
345
352
 
346
353
  assertOwnedOutDir(options, previous);
347
- const library = Library.load(options.libraries, options.girPath, options.isByteArrayTyped === true);
354
+
355
+ const library = Library.load(options.libraries, options.girPath, {
356
+ isByteArrayTyped: options.isByteArrayTyped === true,
357
+ isValueUnwrapped: options.isValueUnwrapped === true,
358
+ isFinishTrimmed: options.isFinishTrimmed === true,
359
+ isInoutInPlace: options.isInoutInPlace === true,
360
+ });
361
+
348
362
  const { pages, namespaces } = generatePages(options, input.basePath, library);
349
363
  clearOutDir(options, previous);
350
364
  mkdirSync(options.outDir, { recursive: true });