@gtkx/codegen 1.0.0 → 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 (316) hide show
  1. package/README.md +1 -1
  2. package/dist/analysis/descriptor-render.d.ts +12 -15
  3. package/dist/analysis/descriptor-render.d.ts.map +1 -1
  4. package/dist/analysis/descriptor-render.js +48 -31
  5. package/dist/analysis/descriptor-render.js.map +1 -1
  6. package/dist/analysis/descriptor.d.ts +16 -7
  7. package/dist/analysis/descriptor.d.ts.map +1 -1
  8. package/dist/analysis/descriptor.js +15 -3
  9. package/dist/analysis/descriptor.js.map +1 -1
  10. package/dist/analysis/inheritance.d.ts +4 -2
  11. package/dist/analysis/inheritance.d.ts.map +1 -1
  12. package/dist/analysis/inheritance.js +80 -38
  13. package/dist/analysis/inheritance.js.map +1 -1
  14. package/dist/analysis/interface-conflicts.d.ts +23 -0
  15. package/dist/analysis/interface-conflicts.d.ts.map +1 -0
  16. package/dist/analysis/interface-conflicts.js +144 -0
  17. package/dist/analysis/interface-conflicts.js.map +1 -0
  18. package/dist/analysis/param-capability.d.ts.map +1 -1
  19. package/dist/analysis/param-capability.js +3 -4
  20. package/dist/analysis/param-capability.js.map +1 -1
  21. package/dist/analysis/param-structure.js +2 -2
  22. package/dist/analysis/param-structure.js.map +1 -1
  23. package/dist/analysis/ts-type.d.ts.map +1 -1
  24. package/dist/analysis/ts-type.js +10 -17
  25. package/dist/analysis/ts-type.js.map +1 -1
  26. package/dist/analysis/type-key.d.ts +5 -0
  27. package/dist/analysis/type-key.d.ts.map +1 -0
  28. package/dist/analysis/type-key.js +9 -0
  29. package/dist/analysis/type-key.js.map +1 -0
  30. package/dist/compile.d.ts +12 -3
  31. package/dist/compile.d.ts.map +1 -1
  32. package/dist/compile.js +73 -24
  33. package/dist/compile.js.map +1 -1
  34. package/dist/docs/api-reference.d.ts.map +1 -1
  35. package/dist/docs/api-reference.js +10 -9
  36. package/dist/docs/api-reference.js.map +1 -1
  37. package/dist/docs/element-page.d.ts.map +1 -1
  38. package/dist/docs/element-page.js +5 -3
  39. package/dist/docs/element-page.js.map +1 -1
  40. package/dist/docs/pipeline.d.ts.map +1 -1
  41. package/dist/docs/pipeline.js +85 -18
  42. package/dist/docs/pipeline.js.map +1 -1
  43. package/dist/docs/render.d.ts +2 -1
  44. package/dist/docs/render.d.ts.map +1 -1
  45. package/dist/docs/render.js +5 -4
  46. package/dist/docs/render.js.map +1 -1
  47. package/dist/docs/symbol-page.d.ts.map +1 -1
  48. package/dist/docs/symbol-page.js +9 -6
  49. package/dist/docs/symbol-page.js.map +1 -1
  50. package/dist/fingerprint.d.ts +12 -1
  51. package/dist/fingerprint.d.ts.map +1 -1
  52. package/dist/fingerprint.js +44 -28
  53. package/dist/fingerprint.js.map +1 -1
  54. package/dist/gi.d.ts.map +1 -1
  55. package/dist/gi.js +1 -0
  56. package/dist/gi.js.map +1 -1
  57. package/dist/gir/ancestry.d.ts +7 -1
  58. package/dist/gir/ancestry.d.ts.map +1 -1
  59. package/dist/gir/ancestry.js +9 -1
  60. package/dist/gir/ancestry.js.map +1 -1
  61. package/dist/gir/annotations.d.ts +1 -2
  62. package/dist/gir/annotations.d.ts.map +1 -1
  63. package/dist/gir/annotations.js +1 -1
  64. package/dist/gir/annotations.js.map +1 -1
  65. package/dist/gir/cursor-overrides.d.ts +8 -0
  66. package/dist/gir/cursor-overrides.d.ts.map +1 -0
  67. package/dist/gir/cursor-overrides.js +6 -0
  68. package/dist/gir/cursor-overrides.js.map +1 -0
  69. package/dist/gir/emittable.d.ts +7 -0
  70. package/dist/gir/emittable.d.ts.map +1 -0
  71. package/dist/gir/emittable.js +3 -0
  72. package/dist/gir/emittable.js.map +1 -0
  73. package/dist/gir/function.d.ts.map +1 -1
  74. package/dist/gir/function.js +28 -2
  75. package/dist/gir/function.js.map +1 -1
  76. package/dist/gir/library.js +1 -1
  77. package/dist/gir/library.js.map +1 -1
  78. package/dist/gir/namespace.d.ts +5 -1
  79. package/dist/gir/namespace.d.ts.map +1 -1
  80. package/dist/gir/namespace.js +4 -2
  81. package/dist/gir/namespace.js.map +1 -1
  82. package/dist/gir/parameter.d.ts +13 -1
  83. package/dist/gir/parameter.d.ts.map +1 -1
  84. package/dist/gir/parameter.js +1 -0
  85. package/dist/gir/parameter.js.map +1 -1
  86. package/dist/gir/parse.d.ts.map +1 -1
  87. package/dist/gir/parse.js +3 -6
  88. package/dist/gir/parse.js.map +1 -1
  89. package/dist/guards.d.ts +16 -0
  90. package/dist/guards.d.ts.map +1 -0
  91. package/dist/guards.js +11 -0
  92. package/dist/guards.js.map +1 -0
  93. package/dist/internal.d.ts +2 -0
  94. package/dist/internal.d.ts.map +1 -1
  95. package/dist/internal.js +2 -0
  96. package/dist/internal.js.map +1 -1
  97. package/dist/json.d.ts +3 -0
  98. package/dist/json.d.ts.map +1 -0
  99. package/dist/json.js +11 -0
  100. package/dist/json.js.map +1 -0
  101. package/dist/khronos/modules.d.ts.map +1 -1
  102. package/dist/khronos/modules.js +22 -7
  103. package/dist/khronos/modules.js.map +1 -1
  104. package/dist/khronos/parse.d.ts.map +1 -1
  105. package/dist/khronos/parse.js +3 -4
  106. package/dist/khronos/parse.js.map +1 -1
  107. package/dist/khronos/pipeline.d.ts +1 -1
  108. package/dist/khronos/pipeline.d.ts.map +1 -1
  109. package/dist/khronos/pipeline.js.map +1 -1
  110. package/dist/khronos/plan.d.ts +1 -7
  111. package/dist/khronos/plan.d.ts.map +1 -1
  112. package/dist/khronos/plan.js +1 -1
  113. package/dist/khronos/plan.js.map +1 -1
  114. package/dist/runner.d.ts +5 -1
  115. package/dist/runner.d.ts.map +1 -1
  116. package/dist/runner.js +16 -0
  117. package/dist/runner.js.map +1 -1
  118. package/dist/staging.d.ts +5 -0
  119. package/dist/staging.d.ts.map +1 -0
  120. package/dist/staging.js +57 -0
  121. package/dist/staging.js.map +1 -0
  122. package/dist/store/compile-store.d.ts.map +1 -1
  123. package/dist/store/compile-store.js +4 -2
  124. package/dist/store/compile-store.js.map +1 -1
  125. package/dist/store/gi/callables.d.ts +7 -2
  126. package/dist/store/gi/callables.d.ts.map +1 -1
  127. package/dist/store/gi/callables.js +25 -30
  128. package/dist/store/gi/callables.js.map +1 -1
  129. package/dist/store/gi/callback.d.ts.map +1 -1
  130. package/dist/store/gi/callback.js +9 -5
  131. package/dist/store/gi/callback.js.map +1 -1
  132. package/dist/store/gi/class.d.ts.map +1 -1
  133. package/dist/store/gi/class.js +59 -38
  134. package/dist/store/gi/class.js.map +1 -1
  135. package/dist/store/gi/companion.d.ts.map +1 -1
  136. package/dist/store/gi/companion.js +6 -6
  137. package/dist/store/gi/companion.js.map +1 -1
  138. package/dist/store/gi/constant.d.ts.map +1 -1
  139. package/dist/store/gi/constant.js +10 -2
  140. package/dist/store/gi/constant.js.map +1 -1
  141. package/dist/store/gi/constructor-props.js +1 -1
  142. package/dist/store/gi/constructor-props.js.map +1 -1
  143. package/dist/store/gi/enum.d.ts.map +1 -1
  144. package/dist/store/gi/enum.js +28 -8
  145. package/dist/store/gi/enum.js.map +1 -1
  146. package/dist/store/gi/function.d.ts +1 -3
  147. package/dist/store/gi/function.d.ts.map +1 -1
  148. package/dist/store/gi/function.js +24 -18
  149. package/dist/store/gi/function.js.map +1 -1
  150. package/dist/store/gi/gtype-binding.d.ts.map +1 -1
  151. package/dist/store/gi/gtype-binding.js +4 -1
  152. package/dist/store/gi/gtype-binding.js.map +1 -1
  153. package/dist/store/gi/interface.d.ts.map +1 -1
  154. package/dist/store/gi/interface.js +32 -17
  155. package/dist/store/gi/interface.js.map +1 -1
  156. package/dist/store/gi/method.d.ts +7 -6
  157. package/dist/store/gi/method.d.ts.map +1 -1
  158. package/dist/store/gi/method.js +13 -21
  159. package/dist/store/gi/method.js.map +1 -1
  160. package/dist/store/gi/param-marshal.d.ts +3 -2
  161. package/dist/store/gi/param-marshal.d.ts.map +1 -1
  162. package/dist/store/gi/param-marshal.js +50 -5
  163. package/dist/store/gi/param-marshal.js.map +1 -1
  164. package/dist/store/gi/pipeline.d.ts.map +1 -1
  165. package/dist/store/gi/pipeline.js +21 -10
  166. package/dist/store/gi/pipeline.js.map +1 -1
  167. package/dist/store/gi/properties.d.ts +2 -1
  168. package/dist/store/gi/properties.d.ts.map +1 -1
  169. package/dist/store/gi/properties.js +6 -3
  170. package/dist/store/gi/properties.js.map +1 -1
  171. package/dist/store/gi/property-accessor.d.ts +10 -5
  172. package/dist/store/gi/property-accessor.d.ts.map +1 -1
  173. package/dist/store/gi/property-accessor.js +95 -44
  174. package/dist/store/gi/property-accessor.js.map +1 -1
  175. package/dist/store/gi/record-constructor.d.ts +8 -1
  176. package/dist/store/gi/record-constructor.d.ts.map +1 -1
  177. package/dist/store/gi/record-constructor.js +31 -10
  178. package/dist/store/gi/record-constructor.js.map +1 -1
  179. package/dist/store/gi/record-field-accessor.d.ts.map +1 -1
  180. package/dist/store/gi/record-field-accessor.js +5 -1
  181. package/dist/store/gi/record-field-accessor.js.map +1 -1
  182. package/dist/store/gi/record-layout.d.ts +6 -1
  183. package/dist/store/gi/record-layout.d.ts.map +1 -1
  184. package/dist/store/gi/record-layout.js +8 -1
  185. package/dist/store/gi/record-layout.js.map +1 -1
  186. package/dist/store/gi/record.d.ts.map +1 -1
  187. package/dist/store/gi/record.js +19 -8
  188. package/dist/store/gi/record.js.map +1 -1
  189. package/dist/store/gi/registration.js +2 -2
  190. package/dist/store/gi/registration.js.map +1 -1
  191. package/dist/store/gi/signal.d.ts +2 -1
  192. package/dist/store/gi/signal.d.ts.map +1 -1
  193. package/dist/store/gi/signal.js +30 -24
  194. package/dist/store/gi/signal.js.map +1 -1
  195. package/dist/store/gi/value-marshalable.d.ts.map +1 -1
  196. package/dist/store/gi/value-marshalable.js +2 -1
  197. package/dist/store/gi/value-marshalable.js.map +1 -1
  198. package/dist/store/gi/vtable.d.ts +4 -1
  199. package/dist/store/gi/vtable.d.ts.map +1 -1
  200. package/dist/store/gi/vtable.js +60 -17
  201. package/dist/store/gi/vtable.js.map +1 -1
  202. package/dist/store/gi-store.d.ts +1 -0
  203. package/dist/store/gi-store.d.ts.map +1 -1
  204. package/dist/store/gi-store.js +15 -20
  205. package/dist/store/gi-store.js.map +1 -1
  206. package/dist/store/jsx/generated-elements.d.ts +2 -1
  207. package/dist/store/jsx/generated-elements.d.ts.map +1 -1
  208. package/dist/store/jsx/generated-elements.js +13 -7
  209. package/dist/store/jsx/generated-elements.js.map +1 -1
  210. package/dist/store/jsx/jsx.js +3 -3
  211. package/dist/store/jsx/jsx.js.map +1 -1
  212. package/dist/store/jsx/metadata.d.ts.map +1 -1
  213. package/dist/store/jsx/metadata.js +3 -1
  214. package/dist/store/jsx/metadata.js.map +1 -1
  215. package/dist/store/jsx-store.d.ts.map +1 -1
  216. package/dist/store/jsx-store.js +3 -3
  217. package/dist/store/jsx-store.js.map +1 -1
  218. package/dist/store/resolve-store.d.ts +14 -3
  219. package/dist/store/resolve-store.d.ts.map +1 -1
  220. package/dist/store/resolve-store.js +98 -15
  221. package/dist/store/resolve-store.js.map +1 -1
  222. package/dist/store/store-fs.d.ts +9 -6
  223. package/dist/store/store-fs.d.ts.map +1 -1
  224. package/dist/store/store-fs.js +59 -25
  225. package/dist/store/store-fs.js.map +1 -1
  226. package/dist/store/store-links.d.ts +3 -0
  227. package/dist/store/store-links.d.ts.map +1 -0
  228. package/dist/store/store-links.js +39 -0
  229. package/dist/store/store-links.js.map +1 -0
  230. package/dist/writer/comparison-context.d.ts +4 -0
  231. package/dist/writer/comparison-context.d.ts.map +1 -0
  232. package/dist/writer/comparison-context.js +13 -0
  233. package/dist/writer/comparison-context.js.map +1 -0
  234. package/dist/writer/context.d.ts +3 -3
  235. package/dist/writer/context.d.ts.map +1 -1
  236. package/dist/writer/context.js +11 -6
  237. package/dist/writer/context.js.map +1 -1
  238. package/dist/writer/module.d.ts +13 -5
  239. package/dist/writer/module.d.ts.map +1 -1
  240. package/dist/writer/module.js +68 -11
  241. package/dist/writer/module.js.map +1 -1
  242. package/dist/xml.d.ts +7 -1
  243. package/dist/xml.d.ts.map +1 -1
  244. package/dist/xml.js +43 -1
  245. package/dist/xml.js.map +1 -1
  246. package/package.json +14 -3
  247. package/src/analysis/descriptor-render.ts +90 -45
  248. package/src/analysis/descriptor.ts +35 -8
  249. package/src/analysis/inheritance.ts +134 -44
  250. package/src/analysis/interface-conflicts.ts +237 -0
  251. package/src/analysis/param-capability.ts +3 -6
  252. package/src/analysis/param-structure.ts +2 -2
  253. package/src/analysis/ts-type.ts +13 -17
  254. package/src/analysis/type-key.ts +14 -0
  255. package/src/compile.ts +110 -26
  256. package/src/docs/api-reference.ts +10 -9
  257. package/src/docs/element-page.ts +5 -2
  258. package/src/docs/pipeline.ts +129 -19
  259. package/src/docs/render.ts +7 -3
  260. package/src/docs/symbol-page.ts +12 -7
  261. package/src/fingerprint.ts +86 -31
  262. package/src/gi.ts +1 -0
  263. package/src/gir/ancestry.ts +17 -1
  264. package/src/gir/annotations.ts +1 -1
  265. package/src/gir/cursor-overrides.ts +12 -0
  266. package/src/gir/emittable.ts +8 -0
  267. package/src/gir/function.ts +45 -9
  268. package/src/gir/library.ts +1 -1
  269. package/src/gir/namespace.ts +8 -2
  270. package/src/gir/parameter.ts +15 -0
  271. package/src/gir/parse.ts +5 -7
  272. package/src/guards.ts +23 -0
  273. package/src/internal.ts +2 -0
  274. package/src/json.ts +11 -0
  275. package/src/khronos/modules.ts +25 -9
  276. package/src/khronos/parse.ts +3 -4
  277. package/src/khronos/pipeline.ts +1 -1
  278. package/src/khronos/plan.ts +0 -1
  279. package/src/runner.ts +19 -1
  280. package/src/staging.ts +69 -0
  281. package/src/store/compile-store.ts +6 -4
  282. package/src/store/gi/callables.ts +41 -33
  283. package/src/store/gi/callback.ts +9 -9
  284. package/src/store/gi/class.ts +79 -48
  285. package/src/store/gi/companion.ts +7 -6
  286. package/src/store/gi/constant.ts +12 -2
  287. package/src/store/gi/constructor-props.ts +1 -1
  288. package/src/store/gi/enum.ts +35 -21
  289. package/src/store/gi/function.ts +30 -24
  290. package/src/store/gi/gtype-binding.ts +7 -2
  291. package/src/store/gi/interface.ts +37 -18
  292. package/src/store/gi/method.ts +28 -29
  293. package/src/store/gi/param-marshal.ts +77 -6
  294. package/src/store/gi/pipeline.ts +25 -15
  295. package/src/store/gi/properties.ts +8 -4
  296. package/src/store/gi/property-accessor.ts +156 -73
  297. package/src/store/gi/record-constructor.ts +50 -18
  298. package/src/store/gi/record-field-accessor.ts +8 -1
  299. package/src/store/gi/record-layout.ts +11 -1
  300. package/src/store/gi/record.ts +20 -12
  301. package/src/store/gi/registration.ts +2 -2
  302. package/src/store/gi/signal.ts +36 -38
  303. package/src/store/gi/value-marshalable.ts +3 -1
  304. package/src/store/gi/vtable.ts +97 -20
  305. package/src/store/gi-store.ts +26 -31
  306. package/src/store/jsx/generated-elements.ts +17 -8
  307. package/src/store/jsx/jsx.ts +3 -3
  308. package/src/store/jsx/metadata.ts +4 -1
  309. package/src/store/jsx-store.ts +3 -3
  310. package/src/store/resolve-store.ts +133 -18
  311. package/src/store/store-fs.ts +87 -34
  312. package/src/store/store-links.ts +49 -0
  313. package/src/writer/comparison-context.ts +18 -0
  314. package/src/writer/context.ts +12 -6
  315. package/src/writer/module.ts +101 -14
  316. package/src/xml.ts +61 -1
