-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathgobject-ffi.ts
More file actions
89 lines (83 loc) · 2.9 KB
/
Copy pathgobject-ffi.ts
File metadata and controls
89 lines (83 loc) · 2.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import { FFIType } from 'bun:ffi';
import { dlopen } from '../dlopen';
import { UnsupportedPlatformError } from '../../../common/errors';
import { currentPlatform } from '../../../common/platform';
/**
* Loads GObject's signal-connection and refcount primitives plus the
* construct-only `g_object_new` path used to build a `WebKitWebView` with a
* pre-wired `WebKitUserContentManager`.
*
* `libgobject-2.0` is a hard dependency of GTK 4, so it is always present
* wherever `libgtk-4` is. Convention: `gboolean` is {@link FFIType.i32};
* `gulong`/`GType` are {@link FFIType.u64} (BigInt); `GConnectFlags` is
* {@link FFIType.u32}; all handles are real pointers.
*/
const LIBGOBJECT_PATH = 'libgobject-2.0.so.0';
/** Default `GConnectFlags` (no after/swapped) for `g_signal_connect_data`. */
export const G_CONNECT_DEFAULT = 0;
/**
* The GObject FFI symbol descriptor table.
*
* `g_signal_connect_data` is the real symbol behind the `g_signal_connect`
* C macro; pass `c_handler = jsCallback.ptr`, `data = 0`, `destroy_data = 0`,
* `connect_flags = 0`. It returns the `gulong` handler id kept as a BigInt.
*
* `g_object_new` is true C varargs; the fixed 4-arity `[u64, cstring, ptr, ptr]`
* is valid ONLY for the literal call
* `(webkit_web_view_get_type(), "user-content-manager", ucm, NULL)`. The
* trailing pointer MUST be a real null terminator or g_object_new walks past the
* varargs and corrupts/crashes.
*/
export const GOBJECT_FFI_SYMBOLS = {
g_signal_connect_data: {
args: [
FFIType.pointer,
FFIType.cstring,
FFIType.pointer,
FFIType.pointer,
FFIType.pointer,
FFIType.u32,
],
returns: FFIType.u64,
},
g_signal_handler_disconnect: {
args: [FFIType.pointer, FFIType.u64],
returns: FFIType.void,
},
g_object_ref: {
args: [FFIType.pointer],
returns: FFIType.pointer,
},
g_object_unref: {
args: [FFIType.pointer],
returns: FFIType.void,
},
g_object_new: {
args: [FFIType.u64, FFIType.cstring, FFIType.pointer, FFIType.pointer],
returns: FFIType.pointer,
},
// C varargs; the fixed `[ptr, cstring, ptr (out), ptr (null)]` arity is valid
// ONLY for reading a SINGLE property into a caller-allocated out buffer, e.g.
// `g_object_get(settings, "gtk-application-prefer-dark-theme", &gboolean, NULL)`.
g_object_get: {
args: [FFIType.pointer, FFIType.cstring, FFIType.pointer, FFIType.pointer],
returns: FFIType.void,
},
} as const;
const cache: { ffi: ReturnType<typeof dlopen<typeof GOBJECT_FFI_SYMBOLS>> | undefined } = {
ffi: undefined,
};
export const loadGObjectFFI = () => {
const platform = currentPlatform();
if (platform !== 'linux') {
throw new UnsupportedPlatformError(
`loadGObjectFFI() is only supported on Linux; current platform is ${platform}`,
);
}
if (cache.ffi) {
return cache.ffi;
}
const ffi = dlopen(LIBGOBJECT_PATH, GOBJECT_FFI_SYMBOLS);
cache.ffi = ffi;
return ffi;
};