@gtkx/runtime 1.0.0-rc.4 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/README.md +5 -5
  2. package/dist/application-class.d.ts +37 -0
  3. package/dist/application-class.d.ts.map +1 -0
  4. package/dist/application-class.js +78 -0
  5. package/dist/application-class.js.map +1 -0
  6. package/dist/arg.d.ts +2 -1
  7. package/dist/arg.d.ts.map +1 -1
  8. package/dist/arg.js +2 -1
  9. package/dist/arg.js.map +1 -1
  10. package/dist/bind.d.ts +11 -0
  11. package/dist/bind.d.ts.map +1 -1
  12. package/dist/bind.js +11 -0
  13. package/dist/bind.js.map +1 -1
  14. package/dist/callback.d.ts +4 -3
  15. package/dist/callback.d.ts.map +1 -1
  16. package/dist/callback.js +124 -29
  17. package/dist/callback.js.map +1 -1
  18. package/dist/closure.d.ts +26 -0
  19. package/dist/closure.d.ts.map +1 -0
  20. package/dist/closure.js +99 -0
  21. package/dist/closure.js.map +1 -0
  22. package/dist/default-application.d.ts +4 -0
  23. package/dist/default-application.d.ts.map +1 -0
  24. package/dist/default-application.js +17 -0
  25. package/dist/default-application.js.map +1 -0
  26. package/dist/descriptors.d.ts +98 -4
  27. package/dist/descriptors.d.ts.map +1 -1
  28. package/dist/descriptors.js +72 -6
  29. package/dist/descriptors.js.map +1 -1
  30. package/dist/error.d.ts +1 -0
  31. package/dist/error.d.ts.map +1 -1
  32. package/dist/error.js.map +1 -1
  33. package/dist/exit-hook.js +13 -0
  34. package/dist/exit-hook.js.map +1 -1
  35. package/dist/fn.d.ts +24 -2
  36. package/dist/fn.d.ts.map +1 -1
  37. package/dist/fn.js +67 -32
  38. package/dist/fn.js.map +1 -1
  39. package/dist/folded-lengths.d.ts +16 -0
  40. package/dist/folded-lengths.d.ts.map +1 -0
  41. package/dist/folded-lengths.js +38 -0
  42. package/dist/folded-lengths.js.map +1 -0
  43. package/dist/index.d.ts +14 -6
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +12 -4
  46. package/dist/index.js.map +1 -1
  47. package/dist/internal.d.ts +2 -0
  48. package/dist/internal.d.ts.map +1 -1
  49. package/dist/internal.js +2 -0
  50. package/dist/internal.js.map +1 -1
  51. package/dist/library.d.ts +3 -1
  52. package/dist/library.d.ts.map +1 -1
  53. package/dist/library.js +3 -1
  54. package/dist/library.js.map +1 -1
  55. package/dist/lifecycle.d.ts +58 -11
  56. package/dist/lifecycle.d.ts.map +1 -1
  57. package/dist/lifecycle.js +95 -22
  58. package/dist/lifecycle.js.map +1 -1
  59. package/dist/listeners.d.ts.map +1 -1
  60. package/dist/listeners.js +19 -5
  61. package/dist/listeners.js.map +1 -1
  62. package/dist/mixin.d.ts +3 -2
  63. package/dist/mixin.d.ts.map +1 -1
  64. package/dist/mixin.js +13 -1
  65. package/dist/mixin.js.map +1 -1
  66. package/dist/native-value.d.ts.map +1 -1
  67. package/dist/native-value.js +4 -3
  68. package/dist/native-value.js.map +1 -1
  69. package/dist/object.d.ts +40 -7
  70. package/dist/object.d.ts.map +1 -1
  71. package/dist/object.js +95 -26
  72. package/dist/object.js.map +1 -1
  73. package/dist/param-spec.d.ts +11 -0
  74. package/dist/param-spec.d.ts.map +1 -0
  75. package/dist/param-spec.js +147 -0
  76. package/dist/param-spec.js.map +1 -0
  77. package/dist/promisify.d.ts.map +1 -1
  78. package/dist/promisify.js +3 -2
  79. package/dist/promisify.js.map +1 -1
  80. package/dist/properties.d.ts +39 -7
  81. package/dist/properties.d.ts.map +1 -1
  82. package/dist/properties.js +310 -43
  83. package/dist/properties.js.map +1 -1
  84. package/dist/register-class.d.ts +147 -12
  85. package/dist/register-class.d.ts.map +1 -1
  86. package/dist/register-class.js +129 -83
  87. package/dist/register-class.js.map +1 -1
  88. package/dist/registry.d.ts +80 -21
  89. package/dist/registry.d.ts.map +1 -1
  90. package/dist/registry.js +86 -33
  91. package/dist/registry.js.map +1 -1
  92. package/dist/signal.d.ts +11 -4
  93. package/dist/signal.d.ts.map +1 -1
  94. package/dist/signal.js +85 -25
  95. package/dist/signal.js.map +1 -1
  96. package/dist/t.d.ts +2 -0
  97. package/dist/t.d.ts.map +1 -1
  98. package/dist/t.js +1 -0
  99. package/dist/t.js.map +1 -1
  100. package/dist/tuple.d.ts +6 -3
  101. package/dist/tuple.d.ts.map +1 -1
  102. package/dist/tuple.js +9 -7
  103. package/dist/tuple.js.map +1 -1
  104. package/dist/type.d.ts +2 -1
  105. package/dist/type.d.ts.map +1 -1
  106. package/dist/type.js +2 -0
  107. package/dist/type.js.map +1 -1
  108. package/dist/value.d.ts +10 -1
  109. package/dist/value.d.ts.map +1 -1
  110. package/dist/value.js +99 -24
  111. package/dist/value.js.map +1 -1
  112. package/dist/vfunc-call.d.ts +37 -0
  113. package/dist/vfunc-call.d.ts.map +1 -0
  114. package/dist/vfunc-call.js +172 -0
  115. package/dist/vfunc-call.js.map +1 -0
  116. package/dist/vfunc-seeds.d.ts +12 -0
  117. package/dist/vfunc-seeds.d.ts.map +1 -0
  118. package/dist/vfunc-seeds.js +19 -0
  119. package/dist/vfunc-seeds.js.map +1 -0
  120. package/dist/vfunc.d.ts +8 -0
  121. package/dist/vfunc.d.ts.map +1 -0
  122. package/dist/vfunc.js +29 -0
  123. package/dist/vfunc.js.map +1 -0
  124. package/package.json +14 -4
  125. package/src/application-class.ts +126 -0
  126. package/src/arg.ts +2 -1
  127. package/src/bind.ts +11 -0
  128. package/src/callback.ts +178 -34
  129. package/src/closure.ts +136 -0
  130. package/src/default-application.ts +21 -0
  131. package/src/descriptors.ts +150 -34
  132. package/src/error.ts +1 -0
  133. package/src/exit-hook.ts +18 -0
  134. package/src/fn.ts +107 -36
  135. package/src/folded-lengths.ts +64 -0
  136. package/src/index.ts +21 -6
  137. package/src/internal.ts +2 -0
  138. package/src/library.ts +3 -1
  139. package/src/lifecycle.ts +138 -25
  140. package/src/listeners.ts +25 -6
  141. package/src/mixin.ts +15 -2
  142. package/src/native-value.ts +5 -3
  143. package/src/object.ts +134 -35
  144. package/src/param-spec.ts +234 -0
  145. package/src/promisify.ts +4 -2
  146. package/src/properties.ts +473 -46
  147. package/src/register-class.ts +386 -114
  148. package/src/registry.ts +169 -49
  149. package/src/signal.ts +116 -42
  150. package/src/t.ts +3 -0
  151. package/src/tuple.ts +18 -12
  152. package/src/type.ts +3 -1
  153. package/src/value.ts +143 -23
  154. package/src/vfunc-call.ts +247 -0
  155. package/src/vfunc-seeds.ts +36 -0
  156. package/src/vfunc.ts +38 -0
package/README.md CHANGED
@@ -108,7 +108,7 @@ React Native and similar frameworks hide the native toolkit so one API can run e
108
108
 
109
109
  ### Why Node.js, and why generated bindings
110
110
 
111
- GTKX runs on Node.js, which puts native modules, the npm ecosystem, and the tooling built for Node.js APIs within reach. GJS is GNOME's own runtime, built on SpiderMonkey rather than V8; node-gtk runs on Node.js but is lightly maintained, on the older nan/V8 ABI rather than N-API, and still centered on GTK3. The [Why GTKX guide](https://gtkx.dev/guide/why-gtkx) covers the comparison in full.
111
+ GTKX runs on Node.js, which puts native modules, the npm ecosystem, and the tooling built for Node.js APIs within reach. GJS is GNOME's own runtime, built on SpiderMonkey rather than V8; node-gtk runs on Node.js but is lightly maintained, on the older nan/V8 ABI rather than N-API, and still centered on GTK3. The [Why GTKX guide](https://gtkx.dev/guide/why-gtkx) covers what running on Node.js means day to day.
112
112
 
