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

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 (113) hide show
  1. package/dist/analysis/descriptor-render.d.ts +2 -0
  2. package/dist/analysis/descriptor-render.d.ts.map +1 -1
  3. package/dist/analysis/descriptor-render.js +25 -4
  4. package/dist/analysis/descriptor-render.js.map +1 -1
  5. package/dist/analysis/ts-type.d.ts.map +1 -1
  6. package/dist/analysis/ts-type.js +4 -8
  7. package/dist/analysis/ts-type.js.map +1 -1
  8. package/dist/docs/api-reference.d.ts.map +1 -1
  9. package/dist/docs/api-reference.js +4 -8
  10. package/dist/docs/api-reference.js.map +1 -1
  11. package/dist/docs/element-page.d.ts.map +1 -1
  12. package/dist/docs/element-page.js +5 -4
  13. package/dist/docs/element-page.js.map +1 -1
  14. package/dist/docs/pipeline.d.ts +2 -0
  15. package/dist/docs/pipeline.d.ts.map +1 -1
  16. package/dist/docs/pipeline.js +2 -0
  17. package/dist/docs/pipeline.js.map +1 -1
  18. package/dist/fingerprint.d.ts +1 -0
  19. package/dist/fingerprint.d.ts.map +1 -1
  20. package/dist/fingerprint.js +3 -0
  21. package/dist/fingerprint.js.map +1 -1
  22. package/dist/gi.d.ts +7 -2
  23. package/dist/gi.d.ts.map +1 -1
  24. package/dist/gi.js +4 -2
  25. package/dist/gi.js.map +1 -1
  26. package/dist/gir/libraries.d.ts +4 -3
  27. package/dist/gir/libraries.d.ts.map +1 -1
  28. package/dist/gir/libraries.js +2 -1
  29. package/dist/gir/libraries.js.map +1 -1
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +1 -0
  33. package/dist/index.js.map +1 -1
  34. package/dist/jsx.d.ts +2 -0
  35. package/dist/jsx.d.ts.map +1 -1
  36. package/dist/jsx.js +4 -0
  37. package/dist/jsx.js.map +1 -1
  38. package/dist/react/element-config.d.ts +3 -0
  39. package/dist/react/element-config.d.ts.map +1 -1
  40. package/dist/react/element-config.js +4 -1
  41. package/dist/react/element-config.js.map +1 -1
  42. package/dist/runner.d.ts +2 -0
  43. package/dist/runner.d.ts.map +1 -1
  44. package/dist/runner.js +4 -1
  45. package/dist/runner.js.map +1 -1
  46. package/dist/store/gi/callables.d.ts.map +1 -1
  47. package/dist/store/gi/callables.js +0 -5
  48. package/dist/store/gi/callables.js.map +1 -1
  49. package/dist/store/gi/function.d.ts.map +1 -1
  50. package/dist/store/gi/function.js +0 -2
  51. package/dist/store/gi/function.js.map +1 -1
  52. package/dist/store/gi/method.d.ts.map +1 -1
  53. package/dist/store/gi/method.js +1 -0
  54. package/dist/store/gi/method.js.map +1 -1
  55. package/dist/store/gi/record-constructor.d.ts.map +1 -1
  56. package/dist/store/gi/record-constructor.js +5 -4
  57. package/dist/store/gi/record-constructor.js.map +1 -1
  58. package/dist/store/gi/record-field-accessor.d.ts +2 -1
  59. package/dist/store/gi/record-field-accessor.d.ts.map +1 -1
  60. package/dist/store/gi/record-field-accessor.js +22 -6
  61. package/dist/store/gi/record-field-accessor.js.map +1 -1
  62. package/dist/store/gi/record.d.ts.map +1 -1
  63. package/dist/store/gi/record.js +0 -7
  64. package/dist/store/gi/record.js.map +1 -1
  65. package/dist/store/gi/value-marshalable.d.ts +15 -0
  66. package/dist/store/gi/value-marshalable.d.ts.map +1 -0
  67. package/dist/store/gi/value-marshalable.js +66 -0
  68. package/dist/store/gi/value-marshalable.js.map +1 -0
  69. package/dist/store/jsx/intrinsic-elements.d.ts +1 -2
  70. package/dist/store/jsx/intrinsic-elements.d.ts.map +1 -1
  71. package/dist/store/jsx/intrinsic-elements.js +1 -2
  72. package/dist/store/jsx/intrinsic-elements.js.map +1 -1
  73. package/dist/store/jsx/omitted-props.d.ts +10 -0
  74. package/dist/store/jsx/omitted-props.d.ts.map +1 -0
  75. package/dist/store/jsx/omitted-props.js +22 -0
  76. package/dist/store/jsx/omitted-props.js.map +1 -0
  77. package/dist/store/jsx/pipeline.d.ts +2 -0
  78. package/dist/store/jsx/pipeline.d.ts.map +1 -1
  79. package/dist/store/jsx/pipeline.js +2 -0
  80. package/dist/store/jsx/pipeline.js.map +1 -1
  81. package/dist/store/jsx/props.d.ts +1 -1
  82. package/dist/store/jsx/props.d.ts.map +1 -1
  83. package/dist/store/jsx/props.js +6 -11
  84. package/dist/store/jsx/props.js.map +1 -1
  85. package/package.json +3 -4
  86. package/src/analysis/descriptor-render.ts +35 -3
  87. package/src/analysis/ts-type.ts +4 -11
  88. package/src/docs/api-reference.ts +4 -9
  89. package/src/docs/element-page.ts +5 -9
  90. package/src/docs/pipeline.ts +3 -0
  91. package/src/fingerprint.ts +16 -2
  92. package/src/gi.ts +12 -3
  93. package/src/gir/libraries.ts +5 -4
  94. package/src/index.ts +1 -0
  95. package/src/jsx.ts +5 -0
  96. package/src/react/element-config.ts +8 -2
  97. package/src/runner.ts +8 -1
  98. package/src/store/gi/callables.ts +0 -6
  99. package/src/store/gi/function.ts +0 -2
  100. package/src/store/gi/method.ts +1 -0
  101. package/src/store/gi/record-constructor.ts +9 -4
  102. package/src/store/gi/record-field-accessor.ts +41 -6
  103. package/src/store/gi/record.ts +0 -9
  104. package/src/store/gi/value-marshalable.ts +96 -0
  105. package/src/store/jsx/intrinsic-elements.ts +0 -9
  106. package/src/store/jsx/omitted-props.ts +32 -0
  107. package/src/store/jsx/pipeline.ts +3 -0
  108. package/src/store/jsx/props.ts +6 -18
  109. package/dist/store/gi/class-struct-record.d.ts +0 -10
  110. package/dist/store/gi/class-struct-record.d.ts.map +0 -1
  111. package/dist/store/gi/class-struct-record.js +0 -52
  112. package/dist/store/gi/class-struct-record.js.map +0 -1
  113. package/src/store/gi/class-struct-record.ts +0 -72
