@gtkx/codegen 1.0.0-rc.2 → 1.0.0-rc.4

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 (254) hide show
  1. package/README.md +4 -5
  2. package/dist/analysis/descriptor-render.d.ts +2 -2
  3. package/dist/analysis/descriptor-render.d.ts.map +1 -1
  4. package/dist/analysis/descriptor-render.js +30 -32
  5. package/dist/analysis/descriptor-render.js.map +1 -1
  6. package/dist/analysis/descriptor.d.ts +6 -6
  7. package/dist/analysis/descriptor.d.ts.map +1 -1
  8. package/dist/analysis/descriptor.js +7 -7
  9. package/dist/analysis/descriptor.js.map +1 -1
  10. package/dist/analysis/param-structure.d.ts +2 -2
  11. package/dist/analysis/param-structure.d.ts.map +1 -1
  12. package/dist/analysis/param-structure.js +5 -7
  13. package/dist/analysis/param-structure.js.map +1 -1
  14. package/dist/analysis/ts-type.d.ts +1 -1
  15. package/dist/analysis/ts-type.d.ts.map +1 -1
  16. package/dist/analysis/ts-type.js +7 -13
  17. package/dist/analysis/ts-type.js.map +1 -1
  18. package/dist/compile.d.ts.map +1 -1
  19. package/dist/compile.js +2 -1
  20. package/dist/compile.js.map +1 -1
  21. package/dist/docs/api-reference.d.ts +77 -1
  22. package/dist/docs/api-reference.d.ts.map +1 -1
  23. package/dist/docs/api-reference.js +66 -8
  24. package/dist/docs/api-reference.js.map +1 -1
  25. package/dist/docs/element-page.d.ts.map +1 -1
  26. package/dist/docs/element-page.js +5 -4
  27. package/dist/docs/element-page.js.map +1 -1
  28. package/dist/docs/pipeline.d.ts +5 -3
  29. package/dist/docs/pipeline.d.ts.map +1 -1
  30. package/dist/docs/pipeline.js +5 -3
  31. package/dist/docs/pipeline.js.map +1 -1
  32. package/dist/docs/render.js +6 -6
  33. package/dist/docs/render.js.map +1 -1
  34. package/dist/docs/symbol-page.d.ts +5 -0
  35. package/dist/docs/symbol-page.d.ts.map +1 -1
  36. package/dist/docs/symbol-page.js +2 -2
  37. package/dist/docs/symbol-page.js.map +1 -1
  38. package/dist/fingerprint.d.ts +2 -4
  39. package/dist/fingerprint.d.ts.map +1 -1
  40. package/dist/fingerprint.js +7 -6
  41. package/dist/fingerprint.js.map +1 -1
  42. package/dist/gi.d.ts +7 -10
  43. package/dist/gi.d.ts.map +1 -1
  44. package/dist/gi.js +4 -9
  45. package/dist/gi.js.map +1 -1
  46. package/dist/gir/field.d.ts +0 -1
  47. package/dist/gir/field.d.ts.map +1 -1
  48. package/dist/gir/field.js +0 -3
  49. package/dist/gir/field.js.map +1 -1
  50. package/dist/gir/gir-path.d.ts +7 -0
  51. package/dist/gir/gir-path.d.ts.map +1 -1
  52. package/dist/gir/gir-path.js +7 -0
  53. package/dist/gir/gir-path.js.map +1 -1
  54. package/dist/gir/libraries.d.ts +17 -3
  55. package/dist/gir/libraries.d.ts.map +1 -1
  56. package/dist/gir/libraries.js +14 -1
  57. package/dist/gir/libraries.js.map +1 -1
  58. package/dist/gir/parameter.d.ts.map +1 -1
  59. package/dist/gir/parameter.js +0 -4
  60. package/dist/gir/parameter.js.map +1 -1
  61. package/dist/gir/size.d.ts.map +1 -1
  62. package/dist/gir/size.js +0 -3
  63. package/dist/gir/size.js.map +1 -1
  64. package/dist/gir/type-id.d.ts +1 -1
  65. package/dist/gir/type-id.d.ts.map +1 -1
  66. package/dist/gir/type-id.js +1 -3
  67. package/dist/gir/type-id.js.map +1 -1
  68. package/dist/gir/type-ref.js +1 -1
  69. package/dist/gir/type-ref.js.map +1 -1
  70. package/dist/index.d.ts +18 -5
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +12 -2
  73. package/dist/index.js.map +1 -1
  74. package/dist/internal.d.ts +3 -0
  75. package/dist/internal.d.ts.map +1 -0
  76. package/dist/internal.js +3 -0
  77. package/dist/internal.js.map +1 -0
  78. package/dist/jsx.d.ts +8 -11
  79. package/dist/jsx.d.ts.map +1 -1
  80. package/dist/jsx.js +18 -15
  81. package/dist/jsx.js.map +1 -1
  82. package/dist/khronos/args.d.ts.map +1 -1
  83. package/dist/khronos/args.js +1 -1
  84. package/dist/khronos/args.js.map +1 -1
  85. package/dist/khronos/pipeline.js +1 -1
  86. package/dist/khronos/pipeline.js.map +1 -1
  87. package/dist/khronos/plan.d.ts +2 -2
  88. package/dist/khronos/plan.d.ts.map +1 -1
  89. package/dist/khronos/plan.js +6 -6
  90. package/dist/khronos/plan.js.map +1 -1
  91. package/dist/react/element-config.d.ts +18 -9
  92. package/dist/react/element-config.d.ts.map +1 -1
  93. package/dist/react/element-config.js +23 -13
  94. package/dist/react/element-config.js.map +1 -1
  95. package/dist/runner.d.ts +36 -16
  96. package/dist/runner.d.ts.map +1 -1
  97. package/dist/runner.js +22 -20
  98. package/dist/runner.js.map +1 -1
  99. package/dist/store/compile-store.d.ts +1 -2
  100. package/dist/store/compile-store.d.ts.map +1 -1
  101. package/dist/store/compile-store.js +2 -2
  102. package/dist/store/compile-store.js.map +1 -1
  103. package/dist/store/gi/callables.d.ts.map +1 -1
  104. package/dist/store/gi/callables.js +4 -9
  105. package/dist/store/gi/callables.js.map +1 -1
  106. package/dist/store/gi/constant.d.ts.map +1 -1
  107. package/dist/store/gi/constant.js +0 -2
  108. package/dist/store/gi/constant.js.map +1 -1
  109. package/dist/store/gi/function.d.ts.map +1 -1
  110. package/dist/store/gi/function.js +1 -7
  111. package/dist/store/gi/function.js.map +1 -1
  112. package/dist/store/gi/method.d.ts.map +1 -1
  113. package/dist/store/gi/method.js +26 -23
  114. package/dist/store/gi/method.js.map +1 -1
  115. package/dist/store/gi/property-accessor.d.ts +1 -1
  116. package/dist/store/gi/property-accessor.d.ts.map +1 -1
  117. package/dist/store/gi/property-accessor.js +5 -7
  118. package/dist/store/gi/property-accessor.js.map +1 -1
  119. package/dist/store/gi/record-constructor.d.ts.map +1 -1
  120. package/dist/store/gi/record-constructor.js +5 -4
  121. package/dist/store/gi/record-constructor.js.map +1 -1
  122. package/dist/store/gi/record-field-accessor.d.ts +3 -2
  123. package/dist/store/gi/record-field-accessor.d.ts.map +1 -1
  124. package/dist/store/gi/record-field-accessor.js +21 -11
  125. package/dist/store/gi/record-field-accessor.js.map +1 -1
  126. package/dist/store/gi/record-layout.d.ts.map +1 -1
  127. package/dist/store/gi/record-layout.js +0 -4
  128. package/dist/store/gi/record-layout.js.map +1 -1
  129. package/dist/store/gi/record.d.ts.map +1 -1
  130. package/dist/store/gi/record.js +0 -7
  131. package/dist/store/gi/record.js.map +1 -1
  132. package/dist/store/gi/return-wrap.d.ts +1 -1
  133. package/dist/store/gi/return-wrap.d.ts.map +1 -1
  134. package/dist/store/gi/return-wrap.js +4 -4
  135. package/dist/store/gi/return-wrap.js.map +1 -1
  136. package/dist/store/gi/signal.d.ts.map +1 -1
  137. package/dist/store/gi/signal.js +13 -16
  138. package/dist/store/gi/signal.js.map +1 -1
  139. package/dist/store/gi/value-marshalable.d.ts +7 -0
  140. package/dist/store/gi/value-marshalable.d.ts.map +1 -0
  141. package/dist/store/gi/value-marshalable.js +57 -0
  142. package/dist/store/gi/value-marshalable.js.map +1 -0
  143. package/dist/store/gi-store.d.ts +2 -3
  144. package/dist/store/gi-store.d.ts.map +1 -1
  145. package/dist/store/gi-store.js.map +1 -1
  146. package/dist/store/jsx/element-components.d.ts +0 -2
  147. package/dist/store/jsx/element-components.d.ts.map +1 -1
  148. package/dist/store/jsx/element-components.js +0 -4
  149. package/dist/store/jsx/element-components.js.map +1 -1
  150. package/dist/store/jsx/element-prop-imports.d.ts +2 -3
  151. package/dist/store/jsx/element-prop-imports.d.ts.map +1 -1
  152. package/dist/store/jsx/element-prop-imports.js +0 -2
  153. package/dist/store/jsx/element-prop-imports.js.map +1 -1
  154. package/dist/store/jsx/element-prop-types.d.ts +0 -1
  155. package/dist/store/jsx/element-prop-types.d.ts.map +1 -1
  156. package/dist/store/jsx/element-prop-types.js +0 -1
  157. package/dist/store/jsx/element-prop-types.js.map +1 -1
  158. package/dist/store/jsx/generated-elements.d.ts +29 -0
  159. package/dist/store/jsx/generated-elements.d.ts.map +1 -0
  160. package/dist/store/jsx/generated-elements.js +30 -0
  161. package/dist/store/jsx/generated-elements.js.map +1 -0
  162. package/dist/store/jsx/intrinsic-elements.d.ts +1 -2
  163. package/dist/store/jsx/intrinsic-elements.d.ts.map +1 -1
  164. package/dist/store/jsx/intrinsic-elements.js +1 -2
  165. package/dist/store/jsx/intrinsic-elements.js.map +1 -1
  166. package/dist/store/jsx/jsx.js +6 -6
  167. package/dist/store/jsx/jsx.js.map +1 -1
  168. package/dist/store/jsx/metadata.js +7 -7
  169. package/dist/store/jsx/metadata.js.map +1 -1
  170. package/dist/store/jsx/omitted-props.d.ts +8 -0
  171. package/dist/store/jsx/omitted-props.d.ts.map +1 -0
  172. package/dist/store/jsx/omitted-props.js +20 -0
  173. package/dist/store/jsx/omitted-props.js.map +1 -0
  174. package/dist/store/jsx/pipeline.d.ts +4 -0
  175. package/dist/store/jsx/pipeline.d.ts.map +1 -1
  176. package/dist/store/jsx/pipeline.js +4 -1
  177. package/dist/store/jsx/pipeline.js.map +1 -1
  178. package/dist/store/jsx/props.d.ts +1 -1
  179. package/dist/store/jsx/props.d.ts.map +1 -1
  180. package/dist/store/jsx/props.js +8 -13
  181. package/dist/store/jsx/props.js.map +1 -1
  182. package/dist/store/jsx-store.d.ts +2 -3
  183. package/dist/store/jsx-store.d.ts.map +1 -1
  184. package/dist/store/jsx-store.js +3 -3
  185. package/dist/store/jsx-store.js.map +1 -1
  186. package/dist/store/resolve-store.d.ts +28 -0
  187. package/dist/store/resolve-store.d.ts.map +1 -0
  188. package/dist/store/resolve-store.js +65 -0
  189. package/dist/store/resolve-store.js.map +1 -0
  190. package/dist/store/store-fs.d.ts +5 -1
  191. package/dist/store/store-fs.d.ts.map +1 -1
  192. package/dist/store/store-fs.js +6 -4
  193. package/dist/store/store-fs.js.map +1 -1
  194. package/overrides/gobject/object.ts.ejs +8 -8
  195. package/package.json +6 -11
  196. package/src/analysis/descriptor-render.ts +45 -38
  197. package/src/analysis/descriptor.ts +13 -13
  198. package/src/analysis/param-structure.ts +8 -10
  199. package/src/analysis/ts-type.ts +8 -17
  200. package/src/compile.ts +2 -1
  201. package/src/docs/api-reference.ts +131 -13
  202. package/src/docs/element-page.ts +5 -9
  203. package/src/docs/pipeline.ts +9 -6
  204. package/src/docs/render.ts +7 -7
  205. package/src/docs/symbol-page.ts +7 -2
  206. package/src/fingerprint.ts +21 -12
  207. package/src/gi.ts +13 -11
  208. package/src/gir/field.ts +0 -4
  209. package/src/gir/gir-path.ts +7 -0
  210. package/src/gir/libraries.ts +18 -4
  211. package/src/gir/parameter.ts +0 -4
  212. package/src/gir/size.ts +0 -3
  213. package/src/gir/type-id.ts +2 -4
  214. package/src/gir/type-ref.ts +1 -1
  215. package/src/index.ts +18 -15
  216. package/src/internal.ts +2 -0
  217. package/src/jsx.ts +26 -21
  218. package/src/khronos/args.ts +1 -1
  219. package/src/khronos/pipeline.ts +1 -1
  220. package/src/khronos/plan.ts +8 -8
  221. package/src/react/element-config.ts +25 -16
  222. package/src/runner.ts +62 -37
  223. package/src/store/compile-store.ts +3 -4
  224. package/src/store/gi/callables.ts +5 -11
  225. package/src/store/gi/constant.ts +0 -2
  226. package/src/store/gi/function.ts +1 -7
  227. package/src/store/gi/method.ts +31 -28
  228. package/src/store/gi/property-accessor.ts +6 -8
  229. package/src/store/gi/record-constructor.ts +9 -4
  230. package/src/store/gi/record-field-accessor.ts +41 -12
  231. package/src/store/gi/record-layout.ts +0 -4
  232. package/src/store/gi/record.ts +0 -9
  233. package/src/store/gi/return-wrap.ts +5 -5
  234. package/src/store/gi/signal.ts +17 -17
  235. package/src/store/gi/value-marshalable.ts +87 -0
  236. package/src/store/gi-store.ts +2 -4
  237. package/src/store/jsx/element-components.ts +0 -6
  238. package/src/store/jsx/element-prop-imports.ts +7 -4
  239. package/src/store/jsx/element-prop-types.ts +0 -1
  240. package/src/store/jsx/generated-elements.ts +60 -0
  241. package/src/store/jsx/intrinsic-elements.ts +0 -9
  242. package/src/store/jsx/jsx.ts +7 -7
  243. package/src/store/jsx/metadata.ts +8 -8
  244. package/src/store/jsx/omitted-props.ts +30 -0
  245. package/src/store/jsx/pipeline.ts +6 -1
  246. package/src/store/jsx/props.ts +8 -20
  247. package/src/store/jsx-store.ts +5 -7
  248. package/src/store/resolve-store.ts +100 -0
  249. package/src/store/store-fs.ts +12 -5
  250. package/dist/store/gi/class-struct-record.d.ts +0 -10
  251. package/dist/store/gi/class-struct-record.d.ts.map +0 -1
  252. package/dist/store/gi/class-struct-record.js +0 -52
  253. package/dist/store/gi/class-struct-record.js.map +0 -1
  254. package/src/store/gi/class-struct-record.ts +0 -72