@@ -1,5 +1,6 @@
1
1
  import type { GirClass } from "../../gir/class.js";
2
2
  import type { ModuleContext } from "../../writer/context.js";
3
+ import type { Declaration } from "../../writer/module.js";
3
4
  import { collectInterfaceProperties } from "../../analysis/inheritance.js";
4
5
  import { renderBracedOrEmpty } from "../../writer/emit.js";
5
6
  import { parentCompanionRef } from "./companion.js";
@@ -8,7 +9,7 @@ import { propertyDoc, type ResolvedAccessor, resolveOwnerAccessor } from "./prop
8
9
  const PROPERTIES_SUFFIX = "Properties";
9
10
 
10
11
  const propertyEntry = (accessor: ResolvedAccessor): string =>
11
- `${propertyDoc(accessor.property)}${accessor.jsName}: ${accessor.tsType};`;
12
+ `${propertyDoc(accessor.property)}${accessor.jsName}: ${accessor.readType};`;
12
13
 
13
14
  const interfaceEntries = (context: ModuleContext, klass: GirClass): string[] => {
14
15
  const entries: string[] = [];
@@ -31,7 +32,7 @@ const renderPropertyDeclarations = (
31
32
  klass: GirClass,
32
33
  className: string,
33
34
  accessors: ResolvedAccessor[],
34
- ): string[] => {
35
+ ): Declaration[] => {
35
36
  const parentRef = parentCompanionRef(context, klass, PROPERTIES_SUFFIX);
36
37
  const extendsClause = parentRef === undefined ? "" : ` extends ${parentRef}`;
37
38
 
@@ -43,8 +44,11 @@ const renderPropertyDeclarations = (
43
44
  const map = `${className}${PROPERTIES_SUFFIX}`;
44
45
 
45
46
  return [
46
- renderBracedOrEmpty(`export interface ${map}${extendsClause}`, entries.join("\n")),
47
- renderBracedOrEmpty(`export interface ${className}`, `__properties__: ${map};`),
47
+ { name: map, code: renderBracedOrEmpty(`export interface ${map}${extendsClause}`, entries.join("\n")) },
48
+ {
49
+ name: className,
50
+ code: renderBracedOrEmpty(`export interface ${className}`, `__properties__: ${map};`),
51
+ },
48
52
  ];
49
53
  };
50
54
 
@@ -6,19 +6,30 @@ import { renderDescriptor } from "../../analysis/descriptor-render.js";
6
6
  import { inputParameters } from "../../analysis/param-structure.js";
7
7
  import { renderTsType } from "../../analysis/ts-type.js";
8
8
  import { type GirProperty, isConstructableProperty } from "../../gir/property.js";
9
+ import { comparisonContextFor } from "../../writer/comparison-context.js";
9
10
  import { renderBlock } from "../../writer/emit.js";
10
11
  import { isEmittableCallable } from "./callables.js";
11
12
  import { getDoc } from "./doc-spec.js";
12
13
  import { methodExportName, renderMethodReturnType } from "./method.js";
13
14
 
15
+ type AccessorTypes = {
16
+ readType: string;
17
+ writeType: string;
18
+ };
19
+
20
+ type InheritedAccessorTypes = {
21
+ readType: string | undefined;
22
+ writeType: string | undefined;
23
+ };
24
+
14
25
  type ResolvedAccessor = {
15
26
  property: GirProperty;
16
27
  jsName: string;
17
- tsType: string;
28
+ readType: string;
29
+ writeType: string;
18
30
  hasGetter: boolean;
19
31
  isWritable: boolean;
20
32
  getterMember: string | undefined;
21
- getterMethod: GirFunction | undefined;
22
33
  setterMember: string | undefined;
23
34
  };
24
35
 
@@ -27,18 +38,15 @@ type PropertyAccessorArgs = {
27
38
  property: GirProperty;
28
39
  claimedNames: Set<string>;
29
40
  methodByName: Map<string, GirFunction>;
30
- inheritedType?: string | undefined;
41
+ inheritedTypes?: InheritedAccessorTypes | undefined;
42
+ inheritedNames?: Set<string> | undefined;
31
43
  };
32
44
 
33
- type AccessorDelegate = { member: string | undefined; method: GirFunction | undefined };
45
+ type AccessorDelegate = { member: string; method: GirFunction };
46
+ type AccessorDelegates = { getter: AccessorDelegate | undefined; setter: AccessorDelegate | undefined };
47
+ type TypedDelegates = { types: AccessorTypes; delegates: AccessorDelegates };
34
48
 
35
- type GetterBodyOptions = {
36
- context: ModuleContext;
37
- property: GirProperty;
38
- getterMember: string | undefined;
39
- getterMethod: GirFunction | undefined;
40
- tsType: string;
41
- };
49
+ const NULLABLE_SUFFIX = " | null";
42
50
 
43
51
  const isNullablePropertyType = (context: ModuleContext, type: TypeId | undefined): boolean => {
44
52
  if (type === undefined) {
@@ -71,14 +79,17 @@ const resolveDelegate = (
71
79
  attribute: string | undefined,
72
80
  member: string | undefined,
73
81
  isDelegatable: (method: GirFunction) => boolean,
74
- ): AccessorDelegate => {
82
+ ): AccessorDelegate | undefined => {
75
83
  const method = member !== undefined && attribute !== undefined ? args.methodByName.get(attribute) : undefined;
76
- const canDelegate = method === undefined || isDelegatable(method);
77
84
 
78
- return canDelegate ? { member, method } : { member: undefined, method: undefined };
85
+ if (member === undefined || method === undefined || !isDelegatable(method)) {
86
+ return undefined;
87
+ }
88
+
89
+ return { member, method };
79
90
  };
80
91
 
81
- const resolveGetterDelegate = (args: PropertyAccessorArgs, jsName: string): AccessorDelegate => {
92
+ const resolveGetterDelegate = (args: PropertyAccessorArgs, jsName: string): AccessorDelegate | undefined => {
82
93
  const { context, property, claimedNames } = args;
83
94
  const member = delegateMember(property.getter, jsName, claimedNames);
84
95
 
@@ -92,7 +103,11 @@ const resolveGetterDelegate = (args: PropertyAccessorArgs, jsName: string): Acce
92
103
  );
93
104
  };
94
105
 
95
- const resolveSetterDelegate = (args: PropertyAccessorArgs, jsName: string, isWritable: boolean): AccessorDelegate => {
106
+ const resolveSetterDelegate = (
107
+ args: PropertyAccessorArgs,
108
+ jsName: string,
109
+ isWritable: boolean,
110
+ ): AccessorDelegate | undefined => {
96
111
  const { context, property, claimedNames } = args;
97
112
  const member = isWritable ? delegateMember(property.setter, jsName, claimedNames) : undefined;
98
113
 
@@ -104,52 +119,114 @@ const resolveSetterDelegate = (args: PropertyAccessorArgs, jsName: string, isWri
104
119
  );
105
120
  };
106
121
 
107
- const resolveOwnType = (
122
+ const baseTypeName = (type: string): string =>
123
+ type.endsWith(NULLABLE_SUFFIX) ? type.slice(0, -NULLABLE_SUFFIX.length) : type;
124
+
125
+ const areDelegateBaseTypesAgreeing = (
108
126
  context: ModuleContext,
109
- property: GirProperty,
110
- getterMethod: GirFunction | undefined,
111
- setterMethod: GirFunction | undefined,
112
- ): string => {
113
- const setterParam = setterMethod?.parameters[0];
127
+ getter: AccessorDelegate | undefined,
128
+ setter: AccessorDelegate | undefined,
129
+ ): boolean => {
130
+ const setterParam = setter?.method.parameters[0];
114
131
 
115
- if (setterParam !== undefined) {
116
- return renderTsType(context, setterParam.type, setterParam.nullable || setterParam.optional);
132
+ if (setterParam === undefined || getter === undefined) {
133
+ return true;
117
134
  }
118
135
 
119
- if (getterMethod !== undefined) {
120
- return renderMethodReturnType(context, getterMethod);
136
+ const scratch = comparisonContextFor(context);
137
+ const read = baseTypeName(renderMethodReturnType(scratch, getter.method));
138
+ const written = baseTypeName(renderTsType(scratch, setterParam.type, false));
139
+
140
+ return read === written;
141
+ };
142
+
143
+ const resolveDelegates = (args: PropertyAccessorArgs, jsName: string, isWritable: boolean): AccessorDelegates => {
144
+ const getter = resolveGetterDelegate(args, jsName);
145
+ const setter = resolveSetterDelegate(args, jsName, isWritable);
146
+
147
+ if (areDelegateBaseTypesAgreeing(args.context, getter, setter)) {
148
+ return { getter, setter };
121
149
  }
122
150
 
123
- return renderTsType(context, property.type, isNullablePropertyType(context, property.type));
151
+ return { getter, setter: undefined };
152
+ };
153
+
154
+ const declaredPropertyType = (context: ModuleContext, property: GirProperty): string =>
155
+ renderTsType(context, property.type, isNullablePropertyType(context, property.type));
156
+
157
+ const resolveOwnTypes = (
158
+ context: ModuleContext,
159
+ property: GirProperty,
160
+ delegates: AccessorDelegates,
161
+ ): AccessorTypes => {
162
+ const getterMethod = delegates.getter?.method;
163
+ const setterParam = delegates.setter?.method.parameters[0];
164
+
165
+ return {
166
+ readType: getterMethod === undefined
167
+ ? declaredPropertyType(context, property)
168
+ : renderMethodReturnType(context, getterMethod),
169
+ writeType: setterParam === undefined
170
+ ? declaredPropertyType(context, property)
171
+ : renderTsType(context, setterParam.type, setterParam.nullable || setterParam.optional),
172
+ };
124
173
  };
125
174
 
126
- const isSkippedAccessor = (property: GirProperty, jsName: string, claimedNames: Set<string>): boolean =>
127
- !property.introspectable || claimedNames.has(jsName) || jsName === "constructor";
175
+ const isAssignableType = (source: string, target: string): boolean =>
176
+ source === target || baseTypeName(target) === source;
128
177
 
129
- const resolveTsType = (inheritedType: string | undefined, ownType: string): string =>
130
- inheritedType !== undefined && inheritedType !== ownType ? inheritedType : ownType;
178
+ const agreeingDelegates = (
179
+ delegates: AccessorDelegates,
180
+ ownTypes: AccessorTypes,
181
+ declaredTypes: AccessorTypes,
182
+ ): AccessorDelegates => ({
183
+ getter: isAssignableType(ownTypes.readType, declaredTypes.readType) ? delegates.getter : undefined,
184
+ setter: isAssignableType(declaredTypes.writeType, ownTypes.writeType) ? delegates.setter : undefined,
185
+ });
186
+
187
+ const resolveTypedDelegates = (args: PropertyAccessorArgs, resolved: AccessorDelegates): TypedDelegates => {
188
+ const ownTypes = resolveOwnTypes(args.context, args.property, resolved);
189
+
190
+ const types = {
191
+ readType: args.inheritedTypes?.readType ?? ownTypes.readType,
192
+ writeType: args.inheritedTypes?.writeType ?? ownTypes.writeType,
193
+ };
194
+
195
+ return { types, delegates: agreeingDelegates(resolved, ownTypes, types) };
196
+ };
197
+
198
+ const isSkippedAccessor = (args: PropertyAccessorArgs, jsName: string): boolean =>
199
+ !args.property.introspectable ||
200
+ args.claimedNames.has(jsName) ||
201
+ args.inheritedNames?.has(jsName) === true ||
202
+ jsName === "constructor";
131
203
 
132
204
  const resolveAccessor = (args: PropertyAccessorArgs): ResolvedAccessor | undefined => {
133
- const { context, property, claimedNames } = args;
205
+ const { property } = args;
134
206
  const jsName = toCamelIdentifier(property.name);
135
207
 
136
- if (isSkippedAccessor(property, jsName, claimedNames)) {
208
+ if (isSkippedAccessor(args, jsName)) {
137
209
  return undefined;
138
210
  }
139
211
 
140
212
  const isWritable = isConstructableProperty(property) && !property.constructOnly;
141
- const { member: getterMember, method: getterMethod } = resolveGetterDelegate(args, jsName);
142
- const { member: setterMember, method: setterMethod } = resolveSetterDelegate(args, jsName, isWritable);
143
- const hasGetter = property.readable || getterMember !== undefined;
213
+ const { types, delegates } = resolveTypedDelegates(args, resolveDelegates(args, jsName, isWritable));
214
+ const hasGetter = property.readable || delegates.getter !== undefined;
144
215
 
145
216
  if (!hasGetter && !isWritable) {
146
217
  return undefined;
147
218
  }
148
219
 
149
- const ownType = resolveOwnType(context, property, getterMethod, setterMethod);
150
- const tsType = resolveTsType(args.inheritedType, ownType);
151
-
152
- return { property, jsName, tsType, hasGetter, isWritable, getterMember, getterMethod, setterMember };
220
+ return {
221
+ property,
222
+ jsName,
223
+ readType: types.readType,
224
+ writeType: types.writeType,
225
+ hasGetter,
226
+ isWritable,
227
+ getterMember: delegates.getter?.member,
228
+ setterMember: delegates.setter?.member,
229
+ };
153
230
  };
154
231
 
155
232
  const resolveOwnerAccessor = (
@@ -172,11 +249,22 @@ const resolveOwnerAccessor = (
172
249
  return resolveAccessor({ context, property, claimedNames, methodByName });
173
250
  };
174
251
 
175
- const resolveAccessorType = (
252
+ const resolveAccessorTypes = (
176
253
  context: ModuleContext,
177
254
  property: GirProperty,
178
255
  methods: GirFunction[],
179
- ): string | undefined => resolveOwnerAccessor(context, property, methods)?.tsType;
256
+ ): InheritedAccessorTypes | undefined => {
257
+ const accessor = resolveOwnerAccessor(context, property, methods);
258
+
259
+ if (accessor === undefined) {
260
+ return undefined;
261
+ }
262
+
263
+ return {
264
+ readType: accessor.hasGetter ? accessor.readType : undefined,
265
+ writeType: accessor.isWritable ? accessor.writeType : undefined,
266
+ };
267
+ };
180
268
 
181
269
  const withAccessor = (
182
270
  args: PropertyAccessorArgs,
@@ -196,19 +284,18 @@ const renderResolvedPropertyAccessor = (
196
284
  property: GirProperty,
197
285
  accessor: ResolvedAccessor,
198
286
  ): string => {
199
- const { jsName, tsType, hasGetter, isWritable, getterMember, getterMethod, setterMember } = accessor;
287
+ const { jsName, readType, writeType, hasGetter, isWritable, setterMember } = accessor;
200
288
  const blocks: string[] = [];
201
289
 
202
290
  if (hasGetter) {
203
- const getterBody = renderGetterBody({ context, property, getterMember, getterMethod, tsType });
204
- blocks.push(renderBlock(`get ${jsName}(): ${tsType}`, getterBody));
291
+ blocks.push(renderBlock(`get ${jsName}(): ${readType}`, renderGetterBody(context, property, accessor)));
205
292
  }
206
293
 
207
294
  if (isWritable) {
208
295
  const setterBody =
209
296
  setterMember === undefined ? renderGenericSetBody(context, property) : `this.${setterMember}(value);`;
210
297
 
211
- blocks.push(renderBlock(`set ${jsName}(value: ${tsType})`, setterBody));
298
+ blocks.push(renderBlock(`set ${jsName}(value: ${writeType})`, setterBody));
212
299
  }
213
300
 
214
301
  return `${propertyDoc(property)}${blocks.join("\n\n")}`;
@@ -220,20 +307,26 @@ const propertyDoc = (property: GirProperty): string =>
220
307
  const renderPropertyAccessor = (args: PropertyAccessorArgs): string | undefined =>
221
308
  withAccessor(args, (accessor) => renderResolvedPropertyAccessor(args.context, args.property, accessor));
222
309
 
223
- const renderPropertyAccessorSignature = (args: PropertyAccessorArgs): string | undefined =>
224
- withAccessor(args, ({ jsName, tsType, hasGetter, isWritable }) => {
225
- const doc = propertyDoc(args.property);
310
+ const renderAccessorPairSignature = (accessor: ResolvedAccessor): string => {
311
+ const { jsName, readType, writeType, hasGetter, isWritable } = accessor;
226
312
 
227
- if (hasGetter && isWritable) {
228
- return `${doc}${jsName}: ${tsType};`;
229
- }
313
+ if (!hasGetter) {
314
+ return `set ${jsName}(value: ${writeType});`;
315
+ }
230
316
 
231
- if (hasGetter) {
232
- return `${doc}get ${jsName}(): ${tsType};`;
233
- }
317
+ if (!isWritable) {
318
+ return `get ${jsName}(): ${readType};`;
319
+ }
320
+
321
+ if (readType === writeType) {
322
+ return `${jsName}: ${readType};`;
323
+ }
234
324
 
235
- return `${doc}set ${jsName}(value: ${tsType});`;
236
- });
325
+ return `get ${jsName}(): ${readType};\nset ${jsName}(value: ${writeType});`;
326
+ };
327
+
328
+ const renderPropertyAccessorSignature = (args: PropertyAccessorArgs): string | undefined =>
329
+ withAccessor(args, (accessor) => `${propertyDoc(args.property)}${renderAccessorPairSignature(accessor)}`);
237
330
 
238
331
  const renderPropertyDescriptor = (context: ModuleContext, property: GirProperty): string =>
239
332
  renderDescriptor(context, property.type, property.transferOwnership);
@@ -254,21 +347,10 @@ const renderGenericSetBody = (context: ModuleContext, property: GirProperty): st
254
347
  return `setObjectProperty(this, ${sourceStringLiteral(property.name)}, ${descriptor}, value);`;
255
348
  };
256
349
 
257
- const renderGetterBody = (options: GetterBodyOptions): string => {
258
- const { context, property, getterMember, getterMethod, tsType } = options;
259
-
260
- if (getterMember === undefined) {
261
- return renderGenericGetBody(context, property, tsType);
262
- }
263
-
264
- if (getterMethod === undefined) {
265
- return `return this.${getterMember}() as ${tsType};`;
266
- }
267
-
268
- const getterType = renderMethodReturnType(context, getterMethod);
269
-
270
- return getterType === tsType ? `return this.${getterMember}();` : `return this.${getterMember}() as ${tsType};`;
271
- };
350
+ const renderGetterBody = (context: ModuleContext, property: GirProperty, accessor: ResolvedAccessor): string =>
351
+ accessor.getterMember === undefined
352
+ ? renderGenericGetBody(context, property, accessor.readType)
353
+ : `return this.${accessor.getterMember}();`;
272
354
 
273
355
  const delegateMember = (
274
356
  attribute: string | undefined,
@@ -296,10 +378,11 @@ export {
296
378
  propertyDoc,
297
379
  resolveAccessor,
298
380
  resolveOwnerAccessor,
299
- resolveAccessorType,
381
+ resolveAccessorTypes,
300
382
  renderResolvedPropertyAccessor,
301
383
  renderPropertyAccessor,
302
384
  renderPropertyAccessorSignature,
385
+ type InheritedAccessorTypes,
303
386
  type ResolvedAccessor,
304
387
  type PropertyAccessorArgs,
305
388
  };
@@ -1,11 +1,14 @@
1
1
  import { sourceStringLiteral, toCamelIdentifier } from "@gtkx/utils";
2
2
  import type { GirField } from "../../gir/field.js";
3
+ import type { GirFunction } from "../../gir/function.js";
3
4
  import type { GirRecord } from "../../gir/record.js";
4
5
  import type { TypeId } from "../../gir/type-id.js";
5
6
  import type { ModuleContext } from "../../writer/context.js";
6
7
  import { renderDescriptor } from "../../analysis/descriptor-render.js";
8
+ import { inputParameters, parameterIdentifier } from "../../analysis/param-structure.js";
7
9
  import { renderTsType } from "../../analysis/ts-type.js";
8
10
  import { renderBlock, renderBracedOrEmpty } from "../../writer/emit.js";
11
+ import { type Callables, staticMembers } from "./callables.js";
9
12
  import { getDoc } from "./doc-spec.js";
10
13
  import { renderSourceGtype } from "./gtype-binding.js";
11
14
  import { emitFieldWrite, isEmittableField, isInlineField } from "./record-field-accessor.js";
@@ -14,22 +17,22 @@ import { isConstructibleRecord } from "./value-marshalable.js";
14
17
 
15
18
  type WritableFieldSlot = RecordFieldSlot & { field: GirField & { type: TypeId } };
16
19
 
20
+ type RecordConstructorSpec = {
21
+ record: GirRecord;
22
+ className: string;
23
+ callables: Callables;
24
+ isErrorSubclass: boolean;
25
+ };
26
+
17
27
  const isWritableFieldSlot = (context: ModuleContext, entry: RecordFieldSlot): entry is WritableFieldSlot =>
18
28
  entry.field.writable && isEmittableField(context, entry.field);
19
29
 
20
- const isOpaque = (record: GirRecord): boolean => record.opaque || record.disguised;
21
-
22
30
  const renderRecordConstructorPropsInterface = (
23
31
  context: ModuleContext,
24
32
  record: GirRecord,
25
33
  className: string,
26
34
  ): string => {
27
35
  const head = `export interface ${className}ConstructorProps`;
28
-
29
- if (isOpaque(record) || !isConstructibleRecord(context, context.namespace.name, record)) {
30
- return renderBracedOrEmpty(head, "");
31
- }
32
-
33
36
  const { slots } = computeRecordFieldSlots(context, record.fields, record.isUnion);
34
37
 
35
38
  const lines = slots
@@ -43,8 +46,41 @@ const renderRecordConstructorPropsInterface = (
43
46
  return renderBracedOrEmpty(head, lines.join("\n"));
44
47
  };
45
48
 
46
- const renderOpaqueConstructor = (className: string, superCall: string[]): string => {
47
- const message = sourceStringLiteral(`Cannot construct ${className}: opaque boxed type with no known layout`);
49
+ const isSelfReturning = (context: ModuleContext, record: GirRecord, callable: GirFunction): boolean => {
50
+ const ref = callable.returnValue.type;
51
+ const name = ref === undefined ? undefined : context.library.nameFor(ref);
52
+
53
+ return name?.namespaceName === context.namespace.name && name.typeName === record.name;
54
+ };
55
+
56
+ const renderStaticCall = (context: ModuleContext, callable: GirFunction, name: string): string => {
57
+ const args = inputParameters(context.library, callable).map(({ parameter, index }) =>
58
+ parameterIdentifier(parameter, index));
59
+
60
+ return `${name}(${args.join(", ")})`;
61
+ };
62
+
63
+ const constructionHint = (context: ModuleContext, spec: RecordConstructorSpec): string | undefined => {
64
+ const candidates = staticMembers(context, spec.callables).filter(({ callable }) =>
65
+ isSelfReturning(context, spec.record, callable));
66
+
67
+ const candidate = candidates.find(({ name }) => name === "new") ?? candidates[0];
68
+
69
+ return candidate === undefined ? undefined : renderStaticCall(context, candidate.callable, candidate.name);
70
+ };
71
+
72
+ const unconstructibleMessage = (context: ModuleContext, spec: RecordConstructorSpec): string => {
73
+ const qualified = `${context.namespace.name}.${spec.className}`;
74
+ const hint = constructionHint(context, spec);
75
+
76
+ return hint === undefined
77
+ ? `Cannot construct ${qualified} with new: its instances come from the functions that return them.`
78
+ : `Cannot construct ${qualified} with new: use ${qualified}.${hint} instead.`;
79
+ };
80
+
81
+ const renderUnconstructibleGuard = (context: ModuleContext, spec: RecordConstructorSpec): string => {
82
+ const superCall = spec.isErrorSubclass ? ["super();"] : [];
83
+ const message = sourceStringLiteral(unconstructibleMessage(context, spec));
48
84
 
49
85
  return renderBlock("constructor()", [...superCall, `throw new globalThis.Error(${message});`].join("\n"));
50
86
  };
@@ -66,18 +102,14 @@ const renderFieldWrites = (context: ModuleContext, slots: RecordFieldSlot[]): st
66
102
  return statements;
67
103
  };
68
104
 
69
- const renderRecordConstructor = (
70
- context: ModuleContext,
71
- record: GirRecord,
72
- className: string,
73
- isErrorSubclass = false,
74
- ): string => {
75
- const superCall = isErrorSubclass ? ["super();"] : [];
105
+ const renderRecordConstructor = (context: ModuleContext, spec: RecordConstructorSpec): string => {
106
+ const { record, className, isErrorSubclass } = spec;
76
107
 
77
- if (isOpaque(record) || !isConstructibleRecord(context, context.namespace.name, record)) {
78
- return renderOpaqueConstructor(className, superCall);
108
+ if (!isConstructibleRecord(context, context.namespace.name, record)) {
109
+ return renderUnconstructibleGuard(context, spec);
79
110
  }
80
111
 
112
+ const superCall = isErrorSubclass ? ["super();"] : [];
81
113
  const { slots, size } = computeRecordFieldSlots(context, record.fields, record.isUnion);
82
114
 
83
115
  if (size === 0) {
@@ -1,6 +1,7 @@
1
1
  import { toCamelIdentifier } from "@gtkx/utils";
2
2
  import type { GirAnnotations } from "../../gir/annotations.js";
3
3
  import type { GirField } from "../../gir/field.js";
4
+ import type { GirRecord } from "../../gir/record.js";
4
5
  import type { FieldSlot } from "../../gir/size.js";
5
6
  import type { TypeId } from "../../gir/type-id.js";
6
7
  import type { GirType } from "../../gir/type.js";
@@ -479,6 +480,12 @@ const structArraySetterBlock = (options: StructArrayAccessorOptions): string =>
479
480
  structArraySetterStatements(options.context, options),
480
481
  );
481
482
 
483
+ const isPlainDataRecord = (record: GirRecord): boolean =>
484
+ record.glibGetType === undefined &&
485
+ record.constructors.length === 0 &&
486
+ record.functions.length === 0 &&
487
+ record.methods.length === 0;
488
+
482
489
  const resolveStructArrayElements = (context: ModuleContext, fieldType: TypeId): StructArrayElements | undefined => {
483
490
  const arrayType = context.library.typeFor(fieldType);
484
491
 
@@ -488,7 +495,7 @@ const resolveStructArrayElements = (context: ModuleContext, fieldType: TypeId):
488
495
 
489
496
  const elementType = context.library.typeFor(arrayType.element);
490
497
 
491
- if (elementType?.kind === "record" && elementType.value.glibGetType !== undefined) {
498
+ if (elementType?.kind === "record" && !isPlainDataRecord(elementType.value)) {
492
499
  return undefined;
493
500
  }
494
501
 
@@ -46,6 +46,16 @@ const computeRecordFieldSlots = (
46
46
  return { slots, size: result.size };
47
47
  };
48
48
 
49
+ const recordInlineSize = (context: ModuleContext, record: ResolvedRecordValue): number | undefined => {
50
+ if (record.opaque || record.disguised || record.fields.length === 0) {
51
+ return undefined;
52
+ }
53
+
54
+ const { size } = computeRecordFieldSlots(context, record.fields, record.isUnion);
55
+
56
+ return size > 0 ? size : undefined;
57
+ };
58
+
49
59
  const bitMask = (width: number): number => {
50
60
  if (width >= 32) {
51
61
  return 0xFF_FF_FF_FF;
@@ -214,4 +224,4 @@ const resolveAliasLayout = (
214
224
  return layoutOfType(context, ref, resolved.value.targetCType, visited);
215
225
  };
216
226
 
217
- export { computeRecordFieldSlots, bitMask, mergeBitfield, type RecordFieldSlot };
227
+ export { computeRecordFieldSlots, recordInlineSize, bitMask, mergeBitfield, type RecordFieldSlot };
@@ -1,5 +1,7 @@
1
+ import { sanitizeTypeIdentifier } from "@gtkx/utils";
1
2
  import type { GirRecord } from "../../gir/record.js";
2
3
  import type { ModuleContext } from "../../writer/context.js";
4
+ import { isEmittableEntity } from "../../gir/emittable.js";
3
5
  import { indentMembers } from "../../writer/emit.js";
4
6
  import { type Callables, dedupeCallables, generateBindings, renderPlainTypeMembers } from "./callables.js";
5
7
  import { getDoc } from "./doc-spec.js";
@@ -8,20 +10,17 @@ import { renderRecordConstructor, renderRecordConstructorPropsInterface } from "
8
10
  import { renderRecordFieldAccessor } from "./record-field-accessor.js";
9
11
  import { computeRecordFieldSlots } from "./record-layout.js";
10
12
  import { appendWrapperClassRegistration } from "./registration.js";
13
+ import { isConstructibleRecord } from "./value-marshalable.js";
11
14
 
12
15
  const isGErrorRecord = (context: ModuleContext, record: GirRecord): boolean =>
13
16
  context.namespace.name === "GLib" && record.glibGetType === "g_error_get_type";
14
17
 
15
18
  const generateRecord = (context: ModuleContext, record: GirRecord): void => {
16
- if (!record.introspectable) {
19
+ if (!isEmittableEntity(record)) {
17
20
  return;
18
21
  }
19
22
 
20
- if (record.name.length === 0) {
21
- return;
22
- }
23
-
24
- const className = record.name;
23
+ const className = sanitizeTypeIdentifier(record.name);
25
24
  const isErrorSubclass = isGErrorRecord(context, record);
26
25
 
27
26
  const callables: Callables = {
@@ -35,13 +34,22 @@ const generateRecord = (context: ModuleContext, record: GirRecord): void => {
35
34
  const body = indentMembers(members);
36
35
  const heritage = isErrorSubclass ? " extends globalThis.Error" : "";
37
36
  const doc = getDoc(record);
37
+ const isConstructible = isConstructibleRecord(context, context.namespace.name, record);
38
+ const modifier = isConstructible ? "" : "abstract ";
38
39
 
39
- context.module.appendDeclaration(
40
- `${doc}export class ${className}${heritage} {\n${body}\n}`,
41
- context.declaredType(className),
42
- );
40
+ context.declare({
41
+ name: className,
42
+ code: `${doc}export ${modifier}class ${className}${heritage} {\n${body}\n}`,
43
+ owner: record.name,
44
+ });
45
+
46
+ if (isConstructible) {
47
+ context.declare({
48
+ name: `${className}ConstructorProps`,
49
+ code: renderRecordConstructorPropsInterface(context, record, className),
50
+ });
51
+ }
43
52
 
44
- context.module.appendDeclaration(renderRecordConstructorPropsInterface(context, record, className));
45
53
  const gtypeExpr = renderSourceGtype(context, record);
46
54
 
47
55
  appendWrapperClassRegistration(context, {
@@ -65,7 +73,7 @@ const renderRecordMembers = (
65
73
  hasGtype: record.glibGetType !== undefined,
66
74
  });
67
75
 
68
- members.unshift(renderRecordConstructor(context, record, className, isErrorSubclass));
76
+ members.unshift(renderRecordConstructor(context, { record, className, callables, isErrorSubclass }));
69
77
  const { slots } = computeRecordFieldSlots(context, record.fields, record.isUnion);
70
78
 
71
79
  for (const slot of slots) {
@@ -25,7 +25,7 @@ const appendWrapperClassRegistration = (
25
25
 
26
26
  context.addRuntimeImport("registerWrapperClass");
27
27
  const args = vfuncs === undefined ? gtypeExpr : `${gtypeExpr}, ${vfuncs}`;
28
- context.module.appendRegistration(`registerWrapperClass(${className}, ${args});`);
28
+ context.module.appendRegistration(`registerWrapperClass(${className}, ${args});`, [className]);
29
29
  };
30
30
 
31
31
  const appendInterfaceRegistration = (context: ModuleContext, registration: InterfaceRegistration): void => {
@@ -38,7 +38,7 @@ const appendInterfaceRegistration = (context: ModuleContext, registration: Inter
38
38
  context.addRuntimeImport("registerInterface");
39
39
  const base = `${className}, ${gtypeExpr}, ${makerName}`;
40
40
  const args = layout === undefined ? base : `${base}, ${layout}`;
41
- context.module.appendRegistration(`registerInterface(${args});`);
41
+ context.module.appendRegistration(`registerInterface(${args});`, [className, makerName]);
42
42
  };
43
43
 
44
44
  export { appendWrapperClassRegistration, appendInterfaceRegistration };