@@ -0,0 +1,96 @@
1
+ import type { GirField } from "../../gir/field.js";
2
+ import type { PrimitiveCategory } from "../../gir/primitives.js";
3
+ import type { GirRecord } from "../../gir/record.js";
4
+ import type { TypeId } from "../../gir/type-id.js";
5
+ import type { GirType } from "../../gir/type.js";
6
+ import type { ModuleContext } from "../../writer/context.js";
7
+
8
+ type Scope = { context: ModuleContext; seen: Set<string> };
9
+
10
+ /** Primitive categories that are a pointer at the C level, so copying the bytes aliases the pointee. */
11
+ const POINTER_CATEGORIES: Set<PrimitiveCategory> = new Set<PrimitiveCategory>(["string", "pointer"]);
12
+
13
+ const recordKey = (namespaceName: string, record: GirRecord): string => `${namespaceName}.${record.name}`;
14
+
15
+ const hasOwnCopySemantics = (record: GirRecord): boolean =>
16
+ record.glibGetType !== undefined ||
17
+ ((record.glibRefFunc ?? record.copyFunc) !== undefined && (record.glibUnrefFunc ?? record.freeFunc) !== undefined);
18
+
19
+ const isValueSafeArray = (scope: Scope, type: Extract<GirType, { kind: "carray" }>): boolean =>
20
+ type.fixedSize !== undefined && isValueSafeRef(scope, type.element, type.elementCType);
21
+
22
+ const isValueSafeAlias = (scope: Scope, type: Extract<GirType, { kind: "alias" }>): boolean =>
23
+ isValueSafeRef(scope, type.value.target, type.value.targetCType);
24
+
25
+ function isValueSafeType(scope: Scope, type: GirType): boolean {
26
+ switch (type.kind) {
27
+ case "primitive": {
28
+ return !POINTER_CATEGORIES.has(type.category);
29
+ }
30
+ case "enum": {
31
+ return true;
32
+ }
33
+ case "record": {
34
+ return isValueSafeRecord(scope, type.namespace.name, type.value);
35
+ }
36
+ case "carray": {
37
+ return isValueSafeArray(scope, type);
38
+ }
39
+ case "alias": {
40
+ return isValueSafeAlias(scope, type);
41
+ }
42
+ case "callback":
43
+ case "class":
44
+ case "hashtable":
45
+ case "interface":
46
+ case "list":
47
+ case "varargs": {
48
+ return false;
49
+ }
50
+ }
51
+ }
52
+
53
+ function isValueSafeRef(scope: Scope, ref: TypeId | undefined, cType: string | undefined): boolean {
54
+ if (ref === undefined || cType?.endsWith("*") === true) {
55
+ return false;
56
+ }
57
+
58
+ const type = scope.context.library.typeFor(ref);
59
+
60
+ return type === undefined ? false : isValueSafeType(scope, type);
61
+ }
62
+
63
+ const isValueSafeField = (scope: Scope, field: GirField): boolean =>
64
+ field.inlineMembers === undefined
65
+ ? isValueSafeRef(scope, field.type, field.cType)
66
+ : field.inlineMembers.every((member) => isValueSafeField(scope, member));
67
+
68
+ function isValueSafeRecord(scope: Scope, namespaceName: string, record: GirRecord): boolean {
69
+ const key = recordKey(namespaceName, record);
70
+
71
+ if (scope.seen.has(key) || record.fields.length === 0) {
72
+ return false;
73
+ }
74
+
75
+ scope.seen.add(key);
76
+ const isSafe = record.fields.every((field) => isValueSafeField(scope, field));
77
+ scope.seen.delete(key);
78
+
79
+ return isSafe;
80
+ }
81
+
82
+ /**
83
+ * Whether a record can be copied by value. A plain struct is duplicated with a byte-wise `g_memdup2`,
84
+ * which shallow-copies whatever the bytes hold, so only a record whose every field is transitively a
85
+ * scalar can be owned, allocated or written into an inline slot. A pointer, a string, a function
86
+ * pointer or an opaque record makes it borrow-only. Records that carry their own copy/free pair are
87
+ * duplicated through that instead and never reach the byte-wise path.
88
+ */
89
+ const isValueMarshalable = (context: ModuleContext, namespaceName: string, record: GirRecord): boolean =>
90
+ isValueSafeRecord({ context, seen: new Set<string>() }, namespaceName, record);
91
+
92
+ /** Whether a record can be allocated and populated from JavaScript. */
93
+ const isConstructibleRecord = (context: ModuleContext, namespaceName: string, record: GirRecord): boolean =>
94
+ hasOwnCopySemantics(record) || isValueMarshalable(context, namespaceName, record);
95
+
96
+ export { hasOwnCopySemantics, isConstructibleRecord, isValueMarshalable };
@@ -214,14 +214,6 @@ const hasMatchingAncestorName = (
214
214
  isMatch: (glibName: string) => boolean,
215
215
  ): boolean => hasMatchingAncestor(klass, namespace, library, (_klass, glibName) => isMatch(glibName));