@@ -5,7 +5,6 @@ import { hasCallerAllocatedArrayLength } from "../../analysis/param-structure.js
5
5
  import { renderJsDoc } from "../../writer/doc.js";
6
6
  import { renderBlock } from "../../writer/emit.js";
7
7
  import { matchAsyncFinish } from "./async.js";
8
- import { hasClassStructReference } from "./class-struct-record.js";
9
8
  import { renderFnExpression } from "./function.js";
10
9
  import { gtypeMemberDeclaration } from "./gtype-binding.js";
11
10
  import {
@@ -35,7 +34,7 @@ type CallableMemberOptions = {
35
34
  resolveName: (callable: GirFunction) => string | undefined;
36
35
  isStatic: boolean;
37
36
  returnTypeOverride?: string | undefined;
38
- allowRuntimeOverride?: boolean;
37
+ canUseRuntimeOverride?: boolean;
39
38
  };
40
39
 
41
40
  type StaticEntryOptions = {
@@ -111,10 +110,6 @@ const renderBinding = (
111
110
  return undefined;
112
111
  }
113
112
 
114
- if (hasClassStructReference(context, callable)) {
115
- return undefined;
116
- }
117
-
118
113
  const expression = renderFnExpression(context, callable);
119
114
 
120
115
  if (expression === undefined) {
@@ -164,9 +159,9 @@ const runtimeOverrideMember = (
164
159
  callable: GirFunction,
165
160
  name: string,
166
161
  doc: string,
167
- allow: boolean | undefined,
162
+ canUseRuntimeOverride: boolean | undefined,
168
163
  ): string | undefined => {
169
- if (allow !== true) {
164
+ if (canUseRuntimeOverride !== true) {
170
165
  return undefined;
171
166
  }
172
167
 
@@ -188,7 +183,7 @@ const renderCallableMember = (
188
183
 
189
184
  const { cIdentifier, name } = resolved;
190
185
  const doc = renderJsDoc(callable.doc);
191
- const override = runtimeOverrideMember(callable, name, doc, options.allowRuntimeOverride);
186
+ const override = runtimeOverrideMember(callable, name, doc, options.canUseRuntimeOverride);
192
187
 
193
188
  if (override !== undefined) {
194
189
  return override;
@@ -245,7 +240,7 @@ const renderInstanceMethod = (
245
240
  renderCallableMember(context, callable, {
246
241
  resolveName: (member) => nameOverride ?? methodExportName(member),
247
242
  isStatic: false,
248
- allowRuntimeOverride: true,
243
+ canUseRuntimeOverride: true,
249
244
  });
250
245
 
251
246
  const resolveInstanceMember = (
@@ -371,7 +366,6 @@ const isEmittableCallable = (context: ModuleContext, callable: GirFunction): boo
371
366
  callable.introspectable &&
372
367
  callable.shadowedBy === undefined &&
373
368
  callable.cIdentifier !== undefined &&
374
- !hasClassStructReference(context, callable) &&
375
369
  !hasCallerAllocatedArrayLength(context.library, callable);
376
370
 
377
371
  const constructorMemberName = (girName: string): string | undefined => {
@@ -6,8 +6,6 @@ import type { ModuleContext } from "../../writer/context.js";
6
6
  import { renderJsDoc } from "../../writer/doc.js";
7
7
 
8
8
  const TRUE_VALUES: Set<string> = new Set(["true", "1"]);
9
- // A `gint64`/`guint64` constant is typed `bigint`, and its decimal text does not survive a double:
10
- // G_MAXINT64 rounds to 2^63. The literal has to carry the BigInt suffix the type promises.
11
9
  const BIGINT_CATEGORIES: Set<PrimitiveCategory> = new Set(["bigint64", "biguint64", "gtype"]);
12
10
 
13
11
  const generateConstant = (context: ModuleContext, constant: GirConstant): void => {
@@ -7,7 +7,6 @@ import { hasCallerAllocatedArrayLength } from "../../analysis/param-structure.js
7
7
  import { renderJsDoc } from "../../writer/doc.js";
8
8
  import { arrayLiteral, renderBlock } from "../../writer/emit.js";
9
9
  import { matchAsyncFinish } from "./async.js";
10
- import { hasClassStructReference } from "./class-struct-record.js";
11
10
  import {
12
11
  planCallArgs,
13
12
  renderMethodBody,
@@ -33,13 +32,9 @@ const renderFnExpression = (context: ModuleContext, fn: GirFunction): string | u
33
32
  const params = planCallArgs(context, fn).map((arg) => arg.paramLiteral);
34
33
  const ret = renderReturnDescriptor(context, fn);
35
34
 
36
- return tFn(library, fn.cIdentifier, { args: arrayLiteral(params), returns: ret, throws: fn.throws });
35
+ return tFn(library, fn.cIdentifier, { args: arrayLiteral(params), returns: ret, canThrow: fn.throws });
37
36
  };
38
37
 
39
- // `moved-to` names the type member this function is also reachable as, so the namespace-level copy
40
- // is a second export of one binding. Suppressing it is only right when that member is really
41
- // emitted: 15 of Gtk-4.0's 28 `moved-to` targets are enum or error-domain members codegen emits no
42
- // static for, and dropping those would delete API with nothing to replace it.
43
38
  const isMovedOntoEmittedMember = (context: ModuleContext, fn: GirFunction): boolean => {
44
39
  const [typeName, memberName] = fn.movedTo?.split(".") ?? [];
45
40
 
@@ -63,7 +58,6 @@ const canEmitNamespaceFunction = (context: ModuleContext, fn: GirFunction): bool
63
58
  !isMovedOntoEmittedMember(context, fn) &&
64
59
  fn.shadowedBy === undefined &&
65
60
  fn.cIdentifier !== undefined &&
66
- !hasClassStructReference(context, fn) &&
67
61
  !hasCallerAllocatedArrayLength(context.library, fn);
68
62
 
69
63
  const generateNamespaceFunction = (context: ModuleContext, fn: GirFunction): void => {
@@ -23,7 +23,7 @@ import { hasUnknownArrayLength, type TypeId } from "../../gir/type-id.js";
23
23
  import { itemComparatorArgDescriptors, itemComparatorTsType } from "./item-comparators.js";
24
24
  import { isCollectibleCallerOut, isHandlePassedInPlace, isHandlePassing } from "./param-marshal.js";
25
25
 
26
- type PromisifiedStep = { sawOptional: boolean; expression: string | undefined };
26
+ type PromisifiedStep = { hasSeenOptional: boolean; expression: string | undefined };
27
27
 
28
28
  type PromisifyContext = {
29
29
  context: ModuleContext;
@@ -44,8 +44,8 @@ type CallArgPlan = {
44
44
 
45
45
  type ParamDescriptorOptions = {
46
46
  direction?: "out" | "inout";
47
- callerAllocated?: boolean;
48
- consumed?: boolean;
47
+ isCallerAllocated?: boolean;
48
+ isConsumed?: boolean;
49
49
  };
50
50
 
51
51
  type ArgIndexOptions = {
@@ -94,7 +94,7 @@ const renderInputParameters = (
94
94
  isOptionalExtra: (parameter: GirParameter) => boolean,
95
95
  ): string => {
96
96
  const parts: string[] = [];
97
- let isSawOptional = false;
97
+ let hasSeenOptional = false;
98
98
 
99
99
  for (const { parameter, index } of inputParameters(context.library, fn)) {
100
100
  if (shouldSkip(parameter)) {
@@ -104,10 +104,10 @@ const renderInputParameters = (
104
104
  const name = parameterIdentifier(parameter, index);
105
105
 
106
106
  if (isParameterOptional(parameter, isOptionalExtra)) {
107
- isSawOptional = true;
107
+ hasSeenOptional = true;
108
108
  }
109
109
 
110
- parts.push(formatParameterPart(name, parameterAnnotation(context, fn, parameter), isSawOptional));
110
+ parts.push(formatParameterPart(name, parameterAnnotation(context, fn, parameter), hasSeenOptional));
111
111
  }
112
112
 
113
113
  return parts.join(", ");
@@ -139,36 +139,36 @@ const classifyPromisifiedParameter = (
139
139
  promisify: PromisifyContext,
140
140
  parameter: GirParameter,
141
141
  index: number,
142
- state: { cancellableIndex: number; sawOptional: boolean },
142
+ state: { cancellableIndex: number; hasSeenOptional: boolean },
143
143
  ): PromisifiedStep => {
144
144
  if (parameter.isVarargs) {
145
- return { sawOptional: state.sawOptional, expression: undefined };
145
+ return { hasSeenOptional: state.hasSeenOptional, expression: undefined };
146
146
  }
147
147
 
148
148
  if (index === state.cancellableIndex) {
149
- return { sawOptional: true, expression: undefined };
149
+ return { hasSeenOptional: true, expression: undefined };
150
150
  }
151
151
 
152
152
  if (shouldSkipPromisifiedParameter(promisify, parameter, index)) {
153
- return { sawOptional: state.sawOptional, expression: undefined };
153
+ return { hasSeenOptional: state.hasSeenOptional, expression: undefined };
154
154
  }
155
155
 
156
- const isSawOptional = state.sawOptional || parameter.optional;
156
+ const hasSeenOptional = state.hasSeenOptional || parameter.optional;
157
157
 
158
- return { sawOptional: isSawOptional, expression: promisifiedArgument(promisify, parameter, index, isSawOptional) };
158
+ return { hasSeenOptional, expression: promisifiedArgument(promisify, parameter, index, hasSeenOptional) };
159
159
  };
160
160
 
161
161
  const collectPromisifiedArguments = (promisify: PromisifyContext, cancellableIndex: number): string[] => {
162
162
  const expressions: string[] = [];
163
- let isSawOptional = false;
163
+ let hasSeenOptional = false;
164
164
 
165
165
  for (const [index, parameter] of promisify.asyncFn.parameters.entries()) {
166
166
  const step = classifyPromisifiedParameter(promisify, parameter, index, {
167
167
  cancellableIndex,
168
- sawOptional: isSawOptional,
168
+ hasSeenOptional,
169
169
  });
170
170
 
171
- isSawOptional = step.sawOptional;
171
+ hasSeenOptional = step.hasSeenOptional;
172
172
 
173
173
  if (step.expression !== undefined) {
174
174
  expressions.push(step.expression);
@@ -298,12 +298,12 @@ const paramDescriptorLiteral = (descriptor: string, options: ParamDescriptorOpti
298
298
  parts.push(`direction: ${sourceStringLiteral(options.direction)}`);
299
299
  }
300
300
 
301
- if (options.callerAllocated === true) {
302
- parts.push("callerAllocated: true");
301
+ if (options.isCallerAllocated === true) {
302
+ parts.push("isCallerAllocated: true");
303
303
  }
304
304
 
305
- if (options.consumed === true) {
306
- parts.push("consumed: true");
305
+ if (options.isConsumed === true) {
306
+ parts.push("isConsumed: true");
307
307
  }
308
308
 
309
309
  return `{ ${parts.join(", ")} }`;
@@ -315,6 +315,7 @@ const renderReturnDescriptor = (context: ModuleContext, fn: GirFunction): string
315
315
  return renderDescriptor(context, fn.returnValue.type, fn.returnValue.transferOwnership, {
316
316
  argIndexOffset: instanceOffset,
317
317
  argIndexMap: emittedArgIndices(fn, instanceOffset),
318
+ isNewlyCreated: fn.instance === undefined,
318
319
  });
319
320
  };
320
321
 
@@ -406,7 +407,7 @@ const planInoutArgument = (
406
407
  return planInoutParam(context, parameter, {
407
408
  index,
408
409
  argIndex: planContext.argIndex,
409
- consumed: folded.has(index),
410
+ isConsumed: folded.has(index),
410
411
  lengthSource,
411
412
  });
412
413
  };
@@ -435,7 +436,7 @@ const planOutParam = (
435
436
  const descriptor = renderDescriptor(context, parameter.type, parameter.transferOwnership, argIndex);
436
437
 
437
438
  return {
438
- paramLiteral: paramDescriptorLiteral(descriptor, { direction: "out", consumed: isConsumed }),
439
+ paramLiteral: paramDescriptorLiteral(descriptor, { direction: "out", isConsumed }),
439
440
  inputExpr: undefined,
440
441
  };
441
442
  };
@@ -473,7 +474,7 @@ const planCallerOut = (
473
474
  const classExpression = context.qualify(name.namespaceName, name.typeName);
474
475
 
475
476
  return {
476
- paramLiteral: paramDescriptorLiteral(descriptor, { direction: "out", callerAllocated: true }),
477
+ paramLiteral: paramDescriptorLiteral(descriptor, { direction: "out", isCallerAllocated: true }),
477
478
  inputExpr: `new ${classExpression}()`,
478
479
  };
479
480
  }
@@ -487,17 +488,21 @@ const planInoutParam = (
487
488
  options: {
488
489
  index: number;
489
490
  argIndex: ArgIndexOptions;
490
- consumed: boolean;
491
+ isConsumed: boolean;
491
492
  lengthSource?: { source: GirParameter; index: number } | undefined;
492
493
  },
493
494
  ): CallArgPlan => {
494
- const { index, argIndex, consumed, lengthSource } = options;
495
+ const { index, argIndex, isConsumed, lengthSource } = options;
495
496
 
496
497
  if (isHandlePassedInPlace(context, parameter)) {
497
498
  const descriptor = renderDescriptor(context, parameter.type, "none", argIndex);
498
499
 
499
500
  return {
500
- paramLiteral: paramDescriptorLiteral(descriptor, { direction: "inout", callerAllocated: true, consumed }),
501
+ paramLiteral: paramDescriptorLiteral(descriptor, {
502
+ direction: "inout",
503
+ isCallerAllocated: true,
504
+ isConsumed,
505
+ }),
501
506
  inputExpr: parameterIdentifier(parameter, index),
502
507
  };
503
508
  }
@@ -505,7 +510,7 @@ const planInoutParam = (
505
510
  const descriptor = renderDescriptor(context, parameter.type, parameter.transferOwnership, argIndex);
506
511
 
507
512
  return {
508
- paramLiteral: paramDescriptorLiteral(descriptor, { direction: "inout", consumed }),
513
+ paramLiteral: paramDescriptorLiteral(descriptor, { direction: "inout", isConsumed }),
509
514
  inputExpr:
510
515
  lengthSource === undefined
511
516
  ? parameterCallExpression(context, parameter, index)
@@ -587,8 +592,6 @@ const collectionArgument = (
587
592
  return mapHandleExpression(name, isNullable);
588
593
  };
589
594
 
590
- // An array whose length nothing states is marshalled as the bare pointer it is, so there is nothing
591
- // to map over.
592
595
  const isMappableSequence = (context: ModuleContext, type: GirType | undefined): boolean => {
593
596
  if (type?.kind === "carray") {
594
597
  return !hasUnknownArrayLength(type) && isHandlePassing(context, type.element);
@@ -15,7 +15,7 @@ type ResolvedAccessor = {
15
15
  jsName: string;
16
16
  tsType: string;
17
17
  hasGetter: boolean;
18
- writable: boolean;
18
+ isWritable: boolean;
19
19
  getterMember: string | undefined;
20
20
  getterMethod: GirFunction | undefined;
21
21
  setterMember: string | undefined;
@@ -136,8 +136,6 @@ const resolveAccessor = (args: PropertyAccessorArgs): ResolvedAccessor | undefin
136
136
  return undefined;
137
137
  }
138
138
 
139
- // `g_object_set_property` rejects a construct-only pspec with a critical and drops the write, so
140
- // the property is settable at construction time only and must not advertise a setter.
141
139
  const isWritable = isConstructableProperty(property) && !property.constructOnly;
142
140
  const { member: getterMember, method: getterMethod } = resolveGetterDelegate(args, jsName);
143
141
  const { member: setterMember, method: setterMethod } = resolveSetterDelegate(args, jsName, isWritable);
@@ -150,7 +148,7 @@ const resolveAccessor = (args: PropertyAccessorArgs): ResolvedAccessor | undefin
150
148
  const ownType = resolveOwnType(context, property, getterMethod, setterMethod);
151
149
  const tsType = resolveTsType(args.inheritedType, ownType);
152
150
 
153
- return { jsName, tsType, hasGetter, writable: isWritable, getterMember, getterMethod, setterMember };
151
+ return { jsName, tsType, hasGetter, isWritable, getterMember, getterMethod, setterMember };
154
152
  };
155
153
 
156
154
  const resolveOwnerAccessor = (
@@ -197,7 +195,7 @@ const renderResolvedPropertyAccessor = (
197
195
  property: GirProperty,
198
196
  accessor: ResolvedAccessor,
199
197
  ): string => {
200
- const { jsName, tsType, hasGetter, writable, getterMember, getterMethod, setterMember } = accessor;
198
+ const { jsName, tsType, hasGetter, isWritable, getterMember, getterMethod, setterMember } = accessor;
201
199
  const blocks: string[] = [];
202
200
 
203
201
  if (hasGetter) {
@@ -205,7 +203,7 @@ const renderResolvedPropertyAccessor = (
205
203
  blocks.push(renderBlock(`get ${jsName}(): ${tsType}`, getterBody));
206
204
  }
207
205
 
208
- if (writable) {
206
+ if (isWritable) {
209
207
  const setterBody =
210
208
  setterMember === undefined ? renderGenericSetBody(context, property) : `this.${setterMember}(value);`;
211
209
 
@@ -219,10 +217,10 @@ const renderPropertyAccessor = (args: PropertyAccessorArgs): string | undefined
219
217
  withAccessor(args, (accessor) => renderResolvedPropertyAccessor(args.context, args.property, accessor));
220
218
 
221
219
  const renderPropertyAccessorSignature = (args: PropertyAccessorArgs): string | undefined =>
222
- withAccessor(args, ({ jsName, tsType, hasGetter, writable }) => {
220
+ withAccessor(args, ({ jsName, tsType, hasGetter, isWritable }) => {
223
221
  const doc = renderJsDoc(args.property.doc);
224
222
 
225
- if (hasGetter && writable) {
223
+ if (hasGetter && isWritable) {
226
224
  return `${doc}${jsName}: ${tsType};`;
227
225
  }
228
226
 
@@ -7,8 +7,9 @@ import { renderDescriptor } from "../../analysis/descriptor-render.js";
7
7
  import { renderTsType } from "../../analysis/ts-type.js";
8
8
  import { renderBlock, renderBracedOrEmpty } from "../../writer/emit.js";
9
9
  import { renderSourceGtype } from "./gtype-binding.js";
10
- import { emitFieldWrite, isEmittableField } from "./record-field-accessor.js";
10
+ import { emitFieldWrite, isEmittableField, isInlineField } from "./record-field-accessor.js";
11
11
  import { computeRecordFieldSlots, type RecordFieldSlot } from "./record-layout.js";
12
+ import { isConstructibleRecord } from "./value-marshalable.js";
12
13
 
13
14
  type WritableFieldSlot = RecordFieldSlot & { field: GirField & { type: TypeId } };
14
15
 
@@ -24,7 +25,7 @@ const renderRecordConstructorPropsInterface = (
24
25
  ): string => {
25
26
  const head = `export interface ${className}ConstructorProps`;
26
27
 
27
- if (isOpaque(record)) {
28
+ if (isOpaque(record) || !isConstructibleRecord(context, context.namespace.name, record)) {
28
29
  return renderBracedOrEmpty(head, "");
29
30
  }
30
31
 
@@ -68,7 +69,7 @@ const renderRecordConstructor = (
68
69
  ): string => {
69
70
  const superCall = isErrorSubclass ? ["super();"] : [];
70
71
 
71
- if (isOpaque(record)) {
72
+ if (isOpaque(record) || !isConstructibleRecord(context, context.namespace.name, record)) {
72
73
  return renderOpaqueConstructor(className, superCall);
73
74
  }
74
75
 
@@ -103,7 +104,11 @@ const allocArgs = (context: ModuleContext, record: GirRecord, size: number): str
103
104
 
104
105
  const renderFieldWrite = (context: ModuleContext, entry: WritableFieldSlot): string => {
105
106
  context.addRuntimeImport("t");
106
- const descriptor = context.hoistDescriptor(renderDescriptor(context, entry.field.type, "none"));
107
+
108
+ const descriptor = context.hoistDescriptor(
109
+ renderDescriptor(context, entry.field.type, "none", { isInline: isInlineField(context, entry.field) }),
110
+ );
111
+
107
112
  const name = toCamelIdentifier(entry.field.name);
108
113
 
109
114
  const write = emitFieldWrite(context, {
@@ -9,9 +9,9 @@ import { tStruct } from "../../analysis/descriptor.js";
9
9
  import { renderTsType } from "../../analysis/ts-type.js";
10
10
  import { renderJsDoc } from "../../writer/doc.js";
11
11
  import { indent, renderBlock } from "../../writer/emit.js";
12
- import { isClassStructRef } from "./class-struct-record.js";
13
12
  import { bitMask, computeRecordFieldSlots, mergeBitfield, type RecordFieldSlot } from "./record-layout.js";
14
13
  import { wrapReturnValue } from "./return-wrap.js";
14
+ import { isValueMarshalable } from "./value-marshalable.js";
15
15
 
16
16
  type FieldWriteSpec = {
17
17
  descriptor: string;
@@ -28,7 +28,7 @@ type AdmittedField = {
28
28
  type RecordFieldEntry = {
29
29
  jsName: string;
30
30
  tsType: string;
31
- writable: boolean;
31
+ isWritable: boolean;
32
32
  doc: string | undefined;
33
33
  };
34
34
 
@@ -91,18 +91,37 @@ type AccessorOptions = {
91
91
  fieldType: TypeId;
92
92
  };
93
93
 
94
+ const isMarshalableField = (context: ModuleContext, field: GirField): boolean => {
95
+ if (field.cType?.endsWith("*") === true) {
96
+ return true;
97
+ }
98
+
99
+ const type = field.type === undefined ? undefined : context.library.typeFor(field.type);
100
+
101
+ if (type?.kind !== "record") {
102
+ return true;
103
+ }
104
+
105
+ return isValueMarshalable(context, type.namespace.name, type.value);
106
+ };
107
+
94
108
  const isEmittableField = (context: ModuleContext, field: GirField): field is GirField & { type: TypeId } =>
95
109
  !field.private &&
96
110
  field.type !== undefined &&
97
111
  !isInlineCallbackRef(context.library, field.type) &&
98
- !isClassStructRef(context, field.type);
112
+ isMarshalableField(context, field);
99
113
 
100
114
  const emitFieldWrite = (context: ModuleContext, spec: FieldWriteSpec): string => {
101
115
  const { descriptor, slot, targetExpr, valueExpr } = spec;
102
116
  context.addRuntimeImport("write");
103
117
 
104
118
  if (slot.bitWidth === undefined) {
105
- return `write(${targetExpr}, ${descriptor}, ${String(slot.byteOffset)}, ${valueExpr});`;
119
+ context.addRuntimeImport("toNative");
120
+
121
+ return (
122
+ `write(${targetExpr}, ${descriptor}, ${String(slot.byteOffset)}, ` +
123
+ `toNative(${descriptor}, ${valueExpr}));`
124
+ );
106
125
  }
107
126
 
108
127
  context.addRuntimeImport("read");
@@ -159,7 +178,7 @@ const resolveRecordFieldEntry = (
159
178
  return {
160
179
  jsName: admitted.jsName,
161
180
  tsType: renderTsType(context, admitted.field.type, false),
162
- writable: admitted.field.writable,
181
+ isWritable: admitted.field.writable,
163
182
  doc: admitted.field.doc,
164
183
  };
165
184
  };
@@ -190,10 +209,10 @@ const renderRecordFieldAccessor = (
190
209
  return `${doc}declare ${jsName}: ${tsType};`;
191
210
  }
192
211
 
193
- // A record field whose C type is the record itself rather than a pointer to it holds the value
194
- // in place, so its own address is the value and no word may be loaded out of it.
195
- const isInline = resolveInlineStructFields(context, field.type, field.cType) !== undefined;
196
- const descriptor = context.hoistDescriptor(renderDescriptor(context, field.type, "none", { isInline }));
212
+ const descriptor = context.hoistDescriptor(
213
+ renderDescriptor(context, field.type, "none", { isInline: isInlineField(context, field) }),
214
+ );
215
+
197
216
  const tsType = renderTsType(context, field.type, false);
198
217
 
199
218
  const accessorOptions: AccessorOptions = {
@@ -246,6 +265,9 @@ const isAccessorEligibleType = (context: ModuleContext, ref: TypeId): boolean =>
246
265
  }
247
266
  };
248
267
 
268
+ const isInlineField = (context: ModuleContext, field: GirField): boolean =>
269
+ field.type !== undefined && resolveInlineStructFields(context, field.type, field.cType) !== undefined;
270
+
249
271
  const resolveInlineStructFields = (
250
272
  context: ModuleContext,
251
273
  ref: TypeId | undefined,
@@ -543,7 +565,7 @@ const renderStructArrayAccessor = (context: ModuleContext, target: StructArrayTa
543
565
  elementDescriptor: tStruct("borrowed", {
544
566
  size: `${lengthExpr} * ${String(elementSize)}`,
545
567
  wrapperClass: undefined,
546
- callerAllocated: false,
568
+ isCallerAllocated: false,
547
569
  }),
548
570
  offset: slot.byteOffset,
549
571
  lengthExpr,
@@ -575,7 +597,7 @@ const getterBlock = (options: AccessorOptions): string => {
575
597
 
576
598
  const wrapped = wrapReturnValue(context, {
577
599
  ref: fieldType,
578
- nullable: false,
600
+ isNullable: false,
579
601
  valueExpression,
580
602
  });
581
603
 
@@ -604,4 +626,11 @@ const setterBlock = (options: AccessorOptions): string =>
604
626
  setterBody(options.context, options.descriptor, options.slot),
605
627
  );
606
628
 
607
- export { isEmittableField, emitFieldWrite, resolveRecordFieldEntry, renderRecordFieldAccessor, type RecordFieldEntry };
629
+ export {
630
+ isEmittableField,
631
+ isInlineField,
632
+ emitFieldWrite,
633
+ resolveRecordFieldEntry,
634
+ renderRecordFieldAccessor,
635
+ type RecordFieldEntry,
636
+ };
@@ -20,10 +20,6 @@ type RecordFieldSlot = {
20
20
  const POINTER_LAYOUT: FieldLayout = { size: 8, align: 8 };
21
21
  const recordLayoutCache: Map<string, FieldLayout> = new Map();
22
22
 
23
- // GIR carries no alignment attribute, and a type whose alignment exceeds its widest member cannot be
24
- // derived from the field list: Graphene models `graphene_simd4f_t` as four `gfloat`, which computes
25
- // to align 4 while the real type is a 16-byte SIMD vector. Keying the override on `c:type` keeps it
26
- // to the handful of types where the XML genuinely cannot express the ABI.
27
23
  const ALIGNMENT_OVERRIDES: Map<string, FieldLayout> = new Map([
28
24
  ["graphene_simd4f_t", { size: 16, align: 16 }],
29
25
  ["graphene_simd4x4f_t", { size: 64, align: 16 }],
@@ -3,7 +3,6 @@ import type { ModuleContext } from "../../writer/context.js";
3
3
  import { renderJsDoc } from "../../writer/doc.js";
4
4
  import { indentMembers } from "../../writer/emit.js";
5
5
  import { type Callables, dedupeCallables, generateBindings, renderPlainTypeMembers } from "./callables.js";
6
- import { isClassStructRecord } from "./class-struct-record.js";
7
6
  import { renderSourceGtype } from "./gtype-binding.js";
8
7
  import { renderRecordConstructor, renderRecordConstructorPropsInterface } from "./record-constructor.js";
9
8
  import { renderRecordFieldAccessor } from "./record-field-accessor.js";
@@ -18,18 +17,10 @@ const generateRecord = (context: ModuleContext, record: GirRecord): void => {
18
17
  return;
19
18
  }
20
19
 
21
- if (record.isVtable) {
22
- return;
23
- }
24
-
25
20
  if (record.name.length === 0) {
26
21
  return;
27
22
  }
28
23
 
29
- if (isClassStructRecord(context.library, context.namespace.name, record)) {
30
- return;
31
- }
32
-
33
24
  const className = record.name;
34
25
  const isErrorSubclass = isGErrorRecord(context, record);
35
26
 
@@ -6,14 +6,14 @@ import { renderTsType } from "../../analysis/ts-type.js";
6
6
 
7
7
  type WrapReturnOptions = {
8
8
  ref: TypeId | undefined;
9
- nullable: boolean;
9
+ isNullable: boolean;
10
10
  valueExpression: string;
11
11
  };
12
12
 
13
13
  const BIGINT_CATEGORIES: Set<PrimitiveCategory> = new Set(["gtype", "bigint64", "biguint64"]);
14
14
 
15
15
  const wrapReturnValue = (context: ModuleContext, options: WrapReturnOptions): string => {
16
- const { ref, nullable, valueExpression } = options;
16
+ const { ref, isNullable, valueExpression } = options;
17
17
 
18
18
  if (ref === undefined) {
19
19
  return valueExpression;
@@ -27,7 +27,7 @@ const wrapReturnValue = (context: ModuleContext, options: WrapReturnOptions): st
27
27
 
28
28
  switch (type.kind) {
29
29
  case "primitive": {
30
- return wrapPrimitive(type.category, nullable, valueExpression);
30
+ return wrapPrimitive(type.category, isNullable, valueExpression);
31
31
  }
32
32
  case "varargs": {
33
33
  return `(${valueExpression} as unknown[])`;
@@ -39,7 +39,7 @@ const wrapReturnValue = (context: ModuleContext, options: WrapReturnOptions): st
39
39
  return `(${valueExpression} as number)`;
40
40
  }
41
41
  case "alias": {
42
- return wrapAlias(context, type.value.target, nullable, valueExpression);
42
+ return wrapAlias(context, type.value.target, isNullable, valueExpression);
43
43
  }
44
44
  case "carray":
45
45
  case "class":
@@ -65,7 +65,7 @@ const wrapAlias = (
65
65
  ): string =>
66
66
  target === undefined
67
67
  ? valueExpression
68
- : wrapReturnValue(context, { ref: target, nullable: isNullable, valueExpression });
68
+ : wrapReturnValue(context, { ref: target, isNullable, valueExpression });
69
69
 
70
70
  const wrapValue = (context: ModuleContext, ref: TypeId, valueExpression: string): string => {
71
71
  context.addRuntimeImport("fromNative");