@gtkx/codegen 1.0.0 → 1.2.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 (347) 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 +59 -38
  5. package/dist/analysis/descriptor-render.js.map +1 -1
  6. package/dist/analysis/descriptor.d.ts +25 -10
  7. package/dist/analysis/descriptor.d.ts.map +1 -1
  8. package/dist/analysis/descriptor.js +37 -9
  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 +25 -0
  15. package/dist/analysis/interface-conflicts.d.ts.map +1 -0
  16. package/dist/analysis/interface-conflicts.js +139 -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 +3 -2
  24. package/dist/analysis/ts-type.d.ts.map +1 -1
  25. package/dist/analysis/ts-type.js +26 -26
  26. package/dist/analysis/ts-type.js.map +1 -1
  27. package/dist/analysis/type-key.d.ts +5 -0
  28. package/dist/analysis/type-key.d.ts.map +1 -0
  29. package/dist/analysis/type-key.js +9 -0
  30. package/dist/analysis/type-key.js.map +1 -0
  31. package/dist/analysis/type-shape.d.ts +3 -2
  32. package/dist/analysis/type-shape.d.ts.map +1 -1
  33. package/dist/analysis/type-shape.js +2 -1
  34. package/dist/analysis/type-shape.js.map +1 -1
  35. package/dist/compile.d.ts +14 -6
  36. package/dist/compile.d.ts.map +1 -1
  37. package/dist/compile.js +125 -24
  38. package/dist/compile.js.map +1 -1
  39. package/dist/docs/api-reference.d.ts +2 -0
  40. package/dist/docs/api-reference.d.ts.map +1 -1
  41. package/dist/docs/api-reference.js +11 -10
  42. package/dist/docs/api-reference.js.map +1 -1
  43. package/dist/docs/element-page.d.ts.map +1 -1
  44. package/dist/docs/element-page.js +5 -3
  45. package/dist/docs/element-page.js.map +1 -1
  46. package/dist/docs/pipeline.d.ts +1 -0
  47. package/dist/docs/pipeline.d.ts.map +1 -1
  48. package/dist/docs/pipeline.js +93 -19
  49. package/dist/docs/pipeline.js.map +1 -1
  50. package/dist/docs/render.d.ts +2 -1
  51. package/dist/docs/render.d.ts.map +1 -1
  52. package/dist/docs/render.js +5 -4
  53. package/dist/docs/render.js.map +1 -1
  54. package/dist/docs/symbol-page.d.ts.map +1 -1
  55. package/dist/docs/symbol-page.js +10 -9
  56. package/dist/docs/symbol-page.js.map +1 -1
  57. package/dist/fingerprint.d.ts +20 -3
  58. package/dist/fingerprint.d.ts.map +1 -1
  59. package/dist/fingerprint.js +56 -37
  60. package/dist/fingerprint.js.map +1 -1
  61. package/dist/gi.d.ts +1 -0
  62. package/dist/gi.d.ts.map +1 -1
  63. package/dist/gi.js +8 -2
  64. package/dist/gi.js.map +1 -1
  65. package/dist/gir/ancestry.d.ts +7 -1
  66. package/dist/gir/ancestry.d.ts.map +1 -1
  67. package/dist/gir/ancestry.js +9 -1
  68. package/dist/gir/ancestry.js.map +1 -1
  69. package/dist/gir/annotations.d.ts +1 -2
  70. package/dist/gir/annotations.d.ts.map +1 -1
  71. package/dist/gir/annotations.js +1 -1
  72. package/dist/gir/annotations.js.map +1 -1
  73. package/dist/gir/cursor-overrides.d.ts +8 -0
  74. package/dist/gir/cursor-overrides.d.ts.map +1 -0
  75. package/dist/gir/cursor-overrides.js +6 -0
  76. package/dist/gir/cursor-overrides.js.map +1 -0
  77. package/dist/gir/emittable.d.ts +7 -0
  78. package/dist/gir/emittable.d.ts.map +1 -0
  79. package/dist/gir/emittable.js +3 -0
  80. package/dist/gir/emittable.js.map +1 -0
  81. package/dist/gir/function.d.ts.map +1 -1
  82. package/dist/gir/function.js +28 -2
  83. package/dist/gir/function.js.map +1 -1
  84. package/dist/gir/gir-path.d.ts +1 -1
  85. package/dist/gir/gir-path.js +1 -1
  86. package/dist/gir/gir-path.js.map +1 -1
  87. package/dist/gir/library.d.ts +5 -1
  88. package/dist/gir/library.d.ts.map +1 -1
  89. package/dist/gir/library.js +9 -2
  90. package/dist/gir/library.js.map +1 -1
  91. package/dist/gir/namespace.d.ts +5 -1
  92. package/dist/gir/namespace.d.ts.map +1 -1
  93. package/dist/gir/namespace.js +4 -2
  94. package/dist/gir/namespace.js.map +1 -1
  95. package/dist/gir/parameter.d.ts +13 -1
  96. package/dist/gir/parameter.d.ts.map +1 -1
  97. package/dist/gir/parameter.js +1 -0
  98. package/dist/gir/parameter.js.map +1 -1
  99. package/dist/gir/parse.d.ts.map +1 -1
  100. package/dist/gir/parse.js +6 -6
  101. package/dist/gir/parse.js.map +1 -1
  102. package/dist/gir/primitives.js +1 -1
  103. package/dist/gir/primitives.js.map +1 -1
  104. package/dist/guards.d.ts +16 -0
  105. package/dist/guards.d.ts.map +1 -0
  106. package/dist/guards.js +11 -0
  107. package/dist/guards.js.map +1 -0
  108. package/dist/internal.d.ts +2 -0
  109. package/dist/internal.d.ts.map +1 -1
  110. package/dist/internal.js +2 -0
  111. package/dist/internal.js.map +1 -1
  112. package/dist/json.d.ts +3 -0
  113. package/dist/json.d.ts.map +1 -0
  114. package/dist/json.js +11 -0
  115. package/dist/json.js.map +1 -0
  116. package/dist/khronos/args.d.ts.map +1 -1
  117. package/dist/khronos/args.js +8 -6
  118. package/dist/khronos/args.js.map +1 -1
  119. package/dist/khronos/modules.d.ts.map +1 -1
  120. package/dist/khronos/modules.js +22 -7
  121. package/dist/khronos/modules.js.map +1 -1
  122. package/dist/khronos/parse.d.ts.map +1 -1
  123. package/dist/khronos/parse.js +3 -4
  124. package/dist/khronos/parse.js.map +1 -1
  125. package/dist/khronos/pipeline.d.ts +1 -1
  126. package/dist/khronos/pipeline.d.ts.map +1 -1
  127. package/dist/khronos/pipeline.js.map +1 -1
  128. package/dist/khronos/plan.d.ts +1 -7
  129. package/dist/khronos/plan.d.ts.map +1 -1
  130. package/dist/khronos/plan.js +1 -1
  131. package/dist/khronos/plan.js.map +1 -1
  132. package/dist/khronos/render.d.ts.map +1 -1
  133. package/dist/khronos/render.js +8 -4
  134. package/dist/khronos/render.js.map +1 -1
  135. package/dist/runner.d.ts +7 -1
  136. package/dist/runner.d.ts.map +1 -1
  137. package/dist/runner.js +21 -3
  138. package/dist/runner.js.map +1 -1
  139. package/dist/staging.d.ts +5 -0
  140. package/dist/staging.d.ts.map +1 -0
  141. package/dist/staging.js +57 -0
  142. package/dist/staging.js.map +1 -0
  143. package/dist/store/compile-store.d.ts +0 -1
  144. package/dist/store/compile-store.d.ts.map +1 -1
  145. package/dist/store/compile-store.js +7 -32
  146. package/dist/store/compile-store.js.map +1 -1
  147. package/dist/store/gi/callables.d.ts +6 -3
  148. package/dist/store/gi/callables.d.ts.map +1 -1
  149. package/dist/store/gi/callables.js +40 -30
  150. package/dist/store/gi/callables.js.map +1 -1
  151. package/dist/store/gi/callback.d.ts.map +1 -1
  152. package/dist/store/gi/callback.js +9 -5
  153. package/dist/store/gi/callback.js.map +1 -1
  154. package/dist/store/gi/class.d.ts.map +1 -1
  155. package/dist/store/gi/class.js +104 -44
  156. package/dist/store/gi/class.js.map +1 -1
  157. package/dist/store/gi/companion.d.ts.map +1 -1
  158. package/dist/store/gi/companion.js +6 -6
  159. package/dist/store/gi/companion.js.map +1 -1
  160. package/dist/store/gi/constant.d.ts.map +1 -1
  161. package/dist/store/gi/constant.js +11 -3
  162. package/dist/store/gi/constant.js.map +1 -1
  163. package/dist/store/gi/constructor-props.js +1 -1
  164. package/dist/store/gi/constructor-props.js.map +1 -1
  165. package/dist/store/gi/enum.d.ts.map +1 -1
  166. package/dist/store/gi/enum.js +29 -12
  167. package/dist/store/gi/enum.js.map +1 -1
  168. package/dist/store/gi/function.d.ts +1 -3
  169. package/dist/store/gi/function.d.ts.map +1 -1
  170. package/dist/store/gi/function.js +24 -18
  171. package/dist/store/gi/function.js.map +1 -1
  172. package/dist/store/gi/gtype-binding.d.ts.map +1 -1
  173. package/dist/store/gi/gtype-binding.js +4 -1
  174. package/dist/store/gi/gtype-binding.js.map +1 -1
  175. package/dist/store/gi/interface.d.ts.map +1 -1
  176. package/dist/store/gi/interface.js +34 -19
  177. package/dist/store/gi/interface.js.map +1 -1
  178. package/dist/store/gi/method.d.ts +7 -6
  179. package/dist/store/gi/method.d.ts.map +1 -1
  180. package/dist/store/gi/method.js +13 -24
  181. package/dist/store/gi/method.js.map +1 -1
  182. package/dist/store/gi/param-marshal.d.ts +3 -2
  183. package/dist/store/gi/param-marshal.d.ts.map +1 -1
  184. package/dist/store/gi/param-marshal.js +50 -5
  185. package/dist/store/gi/param-marshal.js.map +1 -1
  186. package/dist/store/gi/pipeline.d.ts.map +1 -1
  187. package/dist/store/gi/pipeline.js +21 -10
  188. package/dist/store/gi/pipeline.js.map +1 -1
  189. package/dist/store/gi/properties.d.ts +2 -1
  190. package/dist/store/gi/properties.d.ts.map +1 -1
  191. package/dist/store/gi/properties.js +6 -3
  192. package/dist/store/gi/properties.js.map +1 -1
  193. package/dist/store/gi/property-accessor.d.ts +10 -8
  194. package/dist/store/gi/property-accessor.d.ts.map +1 -1
  195. package/dist/store/gi/property-accessor.js +49 -91
  196. package/dist/store/gi/property-accessor.js.map +1 -1
  197. package/dist/store/gi/record-constructor.d.ts +8 -1
  198. package/dist/store/gi/record-constructor.d.ts.map +1 -1
  199. package/dist/store/gi/record-constructor.js +34 -13
  200. package/dist/store/gi/record-constructor.js.map +1 -1
  201. package/dist/store/gi/record-field-accessor.d.ts.map +1 -1
  202. package/dist/store/gi/record-field-accessor.js +20 -4
  203. package/dist/store/gi/record-field-accessor.js.map +1 -1
  204. package/dist/store/gi/record-layout.d.ts +6 -1
  205. package/dist/store/gi/record-layout.d.ts.map +1 -1
  206. package/dist/store/gi/record-layout.js +8 -1
  207. package/dist/store/gi/record-layout.js.map +1 -1
  208. package/dist/store/gi/record.d.ts.map +1 -1
  209. package/dist/store/gi/record.js +19 -8
  210. package/dist/store/gi/record.js.map +1 -1
  211. package/dist/store/gi/registration.js +2 -2
  212. package/dist/store/gi/registration.js.map +1 -1
  213. package/dist/store/gi/return-wrap.js +1 -1
  214. package/dist/store/gi/return-wrap.js.map +1 -1
  215. package/dist/store/gi/signal.d.ts +2 -1
  216. package/dist/store/gi/signal.d.ts.map +1 -1
  217. package/dist/store/gi/signal.js +55 -28
  218. package/dist/store/gi/signal.js.map +1 -1
  219. package/dist/store/gi/value-marshalable.d.ts.map +1 -1
  220. package/dist/store/gi/value-marshalable.js +2 -1
  221. package/dist/store/gi/value-marshalable.js.map +1 -1
  222. package/dist/store/gi/vtable.d.ts +4 -1
  223. package/dist/store/gi/vtable.d.ts.map +1 -1
  224. package/dist/store/gi/vtable.js +60 -17
  225. package/dist/store/gi/vtable.js.map +1 -1
  226. package/dist/store/gi-store.d.ts +1 -0
  227. package/dist/store/gi-store.d.ts.map +1 -1
  228. package/dist/store/gi-store.js +15 -20
  229. package/dist/store/gi-store.js.map +1 -1
  230. package/dist/store/jsx/generated-elements.d.ts +2 -1
  231. package/dist/store/jsx/generated-elements.d.ts.map +1 -1
  232. package/dist/store/jsx/generated-elements.js +13 -7
  233. package/dist/store/jsx/generated-elements.js.map +1 -1
  234. package/dist/store/jsx/jsx.js +3 -3
  235. package/dist/store/jsx/jsx.js.map +1 -1
  236. package/dist/store/jsx/metadata.d.ts.map +1 -1
  237. package/dist/store/jsx/metadata.js +3 -1
  238. package/dist/store/jsx/metadata.js.map +1 -1
  239. package/dist/store/jsx-store.d.ts.map +1 -1
  240. package/dist/store/jsx-store.js +3 -4
  241. package/dist/store/jsx-store.js.map +1 -1
  242. package/dist/store/resolve-store.d.ts +14 -3
  243. package/dist/store/resolve-store.d.ts.map +1 -1
  244. package/dist/store/resolve-store.js +98 -15
  245. package/dist/store/resolve-store.js.map +1 -1
  246. package/dist/store/store-fs.d.ts +9 -7
  247. package/dist/store/store-fs.d.ts.map +1 -1
  248. package/dist/store/store-fs.js +54 -25
  249. package/dist/store/store-fs.js.map +1 -1
  250. package/dist/store/store-links.d.ts +3 -0
  251. package/dist/store/store-links.d.ts.map +1 -0
  252. package/dist/store/store-links.js +39 -0
  253. package/dist/store/store-links.js.map +1 -0
  254. package/dist/writer/comparison-context.d.ts +4 -0
  255. package/dist/writer/comparison-context.d.ts.map +1 -0
  256. package/dist/writer/comparison-context.js +13 -0
  257. package/dist/writer/comparison-context.js.map +1 -0
  258. package/dist/writer/context.d.ts +3 -3
  259. package/dist/writer/context.d.ts.map +1 -1
  260. package/dist/writer/context.js +11 -6
  261. package/dist/writer/context.js.map +1 -1
  262. package/dist/writer/module.d.ts +13 -5
  263. package/dist/writer/module.d.ts.map +1 -1
  264. package/dist/writer/module.js +68 -11
  265. package/dist/writer/module.js.map +1 -1
  266. package/dist/xml.d.ts +8 -1
  267. package/dist/xml.d.ts.map +1 -1
  268. package/dist/xml.js +70 -1
  269. package/dist/xml.js.map +1 -1
  270. package/overrides/gobject/object.ts.ejs +2 -0
  271. package/package.json +14 -3
  272. package/src/analysis/descriptor-render.ts +106 -52
  273. package/src/analysis/descriptor.ts +76 -15
  274. package/src/analysis/inheritance.ts +134 -44
  275. package/src/analysis/interface-conflicts.ts +235 -0
  276. package/src/analysis/param-capability.ts +3 -6
  277. package/src/analysis/param-structure.ts +2 -2
  278. package/src/analysis/ts-type.ts +43 -28
  279. package/src/analysis/type-key.ts +14 -0
  280. package/src/analysis/type-shape.ts +5 -2
  281. package/src/compile.ts +192 -27
  282. package/src/docs/api-reference.ts +13 -10
  283. package/src/docs/element-page.ts +5 -2
  284. package/src/docs/pipeline.ts +140 -24
  285. package/src/docs/render.ts +7 -3
  286. package/src/docs/symbol-page.ts +12 -11
  287. package/src/fingerprint.ts +95 -47
  288. package/src/gi.ts +10 -2
  289. package/src/gir/ancestry.ts +17 -1
  290. package/src/gir/annotations.ts +1 -1
  291. package/src/gir/cursor-overrides.ts +12 -0
  292. package/src/gir/emittable.ts +8 -0
  293. package/src/gir/function.ts +45 -9
  294. package/src/gir/gir-path.ts +1 -1
  295. package/src/gir/library.ts +10 -2
  296. package/src/gir/namespace.ts +8 -2
  297. package/src/gir/parameter.ts +15 -0
  298. package/src/gir/parse.ts +10 -7
  299. package/src/gir/primitives.ts +1 -1
  300. package/src/guards.ts +23 -0
  301. package/src/internal.ts +2 -0
  302. package/src/json.ts +11 -0
  303. package/src/khronos/args.ts +9 -6
  304. package/src/khronos/modules.ts +25 -9
  305. package/src/khronos/parse.ts +3 -4
  306. package/src/khronos/pipeline.ts +1 -1
  307. package/src/khronos/plan.ts +0 -1
  308. package/src/khronos/render.ts +8 -6
  309. package/src/runner.ts +26 -4
  310. package/src/staging.ts +67 -0
  311. package/src/store/compile-store.ts +7 -38
  312. package/src/store/gi/callables.ts +60 -33
  313. package/src/store/gi/callback.ts +9 -9
  314. package/src/store/gi/class.ts +140 -53
  315. package/src/store/gi/companion.ts +7 -6
  316. package/src/store/gi/constant.ts +13 -3
  317. package/src/store/gi/constructor-props.ts +1 -1
  318. package/src/store/gi/enum.ts +36 -26
  319. package/src/store/gi/function.ts +30 -24
  320. package/src/store/gi/gtype-binding.ts +7 -2
  321. package/src/store/gi/interface.ts +39 -20
  322. package/src/store/gi/method.ts +26 -32
  323. package/src/store/gi/param-marshal.ts +77 -6
  324. package/src/store/gi/pipeline.ts +25 -15
  325. package/src/store/gi/properties.ts +8 -4
  326. package/src/store/gi/property-accessor.ts +73 -161
  327. package/src/store/gi/record-constructor.ts +53 -21
  328. package/src/store/gi/record-field-accessor.ts +26 -4
  329. package/src/store/gi/record-layout.ts +11 -1
  330. package/src/store/gi/record.ts +20 -12
  331. package/src/store/gi/registration.ts +2 -2
  332. package/src/store/gi/return-wrap.ts +1 -1
  333. package/src/store/gi/signal.ts +66 -42
  334. package/src/store/gi/value-marshalable.ts +3 -1
  335. package/src/store/gi/vtable.ts +97 -20
  336. package/src/store/gi-store.ts +26 -31
  337. package/src/store/jsx/generated-elements.ts +17 -8
  338. package/src/store/jsx/jsx.ts +3 -3
  339. package/src/store/jsx/metadata.ts +4 -1
  340. package/src/store/jsx-store.ts +3 -4
  341. package/src/store/resolve-store.ts +133 -18
  342. package/src/store/store-fs.ts +82 -35
  343. package/src/store/store-links.ts +49 -0
  344. package/src/writer/comparison-context.ts +18 -0
  345. package/src/writer/context.ts +12 -6
  346. package/src/writer/module.ts +101 -14
  347. package/src/xml.ts +103 -1