216
216
 
217
- const hasExposedMethod = (
218
- klass: GirClass,
219
- namespace: GirNamespace,
220
- library: Library,
221
- methodName: string,
222
- ): boolean =>
223
- hasMatchingAncestor(klass, namespace, library, (current) => current.methods.some((m) => m.name === methodName));
224
-
225
217
  const isIntrinsicElementClass = (klass: GirClass, namespace: GirNamespace, library: Library): boolean =>
226
218
  hasMatchingAncestorName(klass, namespace, library, (glibName) => glibName === "GObject");
227
219
 
@@ -253,7 +245,6 @@ export {
253
245
  newlyImplementedInterfaces,
254
246
  collectInterfacePropsClasses,
255
247
  ancestorGlibNames,
256
- hasExposedMethod,
257
248
  isIntrinsicElementClass,
258
249
  collectIntrinsicElementClasses,
259
250
  type GlibNamedClass,
@@ -0,0 +1,32 @@
1
+ /** Props left out of the generated element props, keyed by GLib type name. */
2
+ type OmittedProps = Record<string, string[]>;
3
+
4
+ const omittedProps: Map<string, Set<string>> = new Map();
5
+
6
+ /** Installs the props each element omits (GLib type name → prop names); set once per run. */
7
+ const setOmittedProps = (props: OmittedProps): void => {
8
+ omittedProps.clear();
9
+
10
+ for (const [glibName, names] of Object.entries(props)) {
11
+ omittedProps.set(glibName, new Set(names));
12
+ }
13
+ };
14
+
15
+ /** Whether the element config declares this prop omitted for the type that declares the property. */
16
+ const isOmittedProp = (glibName: string | undefined, jsName: string): boolean =>
17
+ glibName !== undefined && omittedProps.get(glibName)?.has(jsName) === true;
18
+
19
+ /** Merges omitted-prop maps keyed by GLib type name, concatenating the names each map contributes. */
20
+ const mergeOmitProps = (...maps: OmittedProps[]): OmittedProps => {
21
+ const merged: OmittedProps = {};
22
+
23
+ for (const map of maps) {
24
+ for (const [glibName, names] of Object.entries(map)) {
25
+ merged[glibName] = [...(merged[glibName] ?? []), ...names];
26
+ }
27
+ }
28
+
29
+ return merged;
30
+ };
31
+
32
+ export { setOmittedProps, isOmittedProp, mergeOmitProps, type OmittedProps };
@@ -9,6 +9,7 @@ import { buildGirIndex } from "./gir-index.js";
9
9
  import { collectIntrinsicElementClasses, type GlibNamedClass } from "./intrinsic-elements.js";
10
10
  import { generateJsxSection } from "./jsx.js";
11
11
  import { generateMetadata } from "./metadata.js";
12
+ import { type OmittedProps, setOmittedProps } from "./omitted-props.js";
12
13
 
13
14
  type JsxNamespaceFile = {
14
15
  directory: string;
@@ -25,6 +26,7 @@ type JsxGenerationOptions = {
25
26
  reactSubexports?: string[];
26
27
  components?: ElementComponentOverrides;
27
28
  props?: ElementProps;
29
+ omitProps?: OmittedProps;
28
30
  lazyElements?: string[];
29
31
  };
30
32
 
@@ -47,6 +49,7 @@ type JsxNamespaceContext = {
47
49
 
48
50
  const generateJsxFiles = (library: Library, options: JsxGenerationOptions = {}): JsxFiles => {
49
51
  setElementProps(options.props ?? {});
52
+ setOmittedProps(options.omitProps ?? {});
50
53
  const intrinsicElements = collectIntrinsicElementClasses(library);
51
54
  const intrinsicElementByGlibName = new Map(intrinsicElements.map((entry) => [entry.glibName, entry]));
52
55
  const girIndex = buildGirIndex(library);
@@ -9,12 +9,8 @@ import { renderHandlerParameters, renderHandlerResultType } from "../../analysis
9
9
  import { recordTypeTarget, renderBaseType, type TsTypeTarget } from "../../analysis/ts-type.js";
10
10
  import { type GirProperty, isConstructableProperty } from "../../gir/property.js";
11
11
  import { renderJsDoc } from "../../writer/doc.js";
12
- import {
13
- giNamespaceAlias,
14
- hasExposedMethod,
15
- isIntrinsicElementClass,
16
- signalHandlerName,
17
- } from "./intrinsic-elements.js";
12
+ import { getGlibName, giNamespaceAlias, isIntrinsicElementClass, signalHandlerName } from "./intrinsic-elements.js";
13
+ import { isOmittedProp } from "./omitted-props.js";
18
14
 
19
15
  type IntrinsicElementPropsEntries = {
20
16
  propLines: string[];
@@ -75,7 +71,7 @@ const appendPropertyLines = (state: PropCollectorState, property: GirProperty, j
75
71
  const tsType = renderReactPropType(state.types, property.type, false);
76
72
  const doc = renderJsDoc(property.doc);
77
73
 
78
- if (isObjectProp(state.owner, property, jsName)) {
74
+ if (isObjectProp(state.owner.library, property)) {
79
75
  state.propLines.push(`${doc}${jsName}?: ${tsType} | ReactElement | null | undefined;`);
80
76
  state.objectPropNames.push(jsName);
81
77
 
@@ -99,7 +95,7 @@ const acceptCollectorProperty = (state: PropCollectorState, property: GirPropert
99
95
 
100
96
  const jsName = toCamelIdentifier(property.name);
101
97
 
102
- if (state.seen.has(jsName)) {
98
+ if (state.seen.has(jsName) || isOmittedProp(getGlibName(state.owner.klass), jsName)) {
103
99
  return;
104
100
  }
105
101
 
@@ -215,20 +211,12 @@ const isGObjectType = (library: Library, ref: TypeId | undefined): boolean => {
215
211
  return isIntrinsicElementClass(resolved.value, resolved.namespace, library);
216
212
  };
217
213
 
218
- const isObjectProp = (owner: IntrinsicElementScope, property: GirProperty, jsName: string): boolean => {
214
+ const isObjectProp = (library: Library, property: GirProperty): boolean => {
219
215
  if (!property.writable || property.constructOnly) {
220
216
  return false;
221
217
  }
222
218
 
223
- if (!isGObjectType(owner.library, property.type)) {
224
- return false;
225
- }
226
-
227
- if (jsName === "child" && hasExposedMethod(owner.klass, owner.namespace, owner.library, "set_child")) {
228
- return false;
229
- }
230
-
231
- return true;
219
+ return isGObjectType(library, property.type);
232
220
  };
233
221
 
234
222
  const renderSignalHandler = (options: SignalRenderOptions): string => {
@@ -1,10 +0,0 @@
1
- import type { GirFunction } from "../../gir/function.js";
2
- import type { Library } from "../../gir/library.js";
3
- import type { GirRecord } from "../../gir/record.js";
4
- import type { TypeId } from "../../gir/type-id.js";
5
- import type { ModuleContext } from "../../writer/context.js";
6
- declare const isClassStructRecord: (library: Library, namespaceName: string, record: GirRecord) => boolean;
7
- declare const isClassStructRef: (context: ModuleContext, ref: TypeId | undefined) => boolean;
8
- declare const hasClassStructReference: (context: ModuleContext, fn: GirFunction) => boolean;
9
- export { isClassStructRecord, isClassStructRef, hasClassStructReference };
10
- //# sourceMappingURL=class-struct-record.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"class-struct-record.d.ts","sourceRoot":"","sources":["../../../src/store/gi/class-struct-record.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAO7D,QAAA,MAAM,mBAAmB,GAAI,SAAS,OAAO,EAAE,eAAe,MAAM,EAAE,QAAQ,SAAS,KAAG,OAsBzF,CAAC;AAEF,QAAA,MAAM,gBAAgB,GAAI,SAAS,aAAa,EAAE,KAAK,MAAM,GAAG,SAAS,KAAG,OA8B3E,CAAC;AAEF,QAAA,MAAM,uBAAuB,GAAI,SAAS,aAAa,EAAE,IAAI,WAAW,KAAG,OAEK,CAAC;AAEjF,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,CAAC"}
@@ -1,52 +0,0 @@
1
- const TYPE_STRUCT_ROOTS = new Set(["GObject.TypeClass", "GObject.TypeInterface"]);
2
- const EXPLICIT_CLASS_STRUCTS = new Set(["Pango.AttrClass"]);
3
- const qualify = (namespaceName, name) => `${namespaceName}.${name}`;
4
- const isClassStructRecord = (library, namespaceName, record) => {
5
- const qualified = qualify(namespaceName, record.name);
6
- if (TYPE_STRUCT_ROOTS.has(qualified) || EXPLICIT_CLASS_STRUCTS.has(qualified)) {
7
- return true;
8
- }
9
- const first = record.fields[0];
10
- // A class struct embeds its parent vtable by value (`GTypeClass g_type_class`); an instance
11
- // struct stores a pointer to it (`GTypeClass *g_class`). Only the first is a vtable.
12
- if (first?.type === undefined || first.cType?.endsWith("*") === true) {
13
- return false;
14
- }
15
- const name = library.nameFor(first.type);
16
- if (name === undefined) {
17
- return false;
18
- }
19
- return TYPE_STRUCT_ROOTS.has(qualify(name.namespaceName, name.typeName));
20
- };
21
- const isClassStructRef = (context, ref) => {
22
- if (ref === undefined) {
23
- return false;
24
- }
25
- const type = context.library.typeFor(ref);
26
- if (type === undefined) {
27
- return false;
28
- }
29
- switch (type.kind) {
30
- case "record": {
31
- return isClassStructRecord(context.library, type.namespace.name, type.value);
32
- }
33
- case "carray":
34
- case "list": {
35
- return isClassStructRef(context, type.element);
36
- }
37
- case "alias":
38
- case "callback":
39
- case "class":
40
- case "enum":
41
- case "hashtable":
42
- case "interface":
43
- case "primitive":
44
- case "varargs": {
45
- return false;
46
- }
47
- }
48
- };
49
- const hasClassStructReference = (context, fn) => isClassStructRef(context, fn.returnValue.type) ||
50
- fn.parameters.some((parameter) => isClassStructRef(context, parameter.type));
51
- export { isClassStructRecord, isClassStructRef, hasClassStructReference };
52
- //# sourceMappingURL=class-struct-record.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"class-struct-record.js","sourceRoot":"","sources":["../../../src/store/gi/class-struct-record.ts"],"names":[],"mappings":"AAMA,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,mBAAmB,EAAE,uBAAuB,CAAC,CAAC,CAAC;AAClF,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC;AAE5D,MAAM,OAAO,GAAG,CAAC,aAAqB,EAAE,IAAY,EAAU,EAAE,CAAC,GAAG,aAAa,IAAI,IAAI,EAAE,CAAC;AAE5F,MAAM,mBAAmB,GAAG,CAAC,OAAgB,EAAE,aAAqB,EAAE,MAAiB,EAAW,EAAE;IAChG,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAEtD,IAAI,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,sBAAsB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5E,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAE/B,4FAA4F;IAC5F,qFAAqF;IACrF,IAAI,KAAK,EAAE,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;QACnE,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEzC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,OAAO,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC7E,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,CAAC,OAAsB,EAAE,GAAuB,EAAW,EAAE;IAClF,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACpB,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAE1C,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAChB,KAAK,QAAQ,CAAC,CAAC,CAAC;YACZ,OAAO,mBAAmB,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACjF,CAAC;QACD,KAAK,QAAQ,CAAC;QACd,KAAK,MAAM,CAAC,CAAC,CAAC;YACV,OAAO,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACnD,CAAC;QACD,KAAK,OAAO,CAAC;QACb,KAAK,UAAU,CAAC;QAChB,KAAK,OAAO,CAAC;QACb,KAAK,MAAM,CAAC;QACZ,KAAK,WAAW,CAAC;QACjB,KAAK,WAAW,CAAC;QACjB,KAAK,WAAW,CAAC;QACjB,KAAK,SAAS,CAAC,CAAC,CAAC;YACb,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,uBAAuB,GAAG,CAAC,OAAsB,EAAE,EAAe,EAAW,EAAE,CACjF,gBAAgB,CAAC,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC;IAC9C,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;AAEjF,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,CAAC","sourcesContent":["import type { GirFunction } from \"../../gir/function.js\";\nimport type { Library } from \"../../gir/library.js\";\nimport type { GirRecord } from \"../../gir/record.js\";\nimport type { TypeId } from \"../../gir/type-id.js\";\nimport type { ModuleContext } from \"../../writer/context.js\";\n\nconst TYPE_STRUCT_ROOTS = new Set([\"GObject.TypeClass\", \"GObject.TypeInterface\"]);\nconst EXPLICIT_CLASS_STRUCTS = new Set([\"Pango.AttrClass\"]);\n\nconst qualify = (namespaceName: string, name: string): string => `${namespaceName}.${name}`;\n\nconst isClassStructRecord = (library: Library, namespaceName: string, record: GirRecord): boolean => {\n const qualified = qualify(namespaceName, record.name);\n\n if (TYPE_STRUCT_ROOTS.has(qualified) || EXPLICIT_CLASS_STRUCTS.has(qualified)) {\n return true;\n }\n\n const first = record.fields[0];\n\n // A class struct embeds its parent vtable by value (`GTypeClass g_type_class`); an instance\n // struct stores a pointer to it (`GTypeClass *g_class`). Only the first is a vtable.\n if (first?.type === undefined || first.cType?.endsWith(\"*\") === true) {\n return false;\n }\n\n const name = library.nameFor(first.type);\n\n if (name === undefined) {\n return false;\n }\n\n return TYPE_STRUCT_ROOTS.has(qualify(name.namespaceName, name.typeName));\n};\n\nconst isClassStructRef = (context: ModuleContext, ref: TypeId | undefined): boolean => {\n if (ref === undefined) {\n return false;\n }\n\n const type = context.library.typeFor(ref);\n\n if (type === undefined) {\n return false;\n }\n\n switch (type.kind) {\n case \"record\": {\n return isClassStructRecord(context.library, type.namespace.name, type.value);\n }\n case \"carray\":\n case \"list\": {\n return isClassStructRef(context, type.element);\n }\n case \"alias\":\n case \"callback\":\n case \"class\":\n case \"enum\":\n case \"hashtable\":\n case \"interface\":\n case \"primitive\":\n case \"varargs\": {\n return false;\n }\n }\n};\n\nconst hasClassStructReference = (context: ModuleContext, fn: GirFunction): boolean =>\n isClassStructRef(context, fn.returnValue.type) ||\n fn.parameters.some((parameter) => isClassStructRef(context, parameter.type));\n\nexport { isClassStructRecord, isClassStructRef, hasClassStructReference };\n"]}
@@ -1,72 +0,0 @@
1
- import type { GirFunction } from "../../gir/function.js";
2
- import type { Library } from "../../gir/library.js";
3
- import type { GirRecord } from "../../gir/record.js";
4
- import type { TypeId } from "../../gir/type-id.js";
5
- import type { ModuleContext } from "../../writer/context.js";
6
-
7
- const TYPE_STRUCT_ROOTS = new Set(["GObject.TypeClass", "GObject.TypeInterface"]);
8
- const EXPLICIT_CLASS_STRUCTS = new Set(["Pango.AttrClass"]);
9
-
10
- const qualify = (namespaceName: string, name: string): string => `${namespaceName}.${name}`;
11
-
12
- const isClassStructRecord = (library: Library, namespaceName: string, record: GirRecord): boolean => {
13
- const qualified = qualify(namespaceName, record.name);
14
-
15
- if (TYPE_STRUCT_ROOTS.has(qualified) || EXPLICIT_CLASS_STRUCTS.has(qualified)) {
16
- return true;
17
- }
18
-
19
- const first = record.fields[0];
20
-
21
- // A class struct embeds its parent vtable by value (`GTypeClass g_type_class`); an instance
22
- // struct stores a pointer to it (`GTypeClass *g_class`). Only the first is a vtable.
23
- if (first?.type === undefined || first.cType?.endsWith("*") === true) {
24
- return false;
25
- }
26
-
27
- const name = library.nameFor(first.type);
28
-
29
- if (name === undefined) {
30
- return false;
31
- }
32
-
33
- return TYPE_STRUCT_ROOTS.has(qualify(name.namespaceName, name.typeName));
34
- };
35
-
36
- const isClassStructRef = (context: ModuleContext, ref: TypeId | undefined): boolean => {
37
- if (ref === undefined) {
38
- return false;
39
- }
40
-
41
- const type = context.library.typeFor(ref);
42
-
43
- if (type === undefined) {
44
- return false;
45
- }
46
-
47
- switch (type.kind) {
48
- case "record": {
49
- return isClassStructRecord(context.library, type.namespace.name, type.value);
50
- }
51
- case "carray":
52
- case "list": {
53
- return isClassStructRef(context, type.element);
54
- }
55
- case "alias":
56
- case "callback":
57
- case "class":
58
- case "enum":
59
- case "hashtable":
60
- case "interface":
61
- case "primitive":
62
- case "varargs": {
63
- return false;
64
- }
65
- }
66
- };
67
-
68
- const hasClassStructReference = (context: ModuleContext, fn: GirFunction): boolean =>
69
- isClassStructRef(context, fn.returnValue.type) ||
70
- fn.parameters.some((parameter) => isClassStructRef(context, parameter.type));
71
-
72
- export { isClassStructRecord, isClassStructRef, hasClassStructReference };