@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/globals.d.ts CHANGED
@@ -6,38 +6,38 @@ import type { GettextModule } from './gettext.js';
6
6
 
7
7
  /** The legacy GJS `imports` object (a minimal Node-backed subset). */
8
8
  export interface GjsImports {
9
- /** `imports.gi.<Ns>` resolves a namespace; `imports.gi.versions.<Ns>` pins a version. */
10
- gi: {
11
- versions: Record<string, string | undefined>;
12
- [namespace: string]: unknown;
13
- };
14
- /** `imports.system` — the `@gjsify/node-gi/system` module (process identity + lifecycle). */
15
- system: SystemModule;
16
- /** `imports.gettext` — the `@gjsify/node-gi/gettext` module (no-translation passthrough). */
17
- gettext: GettextModule;
18
- /** `imports.byteArray` — the legacy GJS byte-array module (GJS semantics: zero-terminated, fatal decode). */
19
- byteArray: {
20
- ByteArray: new (arg?: number | Uint8Array) => {
21
- length: number;
22
- toString(encoding?: string): string;
23
- toGBytes(): unknown;
9
+ /** `imports.gi.<Ns>` resolves a namespace; `imports.gi.versions.<Ns>` pins a version. */
10
+ gi: {
11
+ versions: Record<string, string | undefined>;
12
+ [namespace: string]: unknown;
24
13
  };
25
- fromArray(array: Iterable<number>): unknown;
26
- fromGBytes(bytes: unknown): Uint8Array;
27
- fromString(string: string, encoding?: string): Uint8Array;
28
- toGBytes(array: Uint8Array): unknown;
29
- toString(byteArray: Uint8Array, encoding?: string): string;
30
- };
31
- versions: Record<string, unknown>;
14
+ /** `imports.system` — the `@gjsify/node-gi/system` module (process identity + lifecycle). */
15
+ system: SystemModule;
16
+ /** `imports.gettext` — the `@gjsify/node-gi/gettext` module (no-translation passthrough). */
17
+ gettext: GettextModule;
18
+ /** `imports.byteArray` — the legacy GJS byte-array module (GJS semantics: zero-terminated, fatal decode). */
19
+ byteArray: {
20
+ ByteArray: new (arg?: number | Uint8Array) => {
21
+ length: number;
22
+ toString(encoding?: string): string;
23
+ toGBytes(): unknown;
24
+ };
25
+ fromArray(array: Iterable<number>): unknown;
26
+ fromGBytes(bytes: unknown): Uint8Array;
27
+ fromString(string: string, encoding?: string): Uint8Array;
28
+ toGBytes(array: Uint8Array): unknown;
29
+ toString(byteArray: Uint8Array, encoding?: string): string;
30
+ };
31
+ versions: Record<string, unknown>;
32
32
  }
33
33
 
34
34
  declare global {
35
- var print: (...args: unknown[]) => void;
36
- var printerr: (...args: unknown[]) => void;
37
- var log: (...args: unknown[]) => void;
38
- var logError: (error: unknown, prefix?: string) => void;
39
- var ARGV: string[];
40
- var imports: GjsImports;
35
+ var print: (...args: unknown[]) => void;
36
+ var printerr: (...args: unknown[]) => void;
37
+ var log: (...args: unknown[]) => void;
38
+ var logError: (error: unknown, prefix?: string) => void;
39
+ var ARGV: string[];
40
+ var imports: GjsImports;
41
41
  }
42
42
 
43
43
  /** Install the GJS ambient globals on `globalThis` (idempotent). */
package/globals.js CHANGED
@@ -29,7 +29,7 @@ import { createPackage } from './overrides/package.js';
29
29
  // GJS stringifies each argument with String() and joins with a space (no
30
30
  // util.inspect object formatting) — match that for fidelity.
31
31
  function gjsFormat(args) {
32
- return args.map((a) => String(a)).join(' ');
32
+ return args.map((a) => String(a)).join(' ');
33
33
  }
34
34
 
35
35
  /**
@@ -37,112 +37,118 @@ function gjsFormat(args) {
37
37
  * only defined if absent, so it never clobbers a host that already provides it).
38
38
  */
39
39
  export function installGjsGlobals() {
40
- const g = globalThis;
40
+ const g = globalThis;
41
41
 
42
- if (typeof g.print === 'undefined') {
43
- g.print = (...args) => console.log(gjsFormat(args));
44
- }
45
- if (typeof g.printerr === 'undefined') {
46
- g.printerr = (...args) => console.error(gjsFormat(args));
47
- }
48
- if (typeof g.log === 'undefined') {
49
- // GJS `log` writes to the GLib structured log (stderr/journal).
50
- g.log = (...args) => console.error(gjsFormat(args));
51
- }
52
- if (typeof g.logError === 'undefined') {
53
- g.logError = (error, prefix) => {
54
- const head = prefix ? `${prefix}: ` : '';
55
- const body = error && error.stack ? error.stack : String(error);
56
- console.error(head + body);
57
- };
58
- }
59
- if (typeof g.ARGV === 'undefined') {
60
- // GJS ARGV excludes the interpreter + the script path (Node's argv[0]+[1]).
61
- g.ARGV = (typeof process !== 'undefined' && Array.isArray(process.argv))
62
- ? process.argv.slice(2)
63
- : [];
64
- }
42
+ if (typeof g.print === 'undefined') {
43
+ g.print = (...args) => console.log(gjsFormat(args));
44
+ }
45
+ if (typeof g.printerr === 'undefined') {
46
+ g.printerr = (...args) => console.error(gjsFormat(args));
47
+ }
48
+ if (typeof g.log === 'undefined') {
49
+ // GJS `log` writes to the GLib structured log (stderr/journal).
50
+ g.log = (...args) => console.error(gjsFormat(args));
51
+ }
52
+ if (typeof g.logError === 'undefined') {
53
+ g.logError = (error, prefix) => {
54
+ const head = prefix ? `${prefix}: ` : '';
55
+ const body = error && error.stack ? error.stack : String(error);
56
+ console.error(head + body);
57
+ };
58
+ }
59
+ if (typeof g.ARGV === 'undefined') {
60
+ // GJS ARGV excludes the interpreter + the script path (Node's argv[0]+[1]).
61
+ g.ARGV = typeof process !== 'undefined' && Array.isArray(process.argv) ? process.argv.slice(2) : [];
62
+ }
65
63
 
66
- if (typeof g.imports === 'undefined') {
67
- g.imports = makeImports();
68
- }
64
+ if (typeof g.imports === 'undefined') {
65
+ g.imports = makeImports();
66
+ }
69
67
 
70
- return g.imports;
68
+ return g.imports;
71
69
  }
72
70
 
73
71
  // Build the legacy `imports` object. `imports.gi.<Ns>` resolves a namespace via
74
72
  // the node-gi backend, honouring a version pinned in `imports.gi.versions.<Ns>`
75
73
  // (which GJS code sets before the first access).
76
74
  function makeImports() {
77
- const giVersions = Object.create(null);
78
- const giCache = new Map();
79
- const gi = new Proxy(
80
- { versions: giVersions },
81
- {
82
- get(target, name) {
83
- if (name === 'versions') return giVersions;
84
- if (typeof name !== 'string') return target[name];
85
- if (giCache.has(name)) return giCache.get(name);
86
- const ns = requireGi(name, giVersions[name]);
87
- giCache.set(name, ns);
88
- return ns;
89
- },
90
- has(_target, name) {
91
- return name === 'versions' || typeof name === 'string';
92
- },
93
- },
94
- );
75
+ const giVersions = Object.create(null);
76
+ const giCache = new Map();
77
+ const gi = new Proxy(
78
+ { versions: giVersions },
79
+ {
80
+ get(target, name) {
81
+ if (name === 'versions') return giVersions;
82
+ if (typeof name !== 'string') return target[name];
83
+ if (giCache.has(name)) return giCache.get(name);
84
+ const ns = requireGi(name, giVersions[name]);
85
+ giCache.set(name, ns);
86
+ return ns;
87
+ },
88
+ has(_target, name) {
89
+ return name === 'versions' || typeof name === 'string';
90
+ },
91
+ },
92
+ );
95
93
 
96
- // `imports.system` + `imports.gettext` + `imports.cairo` are the standalone
97
- // module objects (`./system.js` / `./gettext.js` / `./cairo.js`) — the single
98
- // source of truth for those surfaces, shared with the bare `system` / `gettext` /
99
- // `cairo` specifiers on Node.
100
- //
101
- // `imports.signals` is the pure-JS Signals mixin (`addSignalMethods` + the
102
- // `_connect`/`_disconnect`/`_emit`/… primitives), the SAME module the DBus proxy
103
- // surface uses. `imports.mainloop` (a lazy getter — it needs GLib, and a source
104
- // that never touches the main loop should not pull GLib in) is the thin
105
- // GLib.MainLoop convenience layer.
106
- const { addSignalMethods, _connect, _connectAfter, _disconnect, _emit, _signalHandlerIsConnected, _disconnectAll } =
107
- signalsModule;
108
- const imports = {
109
- gi,
110
- system,
111
- gettext,
112
- cairo,
113
- // `imports.byteArray` — the legacy GJS byte-array module
114
- // (fromGBytes/toGBytes/fromString/toString/fromArray/ByteArray), the seam
115
- // `@gjsify/utils`' gbytesToUint8Array/cli() read subprocess output through.
116
- // GLib is only pulled in lazily (toGBytes), so seeding it here is free.
117
- byteArray: createByteArray(requireGi),
118
- signals: { addSignalMethods, _connect, _connectAfter, _disconnect, _emit, _signalHandlerIsConnected, _disconnectAll },
119
- // GJS's `imports.searchPath` — `imports.package.init` unshifts the app's
120
- // moduledir onto it. Inert on node-gi (ESM + gi://), but present + safe so
121
- // source that reads/mutates it doesn't throw.
122
- searchPath: [],
123
- versions: Object.create(null),
124
- };
125
- let mainloop;
126
- Object.defineProperty(imports, 'mainloop', {
127
- get() {
128
- if (mainloop === undefined) mainloop = createMainloop(requireGi('GLib', '2.0'));
129
- return mainloop;
130
- },
131
- enumerable: true,
132
- configurable: true,
133
- });
134
- // `imports.package` — the GJS application bootstrap (pkg.init/initGettext/
135
- // initFormat). Lazy like `mainloop`: a bundle that never calls it pulls no GLib.
136
- let pkg;
137
- Object.defineProperty(imports, 'package', {
138
- get() {
139
- if (pkg === undefined) pkg = createPackage({ requireGi, gettext, imports });
140
- return pkg;
141
- },
142
- enumerable: true,
143
- configurable: true,
144
- });
145
- return imports;
94
+ // `imports.system` + `imports.gettext` + `imports.cairo` are the standalone
95
+ // module objects (`./system.js` / `./gettext.js` / `./cairo.js`) — the single
96
+ // source of truth for those surfaces, shared with the bare `system` / `gettext` /
97
+ // `cairo` specifiers on Node.
98
+ //
99
+ // `imports.signals` is the pure-JS Signals mixin (`addSignalMethods` + the
100
+ // `_connect`/`_disconnect`/`_emit`/… primitives), the SAME module the DBus proxy
101
+ // surface uses. `imports.mainloop` (a lazy getter — it needs GLib, and a source
102
+ // that never touches the main loop should not pull GLib in) is the thin
103
+ // GLib.MainLoop convenience layer.
104
+ const { addSignalMethods, _connect, _connectAfter, _disconnect, _emit, _signalHandlerIsConnected, _disconnectAll } =
105
+ signalsModule;
106
+ const imports = {
107
+ gi,
108
+ system,
109
+ gettext,
110
+ cairo,
111
+ // `imports.byteArray` — the legacy GJS byte-array module
112
+ // (fromGBytes/toGBytes/fromString/toString/fromArray/ByteArray), the seam
113
+ // `@gjsify/utils`' gbytesToUint8Array/cli() read subprocess output through.
114
+ // GLib is only pulled in lazily (toGBytes), so seeding it here is free.
115
+ byteArray: createByteArray(requireGi),
116
+ signals: {
117
+ addSignalMethods,
118
+ _connect,
119
+ _connectAfter,
120
+ _disconnect,
121
+ _emit,
122
+ _signalHandlerIsConnected,
123
+ _disconnectAll,
124
+ },
125
+ // GJS's `imports.searchPath` — `imports.package.init` unshifts the app's
126
+ // moduledir onto it. Inert on node-gi (ESM + gi://), but present + safe so
127
+ // source that reads/mutates it doesn't throw.
128
+ searchPath: [],
129
+ versions: Object.create(null),
130
+ };
131
+ let mainloop;
132
+ Object.defineProperty(imports, 'mainloop', {
133
+ get() {
134
+ if (mainloop === undefined) mainloop = createMainloop(requireGi('GLib', '2.0'));
135
+ return mainloop;
136
+ },
137
+ enumerable: true,
138
+ configurable: true,
139
+ });
140
+ // `imports.package` — the GJS application bootstrap (pkg.init/initGettext/
141
+ // initFormat). Lazy like `mainloop`: a bundle that never calls it pulls no GLib.
142
+ let pkg;
143
+ Object.defineProperty(imports, 'package', {
144
+ get() {
145
+ if (pkg === undefined) pkg = createPackage({ requireGi, gettext, imports });
146
+ return pkg;
147
+ },
148
+ enumerable: true,
149
+ configurable: true,
150
+ });
151
+ return imports;
146
152
  }
147
153
 
148
154
  // Side effect on import: seed the globals.
package/gtk-runtime.js CHANGED
@@ -1,10 +1,12 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  // @gjsify/node-gi/gtk-runtime — locate + activate a batteries-included, relocated
3
3
  // GTK/GObject-Introspection runtime bundle so gi:// namespaces load with NO system
4
- // or Homebrew GTK (Phase 2 of cross-platform node-gi). Today only darwin-arm64
5
- // ships such a bundle (@gjsify/gtk-runtime-darwin-arm64); this is a no-op on every
6
- // other platform, and harmless when no bundle is present (the addon then uses the
7
- // host's GTK exactly as before).
4
+ // or Homebrew GTK (Phase 2 of cross-platform node-gi). Bundles ship for darwin-arm64,
5
+ // darwin-x64 and win32-x64 (@gjsify/gtk-runtime-<platform>-<arch>); NOTHING below
6
+ // keys on a specific target — the tag is derived from the running process, so a new
7
+ // bundle is found by the mechanism that found the first. This is a no-op on every
8
+ // platform without a bundle, and harmless when no bundle is present (the addon then
9
+ // uses the host's GTK exactly as before).
8
10
  import { createRequire } from 'node:module';
9
11
  import { fileURLToPath } from 'node:url';
10
12
  import { dirname, join } from 'node:path';
@@ -244,7 +246,9 @@ export function activateBundledGtkRuntime(native) {
244
246
  } else {
245
247
  const existing = process.env.DYLD_FALLBACK_LIBRARY_PATH;
246
248
  if (!existing || !existing.split(':').includes(bundle.libDir)) {
247
- process.env.DYLD_FALLBACK_LIBRARY_PATH = existing ? `${bundle.libDir}:${existing}` : `${bundle.libDir}:/usr/lib`;
249
+ process.env.DYLD_FALLBACK_LIBRARY_PATH = existing
250
+ ? `${bundle.libDir}:${existing}`
251
+ : `${bundle.libDir}:/usr/lib`;
248
252
  }
249
253
  }
250
254