@gjsify/terminal-native 0.54.0 → 0.55.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.
@@ -16,6 +16,11 @@ export interface NativeResizeWatcherClass {
16
16
  export interface NativeResizeWatcher {
17
17
  /** Start watching SIGWINCH. Idempotent. */
18
18
  start(): void;
19
+ /**
20
+ * Stop watching SIGWINCH and release the source's reference to this
21
+ * watcher. Idempotent. Without it a started watcher is immortal.
22
+ */
23
+ stop(): void;
19
24
  connect(signal: 'resized', handler: (obj: NativeResizeWatcher, rows: number, cols: number) => void): number;
20
25
  disconnect(id: number): void;
21
26
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/terminal-native",
3
- "version": "0.54.0",
3
+ "version": "0.55.0",
4
4
  "description": "Optional Vala/GObject bridge providing Posix.isatty(), ioctl(TIOCGWINSZ), termios raw-mode and SIGWINCH for GJS. Enhances @gjsify/tty and @gjsify/process with correct terminal behaviour when installed.",
5
5
  "type": "module",
6
6
  "main": "lib/esm/index.js",
@@ -62,10 +62,10 @@
62
62
  "dependencies": {
63
63
  "@girs/glib-2.0": "5.4.0",
64
64
  "@girs/gobject-2.0": "5.4.0",
65
- "@gjsify/utils": "^0.54.0"
65
+ "@gjsify/utils": "^0.55.0"
66
66
  },
67
67
  "devDependencies": {
68
- "@gjsify/cli": "^0.54.0",
68
+ "@gjsify/cli": "^0.55.0",
69
69
  "@ts-for-gir/cli": "^4.1.0",
70
70
  "@types/node": "^25.9.2",
71
71
  "typescript": "^6.0.3"
@@ -81,12 +81,12 @@
81
81
  },
82
82
  "homepage": "https://github.com/gjsify/gjsify/tree/main/packages/node/terminal-native#readme",
83
83
  "optionalDependencies": {
84
- "@gjsify/terminal-native-darwin-arm64": "0.54.0",
85
- "@gjsify/terminal-native-darwin-x64": "0.54.0",
86
- "@gjsify/terminal-native-linux-arm64": "0.54.0",
87
- "@gjsify/terminal-native-linux-ppc64": "0.54.0",
88
- "@gjsify/terminal-native-linux-riscv64": "0.54.0",
89
- "@gjsify/terminal-native-linux-s390x": "0.54.0",
90
- "@gjsify/terminal-native-linux-x64": "0.54.0"
84
+ "@gjsify/terminal-native-darwin-arm64": "0.55.0",
85
+ "@gjsify/terminal-native-darwin-x64": "0.55.0",
86
+ "@gjsify/terminal-native-linux-arm64": "0.55.0",
87
+ "@gjsify/terminal-native-linux-ppc64": "0.55.0",
88
+ "@gjsify/terminal-native-linux-riscv64": "0.55.0",
89
+ "@gjsify/terminal-native-linux-s390x": "0.55.0",
90
+ "@gjsify/terminal-native-linux-x64": "0.55.0"
91
91
  }
92
92
  }
@@ -104,9 +104,18 @@ namespace GjsifyTerminal {
104
104
  * ResizeWatcher — fires #GjsifyTerminal.ResizeWatcher::resized whenever
105
105
  * the terminal window is resized (SIGWINCH).
106
106
  *
107
- * Call start() once; the watcher stays active for the process lifetime.
108
107
  * The signal is dispatched on the GLib main context via GLib.Idle so
109
108
  * JavaScript signal handlers run on the main thread.
109
+ *
110
+ * LIFECYCLE: `start()` takes a GLib source on the DEFAULT main context and
111
+ * that source holds a strong reference to the watcher (it is the callback's
112
+ * user_data), so a watcher that was started and never stopped is immortal —
113
+ * it can never be finalized, keeps its signal handlers alive, and is only
114
+ * torn down when GLib unrefs it during the host's own shutdown. `stop()`
115
+ * releases that reference and `dispose()` calls it, so a caller that is
116
+ * done with a watcher MUST stop or dispose it. Keeping the source id is
117
+ * what makes that possible; discarding it (as this class used to) leaves
118
+ * no way to reach the source again.
110
119
  */
111
120
  public class ResizeWatcher : GLib.Object {
112
121
 
@@ -118,17 +127,19 @@ namespace GjsifyTerminal {
118
127
  public signal void resized (int rows, int cols);
119
128
 
120
129
  private bool _active = false;
130
+ private uint _winch_source = 0;
121
131
 
122
132
  /**
123
133
  * start:
124
134
  *
125
- * Begin watching SIGWINCH. Idempotent — safe to call multiple times.
135
+ * Begin watching SIGWINCH. Idempotent — safe to call multiple times,
136
+ * and safe to call again after stop().
126
137
  */
127
138
  public void start () {
128
139
  if (_active) return;
129
140
  _active = true;
130
141
 
131
- GLib.Unix.signal_add (Posix.Signal.WINCH, () => {
142
+ _winch_source = (uint) GLib.Unix.signal_add (Posix.Signal.WINCH, () => {
132
143
  int r = 0, c = 0, xp = 0, yp = 0;
133
144
  if (Terminal.get_size (1, out r, out c, out xp, out yp)) {
134
145
  int rows_snap = r;
@@ -141,5 +152,39 @@ namespace GjsifyTerminal {
141
152
  return GLib.Source.CONTINUE;
142
153
  });
143
154
  }
155
+
156
+ /**
157
+ * stop:
158
+ *
159
+ * Stop watching SIGWINCH and drop the source's reference to this
160
+ * watcher, so it can be finalized. Idempotent — safe on a watcher
161
+ * that was never started, and safe to call twice.
162
+ *
163
+ * A resize already dispatched to GLib.Idle still fires `resized`:
164
+ * that idle holds its own reference, so a watcher is never emitted on
165
+ * after it is gone.
166
+ */
167
+ public void stop () {
168
+ if (!_active) return;
169
+ _active = false;
170
+
171
+ if (_winch_source != 0) {
172
+ GLib.Source.remove (_winch_source);
173
+ _winch_source = 0;
174
+ }
175
+ }
176
+
177
+ /**
178
+ * dispose:
179
+ *
180
+ * Release the SIGWINCH source on an explicit `run_dispose()`. This is
181
+ * NOT reached when the last JavaScript reference is dropped: the source
182
+ * holds its own reference, so a started watcher is never disposed by
183
+ * garbage collection. Call stop() for that.
184
+ */
185
+ public override void dispose () {
186
+ stop ();
187
+ base.dispose ();
188
+ }
144
189
  }
145
190
  }