113
113
  GTKX generates the TypeScript types and the native FFI calls from the same GObject-Introspection data, so the types cannot drift from the calls they back. Codegen covers the whole GTK4 and Adwaita surface.
114
114
 
@@ -121,10 +121,10 @@ GTKX is Linux-only and needs Node.js 24 or later. See [Requirements](#requiremen
121
121
  Scaffold a new app with the `create-gtkx` initializer:
122
122
 
123
123
  ```sh
124
- npm create gtkx@rc
124
+ npm create gtkx
125
125
  ```
126
126
 
127
- The same command works with other package managers: `pnpm create gtkx@rc` or `yarn create gtkx@rc`.
127
+ The same command works with other package managers: `pnpm create gtkx` or `yarn create gtkx`.
128
128
 
129
129
  Then run your new app:
130
130
 
@@ -145,7 +145,7 @@ The documentation at **[gtkx.dev](https://gtkx.dev)** includes a step-by-step tu
145
145
 
146
146
  GTKX is Linux-only. You need:
147
147
 
148
- - Linux with the GTK4 (4.20 or later), Adwaita (1.8 or later), and GLib development libraries
148
+ - Linux with the GTK4 (4.20 or later) and GLib development libraries, plus Adwaita (1.8 or later) once your project binds `Adw-1`
149
149
  - Node.js 24 or later
150
150
 
151
151
  The `@gtkx/native` addon ships prebuilt for x64 and arm64 glibc Linux; other targets need to build it from the GTKX repository, which requires a Rust toolchain.
@@ -161,7 +161,7 @@ Explore the [example apps](https://github.com/gtkx-org/gtkx/tree/main/examples):
161
161
 
162
162
  ## Status
163
163
 
164
- GTKX 1.0 is at the release candidate stage.
164
+ GTKX is stable and ready for production use.
165
165
 
166
166
  ## Contributing
167
167
 
@@ -0,0 +1,37 @@
1
+ import { type AnyClass } from "@gtkx/utils";
2
+ type CommandLineResult = [boolean, string[], number];
3
+ /**
4
+ * The GIO application surface {@link createApplication} builds on, which `Gio.Application` and
5
+ * every subclass of it satisfies structurally.
6
+ */
7
+ type CommandLineApplication = {
8
+ /** Marks the application as quitting, so GLib's own `run` returns without driving a main loop. */
9
+ quit(): void;
10
+ };
11
+ type LocalCommandLineApplication = {
12
+ runLocalCommandLine(argv: string[]): CommandLineResult;
13
+ };
14
+ type ShutdownApplication = {
15
+ run(argv: string[]): number;
16
+ };
17
+ /** An application class together with the construct properties it accepts. */
18
+ type ApplicationClass<T extends CommandLineApplication, P> = AnyClass<T> & (new (props: P) => T);
19
+ declare const isDerivedApplication: (application: object) => application is LocalCommandLineApplication;
20
+ declare const shutDownThroughRun: (application: ShutdownApplication) => void;
21
+ /**
22
+ * Constructs an application GTKX can shut down. GLib parses an application's command line at most
23
+ * once per instance and crashes on a second parse, so {@link runApplication} and
24
+ * {@link quitApplication} only accept an application built here.
25
+ *
26
+ * Whatever `g_application_constructed` assigned to the process-wide default is handed straight back,
27
+ * so merely building an application never makes it what `Gio.Application.getDefault()` returns.
28
+ * {@link runApplication} is the only place that claims that default, which keeps it pointing at an
29
+ * application GTKX has actually started rather than at one that is still unregistered.
30
+ *
31
+ * @param base The application class to construct, such as `Gtk.Application`.
32
+ * @param props Construct properties, passed through unchanged.
33
+ * @returns An instance of a class derived from `base`, registered once per base class as its own GType.
34
+ */
35
+ declare const createApplication: <T extends CommandLineApplication, P>(base: ApplicationClass<T, P>, props: P) => T;
36
+ export { createApplication, isDerivedApplication, shutDownThroughRun, type ApplicationClass, type CommandLineApplication, type LocalCommandLineApplication, };
37
+ //# sourceMappingURL=application-class.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"application-class.d.ts","sourceRoot":"","sources":["../src/application-class.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAe,MAAM,aAAa,CAAC;AAOzD,KAAK,iBAAiB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,MAAM,CAAC,CAAC;AAErD;;;GAGG;AACH,KAAK,sBAAsB,GAAG;IAC1B,kGAAkG;IAClG,IAAI,IAAI,IAAI,CAAC;CAChB,CAAC;AAEF,KAAK,2BAA2B,GAAG;IAC/B,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,iBAAiB,CAAC;CAC1D,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACvB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;CAC/B,CAAC;AAEF,8EAA8E;AAC9E,KAAK,gBAAgB,CAAC,CAAC,SAAS,sBAAsB,EAAE,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;AA2CjG,QAAA,MAAM,oBAAoB,GAAI,aAAa,MAAM,KAAG,WAAW,IAAI,2BAQlE,CAAC;AAEF,QAAA,MAAM,kBAAkB,GAAI,aAAa,mBAAmB,KAAG,IAY9D,CAAC;AAKF;;;;;;;;;;;;;GAaG;AACH,QAAA,MAAM,iBAAiB,GAAI,CAAC,SAAS,sBAAsB,EAAE,CAAC,EAAE,MAAM,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,KAAG,CAKxG,CAAC;AAEF,OAAO,EACH,iBAAiB,EACjB,oBAAoB,EACpB,kBAAkB,EAClB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,2BAA2B,GACnC,CAAC"}
@@ -0,0 +1,78 @@
1
+ import { getOrInsert } from "@gtkx/utils";
2
+ import { releaseDefaultApplication } from "./default-application.js";
3
+ import { registerClass } from "./register-class.js";
4
+ import { getClassType } from "./registry.js";
5
+ import { typeName } from "./type.js";
6
+ import { callParent } from "./vfunc-call.js";
7
+ const derivedClasses = new WeakMap();
8
+ const derivedApplicationClasses = new Set();
9
+ const quitApplications = new WeakSet();
10
+ const shuttingDownApplications = new WeakSet();
11
+ const derivedTypeName = (base) => `Gtkx${typeName(getClassType(base)) ?? base.name}`;
12
+ const buildApplicationClass = (base) => {
13
+ class DerivedApplication extends base {
14
+ runLocalCommandLine(argv) {
15
+ return this.vfuncLocalCommandLine(argv);
16
+ }
17
+ vfuncLocalCommandLine(argv) {
18
+ if (shuttingDownApplications.has(this)) {
19
+ this.quit();
20
+ return [true, argv, 0];
21
+ }
22
+ return callParent(DerivedApplication, "vfuncLocalCommandLine", this, argv);
23
+ }
24
+ vfuncNameLost() {
25
+ quitApplications.add(this);
26
+ return callParent(DerivedApplication, "vfuncNameLost", this);
27
+ }
28
+ quit() {
29
+ quitApplications.add(this);
30
+ super.quit();
31
+ }
32
+ }
33
+ const derived = registerClass(DerivedApplication, { typeName: derivedTypeName(base) });
34
+ derivedApplicationClasses.add(derived);
35
+ return derived;
36
+ };
37
+ const isDerivedApplication = (application) => {
38
+ for (const derived of derivedApplicationClasses) {
39
+ if (application instanceof derived) {
40
+ return true;
41
+ }
42
+ }
43
+ return false;
44
+ };
45
+ const shutDownThroughRun = (application) => {
46
+ if (!isDerivedApplication(application) || quitApplications.has(application)) {
47
+ return;
48
+ }
49
+ shuttingDownApplications.add(application);
50
+ try {
51
+ application.run([]);
52
+ }
53
+ finally {
54
+ shuttingDownApplications.delete(application);
55
+ }
56
+ };
57
+ const deriveApplicationClass = (base) => getOrInsert(derivedClasses, base, () => buildApplicationClass(base));
58
+ /**
59
+ * Constructs an application GTKX can shut down. GLib parses an application's command line at most
60
+ * once per instance and crashes on a second parse, so {@link runApplication} and
61
+ * {@link quitApplication} only accept an application built here.
62
+ *
63
+ * Whatever `g_application_constructed` assigned to the process-wide default is handed straight back,
64
+ * so merely building an application never makes it what `Gio.Application.getDefault()` returns.
65
+ * {@link runApplication} is the only place that claims that default, which keeps it pointing at an
66
+ * application GTKX has actually started rather than at one that is still unregistered.
67
+ *
68
+ * @param base The application class to construct, such as `Gtk.Application`.
69
+ * @param props Construct properties, passed through unchanged.
70
+ * @returns An instance of a class derived from `base`, registered once per base class as its own GType.
71
+ */
72
+ const createApplication = (base, props) => {
73
+ const application = new (deriveApplicationClass(base))(props);
74
+ releaseDefaultApplication(application);
75
+ return application;
76
+ };
77
+ export { createApplication, isDerivedApplication, shutDownThroughRun, };
78
+ //# sourceMappingURL=application-class.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"application-class.js","sourceRoot":"","sources":["../src/application-class.ts"],"names":[],"mappings":"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","sourcesContent":["import { type AnyClass, getOrInsert } from \"@gtkx/utils\";\nimport { releaseDefaultApplication } from \"./default-application.js\";\nimport { registerClass } from \"./register-class.js\";\nimport { getClassType } from \"./registry.js\";\nimport { typeName } from \"./type.js\";\nimport { callParent } from \"./vfunc-call.js\";\n\ntype CommandLineResult = [boolean, string[], number];\n\n/**\n * The GIO application surface {@link createApplication} builds on, which `Gio.Application` and\n * every subclass of it satisfies structurally.\n */\ntype CommandLineApplication = {\n /** Marks the application as quitting, so GLib's own `run` returns without driving a main loop. */\n quit(): void;\n};\n\ntype LocalCommandLineApplication = {\n runLocalCommandLine(argv: string[]): CommandLineResult;\n};\n\ntype ShutdownApplication = {\n run(argv: string[]): number;\n};\n\n/** An application class together with the construct properties it accepts. */\ntype ApplicationClass<T extends CommandLineApplication, P> = AnyClass<T> & (new (props: P) => T);\n\nconst derivedClasses: WeakMap<AnyClass, AnyClass> = new WeakMap();\nconst derivedApplicationClasses: Set<AnyClass> = new Set();\nconst quitApplications: WeakSet<object> = new WeakSet();\nconst shuttingDownApplications: WeakSet<object> = new WeakSet();\n\nconst derivedTypeName = (base: AnyClass): string => `Gtkx${typeName(getClassType(base)) ?? base.name}`;\n\nconst buildApplicationClass = (base: AnyClass<CommandLineApplication>): AnyClass<CommandLineApplication> => {\n class DerivedApplication extends base {\n runLocalCommandLine(argv: string[]): CommandLineResult {\n return this.vfuncLocalCommandLine(argv);\n }\n\n protected vfuncLocalCommandLine(argv: string[]): CommandLineResult {\n if (shuttingDownApplications.has(this)) {\n this.quit();\n\n return [true, argv, 0];\n }\n\n return callParent(DerivedApplication, \"vfuncLocalCommandLine\", this, argv) as CommandLineResult;\n }\n\n protected vfuncNameLost(): boolean {\n quitApplications.add(this);\n\n return callParent(DerivedApplication, \"vfuncNameLost\", this) as boolean;\n }\n\n override quit(): void {\n quitApplications.add(this);\n super.quit();\n }\n }\n\n const derived = registerClass(DerivedApplication, { typeName: derivedTypeName(base) });\n derivedApplicationClasses.add(derived);\n\n return derived;\n};\n\nconst isDerivedApplication = (application: object): application is LocalCommandLineApplication => {\n for (const derived of derivedApplicationClasses) {\n if (application instanceof derived) {\n return true;\n }\n }\n\n return false;\n};\n\nconst shutDownThroughRun = (application: ShutdownApplication): void => {\n if (!isDerivedApplication(application) || quitApplications.has(application)) {\n return;\n }\n\n shuttingDownApplications.add(application);\n\n try {\n application.run([]);\n } finally {\n shuttingDownApplications.delete(application);\n }\n};\n\nconst deriveApplicationClass = <T extends CommandLineApplication>(base: AnyClass<T>): AnyClass<T> =>\n getOrInsert(derivedClasses, base, () => buildApplicationClass(base)) as AnyClass<T>;\n\n/**\n * Constructs an application GTKX can shut down. GLib parses an application's command line at most\n * once per instance and crashes on a second parse, so {@link runApplication} and\n * {@link quitApplication} only accept an application built here.\n *\n * Whatever `g_application_constructed` assigned to the process-wide default is handed straight back,\n * so merely building an application never makes it what `Gio.Application.getDefault()` returns.\n * {@link runApplication} is the only place that claims that default, which keeps it pointing at an\n * application GTKX has actually started rather than at one that is still unregistered.\n *\n * @param base The application class to construct, such as `Gtk.Application`.\n * @param props Construct properties, passed through unchanged.\n * @returns An instance of a class derived from `base`, registered once per base class as its own GType.\n */\nconst createApplication = <T extends CommandLineApplication, P>(base: ApplicationClass<T, P>, props: P): T => {\n const application = new (deriveApplicationClass(base) as new (props: P) => T)(props);\n releaseDefaultApplication(application);\n\n return application;\n};\n\nexport {\n createApplication,\n isDerivedApplication,\n shutDownThroughRun,\n type ApplicationClass,\n type CommandLineApplication,\n type LocalCommandLineApplication,\n};\n"]}
package/dist/arg.d.ts CHANGED
@@ -14,5 +14,6 @@ declare const isOutputArg: (arg: Arg) => boolean;
14
14
  declare const isInoutArg: (arg: Arg) => boolean;
15
15
  declare const isCallerAllocatedArg: (arg: Arg) => boolean;
16
16
  declare const isRefArg: (arg: Arg) => boolean;
17
- export { isOutputArg, isInoutArg, isCallerAllocatedArg, isRefArg, type Arg };
17
+ declare const requiresInputArg: (arg: Arg) => boolean;
18
+ export { isOutputArg, isInoutArg, isCallerAllocatedArg, isRefArg, requiresInputArg, type Arg };
18
19
  //# sourceMappingURL=arg.d.ts.map
package/dist/arg.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"arg.d.ts","sourceRoot":"","sources":["../src/arg.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,iGAAiG;AACjG,KAAK,GAAG,GAAG;IACP,kGAAkG;IAClG,IAAI,EAAE,UAAU,CAAC;IACjB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC;IAC5B,wGAAwG;IACxG,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,wFAAwF;IACxF,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,QAAA,MAAM,WAAW,GAAI,KAAK,GAAG,KAAG,OAAsC,CAAC;AACvE,QAAA,MAAM,UAAU,GAAI,KAAK,GAAG,KAAG,OAAoC,CAAC;AACpE,QAAA,MAAM,oBAAoB,GAAI,KAAK,GAAG,KAAG,OAAyC,CAAC;AACnF,QAAA,MAAM,QAAQ,GAAI,KAAK,GAAG,KAAG,OAAwE,CAAC;AAEtG,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,oBAAoB,EAAE,QAAQ,EAAE,KAAK,GAAG,EAAE,CAAC"}
1
+ {"version":3,"file":"arg.d.ts","sourceRoot":"","sources":["../src/arg.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,iGAAiG;AACjG,KAAK,GAAG,GAAG;IACP,kGAAkG;IAClG,IAAI,EAAE,UAAU,CAAC;IACjB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC;IAC5B,wGAAwG;IACxG,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,wFAAwF;IACxF,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,QAAA,MAAM,WAAW,GAAI,KAAK,GAAG,KAAG,OAAsC,CAAC;AACvE,QAAA,MAAM,UAAU,GAAI,KAAK,GAAG,KAAG,OAAoC,CAAC;AACpE,QAAA,MAAM,oBAAoB,GAAI,KAAK,GAAG,KAAG,OAAyC,CAAC;AACnF,QAAA,MAAM,QAAQ,GAAI,KAAK,GAAG,KAAG,OAAwE,CAAC;AACtG,QAAA,MAAM,gBAAgB,GAAI,KAAK,GAAG,KAAG,OAA4C,CAAC;AAElF,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,oBAAoB,EAAE,QAAQ,EAAE,gBAAgB,EAAE,KAAK,GAAG,EAAE,CAAC"}
package/dist/arg.js CHANGED
@@ -2,5 +2,6 @@ const isOutputArg = (arg) => arg.direction !== undefined;
2
2
  const isInoutArg = (arg) => arg.direction === "inout";
3
3
  const isCallerAllocatedArg = (arg) => arg.isCallerAllocated === true;
4
4
  const isRefArg = (arg) => arg.direction !== undefined && arg.isCallerAllocated !== true;
5
- export { isOutputArg, isInoutArg, isCallerAllocatedArg, isRefArg };
5
+ const requiresInputArg = (arg) => !isRefArg(arg) || isInoutArg(arg);
6
+ export { isOutputArg, isInoutArg, isCallerAllocatedArg, isRefArg, requiresInputArg };
6
7
  //# sourceMappingURL=arg.js.map
package/dist/arg.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"arg.js","sourceRoot":"","sources":["../src/arg.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,GAAG,CAAC,GAAQ,EAAW,EAAE,CAAC,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC;AACvE,MAAM,UAAU,GAAG,CAAC,GAAQ,EAAW,EAAE,CAAC,GAAG,CAAC,SAAS,KAAK,OAAO,CAAC;AACpE,MAAM,oBAAoB,GAAG,CAAC,GAAQ,EAAW,EAAE,CAAC,GAAG,CAAC,iBAAiB,KAAK,IAAI,CAAC;AACnF,MAAM,QAAQ,GAAG,CAAC,GAAQ,EAAW,EAAE,CAAC,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,GAAG,CAAC,iBAAiB,KAAK,IAAI,CAAC;AAEtG,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,oBAAoB,EAAE,QAAQ,EAAY,CAAC","sourcesContent":["import type { Descriptor } from \"@gtkx/native\";\n\n/** How one argument of a native call or signal emission is marshalled and which way it flows. */\ntype Arg = {\n /** Descriptor the value is marshalled with, wrapped in a pointer to it for an output argument. */\n type: Descriptor;\n /** Direction of an output argument, omitted for a plain input argument. */\n direction?: \"out\" | \"inout\";\n /** When true, the caller supplies the storage the callee writes into, rather than a pointer to fill. */\n isCallerAllocated?: boolean;\n /** When true, the argument is consumed internally and left out of the packed result. */\n isConsumed?: boolean;\n};\n\nconst isOutputArg = (arg: Arg): boolean => arg.direction !== undefined;\nconst isInoutArg = (arg: Arg): boolean => arg.direction === \"inout\";\nconst isCallerAllocatedArg = (arg: Arg): boolean => arg.isCallerAllocated === true;\nconst isRefArg = (arg: Arg): boolean => arg.direction !== undefined && arg.isCallerAllocated !== true;\n\nexport { isOutputArg, isInoutArg, isCallerAllocatedArg, isRefArg, type Arg };\n"]}
1
+ {"version":3,"file":"arg.js","sourceRoot":"","sources":["../src/arg.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,GAAG,CAAC,GAAQ,EAAW,EAAE,CAAC,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC;AACvE,MAAM,UAAU,GAAG,CAAC,GAAQ,EAAW,EAAE,CAAC,GAAG,CAAC,SAAS,KAAK,OAAO,CAAC;AACpE,MAAM,oBAAoB,GAAG,CAAC,GAAQ,EAAW,EAAE,CAAC,GAAG,CAAC,iBAAiB,KAAK,IAAI,CAAC;AACnF,MAAM,QAAQ,GAAG,CAAC,GAAQ,EAAW,EAAE,CAAC,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,GAAG,CAAC,iBAAiB,KAAK,IAAI,CAAC;AACtG,MAAM,gBAAgB,GAAG,CAAC,GAAQ,EAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;AAElF,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,oBAAoB,EAAE,QAAQ,EAAE,gBAAgB,EAAY,CAAC","sourcesContent":["import type { Descriptor } from \"@gtkx/native\";\n\n/** How one argument of a native call or signal emission is marshalled and which way it flows. */\ntype Arg = {\n /** Descriptor the value is marshalled with, wrapped in a pointer to it for an output argument. */\n type: Descriptor;\n /** Direction of an output argument, omitted for a plain input argument. */\n direction?: \"out\" | \"inout\";\n /** When true, the caller supplies the storage the callee writes into, rather than a pointer to fill. */\n isCallerAllocated?: boolean;\n /** When true, the argument is consumed internally and left out of the packed result. */\n isConsumed?: boolean;\n};\n\nconst isOutputArg = (arg: Arg): boolean => arg.direction !== undefined;\nconst isInoutArg = (arg: Arg): boolean => arg.direction === \"inout\";\nconst isCallerAllocatedArg = (arg: Arg): boolean => arg.isCallerAllocated === true;\nconst isRefArg = (arg: Arg): boolean => arg.direction !== undefined && arg.isCallerAllocated !== true;\nconst requiresInputArg = (arg: Arg): boolean => !isRefArg(arg) || isInoutArg(arg);\n\nexport { isOutputArg, isInoutArg, isCallerAllocatedArg, isRefArg, requiresInputArg, type Arg };\n"]}
package/dist/bind.d.ts CHANGED
@@ -1,4 +1,15 @@
1
1
  import { type Descriptor } from "@gtkx/native";
2
+ /**
3
+ * Precompiles a call to a C function, marshalling the values it is given through the argument
4
+ * descriptors and the result through the return one. The symbol is resolved in the shared library
5
+ * on the first call.
6
+ *
7
+ * @param sharedLibrary The shared library to resolve the symbol in.
8
+ * @param symbol The name of the C function to bind.
9
+ * @param argDescriptors Describe the C arguments, in declaration order.
10
+ * @param returnDescriptor Describes the C return value.
11
+ * @returns A function calling the bound symbol.
12
+ */
2
13
  declare function bind(sharedLibrary: string, symbol: string, argDescriptors: Descriptor[], returnDescriptor: Descriptor): (...values: unknown[]) => unknown;
3
14
  declare function createBindCache(): (key: string, ...args: Parameters<typeof bind>) => ReturnType<typeof bind>;
4
15
  export { bind, createBindCache };
@@ -1 +1 @@
1
- {"version":3,"file":"bind.d.ts","sourceRoot":"","sources":["../src/bind.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,UAAU,EAAsB,MAAM,cAAc,CAAC;AAEzE,iBAAS,IAAI,CACT,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,UAAU,EAAE,EAC5B,gBAAgB,EAAE,UAAU,GAC7B,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,KAAK,OAAO,CAInC;AAED,iBAAS,eAAe,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,KAAK,UAAU,CAAC,OAAO,IAAI,CAAC,CAerG;AAED,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"bind.d.ts","sourceRoot":"","sources":["../src/bind.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,UAAU,EAAsB,MAAM,cAAc,CAAC;AAEzE;;;;;;;;;;GAUG;AACH,iBAAS,IAAI,CACT,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,UAAU,EAAE,EAC5B,gBAAgB,EAAE,UAAU,GAC7B,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,KAAK,OAAO,CAInC;AAED,iBAAS,eAAe,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,KAAK,UAAU,CAAC,OAAO,IAAI,CAAC,CAerG;AAED,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC"}
package/dist/bind.js CHANGED
@@ -1,4 +1,15 @@
1
1
  import { call, bind as nativeBind } from "@gtkx/native";
2
+ /**
3
+ * Precompiles a call to a C function, marshalling the values it is given through the argument
4
+ * descriptors and the result through the return one. The symbol is resolved in the shared library
5
+ * on the first call.
6
+ *
7
+ * @param sharedLibrary The shared library to resolve the symbol in.
8
+ * @param symbol The name of the C function to bind.
9
+ * @param argDescriptors Describe the C arguments, in declaration order.
10
+ * @param returnDescriptor Describes the C return value.
11
+ * @returns A function calling the bound symbol.
12
+ */
2
13
  function bind(sharedLibrary, symbol, argDescriptors, returnDescriptor) {
3
14
  const descriptor = nativeBind(sharedLibrary, symbol, argDescriptors, returnDescriptor);
4
15
  return (...values) => call(descriptor, values);
package/dist/bind.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bind.js","sourceRoot":"","sources":["../src/bind.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAmB,IAAI,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AAEzE,SAAS,IAAI,CACT,aAAqB,EACrB,MAAc,EACd,cAA4B,EAC5B,gBAA4B;IAE5B,MAAM,UAAU,GAAG,UAAU,CAAC,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,gBAAgB,CAAC,CAAC;IAEvF,OAAO,CAAC,GAAG,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,eAAe;IACpB,MAAM,KAAK,GAAyC,IAAI,GAAG,EAAE,CAAC;IAE9D,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,EAAE;QACpB,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEhC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,QAAQ,CAAC;QACpB,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QAC5B,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAEtB,OAAO,KAAK,CAAC;IACjB,CAAC,CAAC;AACN,CAAC;AAED,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC","sourcesContent":["import { call, type Descriptor, bind as nativeBind } from \"@gtkx/native\";\n\nfunction bind(\n sharedLibrary: string,\n symbol: string,\n argDescriptors: Descriptor[],\n returnDescriptor: Descriptor,\n): (...values: unknown[]) => unknown {\n const descriptor = nativeBind(sharedLibrary, symbol, argDescriptors, returnDescriptor);\n\n return (...values) => call(descriptor, values);\n}\n\nfunction createBindCache(): (key: string, ...args: Parameters<typeof bind>) => ReturnType<typeof bind> {\n const cache: Map<string, ReturnType<typeof bind>> = new Map();\n\n return (key, ...args) => {\n const existing = cache.get(key);\n\n if (existing !== undefined) {\n return existing;\n }\n\n const bound = bind(...args);\n cache.set(key, bound);\n\n return bound;\n };\n}\n\nexport { bind, createBindCache };\n"]}
1
+ {"version":3,"file":"bind.js","sourceRoot":"","sources":["../src/bind.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAmB,IAAI,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AAEzE;;;;;;;;;;GAUG;AACH,SAAS,IAAI,CACT,aAAqB,EACrB,MAAc,EACd,cAA4B,EAC5B,gBAA4B;IAE5B,MAAM,UAAU,GAAG,UAAU,CAAC,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,gBAAgB,CAAC,CAAC;IAEvF,OAAO,CAAC,GAAG,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,eAAe;IACpB,MAAM,KAAK,GAAyC,IAAI,GAAG,EAAE,CAAC;IAE9D,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,EAAE;QACpB,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEhC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,QAAQ,CAAC;QACpB,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QAC5B,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAEtB,OAAO,KAAK,CAAC;IACjB,CAAC,CAAC;AACN,CAAC;AAED,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC","sourcesContent":["import { call, type Descriptor, bind as nativeBind } from \"@gtkx/native\";\n\n/**\n * Precompiles a call to a C function, marshalling the values it is given through the argument\n * descriptors and the result through the return one. The symbol is resolved in the shared library\n * on the first call.\n *\n * @param sharedLibrary The shared library to resolve the symbol in.\n * @param symbol The name of the C function to bind.\n * @param argDescriptors Describe the C arguments, in declaration order.\n * @param returnDescriptor Describes the C return value.\n * @returns A function calling the bound symbol.\n */\nfunction bind(\n sharedLibrary: string,\n symbol: string,\n argDescriptors: Descriptor[],\n returnDescriptor: Descriptor,\n): (...values: unknown[]) => unknown {\n const descriptor = nativeBind(sharedLibrary, symbol, argDescriptors, returnDescriptor);\n\n return (...values) => call(descriptor, values);\n}\n\nfunction createBindCache(): (key: string, ...args: Parameters<typeof bind>) => ReturnType<typeof bind> {\n const cache: Map<string, ReturnType<typeof bind>> = new Map();\n\n return (key, ...args) => {\n const existing = cache.get(key);\n\n if (existing !== undefined) {\n return existing;\n }\n\n const bound = bind(...args);\n cache.set(key, bound);\n\n return bound;\n };\n}\n\nexport { bind, createBindCache };\n"]}
@@ -1,13 +1,14 @@
1
1
  import { type Descriptor } from "@gtkx/native";
2
2
  import type { CallbackDescriptor } from "./descriptors.js";
3
3
  type Callback = (...args: unknown[]) => unknown;
4
- type CallbackReceiver = "this" | "emitter" | "none";
4
+ type CallbackKind = "vfunc" | "signal" | "callback";
5
5
  type CallbackSpec = {
6
6
  argDescriptors: Descriptor[];
7
7
  returnDescriptor: Descriptor;
8
8
  userDataIndex?: number;
9
9
  };
10
+ declare const isCallerAllocatedOut: (descriptor: Descriptor) => boolean;
10
11
  declare const wrapCallbackValue: (spec: CallbackDescriptor, callback: unknown) => unknown;
11
- declare function wrapCallback(fn: Callback, spec: CallbackSpec, receiver: CallbackReceiver): Callback;
12
- export { wrapCallbackValue, wrapCallback };
12
+ declare function wrapCallback(fn: Callback, spec: CallbackSpec, kind: CallbackKind): Callback;
13
+ export { isCallerAllocatedOut, wrapCallbackValue, wrapCallback };
13
14
  //# sourceMappingURL=callback.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"callback.d.ts","sourceRoot":"","sources":["../src/callback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,kBAAkB,EAAiB,MAAM,kBAAkB,CAAC;AAM1E,KAAK,QAAQ,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;AAChD,KAAK,gBAAgB,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AAGpD,KAAK,YAAY,GAAG;IAChB,cAAc,EAAE,UAAU,EAAE,CAAC;IAC7B,gBAAgB,EAAE,UAAU,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAsHF,QAAA,MAAM,iBAAiB,GAAI,MAAM,kBAAkB,EAAE,UAAU,OAAO,KAAG,OACS,CAAC;AAEnF,iBAAS,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,GAAG,QAAQ,CAU5F;AAED,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"callback.d.ts","sourceRoot":"","sources":["../src/callback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,kBAAkB,EAAiB,MAAM,kBAAkB,CAAC;AAQ1E,KAAK,QAAQ,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;AAChD,KAAK,YAAY,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAC;AAOpD,KAAK,YAAY,GAAG;IAChB,cAAc,EAAE,UAAU,EAAE,CAAC;IAC7B,gBAAgB,EAAE,UAAU,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAoCF,QAAA,MAAM,oBAAoB,GAAI,YAAY,UAAU,KAAG,OACmD,CAAC;AAmN3G,QAAA,MAAM,iBAAiB,GAAI,MAAM,kBAAkB,EAAE,UAAU,OAAO,KAAG,OACa,CAAC;AAEvF,iBAAS,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,GAAG,QAAQ,CAkBpF;AAED,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,YAAY,EAAE,CAAC"}
package/dist/callback.js CHANGED
@@ -1,8 +1,15 @@
1
1
  import { copy } from "@gtkx/native";
2
+ import { foldedLengthSources } from "./folded-lengths.js";
2
3
  import { fromNative, toNative } from "./native-value.js";
3
4
  import { getHandle } from "./registry.js";
4
5
  import { splitTupleResult } from "./tuple.js";
5
6
  import { copyValue } from "./value.js";
7
+ import { popSeedFrame, pushSeedFrame } from "./vfunc-seeds.js";
8
+ const CALLBACK_TRAITS = {
9
+ callback: { isInstanceBound: false, hasInstanceArg: false, hasFoldedLengths: true },
10
+ signal: { isInstanceBound: false, hasInstanceArg: true, hasFoldedLengths: false },
11
+ vfunc: { isInstanceBound: true, hasInstanceArg: true, hasFoldedLengths: true },
12
+ };
6
13
  const fillCallerAllocatedBuffer = (descriptor, target, source) => {
7
14
  if (descriptor.kind === "boxed" && descriptor.typeName === "GValue") {
8
15
  copyValue(getHandle(target), getHandle(source));
@@ -15,55 +22,136 @@ const fillCallerAllocatedBuffer = (descriptor, target, source) => {
15
22
  throw new Error(`Cannot write caller-allocated ${descriptor.kind} out-parameter: no known byte size`);
16
23
  };
17
24
  const isCallerAllocatedOut = (descriptor) => (descriptor.kind === "boxed" || descriptor.kind === "struct") && descriptor.isCallerAllocated === true;
18
- const collectRefArg = (descriptor, wrappedValue, inputs, outParams) => {
25
+ const collectRefArg = (descriptor, wrappedValue, inputs, out) => {
19
26
  if (descriptor.inout === true) {
20
27
  inputs.push(wrappedValue.value);
21
28
  }
22
- outParams.push({ value: wrappedValue, descriptor });
29
+ out.params.push({ value: wrappedValue, descriptor, argIndex: out.argIndex });
23
30
  };
24
- const collectCallbackArg = (descriptor, wrappedValue, inputs, outParams) => {
31
+ const collectCallbackArg = (descriptor, wrappedValue, inputs, out) => {
25
32
  if (descriptor?.kind === "ref") {
26
- collectRefArg(descriptor, wrappedValue, inputs, outParams);
33
+ collectRefArg(descriptor, wrappedValue, inputs, out);
27
34
  return;
28
35
  }
29
36
  inputs.push(wrappedValue);
30
37
  if (descriptor !== undefined && isCallerAllocatedOut(descriptor)) {
31
- outParams.push({ value: wrappedValue, descriptor });
38
+ out.params.push({ value: wrappedValue, descriptor, argIndex: out.argIndex });
32
39
  }
33
40
  };
34
41
  const partitionCallbackArgs = (effectiveTypes, wrapped, start) => {
35
42
  const inputs = [];
36
- const outParams = [];
43
+ const params = [];
44
+ const collected = { params, argIndex: start };
37
45
  for (let i = start; i < effectiveTypes.length; i++) {
38
- collectCallbackArg(effectiveTypes[i], wrapped[i], inputs, outParams);
46
+ collected.argIndex = i;
47
+ collectCallbackArg(effectiveTypes[i], wrapped[i], inputs, collected);
48
+ }
49
+ return { inputs, outParams: params };
50
+ };
51
+ const hasOutParamArg = (descriptor) => descriptor !== undefined && (descriptor.kind === "ref" || isCallerAllocatedOut(descriptor));
52
+ const hasRefOutParamArg = (descriptor) => descriptor?.kind === "ref" && descriptor.inout !== true;
53
+ const haveOutParamArgs = (effectiveTypes, start) => effectiveTypes.slice(start).some((descriptor) => hasOutParamArg(descriptor));
54
+ const haveRefOutParamArgs = (effectiveTypes, start) => effectiveTypes.slice(start).some((descriptor) => hasRefOutParamArg(descriptor));
55
+ const groupOutParams = (outParams, lengthSources) => {
56
+ const groups = { lengthLinks: [], valueParams: [] };
57
+ for (const outParam of outParams) {
58
+ const sources = lengthSources.get(outParam.argIndex);
59
+ if (sources === undefined) {
60
+ groups.valueParams.push(outParam);
61
+ }
62
+ else {
63
+ groups.lengthLinks.push({ target: outParam, sources });
64
+ }
39
65
  }
40
- return { inputs, outParams };
66
+ return groups;
67
+ };
68
+ const getLength = (value) => {
69
+ const length = value?.length;
70
+ return typeof length === "number" ? length : 0;
71
+ };
72
+ const lengthSourceValue = (source, outValues, primary) => source.kind === "return" ? primary : outValues.get(source.argIndex);
73
+ const foldedLength = (sources, outValues, primary) => Math.min(...sources.map((source) => getLength(lengthSourceValue(source, outValues, primary))));
74
+ const resolveOutValues = (groups, values, primary) => {
75
+ const outValues = new Map();
76
+ for (const [position, outParam] of groups.valueParams.entries()) {
77
+ outValues.set(outParam.argIndex, values[position]);
78
+ }
79
+ for (const link of groups.lengthLinks) {
80
+ outValues.set(link.target.argIndex, foldedLength(link.sources, outValues, primary));
81
+ }
82
+ return outValues;
41
83
  };
42
84
  const writeOutParams = (outParams, outValues) => {
43
- for (const [position, outParam] of outParams.entries()) {
44
- const outValue = outValues[position];
45
- if (outParam.descriptor.kind === "ref") {
46
- outParam.value.value = outValue;
85
+ for (const outParam of outParams) {
86
+ const { descriptor } = outParam;
87
+ const outValue = outValues.get(outParam.argIndex);
88
+ if (descriptor.kind === "ref") {
89
+ outParam.value.value = toNative(descriptor.innerDescriptor, outValue);
47
90
  }
48
91
  else if (outValue != null && outParam.value != null) {
49
- fillCallerAllocatedBuffer(outParam.descriptor, outParam.value, outValue);
92
+ fillCallerAllocatedBuffer(descriptor, outParam.value, outValue);
93
+ }
94
+ }
95
+ };
96
+ const collectRefSeeds = (outParams) => {
97
+ const seeds = new Map();
98
+ for (const outParam of outParams) {
99
+ const seed = outParam.value?.value;
100
+ if (seed != null && hasRefOutParamArg(outParam.descriptor)) {
101
+ seeds.set(outParam.argIndex, seed);
50
102
  }
51
103
  }
104
+ return seeds;
105
+ };
106
+ const applyCallback = (plan, thisArg, inputs, outParams) => {
107
+ if (!plan.hasRefOutParams) {
108
+ return plan.fn.apply(thisArg, inputs);
109
+ }
110
+ pushSeedFrame({ argDescriptors: plan.effectiveTypes, instance: thisArg, seeds: collectRefSeeds(outParams) });
111
+ try {
112
+ return plan.fn.apply(thisArg, inputs);
113
+ }
114
+ finally {
115
+ popSeedFrame();
116
+ }
52
117
  };
53
- const getThisArg = (receiver, wrapped) => receiver === "this" ? (wrapped[0] ?? null) : null;
118
+ const getThisArg = (isInstanceBound, wrapped) => isInstanceBound ? (wrapped[0] ?? null) : null;
119
+ const wrapCallbackArgs = (effectiveTypes, rawArgs) => {
120
+ let index = 0;
121
+ for (const descriptor of effectiveTypes) {
122
+ rawArgs[index] = fromNative(descriptor, rawArgs[index]);
123
+ index += 1;
124
+ }
125
+ };
126
+ const trimCallbackInputs = (plan, wrapped) => {
127
+ const count = plan.effectiveTypes.length;
128
+ if (wrapped.length > count) {
129
+ wrapped.length = count;
130
+ }
131
+ for (let index = 0; index < plan.start; index++) {
132
+ wrapped.shift();
133
+ }
134
+ return wrapped;
135
+ };
136
+ const nativeReturn = (plan, primary) => toNative(plan.returnDescriptor, plan.hasPrimary ? primary : undefined);
54
137
  const runCallback = (plan, rawArgs) => {
55
- const { effectiveTypes, returnDescriptor } = plan;
56
- const wrapped = effectiveTypes.map((descriptor, i) => fromNative(descriptor, rawArgs[i]));
57
- const thisArg = getThisArg(plan.receiver, wrapped);
58
- const { inputs, outParams } = partitionCallbackArgs(effectiveTypes, wrapped, plan.start);
59
- const result = plan.fn.apply(thisArg, inputs);
138
+ const { effectiveTypes } = plan;
139
+ wrapCallbackArgs(effectiveTypes, rawArgs);
140
+ const thisArg = getThisArg(plan.isInstanceBound, rawArgs);
141
+ if (!plan.hasOutParams) {
142
+ return nativeReturn(plan, plan.fn.apply(thisArg, trimCallbackInputs(plan, rawArgs)));
143
+ }
144
+ const { inputs, outParams } = partitionCallbackArgs(effectiveTypes, rawArgs, plan.start);
145
+ const result = applyCallback(plan, thisArg, inputs, outParams);
60
146
  if (outParams.length === 0) {
61
- return toNative(returnDescriptor, result);
147
+ return nativeReturn(plan, result);
62
148
  }
63
- const { primary, outValues } = splitTupleResult(result, returnDescriptor.kind !== "void", outParams.length);
64
- writeOutParams(outParams, outValues);
65
- return toNative(returnDescriptor, primary);
149
+ const groups = groupOutParams(outParams, plan.lengthSources);
150
+ const { primary, outValues } = splitTupleResult(result, plan.hasPrimary, groups.valueParams.length);
151
+ writeOutParams(outParams, resolveOutValues(groups, outValues, primary));
152
+ return nativeReturn(plan, primary);
66
153
  };
154
+ const planLengthSources = (spec, hasFoldedLengths) => hasFoldedLengths ? foldedLengthSources(spec) : new Map();
67
155
  const getEffectiveTypes = (spec) => {
68
156
  const { userDataIndex } = spec;
69
157
  if (userDataIndex === undefined) {
@@ -71,16 +159,23 @@ const getEffectiveTypes = (spec) => {
71
159
  }
72
160
  return spec.argDescriptors.filter((_, i) => i !== userDataIndex);
73
161
  };
74
- const wrapCallbackValue = (spec, callback) => callback == null ? callback : wrapCallback(callback, spec, "none");
75
- function wrapCallback(fn, spec, receiver) {
162
+ const wrapCallbackValue = (spec, callback) => callback == null ? callback : wrapCallback(callback, spec, "callback");
163
+ function wrapCallback(fn, spec, kind) {
164
+ const effectiveTypes = getEffectiveTypes(spec);
165
+ const { isInstanceBound, hasInstanceArg, hasFoldedLengths } = CALLBACK_TRAITS[kind];
166
+ const start = hasInstanceArg ? 1 : 0;
76
167
  const plan = {
77
168
  fn,
78
- effectiveTypes: getEffectiveTypes(spec),
169
+ effectiveTypes,
79
170
  returnDescriptor: spec.returnDescriptor,
80
- start: receiver === "none" ? 0 : 1,
81
- receiver,
171
+ hasPrimary: spec.returnDescriptor.kind !== "void",
172
+ start,
173
+ isInstanceBound,
174
+ lengthSources: planLengthSources(spec, hasFoldedLengths),
175
+ hasOutParams: haveOutParamArgs(effectiveTypes, start),
176
+ hasRefOutParams: haveRefOutParamArgs(effectiveTypes, start),
82
177
  };
83
178
  return (...rawArgs) => runCallback(plan, rawArgs);
84
179
  }
85
- export { wrapCallbackValue, wrapCallback };
180
+ export { isCallerAllocatedOut, wrapCallbackValue, wrapCallback };
86
181
  //# sourceMappingURL=callback.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"callback.js","sourceRoot":"","sources":["../src/callback.ts"],"names":[],"mappings":"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","sourcesContent":["import { copy, type Descriptor } from \"@gtkx/native\";\nimport type { CallbackDescriptor, RefDescriptor } from \"./descriptors.js\";\nimport { fromNative, toNative } from \"./native-value.js\";\nimport { getHandle } from \"./registry.js\";\nimport { splitTupleResult } from \"./tuple.js\";\nimport { copyValue } from \"./value.js\";\n\ntype Callback = (...args: unknown[]) => unknown;\ntype CallbackReceiver = \"this\" | \"emitter\" | \"none\";\ntype OutParam = { value: unknown; descriptor: Descriptor };\n\ntype CallbackSpec = {\n argDescriptors: Descriptor[];\n returnDescriptor: Descriptor;\n userDataIndex?: number;\n};\n\ntype CallbackPlan = {\n fn: Callback;\n effectiveTypes: Descriptor[];\n returnDescriptor: Descriptor;\n start: number;\n receiver: CallbackReceiver;\n};\n\nconst fillCallerAllocatedBuffer = (descriptor: Descriptor, target: object, source: object): void => {\n if (descriptor.kind === \"boxed\" && descriptor.typeName === \"GValue\") {\n copyValue(getHandle(target), getHandle(source));\n\n return;\n }\n\n if ((descriptor.kind === \"boxed\" || descriptor.kind === \"struct\") && descriptor.size !== undefined) {\n copy(getHandle(target), getHandle(source), descriptor.size);\n\n return;\n }\n\n throw new Error(`Cannot write caller-allocated ${descriptor.kind} out-parameter: no known byte size`);\n};\n\nconst isCallerAllocatedOut = (descriptor: Descriptor): boolean =>\n (descriptor.kind === \"boxed\" || descriptor.kind === \"struct\") && descriptor.isCallerAllocated === true;\n\nconst collectRefArg = (\n descriptor: RefDescriptor,\n wrappedValue: unknown,\n inputs: unknown[],\n outParams: OutParam[],\n): void => {\n if (descriptor.inout === true) {\n inputs.push((wrappedValue as { value: unknown }).value);\n }\n\n outParams.push({ value: wrappedValue, descriptor });\n};\n\nconst collectCallbackArg = (\n descriptor: Descriptor | undefined,\n wrappedValue: unknown,\n inputs: unknown[],\n outParams: OutParam[],\n): void => {\n if (descriptor?.kind === \"ref\") {\n collectRefArg(descriptor, wrappedValue, inputs, outParams);\n\n return;\n }\n\n inputs.push(wrappedValue);\n\n if (descriptor !== undefined && isCallerAllocatedOut(descriptor)) {\n outParams.push({ value: wrappedValue, descriptor });\n }\n};\n\nconst partitionCallbackArgs = (\n effectiveTypes: Descriptor[],\n wrapped: unknown[],\n start: number,\n): { inputs: unknown[]; outParams: OutParam[] } => {\n const inputs: unknown[] = [];\n const outParams: OutParam[] = [];\n\n for (let i = start; i < effectiveTypes.length; i++) {\n collectCallbackArg(effectiveTypes[i], wrapped[i], inputs, outParams);\n }\n\n return { inputs, outParams };\n};\n\nconst writeOutParams = (outParams: OutParam[], outValues: unknown[]): void => {\n for (const [position, outParam] of outParams.entries()) {\n const outValue = outValues[position];\n\n if (outParam.descriptor.kind === \"ref\") {\n (outParam.value as { value: unknown }).value = outValue;\n } else if (outValue != null && outParam.value != null) {\n fillCallerAllocatedBuffer(outParam.descriptor, outParam.value, outValue);\n }\n }\n};\n\nconst getThisArg = (receiver: CallbackReceiver, wrapped: unknown[]): unknown =>\n receiver === \"this\" ? (wrapped[0] ?? null) : null;\n\nconst runCallback = (plan: CallbackPlan, rawArgs: unknown[]): unknown => {\n const { effectiveTypes, returnDescriptor } = plan;\n const wrapped = effectiveTypes.map((descriptor, i) => fromNative(descriptor, rawArgs[i]));\n const thisArg = getThisArg(plan.receiver, wrapped);\n const { inputs, outParams } = partitionCallbackArgs(effectiveTypes, wrapped, plan.start);\n const result = plan.fn.apply(thisArg, inputs);\n\n if (outParams.length === 0) {\n return toNative(returnDescriptor, result);\n }\n\n const { primary, outValues } = splitTupleResult(result, returnDescriptor.kind !== \"void\", outParams.length);\n writeOutParams(outParams, outValues);\n\n return toNative(returnDescriptor, primary);\n};\n\nconst getEffectiveTypes = (spec: CallbackSpec): Descriptor[] => {\n const { userDataIndex } = spec;\n\n if (userDataIndex === undefined) {\n return spec.argDescriptors;\n }\n\n return spec.argDescriptors.filter((_, i) => i !== userDataIndex);\n};\n\nconst wrapCallbackValue = (spec: CallbackDescriptor, callback: unknown): unknown =>\n callback == null ? callback : wrapCallback(callback as Callback, spec, \"none\");\n\nfunction wrapCallback(fn: Callback, spec: CallbackSpec, receiver: CallbackReceiver): Callback {\n const plan: CallbackPlan = {\n fn,\n effectiveTypes: getEffectiveTypes(spec),\n returnDescriptor: spec.returnDescriptor,\n start: receiver === \"none\" ? 0 : 1,\n receiver,\n };\n\n return (...rawArgs: unknown[]): unknown => runCallback(plan, rawArgs);\n}\n\nexport { wrapCallbackValue, wrapCallback };\n"]}
1
+ {"version":3,"file":"callback.js","sourceRoot":"","sources":["../src/callback.ts"],"names":[],"mappings":"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","sourcesContent":["import { copy, type Descriptor } from \"@gtkx/native\";\nimport type { CallbackDescriptor, RefDescriptor } from \"./descriptors.js\";\nimport { foldedLengthSources, type LengthSource, type LengthSources } from \"./folded-lengths.js\";\nimport { fromNative, toNative } from \"./native-value.js\";\nimport { getHandle } from \"./registry.js\";\nimport { splitTupleResult } from \"./tuple.js\";\nimport { copyValue } from \"./value.js\";\nimport { popSeedFrame, pushSeedFrame, type RefSeeds } from \"./vfunc-seeds.js\";\n\ntype Callback = (...args: unknown[]) => unknown;\ntype CallbackKind = \"vfunc\" | \"signal\" | \"callback\";\ntype CallbackTraits = { isInstanceBound: boolean; hasInstanceArg: boolean; hasFoldedLengths: boolean };\ntype OutParam = { value: unknown; descriptor: Descriptor; argIndex: number };\ntype LengthLink = { target: OutParam; sources: LengthSource[] };\ntype OutParamGroups = { lengthLinks: LengthLink[]; valueParams: OutParam[] };\ntype OutValues = Map<number, unknown>;\n\ntype CallbackSpec = {\n argDescriptors: Descriptor[];\n returnDescriptor: Descriptor;\n userDataIndex?: number;\n};\n\ntype CallbackPlan = {\n fn: Callback;\n effectiveTypes: Descriptor[];\n returnDescriptor: Descriptor;\n hasPrimary: boolean;\n start: number;\n isInstanceBound: boolean;\n lengthSources: LengthSources;\n hasOutParams: boolean;\n hasRefOutParams: boolean;\n};\n\nconst CALLBACK_TRAITS: Record<CallbackKind, CallbackTraits> = {\n callback: { isInstanceBound: false, hasInstanceArg: false, hasFoldedLengths: true },\n signal: { isInstanceBound: false, hasInstanceArg: true, hasFoldedLengths: false },\n vfunc: { isInstanceBound: true, hasInstanceArg: true, hasFoldedLengths: true },\n};\n\nconst fillCallerAllocatedBuffer = (descriptor: Descriptor, target: object, source: object): void => {\n if (descriptor.kind === \"boxed\" && descriptor.typeName === \"GValue\") {\n copyValue(getHandle(target), getHandle(source));\n\n return;\n }\n\n if ((descriptor.kind === \"boxed\" || descriptor.kind === \"struct\") && descriptor.size !== undefined) {\n copy(getHandle(target), getHandle(source), descriptor.size);\n\n return;\n }\n\n throw new Error(`Cannot write caller-allocated ${descriptor.kind} out-parameter: no known byte size`);\n};\n\nconst isCallerAllocatedOut = (descriptor: Descriptor): boolean =>\n (descriptor.kind === \"boxed\" || descriptor.kind === \"struct\") && descriptor.isCallerAllocated === true;\n\nconst collectRefArg = (\n descriptor: RefDescriptor,\n wrappedValue: unknown,\n inputs: unknown[],\n out: { params: OutParam[]; argIndex: number },\n): void => {\n if (descriptor.inout === true) {\n inputs.push((wrappedValue as { value: unknown }).value);\n }\n\n out.params.push({ value: wrappedValue, descriptor, argIndex: out.argIndex });\n};\n\nconst collectCallbackArg = (\n descriptor: Descriptor | undefined,\n wrappedValue: unknown,\n inputs: unknown[],\n out: { params: OutParam[]; argIndex: number },\n): void => {\n if (descriptor?.kind === \"ref\") {\n collectRefArg(descriptor, wrappedValue, inputs, out);\n\n return;\n }\n\n inputs.push(wrappedValue);\n\n if (descriptor !== undefined && isCallerAllocatedOut(descriptor)) {\n out.params.push({ value: wrappedValue, descriptor, argIndex: out.argIndex });\n }\n};\n\nconst partitionCallbackArgs = (\n effectiveTypes: Descriptor[],\n wrapped: unknown[],\n start: number,\n): { inputs: unknown[]; outParams: OutParam[] } => {\n const inputs: unknown[] = [];\n const params: OutParam[] = [];\n const collected = { params, argIndex: start };\n\n for (let i = start; i < effectiveTypes.length; i++) {\n collected.argIndex = i;\n collectCallbackArg(effectiveTypes[i], wrapped[i], inputs, collected);\n }\n\n return { inputs, outParams: params };\n};\n\nconst hasOutParamArg = (descriptor: Descriptor | undefined): boolean =>\n descriptor !== undefined && (descriptor.kind === \"ref\" || isCallerAllocatedOut(descriptor));\n\nconst hasRefOutParamArg = (descriptor: Descriptor | undefined): boolean =>\n descriptor?.kind === \"ref\" && descriptor.inout !== true;\n\nconst haveOutParamArgs = (effectiveTypes: Descriptor[], start: number): boolean =>\n effectiveTypes.slice(start).some((descriptor) => hasOutParamArg(descriptor));\n\nconst haveRefOutParamArgs = (effectiveTypes: Descriptor[], start: number): boolean =>\n effectiveTypes.slice(start).some((descriptor) => hasRefOutParamArg(descriptor));\n\nconst groupOutParams = (outParams: OutParam[], lengthSources: LengthSources): OutParamGroups => {\n const groups: OutParamGroups = { lengthLinks: [], valueParams: [] };\n\n for (const outParam of outParams) {\n const sources = lengthSources.get(outParam.argIndex);\n\n if (sources === undefined) {\n groups.valueParams.push(outParam);\n } else {\n groups.lengthLinks.push({ target: outParam, sources });\n }\n }\n\n return groups;\n};\n\nconst getLength = (value: unknown): number => {\n const length = (value as { length?: unknown } | null | undefined)?.length;\n\n return typeof length === \"number\" ? length : 0;\n};\n\nconst lengthSourceValue = (source: LengthSource, outValues: OutValues, primary: unknown): unknown =>\n source.kind === \"return\" ? primary : outValues.get(source.argIndex);\n\nconst foldedLength = (sources: LengthSource[], outValues: OutValues, primary: unknown): number =>\n Math.min(...sources.map((source) => getLength(lengthSourceValue(source, outValues, primary))));\n\nconst resolveOutValues = (groups: OutParamGroups, values: unknown[], primary: unknown): OutValues => {\n const outValues: OutValues = new Map();\n\n for (const [position, outParam] of groups.valueParams.entries()) {\n outValues.set(outParam.argIndex, values[position]);\n }\n\n for (const link of groups.lengthLinks) {\n outValues.set(link.target.argIndex, foldedLength(link.sources, outValues, primary));\n }\n\n return outValues;\n};\n\nconst writeOutParams = (outParams: OutParam[], outValues: OutValues): void => {\n for (const outParam of outParams) {\n const { descriptor } = outParam;\n const outValue = outValues.get(outParam.argIndex);\n\n if (descriptor.kind === \"ref\") {\n (outParam.value as { value: unknown }).value = toNative(descriptor.innerDescriptor, outValue);\n } else if (outValue != null && outParam.value != null) {\n fillCallerAllocatedBuffer(descriptor, outParam.value, outValue);\n }\n }\n};\n\nconst collectRefSeeds = (outParams: OutParam[]): RefSeeds => {\n const seeds: RefSeeds = new Map();\n\n for (const outParam of outParams) {\n const seed = (outParam.value as { value?: unknown } | null)?.value;\n\n if (seed != null && hasRefOutParamArg(outParam.descriptor)) {\n seeds.set(outParam.argIndex, seed);\n }\n }\n\n return seeds;\n};\n\nconst applyCallback = (plan: CallbackPlan, thisArg: unknown, inputs: unknown[], outParams: OutParam[]): unknown => {\n if (!plan.hasRefOutParams) {\n return plan.fn.apply(thisArg, inputs);\n }\n\n pushSeedFrame({ argDescriptors: plan.effectiveTypes, instance: thisArg, seeds: collectRefSeeds(outParams) });\n\n try {\n return plan.fn.apply(thisArg, inputs);\n } finally {\n popSeedFrame();\n }\n};\n\nconst getThisArg = (isInstanceBound: boolean, wrapped: unknown[]): unknown =>\n isInstanceBound ? (wrapped[0] ?? null) : null;\n\nconst wrapCallbackArgs = (effectiveTypes: Descriptor[], rawArgs: unknown[]): void => {\n let index = 0;\n\n for (const descriptor of effectiveTypes) {\n rawArgs[index] = fromNative(descriptor, rawArgs[index]);\n index += 1;\n }\n};\n\nconst trimCallbackInputs = (plan: CallbackPlan, wrapped: unknown[]): unknown[] => {\n const count = plan.effectiveTypes.length;\n\n if (wrapped.length > count) {\n wrapped.length = count;\n }\n\n for (let index = 0; index < plan.start; index++) {\n wrapped.shift();\n }\n\n return wrapped;\n};\n\nconst nativeReturn = (plan: CallbackPlan, primary: unknown): unknown =>\n toNative(plan.returnDescriptor, plan.hasPrimary ? primary : undefined);\n\nconst runCallback = (plan: CallbackPlan, rawArgs: unknown[]): unknown => {\n const { effectiveTypes } = plan;\n wrapCallbackArgs(effectiveTypes, rawArgs);\n const thisArg = getThisArg(plan.isInstanceBound, rawArgs);\n\n if (!plan.hasOutParams) {\n return nativeReturn(plan, plan.fn.apply(thisArg, trimCallbackInputs(plan, rawArgs)));\n }\n\n const { inputs, outParams } = partitionCallbackArgs(effectiveTypes, rawArgs, plan.start);\n const result = applyCallback(plan, thisArg, inputs, outParams);\n\n if (outParams.length === 0) {\n return nativeReturn(plan, result);\n }\n\n const groups = groupOutParams(outParams, plan.lengthSources);\n const { primary, outValues } = splitTupleResult(result, plan.hasPrimary, groups.valueParams.length);\n writeOutParams(outParams, resolveOutValues(groups, outValues, primary));\n\n return nativeReturn(plan, primary);\n};\n\nconst planLengthSources = (spec: CallbackSpec, hasFoldedLengths: boolean): LengthSources =>\n hasFoldedLengths ? foldedLengthSources(spec) : new Map<number, LengthSource[]>();\n\nconst getEffectiveTypes = (spec: CallbackSpec): Descriptor[] => {\n const { userDataIndex } = spec;\n\n if (userDataIndex === undefined) {\n return spec.argDescriptors;\n }\n\n return spec.argDescriptors.filter((_, i) => i !== userDataIndex);\n};\n\nconst wrapCallbackValue = (spec: CallbackDescriptor, callback: unknown): unknown =>\n callback == null ? callback : wrapCallback(callback as Callback, spec, \"callback\");\n\nfunction wrapCallback(fn: Callback, spec: CallbackSpec, kind: CallbackKind): Callback {\n const effectiveTypes = getEffectiveTypes(spec);\n const { isInstanceBound, hasInstanceArg, hasFoldedLengths } = CALLBACK_TRAITS[kind];\n const start = hasInstanceArg ? 1 : 0;\n\n const plan: CallbackPlan = {\n fn,\n effectiveTypes,\n returnDescriptor: spec.returnDescriptor,\n hasPrimary: spec.returnDescriptor.kind !== \"void\",\n start,\n isInstanceBound,\n lengthSources: planLengthSources(spec, hasFoldedLengths),\n hasOutParams: haveOutParamArgs(effectiveTypes, start),\n hasRefOutParams: haveRefOutParamArgs(effectiveTypes, start),\n };\n\n return (...rawArgs: unknown[]): unknown => runCallback(plan, rawArgs);\n}\n\nexport { isCallerAllocatedOut, wrapCallbackValue, wrapCallback };\n"]}
@@ -0,0 +1,26 @@
1
+ import { type ExternalObject, type Handle } from "@gtkx/native";
2
+ /**
3
+ * Handler backing a `GClosure`. It receives the closure's parameters already converted from their
4
+ * `GValue`s, and its result is written back into the closure's return `GValue` when it has one.
5
+ *
6
+ * A parameter that is itself a `GValue`, such as the target a property binding transform fills in,
7
+ * arrives as the caller's own `GObject.Value` rather than a copy, so writing to it is how the
8
+ * handler produces that parameter's value. It stops being valid once the handler returns.
9
+ */
10
+ type ClosureCallback = (...args: never[]) => unknown;
11
+ /**
12
+ * Marshals a value passed where a `GObject.Closure` is expected into a closure handle: a function
13
+ * becomes a new `GClosure` dispatching into it, and an existing closure yields its own handle.
14
+ * @param value Function to wrap, or an already-built closure.
15
+ * @throws {ClosureMarshalError} When the value is neither.
16
+ */
17
+ declare function toClosure(value: unknown): ExternalObject<Handle>;
18
+ /** Same as {@link toClosure}, but passes a null or undefined value through as no closure at all. */
19
+ declare function tryToClosure(value: unknown): ExternalObject<Handle> | undefined;
20
+ /** Thrown when a value passed where a `GObject.Closure` is expected cannot be marshalled into one. */
21
+ declare class ClosureMarshalError extends TypeError {
22
+ /** Name callers match on when the error is caught as a plain `TypeError`. */
23
+ name: string;
24
+ }
25
+ export { type ClosureCallback, ClosureMarshalError, toClosure, tryToClosure };
26
+ //# sourceMappingURL=closure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"closure.d.ts","sourceRoot":"","sources":["../src/closure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,MAAM,EAAQ,MAAM,cAAc,CAAC;AAStE;;;;;;;GAOG;AACH,KAAK,eAAe,GAAG,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC;AAyFrD;;;;;GAKG;AACH,iBAAS,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAUzD;AAED,oGAAoG;AACpG,iBAAS,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,GAAG,SAAS,CAExE;AAED,sGAAsG;AACtG,cAAM,mBAAoB,SAAQ,SAAS;IACvC,6EAA6E;IAC7D,IAAI,SAAyB;CAChD;AAED,OAAO,EAAE,KAAK,eAAe,EAAE,mBAAmB,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC"}