@gjsify/utils 0.40.0 → 0.42.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 +10 -2
- package/lib/esm/core.js +1 -1
- package/lib/esm/index.js +1 -1
- package/lib/esm/main-loop.js +1 -1
- package/lib/types/main-loop.d.ts +35 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ from decides which one you get. Pick the narrowest one that covers your imports.
|
|
|
19
19
|
|---|---|---|
|
|
20
20
|
| `@gjsify/utils/core` | GJS · Node · browser · NativeScript | everything that is well-defined without GLib/Gio |
|
|
21
21
|
| `@gjsify/utils` | **GJS only** | `…/core` plus the six modules that call into GLib/Gio |
|
|
22
|
-
| `@gjsify/utils/main-loop` | GJS · Node · browser · NativeScript | just `ensureMainLoop` / `quitMainLoop` |
|
|
22
|
+
| `@gjsify/utils/main-loop` | GJS · Node · browser · NativeScript | just `ensureMainLoop` / `holdMainLoop` / `quitMainLoop` |
|
|
23
23
|
|
|
24
24
|
```typescript
|
|
25
25
|
// Cross-runtime — safe from a package whose browser / nativescript slot is
|
|
@@ -36,7 +36,15 @@ import { cli, existsSync, readBytesAsync } from '@gjsify/utils';
|
|
|
36
36
|
`GLIB_FILE_ERROR_TO_NODE` tables — `registerGlobal`, `notImplemented`,
|
|
37
37
|
`warnNotImplemented`, `queueMicrotask`, `structuredClone`) plus the two
|
|
38
38
|
**GJS-guarded** modules that probe `globalThis.imports?.gi` and fall back to a
|
|
39
|
-
portable path (`ensureMainLoop` / `quitMainLoop`, `nextTick`).
|
|
39
|
+
portable path (`ensureMainLoop` / `holdMainLoop` / `quitMainLoop`, `nextTick`).
|
|
40
|
+
|
|
41
|
+
`ensureMainLoop()` arms the GJS main-loop hook only at `GLib.main_depth() === 0`, so it
|
|
42
|
+
never stacks a loop under a test runner's `mainloop.run()` or a
|
|
43
|
+
`Gtk.Application.runAsync()`. A command that must OUTLIVE its entry module — a watch
|
|
44
|
+
loop, a daemon — needs `holdMainLoop()` instead, which arms regardless of depth: GJS
|
|
45
|
+
spins the default context itself while a module's top-level await is pending, so a
|
|
46
|
+
continuation resumed from a timer or a Gio callback runs at depth 1, where
|
|
47
|
+
`ensureMainLoop()` declines and the process exits as soon as the module settles.
|
|
40
48
|
|
|
41
49
|
The root barrel adds `gbytesToUint8Array`, `cli`, `readJSON`, `existsFD`, `existsSync`,
|
|
42
50
|
`gioAsync`, `readBytesAsync`, `inputStreamAsyncIterator`, `resolve`, `getProgramExe`,
|
package/lib/esm/core.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{makeCallable as e}from"./callable.js";import{deferEmit as t}from"./defer.js";import{initErrorV8Methods as n}from"./error.js";import{GIO_ERROR_TO_NODE as r,GLIB_FILE_ERROR_TO_NODE as i,createGLibFileError as a,createNodeError as o,isNotFoundError as s}from"./gio-errors.js";import{registerGlobal as c}from"./globals.js";import{TARGET_OSES as l,hostOs as u,hostPlatform as d,isDarwin as f,isLinux as p,isTargetOs as m,isWin32 as h}from"./host-os.js";import{notImplemented as g,warnNotImplemented as _}from"./message.js";import{queueMicrotask as v}from"./microtask.js";import{encodePathForFileUrl as y,isWindowsPath as b,lastPathSeparatorIndex as x,pathToFileUrlHref as S,splitPathComponents as C}from"./path-shape.js";import{PROBED_GI_LIBDIRS as w,TYPELIB_SUBDIR as T,splitSearchPath as E,systemGiLibraryDirs as D}from"./system-gi-dirs.js";import{mapMachine as O,mapSysname as k}from"./platform-names.js";import{structuredClone as A}from"./structured-clone.js";import{hasProcfs as j,hostExecPath as M,hostPid as N,hostPpid as P,readProcessMemory as F}from"./host-process.js";import{ensureMainLoop as I,quitMainLoop as
|
|
1
|
+
import{makeCallable as e}from"./callable.js";import{deferEmit as t}from"./defer.js";import{initErrorV8Methods as n}from"./error.js";import{GIO_ERROR_TO_NODE as r,GLIB_FILE_ERROR_TO_NODE as i,createGLibFileError as a,createNodeError as o,isNotFoundError as s}from"./gio-errors.js";import{registerGlobal as c}from"./globals.js";import{TARGET_OSES as l,hostOs as u,hostPlatform as d,isDarwin as f,isLinux as p,isTargetOs as m,isWin32 as h}from"./host-os.js";import{notImplemented as g,warnNotImplemented as _}from"./message.js";import{queueMicrotask as v}from"./microtask.js";import{encodePathForFileUrl as y,isWindowsPath as b,lastPathSeparatorIndex as x,pathToFileUrlHref as S,splitPathComponents as C}from"./path-shape.js";import{PROBED_GI_LIBDIRS as w,TYPELIB_SUBDIR as T,splitSearchPath as E,systemGiLibraryDirs as D}from"./system-gi-dirs.js";import{mapMachine as O,mapSysname as k}from"./platform-names.js";import{structuredClone as A}from"./structured-clone.js";import{hasProcfs as j,hostExecPath as M,hostPid as N,hostPpid as P,readProcessMemory as F}from"./host-process.js";import{ensureMainLoop as I,holdMainLoop as L,quitMainLoop as R}from"./main-loop.js";import{__resetBurstStateForTests as z,nextTick as B}from"./next-tick.js";export{r as GIO_ERROR_TO_NODE,i as GLIB_FILE_ERROR_TO_NODE,w as PROBED_GI_LIBDIRS,l as TARGET_OSES,T as TYPELIB_SUBDIR,z as __resetBurstStateForTests,a as createGLibFileError,o as createNodeError,t as deferEmit,y as encodePathForFileUrl,I as ensureMainLoop,j as hasProcfs,L as holdMainLoop,M as hostExecPath,u as hostOs,N as hostPid,d as hostPlatform,P as hostPpid,n as initErrorV8Methods,f as isDarwin,p as isLinux,s as isNotFoundError,m as isTargetOs,h as isWin32,b as isWindowsPath,x as lastPathSeparatorIndex,e as makeCallable,O as mapMachine,k as mapSysname,B as nextTick,g as notImplemented,S as pathToFileUrlHref,v as queueMicrotask,R as quitMainLoop,F as readProcessMemory,c as registerGlobal,C as splitPathComponents,E as splitSearchPath,A as structuredClone,D as systemGiLibraryDirs,_ as warnNotImplemented};
|
package/lib/esm/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{gbytesToUint8Array as e}from"./byte-array.js";import{makeCallable as t}from"./callable.js";import{cli as n}from"./cli.js";import{deferEmit as r}from"./defer.js";import{initErrorV8Methods as i}from"./error.js";import{GIO_ERROR_TO_NODE as a,GLIB_FILE_ERROR_TO_NODE as o,createGLibFileError as s,createNodeError as c,isNotFoundError as l}from"./gio-errors.js";import{registerGlobal as u}from"./globals.js";import{TARGET_OSES as d,hostOs as f,hostPlatform as p,isDarwin as m,isLinux as h,isTargetOs as g,isWin32 as _}from"./host-os.js";import{notImplemented as v,warnNotImplemented as y}from"./message.js";import{queueMicrotask as b}from"./microtask.js";import{encodePathForFileUrl as x,isWindowsPath as S,lastPathSeparatorIndex as C,pathToFileUrlHref as w,splitPathComponents as T}from"./path-shape.js";import{PROBED_GI_LIBDIRS as E,TYPELIB_SUBDIR as D,splitSearchPath as O,systemGiLibraryDirs as k}from"./system-gi-dirs.js";import{mapMachine as A,mapSysname as j}from"./platform-names.js";import{structuredClone as M}from"./structured-clone.js";import{hasProcfs as N,hostExecPath as P,hostPid as F,hostPpid as I,readProcessMemory as L}from"./host-process.js";import{ensureMainLoop as R,quitMainLoop as
|
|
1
|
+
import{gbytesToUint8Array as e}from"./byte-array.js";import{makeCallable as t}from"./callable.js";import{cli as n}from"./cli.js";import{deferEmit as r}from"./defer.js";import{initErrorV8Methods as i}from"./error.js";import{GIO_ERROR_TO_NODE as a,GLIB_FILE_ERROR_TO_NODE as o,createGLibFileError as s,createNodeError as c,isNotFoundError as l}from"./gio-errors.js";import{registerGlobal as u}from"./globals.js";import{TARGET_OSES as d,hostOs as f,hostPlatform as p,isDarwin as m,isLinux as h,isTargetOs as g,isWin32 as _}from"./host-os.js";import{notImplemented as v,warnNotImplemented as y}from"./message.js";import{queueMicrotask as b}from"./microtask.js";import{encodePathForFileUrl as x,isWindowsPath as S,lastPathSeparatorIndex as C,pathToFileUrlHref as w,splitPathComponents as T}from"./path-shape.js";import{PROBED_GI_LIBDIRS as E,TYPELIB_SUBDIR as D,splitSearchPath as O,systemGiLibraryDirs as k}from"./system-gi-dirs.js";import{mapMachine as A,mapSysname as j}from"./platform-names.js";import{structuredClone as M}from"./structured-clone.js";import{hasProcfs as N,hostExecPath as P,hostPid as F,hostPpid as I,readProcessMemory as L}from"./host-process.js";import{ensureMainLoop as R,holdMainLoop as z,quitMainLoop as B}from"./main-loop.js";import{__resetBurstStateForTests as V,nextTick as H}from"./next-tick.js";import"./core.js";import{readJSON as U}from"./file.js";import{existsFD as W,existsSync as G}from"./fs.js";import{gioAsync as K,inputStreamAsyncIterator as q,readBytesAsync as J}from"./gio.js";import{getNodeModulesPath as Y,getPathSeparator as X,getProgramDir as Z,getProgramExe as Q,resolve as $}from"./path.js";export{a as GIO_ERROR_TO_NODE,o as GLIB_FILE_ERROR_TO_NODE,E as PROBED_GI_LIBDIRS,d as TARGET_OSES,D as TYPELIB_SUBDIR,V as __resetBurstStateForTests,n as cli,s as createGLibFileError,c as createNodeError,r as deferEmit,x as encodePathForFileUrl,R as ensureMainLoop,W as existsFD,G as existsSync,e as gbytesToUint8Array,Y as getNodeModulesPath,X as getPathSeparator,Z as getProgramDir,Q as getProgramExe,K as gioAsync,N as hasProcfs,z as holdMainLoop,P as hostExecPath,f as hostOs,F as hostPid,p as hostPlatform,I as hostPpid,i as initErrorV8Methods,q as inputStreamAsyncIterator,m as isDarwin,h as isLinux,l as isNotFoundError,g as isTargetOs,_ as isWin32,S as isWindowsPath,C as lastPathSeparatorIndex,t as makeCallable,A as mapMachine,j as mapSysname,H as nextTick,v as notImplemented,w as pathToFileUrlHref,b as queueMicrotask,B as quitMainLoop,J as readBytesAsync,U as readJSON,L as readProcessMemory,u as registerGlobal,$ as resolve,T as splitPathComponents,O as splitSearchPath,M as structuredClone,k as systemGiLibraryDirs,y as warnNotImplemented};
|
package/lib/esm/main-loop.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";let e=!1,
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";let e=null,t=!1,n=!1;function glib(){return globalThis.imports?.gi?.GLib}function arm(e){n||(n=!0,e.runAsync().catch(()=>{}))}function ensureMainLoop(){let n=glib();if(n)return t?e:(e=new n.MainLoop(null,!1),t=!0,n.main_depth()===0&&arm(e),e)}function holdMainLoop(){let e=ensureMainLoop();return e&&arm(e),e}function quitMainLoop(){e&&=(e.quit(),t=!1,n=!1,null)}export{ensureMainLoop,holdMainLoop,quitMainLoop};
|
package/lib/types/main-loop.d.ts
CHANGED
|
@@ -5,18 +5,49 @@ import type GLib from '@girs/glib-2.0';
|
|
|
5
5
|
*
|
|
6
6
|
* Called automatically by `http.Server.listen()`, `net.Server.listen()`,
|
|
7
7
|
* `dgram.Socket.bind()`. GTK apps must NOT call it — they use
|
|
8
|
-
* `Gtk.Application.runAsync()` instead.
|
|
8
|
+
* `Gtk.Application.runAsync()` instead. A supervisor that must OUTLIVE its entry
|
|
9
|
+
* module wants {@link holdMainLoop} instead; see there for why this one cannot
|
|
10
|
+
* serve it.
|
|
9
11
|
*
|
|
10
12
|
* Teardown hazard: with a main-loop hook set, GJS's `eval_module` drives the
|
|
11
13
|
* hook's *blocking* `loop.run()`, so terminating from an async continuation with
|
|
12
14
|
* a bare `imports.system.exit()` DEADLOCKS — it only sets GJS's internal exit
|
|
13
15
|
* flag, never calls `loop.quit()`, so the parked `loop.run()` never returns.
|
|
14
16
|
* Microtask draining is unaffected; only the exit hangs
|
|
15
|
-
* (`docs/poc/tla-microtask-draining.md`).
|
|
16
|
-
*
|
|
17
|
-
*
|
|
17
|
+
* (`docs/poc/tla-microtask-draining.md`). Calling {@link quitMainLoop} first
|
|
18
|
+
* does NOT lift it — measured, the bare exit still hangs afterwards. Exit
|
|
19
|
+
* through `process.exit()`, which schedules the syscall on an idle source and
|
|
20
|
+
* then drives the default main context until it fires, so the exit happens
|
|
21
|
+
* from inside a dispatch where it works and the call never returns
|
|
22
|
+
* (`tests/e2e/process-exit-terminates`).
|
|
18
23
|
*/
|
|
19
24
|
export declare function ensureMainLoop(): GLib.MainLoop | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Keep this process alive on the GLib main loop AFTER its entry module settles —
|
|
27
|
+
* for a command that SUPERVISES rather than finishes (a watch loop, a daemon).
|
|
28
|
+
* No-op on Node.js, where pending handles do this job. Idempotent.
|
|
29
|
+
*
|
|
30
|
+
* {@link ensureMainLoop} cannot serve that case, and the difference is the whole
|
|
31
|
+
* reason this exists: it declines to arm the hook at `main_depth() !== 0`, and
|
|
32
|
+
* under a GJS *module* entry point that depth is routinely 1. GJS spins the
|
|
33
|
+
* default main context itself while the entry module's top-level await is
|
|
34
|
+
* pending, so every continuation resumed from a dispatched source — a timer, a
|
|
35
|
+
* `Gio` async callback, anything but the first microtask drain — runs inside
|
|
36
|
+
* that spin. `ensureMainLoop()` then silently arms nothing, the spin ends when
|
|
37
|
+
* the module promise settles, and the process exits.
|
|
38
|
+
*
|
|
39
|
+
* Measured on gjs 1.88.1: a module that spawns a child and arms an `fs.watch`
|
|
40
|
+
* from such a continuation prints its startup lines and exits 0 the moment its
|
|
41
|
+
* top-level await settles, orphaning the child; the same code with the spawn
|
|
42
|
+
* BEFORE the first await stays alive. So the depth guard is not a safety net
|
|
43
|
+
* here, it is the defect.
|
|
44
|
+
*
|
|
45
|
+
* Arming regardless of depth is why this is opt-in rather than the default: only
|
|
46
|
+
* a caller that knows it will never unwind may stack a loop under one that may
|
|
47
|
+
* already be running. Exit through `process.exit()` — see {@link ensureMainLoop}
|
|
48
|
+
* for why a bare `imports.system.exit()` deadlocks.
|
|
49
|
+
*/
|
|
50
|
+
export declare function holdMainLoop(): GLib.MainLoop | undefined;
|
|
20
51
|
/**
|
|
21
52
|
* Quit the MainLoop created by `ensureMainLoop()`. Idempotent, no-op on Node.js.
|
|
22
53
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/utils",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.42.0",
|
|
4
4
|
"description": "Utils module for gjsify",
|
|
5
5
|
"module": "lib/esm/index.js",
|
|
6
6
|
"types": "lib/types/index.d.ts",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"fs"
|
|
41
41
|
],
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@gjsify/cli": "^0.
|
|
43
|
+
"@gjsify/cli": "^0.42.0",
|
|
44
44
|
"typescript": "^6.0.3"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|