clojurific 0.12.5 → 0.12.6

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.
Files changed (2) hide show
  1. package/cljf/repl.js +24 -6
  2. package/package.json +1 -1
package/cljf/repl.js CHANGED
@@ -99,14 +99,27 @@ export function complete(code) {
99
99
  return depth <= 0;
100
100
  }
101
101
 
102
- /** An nREPL connection: requests whose responses end with status done. */
102
+ /**
103
+ * An nREPL connection: requests whose responses end with status done. Once the
104
+ * socket closes, pending and later requests reject.
105
+ */
103
106
  export class Connection {
104
107
  #socket;
105
108
  #ids = 0;
106
109
  #pending = new Map();
110
+ #closed = null;
107
111
 
108
112
  constructor(socket) {
109
113
  this.#socket = socket;
114
+ const fail = e => {
115
+ if (this.#closed) return;
116
+ this.#closed = new LauncherError(`cljf repl: the nREPL server closed the connection${e ? `: ${e.message}` : ''}`);
117
+ for (const { reject } of this.#pending.values()) reject(this.#closed);
118
+ this.#pending.clear();
119
+ };
120
+ // an error is followed by close
121
+ socket.on('error', fail);
122
+ socket.on('close', () => fail());
110
123
  const decoder = new Decoder();
111
124
  socket.on('data', chunk => {
112
125
  for (const msg of decoder.push(chunk)) {
@@ -132,8 +145,12 @@ export class Connection {
132
145
  */
133
146
  request(msg, onResponse = () => {}) {
134
147
  const id = msg.id ?? this.newId();
135
- return new Promise(resolve => {
136
- this.#pending.set(id, { onResponse, resolve });
148
+ return new Promise((resolve, reject) => {
149
+ if (this.#closed) {
150
+ reject(this.#closed);
151
+ return;
152
+ }
153
+ this.#pending.set(id, { onResponse, resolve, reject });
137
154
  this.#socket.write(bencode({ ...msg, id }));
138
155
  });
139
156
  }
@@ -247,7 +264,7 @@ export async function repl({
247
264
  rl.close();
248
265
  // the server forgets the session, unless it doesn't answer
249
266
  const timeout = new Promise(r => setTimeout(r, 1000).unref());
250
- Promise.race([conn.request({ op: 'close', session }), timeout]).finally(() => {
267
+ Promise.race([conn.request({ op: 'close', session }), timeout]).catch(() => {}).finally(() => {
251
268
  conn.close();
252
269
  resolve(code);
253
270
  });
@@ -262,7 +279,7 @@ export async function repl({
262
279
 
263
280
  rl.on('SIGINT', () => {
264
281
  if (evaluating) {
265
- conn.request({ op: 'interrupt', session, 'interrupt-id': evaluating });
282
+ conn.request({ op: 'interrupt', session, 'interrupt-id': evaluating }).catch(() => {});
266
283
  } else if (pending || rl.line) {
267
284
  pending = '';
268
285
  interrupted = false;
@@ -307,12 +324,13 @@ export async function repl({
307
324
  return;
308
325
  }
309
326
  evaluating = conn.newId();
327
+ // a lost connection rejects, closed (above) reports it
310
328
  await conn.request({ op: 'eval', session, code, ns, id: evaluating }, msg => {
311
329
  write(output, msg.out);
312
330
  write(errorOutput, msg.err);
313
331
  if (msg.value !== undefined) output.write(`${msg.value}\n`);
314
332
  if (msg.ns) ns = msg.ns;
315
- });
333
+ }).catch(() => {});
316
334
  evaluating = null;
317
335
  if (closing) return;
318
336
  prompt();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clojurific",
3
- "version": "0.12.5",
3
+ "version": "0.12.6",
4
4
  "description": "ClojureScript compiled to ES modules, bundled by Vite",
5
5
  "license": "EPL-1.0",
6
6
  "repository": {