@@ -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 };
@@ -10,7 +10,7 @@ type WrapReturnOptions = {
10
10
  valueExpression: string;
11
11
  };
12
12
 
13
- const BIGINT_CATEGORIES: Set<PrimitiveCategory> = new Set(["gtype", "bigint64", "biguint64"]);
13
+ const BIGINT_CATEGORIES: Set<PrimitiveCategory> = new Set(["gtype", "bigint64", "biguint64", "pointer"]);
14
14
 
15
15
  const wrapReturnValue = (context: ModuleContext, options: WrapReturnOptions): string => {
16
16
  const { ref, isNullable, valueExpression } = options;
@@ -1,13 +1,14 @@
1
1
  import { camelCase, sourceStringLiteral } from "@gtkx/utils";
2
2
  import type { GirClass } from "../../gir/class.js";
3
- import type { GirCallable, GirParameter } from "../../gir/parameter.js";
3
+ import type { GirCallable, GirParameter, GirReturnValue } from "../../gir/parameter.js";
4
4
  import type { GirProperty } from "../../gir/property.js";
5
5
  import type { ModuleContext } from "../../writer/context.js";
6
+ import type { Declaration } from "../../writer/module.js";
6
7
  import {
7
8
  isCellInout,
9
+ primaryReturnKind,
8
10
  renderDescriptor,
9
11
  renderParamDescriptor,
10
- shouldOmitPrimaryReturn,
11
12
  } from "../../analysis/descriptor-render.js";
12
13
  import { tCallback, tObject, tVoid } from "../../analysis/descriptor.js";
13
14
  import {
@@ -23,7 +24,7 @@ import { renderJsDoc } from "../../writer/doc.js";
23
24
  import { indent, renderBlock, renderBracedOrEmpty } from "../../writer/emit.js";
24
25
  import { parentCompanionRef } from "./companion.js";
25
26
  import { getDoc, handlerSpec } from "./doc-spec.js";
26
- import { isRecordCallerOut, isRecordInout } from "./param-marshal.js";
27
+ import { isAllocatableCallerOut, isRecordInout, renderCallerOutInstance } from "./param-marshal.js";
27
28
 
28
29
  type SignalMapSpec = {
29
30
  context: ModuleContext;
@@ -47,6 +48,21 @@ const SIGNAL_HANDLER_TYPE = "(...args: any[]) => any";
47
48
  const SIGNALS_SUFFIX = "Signals";
48
49
  const SIGNAL_EMIT_SUFFIX = "SignalEmit";
49
50
 
51
+ const DEPRECATED_SIGNAL_ALIASES: Map<string, string> = new Map([
52
+ ["addEventListener", "on"],
53
+ ["removeEventListener", "off"],
54
+ ]);
55
+
56
+ const deprecatedAliasDoc = (method: string): string => {
57
+ const replacement = DEPRECATED_SIGNAL_ALIASES.get(method);
58
+
59
+ if (replacement === undefined) {
60
+ return "";
61
+ }
62
+
63
+ return `/** @deprecated Since 1.2. Use \`${replacement}\` instead. Removed in v2. */\n`;
64
+ };
65
+
50
66
  const renderSignalMembers = (context: ModuleContext, klass: GirClass): string[] => {
51
67
  if (klass.glibGetType === undefined) {
52
68
  return [];
@@ -67,7 +83,7 @@ const renderSignalMembers = (context: ModuleContext, klass: GirClass): string[]
67
83
 
68
84
  const connectDefault = isRootObject
69
85
  ? "default:\n throw new globalThis.Error(\"Unknown signal '\" + signal + \"'\");"
70
- : "default:\n return super.connect(signal, handler, isAfter);";
86
+ : "default:\n return super.connect(signal as never, handler as never, isAfter);";
71
87
 
72
88
  const emitDefault = isRootObject
73
89
  ? "default:\n throw new globalThis.Error(\"Unknown signal '\" + sigName + \"'\");"
@@ -92,12 +108,18 @@ const renderSignalDeclarations = (
92
108
  klass: GirClass,
93
109
  className: string,
94
110
  isParentlessObjectSubclass: boolean,
95
- ): string[] => {
111
+ ): Declaration[] => {
96
112
  const base = { context, klass, className, isParentlessObjectSubclass };
97
113
 
98
- const declarations = [
99
- renderSignalMap({ ...base, suffix: SIGNALS_SUFFIX, renderEntry: renderSignalHandlerType }),
100
- renderSignalMap({ ...base, suffix: SIGNAL_EMIT_SUFFIX, renderEntry: renderSignalEmitEntry }),
114
+ const declarations: Declaration[] = [
115
+ {
116
+ name: `${className}${SIGNALS_SUFFIX}`,
117
+ code: renderSignalMap({ ...base, suffix: SIGNALS_SUFFIX, renderEntry: renderSignalHandlerType }),
118
+ },
119
+ {
120
+ name: `${className}${SIGNAL_EMIT_SUFFIX}`,
121
+ code: renderSignalMap({ ...base, suffix: SIGNAL_EMIT_SUFFIX, renderEntry: renderSignalEmitEntry }),
122
+ },
101
123
  ];
102
124
 
103
125
  if (
@@ -107,7 +129,7 @@ const renderSignalDeclarations = (
107
129
  klass.implements.length > 0)
108
130
  ) {
109
131
  const isRootObject = context.namespace.name === "GObject" && klass.name === "Object";
110
- declarations.push(renderSignalConnectInterface(className, isRootObject));
132
+ declarations.push({ name: className, code: renderSignalConnectInterface(className, isRootObject) });
111
133
  }
112
134
 
113
135
  return declarations;
@@ -122,7 +144,11 @@ const renderSignalMap = (spec: SignalMapSpec): string => {
122
144
  (signal) => `${signalDoc(signal)}${sourceStringLiteral(signal.name)}: ${renderEntry(context, signal)};`,
123
145
  );
124
146
 
125
- const entries = [...signalEntries, ...renderNotifyDetailEntries(context, klass, suffix)];
147
+ const entries = [
148
+ ...signalEntries,
149
+ ...renderNotifyDetailEntries(context, klass, suffix),
150
+ ...renderCustomNotifyEntry(context, klass, suffix),
151
+ ];
126
152
 
127
153
  return renderBracedOrEmpty(`export interface ${className}${suffix}${extendsClause}`, entries.join("\n"));
128
154
  };
@@ -130,6 +156,14 @@ const renderSignalMap = (spec: SignalMapSpec): string => {
130
156
  const signalDoc = (signal: GirCallable): string =>
131
157
  renderJsDoc(signal.doc, undefined, handlerSpec(signal, signal.parameters));
132
158
 
159
+ const renderCustomNotifyEntry = (context: ModuleContext, klass: GirClass, suffix: string): string[] => {
160
+ if (context.namespace.name !== "GObject" || klass.name !== "Object") {
161
+ return [];
162
+ }
163
+
164
+ return [`[detail: \`notify::\${string}\`]: ${gobjectObjectMapRef(context, suffix)}["notify"];`];
165
+ };
166
+
133
167
  const renderNotifyDetailEntries = (context: ModuleContext, klass: GirClass, suffix: string): string[] => {
134
168
  const notifyValue = `${gobjectObjectMapRef(context, suffix)}["notify"]`;
135
169
 
@@ -184,7 +218,6 @@ const renderSignalConnectInterface = (className: string, isRootObject: boolean):
184
218
  const lines = [
185
219
  `__signals__?: ${map};`,
186
220
  `connect<K extends keyof ${map}>(signal: K, handler: ${map}[K], isAfter?: boolean): number;`,
187
- `connect(signal: string, handler: ${SIGNAL_HANDLER_TYPE}, isAfter?: boolean): number;`,
188
221
  `emit<K extends keyof ${emitMap}>(sigName: K, ...args: ${emitMap}[K]["args"]): ${emitMap}[K]["result"];`,
189
222
  "emit(sigName: string, ...args: unknown[]): unknown;",
190
223
  ];
@@ -193,8 +226,8 @@ const renderSignalConnectInterface = (className: string, isRootObject: boolean):
193
226
  const chainable = (methods: string[], trailing: string): void => {
194
227
  for (const method of methods) {
195
228
  lines.push(
229
+ deprecatedAliasDoc(method) +
196
230
  `${method}<K extends keyof ${map}>(signal: K, handler: ${map}[K]${trailing}): this;`,
197
- `${method}(signal: string, handler: ${SIGNAL_HANDLER_TYPE}${trailing}): this;`,
198
231
  );
199
232
  }
200
233
  };
@@ -263,7 +296,7 @@ const renderEmitArgLiteral = (options: EmitArgOptions): { literal: string; nextA
263
296
  }
264
297
 
265
298
  if (isCallerAllocatedOut(parameter)) {
266
- const value = renderCallerOutAllocation(context, parameter);
299
+ const value = renderCallerOutInstance(context, parameter);
267
300
 
268
301
  return {
269
302
  literal: `{ type: ${descriptor}, direction: "out", isCallerAllocated: true, value: ${value} }`,
@@ -283,10 +316,18 @@ const renderEmitArgLiteral = (options: EmitArgOptions): { literal: string; nextA
283
316
  return { literal: `{ type: ${descriptor}, value: args[${String(argIndex)}] }`, nextArgIndex: argIndex + 1 };
284
317
  };
285
318
 
319
+ const renderEmitReturnArg = (context: ModuleContext, returnValue: GirReturnValue): string => {
320
+ if (primaryReturnKind(context.library, returnValue) === "void") {
321
+ return "";
322
+ }
323
+
324
+ return `, ${renderDescriptor(context, returnValue.type, returnValue.transferOwnership)}`;
325
+ };
326
+
286
327
  const renderEmitCase = (context: ModuleContext, signal: GirCallable): string => {
287
328
  const params = nonVarargParameters(signal);
288
329
 
289
- if (params.some((parameter) => isCallerAllocatedOut(parameter) && !isRecordCallerOut(context, parameter))) {
330
+ if (params.some((parameter) => isCallerAllocatedOut(parameter) && !isAllocatableCallerOut(context, parameter))) {
290
331
  return renderUnsupportedEmitCase(signal);
291
332
  }
292
333
 
@@ -301,12 +342,7 @@ const renderEmitCase = (context: ModuleContext, signal: GirCallable): string =>
301
342
  return rendered.literal;
302
343
  });
303
344
 
304
- const isVoid = shouldOmitPrimaryReturn(context.library, signal.returnValue);
305
-
306
- const returnArg = isVoid
307
- ? ""
308
- : `, ${renderDescriptor(context, signal.returnValue.type, signal.returnValue.transferOwnership)}`;
309
-
345
+ const returnArg = renderEmitReturnArg(context, signal.returnValue);
310
346
  const body = `return emitSignal(this, sigName, [${argLiterals.join(", ")}]${returnArg});`;
311
347
 
312
348
  return renderBlock(`case ${sourceStringLiteral(signal.name)}:`, body);
@@ -321,16 +357,6 @@ const renderUnsupportedEmitCase = (signal: GirCallable): string => {
321
357
  );
322
358
  };
323
359
 
324
- const renderCallerOutAllocation = (context: ModuleContext, parameter: GirParameter): string => {
325
- const name = parameter.type === undefined ? undefined : context.library.nameFor(parameter.type);
326
-
327
- if (name === undefined) {
328
- throw new Error("renderCallerOutAllocation: expected a named caller-allocated out-parameter");
329
- }
330
-
331
- return `new ${context.qualify(name.namespaceName, name.typeName)}()`;
332
- };
333
-
334
360
  const renderCallback = (context: ModuleContext, signal: GirCallable): string => {
335
361
  const params = nonVarargParameters(signal);
336
362
 
@@ -338,21 +364,19 @@ const renderCallback = (context: ModuleContext, signal: GirCallable): string =>
338
364
  renderParamDescriptor(context, parameter, parameter.type, { argIndexOffset: 1 }),
339
365
  );
340
366
 
341
- const isVoid = shouldOmitPrimaryReturn(context.library, signal.returnValue);
342
-
343
- const returnDescriptor = isVoid
344
- ? tVoid
345
- : renderDescriptor(context, signal.returnValue.type, signal.returnValue.transferOwnership);
346
-
347
367
  const callbackArgs = [tObject("borrowed"), ...callbackParamDescriptors, tVoid];
348
368
  const userDataIndex = String(params.length + 1);
349
- const destroy = "hasDestroy: true, destroyKind: \"closureNotify\"";
350
369
 
351
- return tCallback(
352
- callbackArgs,
353
- returnDescriptor,
354
- `{ ${destroy}, hasUserData: true, userDataIndex: ${userDataIndex} }`,
355
- );
370
+ return tCallback({
371
+ argTypes: callbackArgs,
372
+ returns: renderDescriptor(context, signal.returnValue.type, signal.returnValue.transferOwnership),
373
+ options: [
374
+ "hasDestroy: true",
375
+ "destroyKind: \"closureNotify\"",
376
+ "hasUserData: true",
377
+ `userDataIndex: ${userDataIndex}`,
378
+ ],
379
+ });
356
380
  };
357
381
 
358
382
  const forEachInterfaceSignal = (
@@ -15,6 +15,8 @@ const hasOwnCopySemantics = (record: GirRecord): boolean =>
15
15
  record.glibGetType !== undefined ||
16
16
  ((record.glibRefFunc ?? record.copyFunc) !== undefined && (record.glibUnrefFunc ?? record.freeFunc) !== undefined);
17
17
 
18
+ const isOpaqueRecord = (record: GirRecord): boolean => record.opaque || record.disguised;
19
+
18
20
  const isValueSafeArray = (scope: Scope, type: Extract<GirType, { kind: "carray" }>): boolean =>
19
21
  type.fixedSize !== undefined && isValueSafeRef(scope, type.element, type.elementCType);
20
22
 
@@ -82,6 +84,6 @@ const isValueMarshalable = (context: ModuleContext, namespaceName: string, recor
82
84
  isValueSafeRecord({ context, seen: new Set<string>() }, namespaceName, record);
83
85
 
84
86
  const isConstructibleRecord = (context: ModuleContext, namespaceName: string, record: GirRecord): boolean =>
85
- hasOwnCopySemantics(record) || isValueMarshalable(context, namespaceName, record);
87
+ !isOpaqueRecord(record) && (hasOwnCopySemantics(record) || isValueMarshalable(context, namespaceName, record));
86
88
 
87
89
  export { isConstructibleRecord, isValueMarshalable };
@@ -1,7 +1,8 @@
1
- import { pascalCase, sourceStringLiteral } from "@gtkx/utils";
2
- import type { GirCallback } from "../../gir/callback.js";
1
+ import { pascalCase, sanitizeTypeIdentifier, sourceStringLiteral } from "@gtkx/utils";
3
2
  import type { GirClass, GirVirtualMethod } from "../../gir/class.js";
4
3
  import type { GirField } from "../../gir/field.js";
4
+ import type { GirFunction } from "../../gir/function.js";
5
+ import type { Library } from "../../gir/library.js";
5
6
  import type { GirParameter } from "../../gir/parameter.js";
6
7
  import type { GirRecord } from "../../gir/record.js";
7
8
  import type { TypeId } from "../../gir/type-id.js";
@@ -22,7 +23,9 @@ import {
22
23
  renderHandlerResultType,
23
24
  } from "../../analysis/param-structure.js";
24
25
  import { renderTsType } from "../../analysis/ts-type.js";
26
+ import { typeKey } from "../../analysis/type-key.js";
25
27
  import { ancestorChain, type ResolvedAncestor, resolveInterfaces } from "../../gir/ancestry.js";
28
+ import { callbackAsFunction, type GirCallback } from "../../gir/callback.js";
26
29
  import { renderJsDoc } from "../../writer/doc.js";
27
30
  import { renderBlock, renderBraced } from "../../writer/emit.js";
28
31
  import { handlerSpec, THROWS_TEXT } from "./doc-spec.js";
@@ -80,6 +83,7 @@ const UNCALLABLE_SLOT_KEYS: Set<string> = new Set([
80
83
  "vfuncSetProperty",
81
84
  ]);
82
85
 
86
+ const VTABLE_CACHE: WeakMap<GirClass, Vtable> = new WeakMap();
83
87
  const PROTECTED_SLOT_NOTE = "It is `protected`, so only a subclass chaining up reaches it.";
84
88
  const PUBLIC_SLOT_NOTE = "Calling it from anywhere else re-enters the slot on a live instance.";
85
89
 
@@ -193,7 +197,7 @@ const attachVirtualMethods = (slots: VtableSlot[], klass: GirClass): VtableSlot[
193
197
  return slots.map((slot) => ({ ...slot, vfunc: byKey.get(slot.key) }));
194
198
  };
195
199
 
196
- const collectVtable = (context: ModuleContext, namespaceName: string, klass: GirClass): Vtable | undefined => {
200
+ const buildVtable = (context: ModuleContext, namespaceName: string, klass: GirClass): Vtable | undefined => {
197
201
  const resolved = resolveVtableRecord(context, namespaceName, klass);
198
202
 
199
203
  if (resolved === undefined) {
@@ -210,10 +214,63 @@ const collectVtable = (context: ModuleContext, namespaceName: string, klass: Gir
210
214
  structName: pascalCase(resolved.typeStruct),
211
215
  kind: klass.isInterface ? "interface" : "class",
212
216
  vtableSize,
213
- slots: attachVirtualMethods(slots, klass),
217
+ slots: disambiguateSlots(context, namespaceName, klass, attachVirtualMethods(slots, klass)),
214
218
  };
215
219
  };
216
220
 
221
+ const collectVtable = (context: ModuleContext, namespaceName: string, klass: GirClass): Vtable | undefined => {
222
+ const cached = VTABLE_CACHE.get(klass);
223
+
224
+ if (cached !== undefined) {
225
+ return cached;
226
+ }
227
+
228
+ const vtable = buildVtable(context, namespaceName, klass);
229
+
230
+ if (vtable !== undefined) {
231
+ VTABLE_CACHE.set(klass, vtable);
232
+ }
233
+
234
+ return vtable;
235
+ };
236
+
237
+ const shadowedSlotKey = (klass: GirClass, slot: VtableSlot): string =>
238
+ `vfunc${sanitizeTypeIdentifier(klass.name)}${pascalCase(slot.field.name)}`;
239
+
240
+ const slotSignatureKey = (library: Library, slot: VtableSlot): string => {
241
+ const [, ...parameters] = slot.callback.parameters;
242
+
243
+ const parts = parameters.map(
244
+ (parameter) => `${typeKey(library, parameter.type)}/${parameter.direction}/${String(parameter.nullable)}`);
245
+
246
+ return `${parts.join(",")}->${typeKey(library, slot.callback.returnValue.type)}`;
247
+ };
248
+
249
+ const isShadowingSlot = (library: Library, slot: VtableSlot, inherited: VtableSlot[]): boolean =>
250
+ inherited.some(
251
+ (other) =>
252
+ other.key === slot.key &&
253
+ slotIdentity(other) !== slotIdentity(slot) &&
254
+ slotSignatureKey(library, other) !== slotSignatureKey(library, slot));
255
+
256
+ const disambiguateSlots = (
257
+ context: ModuleContext,
258
+ namespaceName: string,
259
+ klass: GirClass,
260
+ slots: VtableSlot[],
261
+ ): VtableSlot[] => {
262
+ const inherited = ancestorSlots(context, namespaceName, klass);
263
+
264
+ return slots.map((slot) =>
265
+ isShadowingSlot(context.library, slot, inherited) ? { ...slot, key: shadowedSlotKey(klass, slot) } : slot);
266
+ };
267
+
268
+ const ancestorSlots = (context: ModuleContext, namespaceName: string, klass: GirClass): VtableSlot[] => {
269
+ const [, ...ancestors] = [...ancestorChain(context.library, klass, namespaceName)];
270
+
271
+ return ancestors.flatMap((ancestor) => collectVtable(context, ancestor.namespaceName, ancestor.klass)?.slots ?? []);
272
+ };
273
+
217
274
  const vfuncMemberNames = (context: ModuleContext, namespaceName: string, klass: GirClass): string[] =>
218
275
  collectVtable(context, namespaceName, klass)?.slots.map((slot) => slot.key) ?? [];
219
276
 
@@ -231,21 +288,8 @@ const renderVfuncMetadata = (context: ModuleContext, klass: GirClass): string |
231
288
 
232
289
  const slotIdentity = (slot: VtableSlot): string => `${slot.key}:${String(slot.byteOffset)}`;
233
290
 
234
- const inheritedSlotIdentities = (context: ModuleContext, namespaceName: string, klass: GirClass): Set<string> => {
235
- const identities: Set<string> = new Set();
236
- const [, ...ancestors] = [...ancestorChain(context.library, klass, namespaceName)];
237
-
238
- for (const ancestor of ancestors) {
239
- const vtable = collectVtable(context, ancestor.namespaceName, ancestor.klass);
240
- const slots = vtable?.slots ?? [];
241
-
242
- for (const slot of slots) {
243
- identities.add(slotIdentity(slot));
244
- }
245
- }
246
-
247
- return identities;
248
- };
291
+ const inheritedSlotIdentities = (context: ModuleContext, namespaceName: string, klass: GirClass): Set<string> =>
292
+ new Set(ancestorSlots(context, namespaceName, klass).map((slot) => slotIdentity(slot)));
249
293
 
250
294
  const addInterfaceSlotKeys = (
251
295
  context: ModuleContext,
@@ -295,6 +339,37 @@ const protectedSlotKeys = (options: VfuncMembersOptions, slots: VtableSlot[]): S
295
339
  return new Set(slots.map((slot) => slot.key).filter((key) => !shared.has(key)));
296
340
  };
297
341
 
342
+ const vfuncCallables = (context: ModuleContext, namespaceName: string, klass: GirClass): Map<string, GirFunction> => {
343
+ const members: Map<string, GirFunction> = new Map();
344
+
345
+ for (const slot of callableVfuncSlots(context, namespaceName, klass)) {
346
+ const [, ...parameters] = slot.callback.parameters;
347
+ members.set(slot.key, { ...callbackAsFunction(slot.callback), parameters });
348
+ }
349
+
350
+ return members;
351
+ };
352
+
353
+ const addProtectedSlotKeys = (context: ModuleContext, ancestor: ResolvedAncestor, keys: Set<string>): void => {
354
+ const shared = implementedSlotKeys(context, ancestor.namespaceName, ancestor.klass);
355
+
356
+ for (const slot of callableVfuncSlots(context, ancestor.namespaceName, ancestor.klass)) {
357
+ if (!shared.has(slot.key)) {
358
+ keys.add(slot.key);
359
+ }
360
+ }
361
+ };
362
+
363
+ const protectedChainSlotKeys = (context: ModuleContext, klass: GirClass): Set<string> => {
364
+ const keys: Set<string> = new Set();
365
+
366
+ for (const ancestor of ancestorChain(context.library, klass, context.namespace.name)) {
367
+ addProtectedSlotKeys(context, ancestor, keys);
368
+ }
369
+
370
+ return keys;
371
+ };
372
+
298
373
  const callableVfuncSlots = (context: ModuleContext, namespaceName: string, klass: GirClass): VtableSlot[] => {
299
374
  const vtable = collectVtable(context, namespaceName, klass);
300
375
 
@@ -339,7 +414,7 @@ const vfuncEntries = (context: ModuleContext, namespaceName: string, klass: GirC
339
414
 
340
415
  const renderVfuncMembers = (options: VfuncMembersOptions): string[] => {
341
416
  const { context, klass, mode } = options;
342
- const ownerRef = pascalCase(klass.name);
417
+ const ownerRef = sanitizeTypeIdentifier(klass.name);
343
418
  const slots = callableVfuncSlots(context, context.namespace.name, klass);
344
419
 
345
420
  if (slots.length === 0) {
@@ -468,7 +543,9 @@ const renderVtableSlotDescriptor = (context: ModuleContext, vtable: Vtable, slot
468
543
 
469
544
  export {
470
545
  hasCallableVfuncSlots,
546
+ protectedChainSlotKeys,
471
547
  renderVfuncMembers,
548
+ vfuncCallables,
472
549
  renderVfuncMetadata,
473
550
  vfuncEntries,
474
551
  vfuncMemberNames,
@@ -1,64 +1,59 @@
1
1
  import { existsSync, readdirSync, readFileSync } from "node:fs";
2
2
  import { dirname, join, resolve } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
+ import type { SourceModule } from "../compile.js";
4
5
  import { FINGERPRINT_FILENAME, type GiFingerprint } from "../fingerprint.js";
5
- import { buildManifest, type StoreOptions, subpathExport, writeStore } from "./store-fs.js";
6
+ import { buildManifest, namespaceBarrel, type StoreOptions, subpathExport, writeStore } from "./store-fs.js";
6
7
 
7
8
  type GiNamespaceInput = {
8
9
  directory: string;
9
10
  rawSource: string;
10
- };
11
-
12
- type CollectedFile = {
13
- fileName: string;
14
- source: string;
11
+ girFile: string;
15
12
  };
16
13
 
17
14
  const OVERRIDES_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", "overrides");
18
15
 
19
- const overrideFiles = (directory: string): string[] => {
16
+ const overrideFiles = (directory: string): SourceModule[] => {
20
17
  const dir = join(OVERRIDES_ROOT, directory);
21
18
 
22
19
  if (!existsSync(dir)) {
23
20
  return [];
24
21
  }
25
22
 
26
- return readdirSync(dir).filter((name) => name.endsWith(".ejs") && name !== "index.ts.ejs");
23
+ return readdirSync(dir)
24
+ .filter((name) => name.endsWith(".ejs") && name !== "index.ts.ejs")
25
+ .map((name) => overrideModule(`${directory}/overrides/${name.replace(/\.ejs$/, "")}`, join(dir, name)));
27
26
  };
28
27
 
29
- const barrelSource = (directory: string): string => {
28
+ const overrideModule = (fileName: string, overridePath: string): SourceModule => ({
29
+ fileName,
30
+ source: readFileSync(overridePath, "utf8"),
31
+ origin: overridePath,
32
+ });
33
+
34
+ const barrelFile = (directory: string, girFile: string): SourceModule => {
35
+ const barrel = namespaceBarrel(directory);
30
36
  const overrideIndex = join(OVERRIDES_ROOT, directory, "index.ts.ejs");
31
37
 
32
38
  if (!existsSync(overrideIndex)) {
33
- return `export * from "./${directory}.js";\n`;
39
+ return { ...barrel, origin: girFile };
34
40
  }
35
41
 
36
- return readFileSync(overrideIndex, "utf8");
42
+ return overrideModule(barrel.fileName, overrideIndex);
37
43
  };
38
44
 
39
45
  const collectStoreSources = (
40
46
  namespaces: GiNamespaceInput[],
41
- ): { collected: CollectedFile[]; exportsMap: Record<string, unknown> } => {
47
+ ): { collected: SourceModule[]; exportsMap: Record<string, unknown> } => {
42
48
  const exportsMap: Record<string, unknown> = {};
43
- const collected: CollectedFile[] = [];
44
-
45
- for (const { directory, rawSource } of namespaces) {
46
- collected.push({
47
- fileName: `${directory}/${directory}.ts`,
48
- source: rawSource,
49
- });
50
-
51
- for (const file of overrideFiles(directory)) {
52
- collected.push({
53
- fileName: `${directory}/overrides/${file.replace(/\.ejs$/, "")}`,
54
- source: readFileSync(join(OVERRIDES_ROOT, directory, file), "utf8"),
55
- });
56
- }
57
-
58
- collected.push({
59
- fileName: `${directory}/index.ts`,
60
- source: barrelSource(directory),
61
- });
49
+ const collected: SourceModule[] = [];
50
+
51
+ for (const { directory, rawSource, girFile } of namespaces) {
52
+ collected.push(
53
+ { fileName: `${directory}/${directory}.ts`, source: rawSource, origin: girFile },
54
+ ...overrideFiles(directory),
55
+ barrelFile(directory, girFile),
56
+ );
62
57
 
63
58
  exportsMap[`./${directory}`] = subpathExport(`${directory}/index`);
64
59
  }