@gtkx/codegen 0.21.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.
- package/LICENSE +373 -0
- package/dist/dsl/context.d.ts +104 -0
- package/dist/dsl/context.d.ts.map +1 -0
- package/dist/dsl/context.js +140 -0
- package/dist/dsl/context.js.map +1 -0
- package/dist/dsl/emit.d.ts +28 -0
- package/dist/dsl/emit.d.ts.map +1 -0
- package/dist/dsl/emit.js +41 -0
- package/dist/dsl/emit.js.map +1 -0
- package/dist/dsl/identifier.d.ts +28 -0
- package/dist/dsl/identifier.d.ts.map +1 -0
- package/dist/dsl/identifier.js +45 -0
- package/dist/dsl/identifier.js.map +1 -0
- package/dist/dsl/imports.d.ts +58 -0
- package/dist/dsl/imports.d.ts.map +1 -0
- package/dist/dsl/imports.js +107 -0
- package/dist/dsl/imports.js.map +1 -0
- package/dist/dsl/module.d.ts +53 -0
- package/dist/dsl/module.d.ts.map +1 -0
- package/dist/dsl/module.js +76 -0
- package/dist/dsl/module.js.map +1 -0
- package/dist/ffi/pipeline.d.ts +19 -0
- package/dist/ffi/pipeline.d.ts.map +1 -0
- package/dist/ffi/pipeline.js +107 -0
- package/dist/ffi/pipeline.js.map +1 -0
- package/dist/fingerprint.d.ts +30 -0
- package/dist/fingerprint.d.ts.map +1 -0
- package/dist/fingerprint.js +33 -0
- package/dist/fingerprint.js.map +1 -0
- package/dist/gi-store.d.ts +34 -0
- package/dist/gi-store.d.ts.map +1 -0
- package/dist/gi-store.js +154 -0
- package/dist/gi-store.js.map +1 -0
- package/dist/gir/boxed.d.ts +66 -0
- package/dist/gir/boxed.d.ts.map +1 -0
- package/dist/gir/boxed.js +49 -0
- package/dist/gir/boxed.js.map +1 -0
- package/dist/gir/callback.d.ts +15 -0
- package/dist/gir/callback.d.ts.map +1 -0
- package/dist/gir/callback.js +17 -0
- package/dist/gir/callback.js.map +1 -0
- package/dist/gir/class.d.ts +49 -0
- package/dist/gir/class.d.ts.map +1 -0
- package/dist/gir/class.js +42 -0
- package/dist/gir/class.js.map +1 -0
- package/dist/gir/enum.d.ts +39 -0
- package/dist/gir/enum.d.ts.map +1 -0
- package/dist/gir/enum.js +24 -0
- package/dist/gir/enum.js.map +1 -0
- package/dist/gir/field.d.ts +27 -0
- package/dist/gir/field.d.ts.map +1 -0
- package/dist/gir/field.js +19 -0
- package/dist/gir/field.js.map +1 -0
- package/dist/gir/function.d.ts +47 -0
- package/dist/gir/function.d.ts.map +1 -0
- package/dist/gir/function.js +28 -0
- package/dist/gir/function.js.map +1 -0
- package/dist/gir/namespace.d.ts +65 -0
- package/dist/gir/namespace.d.ts.map +1 -0
- package/dist/gir/namespace.js +60 -0
- package/dist/gir/namespace.js.map +1 -0
- package/dist/gir/parameter.d.ts +82 -0
- package/dist/gir/parameter.d.ts.map +1 -0
- package/dist/gir/parameter.js +66 -0
- package/dist/gir/parameter.js.map +1 -0
- package/dist/gir/parse.d.ts +78 -0
- package/dist/gir/parse.d.ts.map +1 -0
- package/dist/gir/parse.js +155 -0
- package/dist/gir/parse.js.map +1 -0
- package/dist/gir/primitives.d.ts +36 -0
- package/dist/gir/primitives.d.ts.map +1 -0
- package/dist/gir/primitives.js +109 -0
- package/dist/gir/primitives.js.map +1 -0
- package/dist/gir/property.d.ts +29 -0
- package/dist/gir/property.d.ts.map +1 -0
- package/dist/gir/property.js +16 -0
- package/dist/gir/property.js.map +1 -0
- package/dist/gir/qualified-name.d.ts +37 -0
- package/dist/gir/qualified-name.d.ts.map +1 -0
- package/dist/gir/qualified-name.js +39 -0
- package/dist/gir/qualified-name.js.map +1 -0
- package/dist/gir/qualify.d.ts +32 -0
- package/dist/gir/qualify.d.ts.map +1 -0
- package/dist/gir/qualify.js +60 -0
- package/dist/gir/qualify.js.map +1 -0
- package/dist/gir/repository.d.ts +82 -0
- package/dist/gir/repository.d.ts.map +1 -0
- package/dist/gir/repository.js +122 -0
- package/dist/gir/repository.js.map +1 -0
- package/dist/gir/signal.d.ts +22 -0
- package/dist/gir/signal.d.ts.map +1 -0
- package/dist/gir/signal.js +20 -0
- package/dist/gir/signal.js.map +1 -0
- package/dist/gir/size.d.ts +67 -0
- package/dist/gir/size.d.ts.map +1 -0
- package/dist/gir/size.js +87 -0
- package/dist/gir/size.js.map +1 -0
- package/dist/gir/type-ref.d.ts +79 -0
- package/dist/gir/type-ref.d.ts.map +1 -0
- package/dist/gir/type-ref.js +101 -0
- package/dist/gir/type-ref.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/jsx-store.d.ts +22 -0
- package/dist/jsx-store.d.ts.map +1 -0
- package/dist/jsx-store.js +40 -0
- package/dist/jsx-store.js.map +1 -0
- package/dist/react/compounds-meta.d.ts +18 -0
- package/dist/react/compounds-meta.d.ts.map +1 -0
- package/dist/react/compounds-meta.js +93 -0
- package/dist/react/compounds-meta.js.map +1 -0
- package/dist/react/compounds.d.ts +27 -0
- package/dist/react/compounds.d.ts.map +1 -0
- package/dist/react/compounds.js +164 -0
- package/dist/react/compounds.js.map +1 -0
- package/dist/react/internal.d.ts +14 -0
- package/dist/react/internal.d.ts.map +1 -0
- package/dist/react/internal.js +79 -0
- package/dist/react/internal.js.map +1 -0
- package/dist/react/jsx.d.ts +22 -0
- package/dist/react/jsx.d.ts.map +1 -0
- package/dist/react/jsx.js +134 -0
- package/dist/react/jsx.js.map +1 -0
- package/dist/react/pipeline.d.ts +13 -0
- package/dist/react/pipeline.d.ts.map +1 -0
- package/dist/react/pipeline.js +25 -0
- package/dist/react/pipeline.js.map +1 -0
- package/dist/react/props.d.ts +38 -0
- package/dist/react/props.d.ts.map +1 -0
- package/dist/react/props.js +231 -0
- package/dist/react/props.js.map +1 -0
- package/dist/react/slot-props.d.ts +10 -0
- package/dist/react/slot-props.d.ts.map +1 -0
- package/dist/react/slot-props.js +56 -0
- package/dist/react/slot-props.js.map +1 -0
- package/dist/react/widgets.d.ts +83 -0
- package/dist/react/widgets.d.ts.map +1 -0
- package/dist/react/widgets.js +152 -0
- package/dist/react/widgets.js.map +1 -0
- package/dist/runner.d.ts +55 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +60 -0
- package/dist/runner.js.map +1 -0
- package/dist/store-fs.d.ts +109 -0
- package/dist/store-fs.d.ts.map +1 -0
- package/dist/store-fs.js +98 -0
- package/dist/store-fs.js.map +1 -0
- package/dist/transpile.d.ts +32 -0
- package/dist/transpile.d.ts.map +1 -0
- package/dist/transpile.js +63 -0
- package/dist/transpile.js.map +1 -0
- package/dist/typecheck-store.d.ts +41 -0
- package/dist/typecheck-store.d.ts.map +1 -0
- package/dist/typecheck-store.js +102 -0
- package/dist/typecheck-store.js.map +1 -0
- package/dist/writers/alias.d.ts +13 -0
- package/dist/writers/alias.d.ts.map +1 -0
- package/dist/writers/alias.js +17 -0
- package/dist/writers/alias.js.map +1 -0
- package/dist/writers/async.d.ts +22 -0
- package/dist/writers/async.d.ts.map +1 -0
- package/dist/writers/async.js +48 -0
- package/dist/writers/async.js.map +1 -0
- package/dist/writers/boxed-constructor.d.ts +26 -0
- package/dist/writers/boxed-constructor.d.ts.map +1 -0
- package/dist/writers/boxed-constructor.js +85 -0
- package/dist/writers/boxed-constructor.js.map +1 -0
- package/dist/writers/boxed-field-accessor.d.ts +18 -0
- package/dist/writers/boxed-field-accessor.d.ts.map +1 -0
- package/dist/writers/boxed-field-accessor.js +260 -0
- package/dist/writers/boxed-field-accessor.js.map +1 -0
- package/dist/writers/boxed-layout.d.ts +27 -0
- package/dist/writers/boxed-layout.d.ts.map +1 -0
- package/dist/writers/boxed-layout.js +128 -0
- package/dist/writers/boxed-layout.js.map +1 -0
- package/dist/writers/boxed.d.ts +20 -0
- package/dist/writers/boxed.d.ts.map +1 -0
- package/dist/writers/boxed.js +71 -0
- package/dist/writers/boxed.js.map +1 -0
- package/dist/writers/callables.d.ts +124 -0
- package/dist/writers/callables.d.ts.map +1 -0
- package/dist/writers/callables.js +283 -0
- package/dist/writers/callables.js.map +1 -0
- package/dist/writers/callback.d.ts +16 -0
- package/dist/writers/callback.d.ts.map +1 -0
- package/dist/writers/callback.js +38 -0
- package/dist/writers/callback.js.map +1 -0
- package/dist/writers/class-struct-record.d.ts +31 -0
- package/dist/writers/class-struct-record.d.ts.map +1 -0
- package/dist/writers/class-struct-record.js +67 -0
- package/dist/writers/class-struct-record.js.map +1 -0
- package/dist/writers/class-struct.d.ts +22 -0
- package/dist/writers/class-struct.d.ts.map +1 -0
- package/dist/writers/class-struct.js +85 -0
- package/dist/writers/class-struct.js.map +1 -0
- package/dist/writers/class.d.ts +16 -0
- package/dist/writers/class.d.ts.map +1 -0
- package/dist/writers/class.js +307 -0
- package/dist/writers/class.js.map +1 -0
- package/dist/writers/constant.d.ts +15 -0
- package/dist/writers/constant.d.ts.map +1 -0
- package/dist/writers/constant.js +23 -0
- package/dist/writers/constant.js.map +1 -0
- package/dist/writers/constants.d.ts +15 -0
- package/dist/writers/constants.d.ts.map +1 -0
- package/dist/writers/constants.js +23 -0
- package/dist/writers/constants.js.map +1 -0
- package/dist/writers/constructor-props.d.ts +32 -0
- package/dist/writers/constructor-props.d.ts.map +1 -0
- package/dist/writers/constructor-props.js +110 -0
- package/dist/writers/constructor-props.js.map +1 -0
- package/dist/writers/enum.d.ts +21 -0
- package/dist/writers/enum.d.ts.map +1 -0
- package/dist/writers/enum.js +48 -0
- package/dist/writers/enum.js.map +1 -0
- package/dist/writers/function.d.ts +40 -0
- package/dist/writers/function.d.ts.map +1 -0
- package/dist/writers/function.js +127 -0
- package/dist/writers/function.js.map +1 -0
- package/dist/writers/gtype-binding.d.ts +19 -0
- package/dist/writers/gtype-binding.d.ts.map +1 -0
- package/dist/writers/gtype-binding.js +40 -0
- package/dist/writers/gtype-binding.js.map +1 -0
- package/dist/writers/inheritance.d.ts +48 -0
- package/dist/writers/inheritance.d.ts.map +1 -0
- package/dist/writers/inheritance.js +90 -0
- package/dist/writers/inheritance.js.map +1 -0
- package/dist/writers/interface.d.ts +16 -0
- package/dist/writers/interface.d.ts.map +1 -0
- package/dist/writers/interface.js +155 -0
- package/dist/writers/interface.js.map +1 -0
- package/dist/writers/method.d.ts +150 -0
- package/dist/writers/method.d.ts.map +1 -0
- package/dist/writers/method.js +510 -0
- package/dist/writers/method.js.map +1 -0
- package/dist/writers/param-classify.d.ts +93 -0
- package/dist/writers/param-classify.d.ts.map +1 -0
- package/dist/writers/param-classify.js +163 -0
- package/dist/writers/param-classify.js.map +1 -0
- package/dist/writers/property-accessor.d.ts +19 -0
- package/dist/writers/property-accessor.d.ts.map +1 -0
- package/dist/writers/property-accessor.js +117 -0
- package/dist/writers/property-accessor.js.map +1 -0
- package/dist/writers/registration.d.ts +27 -0
- package/dist/writers/registration.d.ts.map +1 -0
- package/dist/writers/registration.js +30 -0
- package/dist/writers/registration.js.map +1 -0
- package/dist/writers/return-wrap.d.ts +39 -0
- package/dist/writers/return-wrap.d.ts.map +1 -0
- package/dist/writers/return-wrap.js +152 -0
- package/dist/writers/return-wrap.js.map +1 -0
- package/dist/writers/runtime-override.d.ts +18 -0
- package/dist/writers/runtime-override.d.ts.map +1 -0
- package/dist/writers/runtime-override.js +44 -0
- package/dist/writers/runtime-override.js.map +1 -0
- package/dist/writers/signal.d.ts +21 -0
- package/dist/writers/signal.d.ts.map +1 -0
- package/dist/writers/signal.js +260 -0
- package/dist/writers/signal.js.map +1 -0
- package/dist/writers/ts-type.d.ts +50 -0
- package/dist/writers/ts-type.d.ts.map +1 -0
- package/dist/writers/ts-type.js +75 -0
- package/dist/writers/ts-type.js.map +1 -0
- package/dist/writers/types-ts.d.ts +27 -0
- package/dist/writers/types-ts.d.ts.map +1 -0
- package/dist/writers/types-ts.js +97 -0
- package/dist/writers/types-ts.js.map +1 -0
- package/dist/writers/value.d.ts +89 -0
- package/dist/writers/value.d.ts.map +1 -0
- package/dist/writers/value.js +402 -0
- package/dist/writers/value.js.map +1 -0
- package/package.json +55 -0
- package/src/dsl/context.ts +146 -0
- package/src/dsl/emit.ts +42 -0
- package/src/dsl/identifier.ts +52 -0
- package/src/dsl/imports.ts +109 -0
- package/src/dsl/module.ts +75 -0
- package/src/ffi/pipeline.ts +113 -0
- package/src/fingerprint.ts +50 -0
- package/src/gi-store.ts +199 -0
- package/src/gir/boxed.ts +94 -0
- package/src/gir/callback.ts +26 -0
- package/src/gir/class.ts +79 -0
- package/src/gir/enum.ts +55 -0
- package/src/gir/field.ts +40 -0
- package/src/gir/function.ts +67 -0
- package/src/gir/namespace.ts +118 -0
- package/src/gir/parameter.ts +120 -0
- package/src/gir/parse.ts +171 -0
- package/src/gir/primitives.ts +137 -0
- package/src/gir/property.ts +39 -0
- package/src/gir/qualified-name.ts +55 -0
- package/src/gir/qualify.ts +64 -0
- package/src/gir/repository.ts +149 -0
- package/src/gir/signal.ts +36 -0
- package/src/gir/size.ts +129 -0
- package/src/gir/type-ref.ts +180 -0
- package/src/index.ts +16 -0
- package/src/jsx-store.ts +53 -0
- package/src/react/compounds-meta.ts +99 -0
- package/src/react/compounds.ts +204 -0
- package/src/react/internal.ts +91 -0
- package/src/react/jsx.ts +155 -0
- package/src/react/pipeline.ts +29 -0
- package/src/react/props.ts +307 -0
- package/src/react/slot-props.ts +57 -0
- package/src/react/widgets.ts +185 -0
- package/src/runner.ts +89 -0
- package/src/store-fs.ts +157 -0
- package/src/transpile.ts +80 -0
- package/src/typecheck-store.ts +136 -0
- package/src/writers/alias.ts +19 -0
- package/src/writers/async.ts +44 -0
- package/src/writers/boxed-constructor.ts +105 -0
- package/src/writers/boxed-field-accessor.ts +306 -0
- package/src/writers/boxed-layout.ts +166 -0
- package/src/writers/boxed.ts +77 -0
- package/src/writers/callables.ts +339 -0
- package/src/writers/callback.ts +40 -0
- package/src/writers/class-struct-record.ts +75 -0
- package/src/writers/class-struct.ts +96 -0
- package/src/writers/class.ts +384 -0
- package/src/writers/constant.ts +29 -0
- package/src/writers/constructor-props.ts +130 -0
- package/src/writers/enum.ts +53 -0
- package/src/writers/function.ts +136 -0
- package/src/writers/gtype-binding.ts +48 -0
- package/src/writers/inheritance.ts +104 -0
- package/src/writers/interface.ts +168 -0
- package/src/writers/method.ts +678 -0
- package/src/writers/param-classify.ts +178 -0
- package/src/writers/property-accessor.ts +139 -0
- package/src/writers/registration.ts +42 -0
- package/src/writers/return-wrap.ts +180 -0
- package/src/writers/runtime-override.ts +59 -0
- package/src/writers/signal.ts +318 -0
- package/src/writers/ts-type.ts +115 -0
- package/src/writers/value.ts +485 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { toCamelCase, toIdentifier } from "@gtkx/utils";
|
|
2
|
+
import type { ModuleContext } from "../dsl/context.js";
|
|
3
|
+
import { indent } from "../dsl/emit.js";
|
|
4
|
+
import type { GirField } from "../gir/field.js";
|
|
5
|
+
import type { FieldSlot } from "../gir/size.js";
|
|
6
|
+
import type { GirTypeRef } from "../gir/type-ref.js";
|
|
7
|
+
import { type BoxedFieldSlot, computeBoxedFieldSlots } from "./boxed-layout.js";
|
|
8
|
+
import { typeRefIsClassStruct } from "./class-struct-record.js";
|
|
9
|
+
import { wrapReturnValue } from "./return-wrap.js";
|
|
10
|
+
import { renderTsType } from "./ts-type.js";
|
|
11
|
+
import { renderFfiType } from "./value.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Renders the `get` / `set` accessor pair for a single boxed field.
|
|
15
|
+
*
|
|
16
|
+
* The accessor reads through the runtime's `read(handle, ffiType, offset)`
|
|
17
|
+
* (or `write` for the setter), with bitfield members threading through a
|
|
18
|
+
* read-modify-write sequence into their shared storage word. Fields whose
|
|
19
|
+
* type cannot be marshaled at present (callbacks, varargs, inline arrays
|
|
20
|
+
* of complex types) are skipped silently.
|
|
21
|
+
*
|
|
22
|
+
* @param context - The module context
|
|
23
|
+
* @param slot - The field plus its layout slot
|
|
24
|
+
* @param claimedNames - Names already used by emitted methods
|
|
25
|
+
*/
|
|
26
|
+
export const renderBoxedFieldAccessor = (
|
|
27
|
+
context: ModuleContext,
|
|
28
|
+
slot: BoxedFieldSlot,
|
|
29
|
+
claimedNames: ReadonlySet<string>,
|
|
30
|
+
siblingFields: readonly GirField[],
|
|
31
|
+
): string | undefined => {
|
|
32
|
+
const { field } = slot;
|
|
33
|
+
if (field.private) return undefined;
|
|
34
|
+
if (!field.readable && !field.writable) return undefined;
|
|
35
|
+
if (field.callback !== undefined) return undefined;
|
|
36
|
+
if (field.type === undefined) return undefined;
|
|
37
|
+
if (typeRefIsClassStruct(context, field.type)) return undefined;
|
|
38
|
+
const jsName = toIdentifier(toCamelCase(field.name));
|
|
39
|
+
if (claimedNames.has(jsName)) return undefined;
|
|
40
|
+
if (jsName === "constructor") return undefined;
|
|
41
|
+
|
|
42
|
+
const structArray = renderStructArrayAccessor(context, { field, jsName, slot: slot.slot, siblingFields });
|
|
43
|
+
if (structArray !== undefined) return structArray;
|
|
44
|
+
|
|
45
|
+
if (!isAccessorEligibleType(field.type)) {
|
|
46
|
+
const tsType = renderTsType(context, field.type, false);
|
|
47
|
+
const modifier = field.writable ? "declare" : "declare readonly";
|
|
48
|
+
return `${modifier} ${jsName}: ${tsType};`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const ffiType = renderFfiType(context, field.type, "none");
|
|
52
|
+
const tsType = renderTsType(context, field.type, false);
|
|
53
|
+
const accessorOptions: AccessorOptions = {
|
|
54
|
+
context,
|
|
55
|
+
jsName,
|
|
56
|
+
tsType,
|
|
57
|
+
ffiType,
|
|
58
|
+
slot: slot.slot,
|
|
59
|
+
fieldType: field.type,
|
|
60
|
+
};
|
|
61
|
+
const blocks: string[] = [getterBlock(accessorOptions)];
|
|
62
|
+
if (field.writable) {
|
|
63
|
+
blocks.push(setterBlock(accessorOptions));
|
|
64
|
+
}
|
|
65
|
+
return blocks.join("\n\n");
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const isAccessorEligibleType = (ref: GirTypeRef): boolean => {
|
|
69
|
+
switch (ref.kind) {
|
|
70
|
+
case "primitive":
|
|
71
|
+
return ref.category !== "void" && ref.category !== "unichar";
|
|
72
|
+
case "named":
|
|
73
|
+
return true;
|
|
74
|
+
case "array":
|
|
75
|
+
return ref.fixedSize !== undefined;
|
|
76
|
+
case "list":
|
|
77
|
+
case "hashtable":
|
|
78
|
+
return false;
|
|
79
|
+
case "callback":
|
|
80
|
+
case "varargs":
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const resolveInlineStructFields = (
|
|
86
|
+
context: ModuleContext,
|
|
87
|
+
ref: GirTypeRef | undefined,
|
|
88
|
+
): readonly GirField[] | undefined => {
|
|
89
|
+
if (ref === undefined || ref.kind !== "named") return undefined;
|
|
90
|
+
if (ref.cType?.endsWith("*") === true) return undefined;
|
|
91
|
+
const resolved = context.repository.resolveNamed(ref.namespaceName ?? context.namespace.name, ref.typeName);
|
|
92
|
+
if (resolved === undefined || resolved.kind !== "boxed") return undefined;
|
|
93
|
+
if (resolved.value.cType?.endsWith("*") === true) return undefined;
|
|
94
|
+
if (resolved.value.fields.length === 0) return undefined;
|
|
95
|
+
return resolved.value.fields;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const arrayLengthExpression = (
|
|
99
|
+
arrayRef: Extract<GirTypeRef, { kind: "array" }>,
|
|
100
|
+
siblingFields: readonly GirField[],
|
|
101
|
+
): string | undefined => {
|
|
102
|
+
if (arrayRef.fixedSize !== undefined) return String(arrayRef.fixedSize);
|
|
103
|
+
if (arrayRef.lengthParameterIndex === undefined) return undefined;
|
|
104
|
+
const lengthField = siblingFields.filter((field) => !field.private)[arrayRef.lengthParameterIndex];
|
|
105
|
+
if (lengthField === undefined) return undefined;
|
|
106
|
+
return `this.${toIdentifier(toCamelCase(lengthField.name))}`;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const renderElementReadObject = (context: ModuleContext, fields: readonly GirField[], baseOffset: number): string => {
|
|
110
|
+
const { slots } = computeBoxedFieldSlots(context, fields);
|
|
111
|
+
const entries: string[] = [];
|
|
112
|
+
for (const { field, slot } of slots) {
|
|
113
|
+
if (field.private || field.type === undefined || field.callback !== undefined) continue;
|
|
114
|
+
const jsName = toIdentifier(toCamelCase(field.name));
|
|
115
|
+
const offset = baseOffset + slot.byteOffset;
|
|
116
|
+
const nested = resolveInlineStructFields(context, field.type);
|
|
117
|
+
if (nested !== undefined) {
|
|
118
|
+
entries.push(`${jsName}: ${renderElementReadObject(context, nested, offset)}`);
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (!isAccessorEligibleType(field.type)) continue;
|
|
122
|
+
const ffi = renderFfiType(context, field.type, "none");
|
|
123
|
+
if (slot.bitWidth === undefined) {
|
|
124
|
+
entries.push(
|
|
125
|
+
`${jsName}: read(__array, ${ffi}, __base + ${offset}) as ${renderTsType(context, field.type, false)}`,
|
|
126
|
+
);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
const shift = slot.bitOffset ?? 0;
|
|
130
|
+
entries.push(
|
|
131
|
+
`${jsName}: (((read(__array, ${ffi}, __base + ${offset}) as number) >>> ${shift}) & ${bitMask(slot.bitWidth)})`,
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
return `{ ${entries.join(", ")} }`;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
type ElementWriteOptions = {
|
|
138
|
+
readonly fields: readonly GirField[];
|
|
139
|
+
readonly baseOffset: number;
|
|
140
|
+
readonly valuePath: string;
|
|
141
|
+
readonly out: string[];
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const appendElementWriteStatements = (context: ModuleContext, options: ElementWriteOptions): void => {
|
|
145
|
+
const { fields, baseOffset, valuePath, out } = options;
|
|
146
|
+
const { slots } = computeBoxedFieldSlots(context, fields);
|
|
147
|
+
for (const { field, slot } of slots) {
|
|
148
|
+
if (field.private || field.type === undefined || field.callback !== undefined) continue;
|
|
149
|
+
const valueExpr = `${valuePath}.${toIdentifier(toCamelCase(field.name))}`;
|
|
150
|
+
const offset = baseOffset + slot.byteOffset;
|
|
151
|
+
const nested = resolveInlineStructFields(context, field.type);
|
|
152
|
+
if (nested !== undefined) {
|
|
153
|
+
appendElementWriteStatements(context, { fields: nested, baseOffset: offset, valuePath: valueExpr, out });
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
if (!isAccessorEligibleType(field.type)) continue;
|
|
157
|
+
const ffi = renderFfiType(context, field.type, "none");
|
|
158
|
+
if (slot.bitWidth === undefined) {
|
|
159
|
+
out.push(`write(__array, ${ffi}, __base + ${offset}, ${valueExpr});`);
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
const mask = bitMask(slot.bitWidth);
|
|
163
|
+
const shift = slot.bitOffset ?? 0;
|
|
164
|
+
out.push(
|
|
165
|
+
`write(__array, ${ffi}, __base + ${offset}, ((read(__array, ${ffi}, __base + ${offset}) & ~(${mask} << ${shift})) | ((Number(${valueExpr}) & ${mask}) << ${shift})) >>> 0);`,
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
type StructArrayTarget = {
|
|
171
|
+
readonly field: GirField;
|
|
172
|
+
readonly jsName: string;
|
|
173
|
+
readonly slot: FieldSlot;
|
|
174
|
+
readonly siblingFields: readonly GirField[];
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
type StructArrayAccessorOptions = {
|
|
178
|
+
readonly context: ModuleContext;
|
|
179
|
+
readonly jsName: string;
|
|
180
|
+
readonly tsType: string;
|
|
181
|
+
readonly bufferType: string;
|
|
182
|
+
readonly offset: number;
|
|
183
|
+
readonly lengthExpr: string;
|
|
184
|
+
readonly elementSize: number;
|
|
185
|
+
readonly elementFields: readonly GirField[];
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const structArrayGetterBlock = (options: StructArrayAccessorOptions): string => {
|
|
189
|
+
const { context, jsName, tsType, bufferType, offset, lengthExpr, elementSize, elementFields } = options;
|
|
190
|
+
const element = renderElementReadObject(context, elementFields, 0);
|
|
191
|
+
const loop = [`const __base = __index * ${elementSize};`, `__result.push(${element});`].join("\n");
|
|
192
|
+
const body = [
|
|
193
|
+
`const __array = read(getHandle(this), ${bufferType}, ${offset});`,
|
|
194
|
+
`const __result: ${tsType} = [];`,
|
|
195
|
+
`for (let __index = 0; __index < ${lengthExpr}; __index++) {`,
|
|
196
|
+
indent(loop, 1),
|
|
197
|
+
"}",
|
|
198
|
+
"return __result;",
|
|
199
|
+
].join("\n");
|
|
200
|
+
return `get ${jsName}(): ${tsType} {\n${indent(body, 1)}\n}`;
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
const structArraySetterBlock = (options: StructArrayAccessorOptions): string => {
|
|
204
|
+
const { context, jsName, tsType, bufferType, offset, elementSize, elementFields } = options;
|
|
205
|
+
const writes: string[] = [];
|
|
206
|
+
appendElementWriteStatements(context, {
|
|
207
|
+
fields: elementFields,
|
|
208
|
+
baseOffset: 0,
|
|
209
|
+
valuePath: "__element",
|
|
210
|
+
out: writes,
|
|
211
|
+
});
|
|
212
|
+
const loop = [`const __element = __value[__index];`, `const __base = __index * ${elementSize};`, ...writes].join(
|
|
213
|
+
"\n",
|
|
214
|
+
);
|
|
215
|
+
const body = [
|
|
216
|
+
`const __array = read(getHandle(this), ${bufferType}, ${offset});`,
|
|
217
|
+
`for (let __index = 0; __index < __value.length; __index++) {`,
|
|
218
|
+
indent(loop, 1),
|
|
219
|
+
"}",
|
|
220
|
+
`write(getHandle(this), ${bufferType}, ${offset}, __array);`,
|
|
221
|
+
].join("\n");
|
|
222
|
+
return `set ${jsName}(__value: ${tsType}) {\n${indent(body, 1)}\n}`;
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
const renderStructArrayAccessor = (context: ModuleContext, target: StructArrayTarget): string | undefined => {
|
|
226
|
+
const { field, jsName, slot, siblingFields } = target;
|
|
227
|
+
const arrayRef = field.type;
|
|
228
|
+
if (arrayRef === undefined || arrayRef.kind !== "array" || slot.bitWidth !== undefined) return undefined;
|
|
229
|
+
const elementFields = resolveInlineStructFields(context, arrayRef.element);
|
|
230
|
+
if (elementFields === undefined) return undefined;
|
|
231
|
+
const lengthExpr = arrayLengthExpression(arrayRef, siblingFields);
|
|
232
|
+
if (lengthExpr === undefined) return undefined;
|
|
233
|
+
const elementSize = computeBoxedFieldSlots(context, elementFields).size;
|
|
234
|
+
if (elementSize === 0) return undefined;
|
|
235
|
+
|
|
236
|
+
context.addNativeImport("read");
|
|
237
|
+
context.addRuntimeImport("getHandle");
|
|
238
|
+
context.addRuntimeImport("t");
|
|
239
|
+
const options: StructArrayAccessorOptions = {
|
|
240
|
+
context,
|
|
241
|
+
jsName,
|
|
242
|
+
tsType: renderTsType(context, arrayRef, false),
|
|
243
|
+
bufferType: `t.struct("borrowed", ${lengthExpr} * ${elementSize})`,
|
|
244
|
+
offset: slot.byteOffset,
|
|
245
|
+
lengthExpr,
|
|
246
|
+
elementSize,
|
|
247
|
+
elementFields,
|
|
248
|
+
};
|
|
249
|
+
const blocks: string[] = [];
|
|
250
|
+
if (field.readable) blocks.push(structArrayGetterBlock(options));
|
|
251
|
+
if (field.writable) {
|
|
252
|
+
context.addNativeImport("write");
|
|
253
|
+
blocks.push(structArraySetterBlock(options));
|
|
254
|
+
}
|
|
255
|
+
return blocks.length === 0 ? undefined : blocks.join("\n\n");
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
type AccessorOptions = {
|
|
259
|
+
readonly context: ModuleContext;
|
|
260
|
+
readonly jsName: string;
|
|
261
|
+
readonly tsType: string;
|
|
262
|
+
readonly ffiType: string;
|
|
263
|
+
readonly slot: FieldSlot;
|
|
264
|
+
readonly fieldType: GirTypeRef;
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
const getterBlock = (options: AccessorOptions): string => {
|
|
268
|
+
const { context, jsName, tsType, ffiType, slot, fieldType } = options;
|
|
269
|
+
context.addNativeImport("read");
|
|
270
|
+
context.addRuntimeImport("getHandle");
|
|
271
|
+
if (slot.bitWidth === undefined) {
|
|
272
|
+
const valueExpression = `read(getHandle(this), ${ffiType}, ${slot.byteOffset})`;
|
|
273
|
+
const wrapped = wrapReturnValue(context, {
|
|
274
|
+
ref: fieldType,
|
|
275
|
+
transfer: "none",
|
|
276
|
+
nullable: false,
|
|
277
|
+
valueExpression,
|
|
278
|
+
});
|
|
279
|
+
const body = `return ${wrapped};`;
|
|
280
|
+
return `get ${jsName}(): ${tsType} {\n${indent(body, 1)}\n}`;
|
|
281
|
+
}
|
|
282
|
+
const mask = bitMask(slot.bitWidth);
|
|
283
|
+
const shift = slot.bitOffset ?? 0;
|
|
284
|
+
const body = `const __unit = read(getHandle(this), ${ffiType}, ${slot.byteOffset}) as number;\nreturn (((__unit >>> ${shift}) & ${mask}) >>> 0) as ${tsType};`;
|
|
285
|
+
return `get ${jsName}(): ${tsType} {\n${indent(body, 1)}\n}`;
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
const setterBlock = (options: AccessorOptions): string => {
|
|
289
|
+
const { context, jsName, tsType, ffiType, slot } = options;
|
|
290
|
+
context.addNativeImport("write");
|
|
291
|
+
context.addRuntimeImport("getHandle");
|
|
292
|
+
if (slot.bitWidth === undefined) {
|
|
293
|
+
const body = `write(getHandle(this), ${ffiType}, ${slot.byteOffset}, value);`;
|
|
294
|
+
return `set ${jsName}(value: ${tsType}) {\n${indent(body, 1)}\n}`;
|
|
295
|
+
}
|
|
296
|
+
context.addNativeImport("read");
|
|
297
|
+
const mask = bitMask(slot.bitWidth);
|
|
298
|
+
const shift = slot.bitOffset ?? 0;
|
|
299
|
+
const body = `const __unit = read(getHandle(this), ${ffiType}, ${slot.byteOffset}) as number;\nconst __next = ((__unit & ~(${mask} << ${shift})) | ((Number(value) & ${mask}) << ${shift})) >>> 0;\nwrite(getHandle(this), ${ffiType}, ${slot.byteOffset}, __next);`;
|
|
300
|
+
return `set ${jsName}(value: ${tsType}) {\n${indent(body, 1)}\n}`;
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
const bitMask = (width: number): number => {
|
|
304
|
+
if (width >= 32) return 0xffffffff;
|
|
305
|
+
return (1 << width) - 1;
|
|
306
|
+
};
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import type { ModuleContext } from "../dsl/context.js";
|
|
2
|
+
import type { GirField } from "../gir/field.js";
|
|
3
|
+
import { primitiveCategory } from "../gir/primitives.js";
|
|
4
|
+
import type { ResolvedNamed } from "../gir/repository.js";
|
|
5
|
+
import {
|
|
6
|
+
computeFieldSlots,
|
|
7
|
+
type FieldLayout,
|
|
8
|
+
type FieldLayoutInput,
|
|
9
|
+
type FieldSlot,
|
|
10
|
+
layoutOfPrimitive,
|
|
11
|
+
} from "../gir/size.js";
|
|
12
|
+
import type { GirTypeRef, NamedTypeRef } from "../gir/type-ref.js";
|
|
13
|
+
|
|
14
|
+
const POINTER_LAYOUT: FieldLayout = { size: 8, align: 8 };
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Computed slot for a single boxed field, ready for accessor emission.
|
|
18
|
+
*/
|
|
19
|
+
export type BoxedFieldSlot = {
|
|
20
|
+
readonly field: GirField;
|
|
21
|
+
readonly slot: FieldSlot;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Computes per-field storage slots for a boxed record.
|
|
26
|
+
*
|
|
27
|
+
* Walks every field (private fields included so their storage occupies
|
|
28
|
+
* space) and resolves each to a primitive-size {@link FieldLayoutInput}.
|
|
29
|
+
* Private fields are returned with their slots so callers can filter on
|
|
30
|
+
* `field.private` while still seeing the layout-correct offsets of public
|
|
31
|
+
* fields after them.
|
|
32
|
+
*
|
|
33
|
+
* @param context - The module context
|
|
34
|
+
* @param fields - The boxed's field list in declaration order
|
|
35
|
+
*/
|
|
36
|
+
export const computeBoxedFieldSlots = (
|
|
37
|
+
context: ModuleContext,
|
|
38
|
+
fields: readonly GirField[],
|
|
39
|
+
isUnion = false,
|
|
40
|
+
): { readonly slots: readonly BoxedFieldSlot[]; readonly size: number } => {
|
|
41
|
+
const inputs: FieldLayoutInput[] = [];
|
|
42
|
+
for (const field of fields) {
|
|
43
|
+
inputs.push(fieldLayoutInput(context, field, new Set()));
|
|
44
|
+
}
|
|
45
|
+
const result = computeFieldSlots(inputs, isUnion);
|
|
46
|
+
const slots = result.slots.map((slot, index) => {
|
|
47
|
+
const field = fields[index];
|
|
48
|
+
if (field === undefined) {
|
|
49
|
+
throw new Error("computeBoxedFieldSlots: parallel arrays diverged");
|
|
50
|
+
}
|
|
51
|
+
return { field, slot };
|
|
52
|
+
});
|
|
53
|
+
return { slots, size: result.size };
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const fieldLayoutInput = (context: ModuleContext, field: GirField, visited: ReadonlySet<string>): FieldLayoutInput => {
|
|
57
|
+
if (field.callback !== undefined) {
|
|
58
|
+
return { layout: POINTER_LAYOUT, bits: undefined };
|
|
59
|
+
}
|
|
60
|
+
if (field.type === undefined) {
|
|
61
|
+
return { layout: POINTER_LAYOUT, bits: undefined };
|
|
62
|
+
}
|
|
63
|
+
return { layout: layoutOfType(context, field.type, visited), bits: field.bits };
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const layoutOfType = (context: ModuleContext, ref: GirTypeRef, visited: ReadonlySet<string>): FieldLayout => {
|
|
67
|
+
switch (ref.kind) {
|
|
68
|
+
case "primitive":
|
|
69
|
+
return layoutOfPrimitive(ref.category);
|
|
70
|
+
case "named":
|
|
71
|
+
return layoutOfNamed(context, ref, visited);
|
|
72
|
+
case "array":
|
|
73
|
+
return arrayLayout(context, ref, visited);
|
|
74
|
+
case "list":
|
|
75
|
+
case "hashtable":
|
|
76
|
+
case "callback":
|
|
77
|
+
case "varargs":
|
|
78
|
+
return POINTER_LAYOUT;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const arrayLayout = (
|
|
83
|
+
context: ModuleContext,
|
|
84
|
+
ref: Extract<GirTypeRef, { kind: "array" }>,
|
|
85
|
+
visited: ReadonlySet<string>,
|
|
86
|
+
): FieldLayout => {
|
|
87
|
+
if (ref.fixedSize === undefined) return POINTER_LAYOUT;
|
|
88
|
+
const elementLayout = layoutOfType(context, ref.element, visited);
|
|
89
|
+
return { size: elementLayout.size * ref.fixedSize, align: elementLayout.align };
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const layoutOfNamed = (context: ModuleContext, ref: NamedTypeRef, visited: ReadonlySet<string>): FieldLayout => {
|
|
93
|
+
if (ref.cType?.endsWith("*") === true) return POINTER_LAYOUT;
|
|
94
|
+
const namespaceName = ref.namespaceName ?? context.namespace.name;
|
|
95
|
+
const resolved = context.repository.resolveNamed(namespaceName, ref.typeName);
|
|
96
|
+
if (resolved === undefined) return POINTER_LAYOUT;
|
|
97
|
+
return layoutOfResolved(context, resolved, visited);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const layoutOfResolved = (
|
|
101
|
+
context: ModuleContext,
|
|
102
|
+
resolved: ResolvedNamed,
|
|
103
|
+
visited: ReadonlySet<string>,
|
|
104
|
+
): FieldLayout => {
|
|
105
|
+
switch (resolved.kind) {
|
|
106
|
+
case "class":
|
|
107
|
+
case "interface":
|
|
108
|
+
return POINTER_LAYOUT;
|
|
109
|
+
case "boxed":
|
|
110
|
+
return layoutOfBoxedRecord(context, resolved, visited);
|
|
111
|
+
case "enum":
|
|
112
|
+
return layoutOfPrimitive("int32");
|
|
113
|
+
case "callback":
|
|
114
|
+
return POINTER_LAYOUT;
|
|
115
|
+
case "alias":
|
|
116
|
+
return resolveAliasLayout(context, resolved, visited);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const layoutOfBoxedRecord = (
|
|
121
|
+
context: ModuleContext,
|
|
122
|
+
resolved: Extract<ResolvedNamed, { kind: "boxed" }>,
|
|
123
|
+
visited: ReadonlySet<string>,
|
|
124
|
+
): FieldLayout => {
|
|
125
|
+
if (resolved.value.cType?.endsWith("*") === true) return POINTER_LAYOUT;
|
|
126
|
+
const key = `${resolved.namespace.name}.${resolved.value.name}`;
|
|
127
|
+
if (visited.has(key)) return POINTER_LAYOUT;
|
|
128
|
+
const cached = recordLayoutCache.get(key);
|
|
129
|
+
if (cached !== undefined) return cached;
|
|
130
|
+
const nextVisited = new Set(visited);
|
|
131
|
+
nextVisited.add(key);
|
|
132
|
+
const inputs: FieldLayoutInput[] = [];
|
|
133
|
+
for (const field of resolved.value.fields) {
|
|
134
|
+
if (field.callback !== undefined) {
|
|
135
|
+
inputs.push({ layout: POINTER_LAYOUT, bits: undefined });
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (field.type === undefined) {
|
|
139
|
+
inputs.push({ layout: POINTER_LAYOUT, bits: undefined });
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
inputs.push({ layout: layoutOfType(context, field.type, nextVisited), bits: field.bits });
|
|
143
|
+
}
|
|
144
|
+
if (inputs.length === 0) return POINTER_LAYOUT;
|
|
145
|
+
const { size } = computeFieldSlots(inputs, resolved.value.isUnion);
|
|
146
|
+
const align = Math.max(1, ...inputs.map((input) => input.layout.align));
|
|
147
|
+
const layout: FieldLayout = { size, align };
|
|
148
|
+
recordLayoutCache.set(key, layout);
|
|
149
|
+
return layout;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const recordLayoutCache = new Map<string, FieldLayout>();
|
|
153
|
+
|
|
154
|
+
const resolveAliasLayout = (
|
|
155
|
+
context: ModuleContext,
|
|
156
|
+
resolved: Extract<ResolvedNamed, { kind: "alias" }>,
|
|
157
|
+
visited: ReadonlySet<string>,
|
|
158
|
+
): FieldLayout => {
|
|
159
|
+
const ref = resolved.targetRef;
|
|
160
|
+
if (ref === undefined) return POINTER_LAYOUT;
|
|
161
|
+
if (ref.kind === "named") {
|
|
162
|
+
const primitive = primitiveCategory(ref.typeName);
|
|
163
|
+
if (primitive !== undefined) return layoutOfPrimitive(primitive);
|
|
164
|
+
}
|
|
165
|
+
return layoutOfType(context, ref, visited);
|
|
166
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { ModuleContext } from "../dsl/context.js";
|
|
2
|
+
import { indent } from "../dsl/emit.js";
|
|
3
|
+
import type { GirBoxed } from "../gir/boxed.js";
|
|
4
|
+
import { renderBoxedConstructor, renderBoxedConstructorPropsInterface } from "./boxed-constructor.js";
|
|
5
|
+
import { renderBoxedFieldAccessor } from "./boxed-field-accessor.js";
|
|
6
|
+
import { computeBoxedFieldSlots } from "./boxed-layout.js";
|
|
7
|
+
import { type Callables, dedupeCallables, emitBindings, renderPlainTypeMembers } from "./callables.js";
|
|
8
|
+
import { isClassStructRecord } from "./class-struct-record.js";
|
|
9
|
+
import { renderGetTypeReference } from "./gtype-binding.js";
|
|
10
|
+
import { appendNativeClassRegistration } from "./registration.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Emits a class declaration plus optional boxed registration for a
|
|
14
|
+
* `<record>`, `<union>`, or `<glib:boxed>`.
|
|
15
|
+
*
|
|
16
|
+
* Walks constructors, static functions, and methods just like
|
|
17
|
+
* {@link emitClass}, attaching them to the boxed class. Field accessors
|
|
18
|
+
* and construction metadata are emitted by their dedicated writers.
|
|
19
|
+
*
|
|
20
|
+
* Vtable records (`glib:is-gtype-struct-for`) are skipped here — they are
|
|
21
|
+
* consumed by the owning class's vtable registration. Class- and
|
|
22
|
+
* interface-struct records (`GTypeClass`, `GEnumClass`, …) are likewise skipped
|
|
23
|
+
* as they are runtime vtables rather than marshallable values.
|
|
24
|
+
*
|
|
25
|
+
* @param context - The module context
|
|
26
|
+
* @param boxed - The boxed to emit
|
|
27
|
+
*/
|
|
28
|
+
export const emitBoxed = (context: ModuleContext, boxed: GirBoxed): void => {
|
|
29
|
+
if (!boxed.introspectable) return;
|
|
30
|
+
if (boxed.kind === "vtable") return;
|
|
31
|
+
if (boxed.name.length === 0) return;
|
|
32
|
+
if (isClassStructRecord(context.namespace.name, boxed)) return;
|
|
33
|
+
const className = boxed.name;
|
|
34
|
+
const callables: Callables = {
|
|
35
|
+
constructors: dedupeCallables(boxed.constructors),
|
|
36
|
+
functions: dedupeCallables(boxed.functions),
|
|
37
|
+
methods: dedupeCallables(boxed.methods),
|
|
38
|
+
};
|
|
39
|
+
emitBindings(context, callables);
|
|
40
|
+
|
|
41
|
+
const members = renderBoxedMembers(context, boxed, className, callables);
|
|
42
|
+
const body = members.map((member) => indent(member, 1)).join("\n\n");
|
|
43
|
+
context.module.appendDeclaration(`export class ${className} {\n${body}\n}`);
|
|
44
|
+
context.module.appendDeclaration(renderBoxedConstructorPropsInterface(context, boxed, className));
|
|
45
|
+
|
|
46
|
+
const getTypeRef =
|
|
47
|
+
boxed.glibGetType === undefined
|
|
48
|
+
? undefined
|
|
49
|
+
: renderGetTypeReference(context, boxed.glibGetType, boxed.glibTypeName);
|
|
50
|
+
appendNativeClassRegistration(context, {
|
|
51
|
+
className,
|
|
52
|
+
role: "boxed",
|
|
53
|
+
getTypeRef,
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const renderBoxedMembers = (
|
|
58
|
+
context: ModuleContext,
|
|
59
|
+
boxed: GirBoxed,
|
|
60
|
+
className: string,
|
|
61
|
+
callables: Callables,
|
|
62
|
+
): readonly string[] => {
|
|
63
|
+
const { members, claimedNames } = renderPlainTypeMembers({
|
|
64
|
+
context,
|
|
65
|
+
className,
|
|
66
|
+
callables,
|
|
67
|
+
hasGType: boxed.glibGetType !== undefined,
|
|
68
|
+
wrap: "boxed",
|
|
69
|
+
});
|
|
70
|
+
members.unshift(renderBoxedConstructor(context, boxed, className));
|
|
71
|
+
const { slots } = computeBoxedFieldSlots(context, boxed.fields, boxed.isUnion);
|
|
72
|
+
for (const slot of slots) {
|
|
73
|
+
const block = renderBoxedFieldAccessor(context, slot, claimedNames, boxed.fields);
|
|
74
|
+
if (block !== undefined) members.push(block);
|
|
75
|
+
}
|
|
76
|
+
return members;
|
|
77
|
+
};
|