@gjsify/node-gi 0.26.0 → 0.27.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/README.md +57 -12
- package/cairo.d.ts +121 -121
- package/cairo.js +425 -426
- package/gettext.d.ts +24 -24
- package/gettext.js +42 -42
- package/gi.d.ts +170 -122
- package/gi.js +1449 -1460
- package/globals.d.ts +28 -28
- package/globals.js +103 -97
- package/gtk-runtime.js +9 -5
- package/index.d.ts +133 -152
- package/index.js +82 -100
- package/native-paths.js +104 -0
- package/overrides/_signals.js +108 -111
- package/overrides/byte-array.js +135 -135
- package/overrides/gio-dbus.js +681 -658
- package/overrides/mainloop.js +27 -27
- package/overrides/package.js +128 -128
- package/package.json +6 -2
- package/prebuilds/darwin-arm64/node_gi.node +0 -0
- package/prebuilds/darwin-x64/node_gi.node +0 -0
- package/prebuilds/win32-x64/node_gi.node +0 -0
- package/scripts/install.mjs +238 -0
- package/scripts/win-gi-gyp-flags.mjs +160 -0
- package/system.d.ts +13 -13
- package/system.js +35 -35
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Emit Windows/MSVC-ready include dirs or import-lib paths for binding.gyp's
|
|
3
|
+
// `OS=="win"` branch, derived from pkg-config/pkgconf (gvsbuild ships pkgconf.exe
|
|
4
|
+
// + a pkg-config.exe copy in bin/, put on PATH by the CI job).
|
|
5
|
+
//
|
|
6
|
+
// node scripts/win-gi-gyp-flags.mjs --includes -> one bare include dir per line
|
|
7
|
+
// node scripts/win-gi-gyp-flags.mjs --libs -> one import-lib path per line
|
|
8
|
+
//
|
|
9
|
+
// gyp's msvs generator ignores `cflags`/`cflags_cc`/`xcode_settings` (those feed
|
|
10
|
+
// the make/xcode generators only), so the Windows branch must feed BARE include
|
|
11
|
+
// dirs into `include_dirs` and FULL .lib paths into `libraries` — the exact shapes
|
|
12
|
+
// gyp hands straight to cl.exe / link.exe. Emitting resolved paths here avoids the
|
|
13
|
+
// `-I`/`-l`/`-L`→MSVC translation ambiguity of raw pkg-config output going through
|
|
14
|
+
// gyp.
|
|
15
|
+
//
|
|
16
|
+
// --libs uses `--static` so the PRIVATE closure is pulled: girepository-2.0.pc has
|
|
17
|
+
// `Requires.private: gmodule-no-export-2.0, gio-2.0, libffi` and node-gi calls
|
|
18
|
+
// ffi_call / Gio directly. On Linux the dynamic linker resolves those lazily from
|
|
19
|
+
// the shared-object global scope, but MSVC/PE resolves every import at link time,
|
|
20
|
+
// so the private libs must be named explicitly.
|
|
21
|
+
//
|
|
22
|
+
// `--define-prefix` makes pkgconf recompute each .pc's `prefix` from the .pc file
|
|
23
|
+
// location, so the bundle works regardless of where gvsbuild's tree is extracted
|
|
24
|
+
// (its .pc files bake an absolute build-machine prefix otherwise).
|
|
25
|
+
import { execFileSync } from 'node:child_process';
|
|
26
|
+
import { existsSync, readdirSync } from 'node:fs';
|
|
27
|
+
import { join } from 'node:path';
|
|
28
|
+
|
|
29
|
+
const PKGS = ['girepository-2.0', 'cairo'];
|
|
30
|
+
const mode = process.argv[2];
|
|
31
|
+
const pkgConfig = process.env.PKG_CONFIG || 'pkg-config';
|
|
32
|
+
|
|
33
|
+
function pkgConfigOut(extraArgs) {
|
|
34
|
+
// Exit-tolerant: gvsbuild's pkgconf can exit non-zero (e.g. `--static` walks a
|
|
35
|
+
// Requires.private graph and trips over a missing .pc) yet still print the
|
|
36
|
+
// resolvable flags. execFileSync THROWS on a non-zero exit — so capture the
|
|
37
|
+
// stdout it attached to the error instead of letting the whole helper crash
|
|
38
|
+
// (that empty-stdout crash left include_dirs blank → C1083 on ffi.h).
|
|
39
|
+
try {
|
|
40
|
+
return execFileSync(pkgConfig, ['--define-prefix', ...extraArgs, ...PKGS], {
|
|
41
|
+
encoding: 'utf8',
|
|
42
|
+
}).trim();
|
|
43
|
+
} catch (error) {
|
|
44
|
+
return typeof error?.stdout === 'string' ? error.stdout.trim() : '';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function tokens(s) {
|
|
49
|
+
// pkg-config separates with spaces; paths from gvsbuild carry no spaces.
|
|
50
|
+
return s.split(/\s+/).filter(Boolean);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function stripQuotes(s) {
|
|
54
|
+
return s.replace(/^"(.*)"$/, '$1');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// gyp/MSBuild + cl.exe accept forward slashes and treat them uniformly; emit them
|
|
58
|
+
// so an include dir / .lib path never carries a backslash that a downstream
|
|
59
|
+
// generator might mis-handle (the pkg-config dirs already use forward slashes).
|
|
60
|
+
function toGyp(p) {
|
|
61
|
+
return p.replace(/\\/g, '/');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Shallow BFS for a header under `root` (bounded depth so we never walk the whole
|
|
65
|
+
// ~300 MB GTK tree). Returns the CONTAINING directory, or null.
|
|
66
|
+
function findHeaderDir(root, filename, maxDepth = 4) {
|
|
67
|
+
const queue = [[root, 0]];
|
|
68
|
+
while (queue.length) {
|
|
69
|
+
const [dir, depth] = queue.shift();
|
|
70
|
+
let entries;
|
|
71
|
+
try {
|
|
72
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
73
|
+
} catch {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
for (const e of entries) {
|
|
77
|
+
if (e.isFile() && e.name === filename) return dir;
|
|
78
|
+
}
|
|
79
|
+
if (depth < maxDepth) {
|
|
80
|
+
for (const e of entries) {
|
|
81
|
+
if (e.isDirectory()) queue.push([join(dir, e.name), depth + 1]);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (mode === '--includes') {
|
|
89
|
+
// NON-static --cflags-only-I: on gvsbuild `--static` exits non-zero (a private
|
|
90
|
+
// .pc misses) and once threw the whole helper, blanking include_dirs. The plain
|
|
91
|
+
// form resolves glib-2.0/lib-glib-2.0-include/cairo cleanly. It does NOT emit
|
|
92
|
+
// libffi's include dir (libffi is Requires.private), but the addon needs <ffi.h>
|
|
93
|
+
// via girffi.h — the GTK_PREFIX fallback below supplies it.
|
|
94
|
+
const dirs = tokens(pkgConfigOut(['--cflags-only-I']))
|
|
95
|
+
.filter((t) => t.startsWith('-I'))
|
|
96
|
+
.map((t) => stripQuotes(t.slice(2)));
|
|
97
|
+
const prefix = process.env.GTK_PREFIX;
|
|
98
|
+
if (prefix) {
|
|
99
|
+
// Guaranteed base from the known gvsbuild layout (in case pkg-config yields
|
|
100
|
+
// nothing) PLUS the bare include root, where gvsbuild installs libffi's
|
|
101
|
+
// ffi.h + ffitarget.h (MSVC does not auto-search a prefix include root).
|
|
102
|
+
dirs.push(
|
|
103
|
+
join(prefix, 'include'),
|
|
104
|
+
join(prefix, 'include', 'glib-2.0'),
|
|
105
|
+
join(prefix, 'lib', 'glib-2.0', 'include'),
|
|
106
|
+
join(prefix, 'include', 'cairo'),
|
|
107
|
+
);
|
|
108
|
+
// Last resort: locate ffi.h anywhere under the tree and add its dir.
|
|
109
|
+
if (!dirs.some((d) => existsSync(join(d, 'ffi.h')))) {
|
|
110
|
+
const ffiDir =
|
|
111
|
+
findHeaderDir(join(prefix, 'include'), 'ffi.h') ?? findHeaderDir(join(prefix, 'lib'), 'ffi.h');
|
|
112
|
+
if (ffiDir) dirs.push(ffiDir);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
process.stdout.write([...new Set(dirs.filter((d) => existsSync(d)).map(toGyp))].join('\n'));
|
|
116
|
+
} else if (mode === '--libs') {
|
|
117
|
+
// A SHARED addon links each GTK/GLib DLL through its DIRECT import lib and lets
|
|
118
|
+
// that DLL resolve its own private deps at load — so link only the import libs
|
|
119
|
+
// whose symbols the addon's own object files reference, NOT pkg-config's
|
|
120
|
+
// `--static` transitive closure (which over-pulls cairo's/glib's private static
|
|
121
|
+
// deps — libpng/freetype/harfbuzz/pcre2/`-lz`→zlib.lib — whose `-l`→`.lib` names
|
|
122
|
+
// don't all map on gvsbuild, breaking the link). This DIRECT set is known + stable:
|
|
123
|
+
// girepository-2.0 the gi_* engine
|
|
124
|
+
// glib/gobject/gio/gmodule-2.0 g_*/GObject/GValue/GSignal/GClosure/Gio
|
|
125
|
+
// ffi ffi_call / ffi_closure_alloc (girffi + the vfunc/callback trampolines)
|
|
126
|
+
// cairo the native cairo foreign-struct binding (src/cairo.cc)
|
|
127
|
+
// Pango/GdkPixbuf/Graphene are NOT linked — the conformance programs load their
|
|
128
|
+
// typelibs at RUNTIME (girepository dlopens the DLL by soname), not at link time.
|
|
129
|
+
const DIRECT_LIBS = ['girepository-2.0', 'gio-2.0', 'gobject-2.0', 'gmodule-2.0', 'glib-2.0', 'ffi', 'cairo'];
|
|
130
|
+
// Locate the import-lib dir: GTK_PREFIX/lib, else pkg-config's -L.
|
|
131
|
+
const searchDirs = [];
|
|
132
|
+
if (process.env.GTK_PREFIX) searchDirs.push(join(process.env.GTK_PREFIX, 'lib'));
|
|
133
|
+
for (const t of tokens(pkgConfigOut(['--libs-only-L']))) {
|
|
134
|
+
if (t.startsWith('-L')) searchDirs.push(stripQuotes(t.slice(2)));
|
|
135
|
+
}
|
|
136
|
+
const resolved = [];
|
|
137
|
+
for (const name of new Set(DIRECT_LIBS)) {
|
|
138
|
+
let found = null;
|
|
139
|
+
for (const dir of new Set(searchDirs)) {
|
|
140
|
+
for (const cand of [`${name}.lib`, `lib${name}.lib`]) {
|
|
141
|
+
const p = join(dir, cand);
|
|
142
|
+
if (existsSync(p)) {
|
|
143
|
+
found = p;
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (found) break;
|
|
148
|
+
}
|
|
149
|
+
if (found) resolved.push(found);
|
|
150
|
+
else if (name !== 'gmodule-2.0') {
|
|
151
|
+
// gmodule is optional (girepository may pull it internally); everything
|
|
152
|
+
// else is required — surface a missing import lib loudly.
|
|
153
|
+
throw new Error(`win-gi-gyp-flags: import lib for '${name}' not found under ${searchDirs.join(', ')}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
process.stdout.write([...new Set(resolved.map(toGyp))].join('\n'));
|
|
157
|
+
} else {
|
|
158
|
+
console.error('usage: node scripts/win-gi-gyp-flags.mjs <--includes|--libs>');
|
|
159
|
+
process.exit(2);
|
|
160
|
+
}
|
package/system.d.ts
CHANGED
|
@@ -30,19 +30,19 @@ export function dumpMemoryInfo(): void;
|
|
|
30
30
|
|
|
31
31
|
/** The GJS `System` module object (`import System from 'system'`). */
|
|
32
32
|
export interface SystemModule {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
33
|
+
exit(code?: number): void;
|
|
34
|
+
gc(): void;
|
|
35
|
+
version: number;
|
|
36
|
+
readonly programArgs: string[];
|
|
37
|
+
readonly programInvocationName: string;
|
|
38
|
+
readonly programPath: string | null;
|
|
39
|
+
addressOf(): string;
|
|
40
|
+
addressOfGObject(): string;
|
|
41
|
+
refcount(): number;
|
|
42
|
+
breakpoint(): void;
|
|
43
|
+
clearDateCaches(): void;
|
|
44
|
+
dumpHeap(): void;
|
|
45
|
+
dumpMemoryInfo(): void;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
declare const System: SystemModule;
|
package/system.js
CHANGED
|
@@ -35,14 +35,14 @@
|
|
|
35
35
|
// module is loaded from `@gjsify/node-gi/globals`, before any bundle body (and
|
|
36
36
|
// therefore before any register side effect) runs.
|
|
37
37
|
const runtimeProcess = (() => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
38
|
+
const hostProcess = typeof process !== 'undefined' ? process : undefined;
|
|
39
|
+
try {
|
|
40
|
+
const builtin = hostProcess?.getBuiltinModule?.('node:process');
|
|
41
|
+
if (builtin && typeof builtin.exit === 'function') return builtin;
|
|
42
|
+
} catch {
|
|
43
|
+
// getBuiltinModule missing or refusing the specifier — use the captured one.
|
|
44
|
+
}
|
|
45
|
+
return hostProcess;
|
|
46
46
|
})();
|
|
47
47
|
|
|
48
48
|
const runtimeExit = typeof runtimeProcess?.exit === 'function' ? runtimeProcess.exit.bind(runtimeProcess) : undefined;
|
|
@@ -50,17 +50,17 @@ const runtimeExit = typeof runtimeProcess?.exit === 'function' ? runtimeProcess.
|
|
|
50
50
|
// `programArgs` mirrors GJS's ARGV: the script arguments, excluding the
|
|
51
51
|
// interpreter (argv[0]) and the script path (argv[1]).
|
|
52
52
|
function readProgramArgs() {
|
|
53
|
-
|
|
53
|
+
return Array.isArray(runtimeProcess?.argv) ? runtimeProcess.argv.slice(2) : [];
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
// `programInvocationName` / `programPath` track the running script — Node's
|
|
57
57
|
// `process.argv[1]`.
|
|
58
58
|
function readProgramInvocationName() {
|
|
59
|
-
|
|
59
|
+
return runtimeProcess?.argv?.[1] || '';
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
function readProgramPath() {
|
|
63
|
-
|
|
63
|
+
return runtimeProcess?.argv?.[1] || null;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
/**
|
|
@@ -74,12 +74,12 @@ function readProgramPath() {
|
|
|
74
74
|
* `conformance/programs/system-exit-lifetime.conf.mjs`).
|
|
75
75
|
*/
|
|
76
76
|
export function exit(code) {
|
|
77
|
-
|
|
77
|
+
if (runtimeExit !== undefined) runtimeExit(code ?? 0);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
/** Trigger a garbage collection if the host exposed `globalThis.gc` (`--expose-gc`). */
|
|
81
81
|
export function gc() {
|
|
82
|
-
|
|
82
|
+
if (typeof globalThis.gc === 'function') globalThis.gc();
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
/** The SpiderMonkey/mozjs version number — no equivalent on Node, reported as 0. */
|
|
@@ -96,17 +96,17 @@ export const programPath = readProgramPath();
|
|
|
96
96
|
|
|
97
97
|
/** Return the address of a JS object as a string. No Node equivalent — stub. */
|
|
98
98
|
export function addressOf() {
|
|
99
|
-
|
|
99
|
+
return '0x0';
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
/** Return the address of a GObject as a string. No Node equivalent — stub. */
|
|
103
103
|
export function addressOfGObject() {
|
|
104
|
-
|
|
104
|
+
return '0x0';
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
/** Return the refcount of a GObject. No Node equivalent — stub. */
|
|
108
108
|
export function refcount() {
|
|
109
|
-
|
|
109
|
+
return 0;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
/** Trigger a debugger breakpoint. No-op on Node. */
|
|
@@ -128,25 +128,25 @@ export function dumpMemoryInfo() {}
|
|
|
128
128
|
* track the running script.
|
|
129
129
|
*/
|
|
130
130
|
const System = {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
131
|
+
exit,
|
|
132
|
+
gc,
|
|
133
|
+
version,
|
|
134
|
+
addressOf,
|
|
135
|
+
addressOfGObject,
|
|
136
|
+
refcount,
|
|
137
|
+
breakpoint,
|
|
138
|
+
clearDateCaches,
|
|
139
|
+
dumpHeap,
|
|
140
|
+
dumpMemoryInfo,
|
|
141
|
+
get programArgs() {
|
|
142
|
+
return readProgramArgs();
|
|
143
|
+
},
|
|
144
|
+
get programInvocationName() {
|
|
145
|
+
return readProgramInvocationName();
|
|
146
|
+
},
|
|
147
|
+
get programPath() {
|
|
148
|
+
return readProgramPath();
|
|
149
|
+
},
|
|
150
150
|
};
|
|
151
151
|
|
|
152
152
|
export default System;
|