export-runtime 0.0.21 → 0.0.23

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 (3) hide show
  1. package/handler.js +16 -24
  2. package/package.json +1 -1
  3. package/rpc.js +11 -16
package/handler.js CHANGED
@@ -323,7 +323,6 @@ export const createHandler = (moduleMap, generatedTypes, minifiedCore, coreId, m
323
323
  // Track session state and connection state for this WebSocket connection
324
324
  const wsSession = { token: null };
325
325
  let isClosed = false;
326
- const pendingOps = new Set();
327
326
 
328
327
  // Safe send that ignores errors when connection is closed
329
328
  const safeSend = (data) => {
@@ -335,22 +334,19 @@ export const createHandler = (moduleMap, generatedTypes, minifiedCore, coreId, m
335
334
  }
336
335
  };
337
336
 
338
- // Wrap async operations to track them
339
- const trackOp = async (op) => {
340
- const promise = op();
341
- pendingOps.add(promise);
342
- try {
343
- return await promise;
344
- } finally {
345
- pendingOps.delete(promise);
337
+ const handleClose = () => {
338
+ if (isClosed) return;
339
+ isClosed = true;
340
+ if (onClose) {
341
+ try { onClose(); } catch {}
346
342
  }
347
343
  };
348
344
 
349
345
  server.addEventListener("message", (event) => {
350
346
  if (isClosed) return;
351
347
 
352
- // Handle message asynchronously but don't await it
353
- trackOp(async () => {
348
+ // Handle message asynchronously - fire and forget
349
+ (async () => {
354
350
  let id;
355
351
  try {
356
352
  if (isClosed) return;
@@ -376,25 +372,20 @@ export const createHandler = (moduleMap, generatedTypes, minifiedCore, coreId, m
376
372
 
377
373
  if (result) safeSend(stringify({ ...result, id }));
378
374
  } catch (err) {
379
- if (isClosed || String(err).includes("Connection closed")) return;
380
- if (id !== undefined) safeSend(stringify({ type: "error", id, error: String(err) }));
375
+ if (isClosed) return;
376
+ const errStr = String(err);
377
+ if (errStr.includes("Connection closed") || errStr.includes("WebSocket")) return;
378
+ if (id !== undefined) safeSend(stringify({ type: "error", id, error: errStr }));
381
379
  }
382
- });
380
+ })();
383
381
  });
384
382
 
385
- server.addEventListener("close", () => {
386
- isClosed = true;
387
- if (onClose) onClose();
388
- });
389
-
390
- server.addEventListener("error", () => {
391
- isClosed = true;
392
- if (onClose) onClose();
393
- });
383
+ server.addEventListener("close", handleClose);
384
+ server.addEventListener("error", handleClose);
394
385
  };
395
386
 
396
387
  return {
397
- async fetch(request, env) {
388
+ async fetch(request, env, ctx) {
398
389
  const url = new URL(request.url);
399
390
  const isShared = url.searchParams.has("shared");
400
391
  const origin = request.headers.get("Origin");
@@ -417,6 +408,7 @@ export const createHandler = (moduleMap, generatedTypes, minifiedCore, coreId, m
417
408
 
418
409
  const pair = new WebSocketPair();
419
410
  const [client, server] = Object.values(pair);
411
+
420
412
  server.accept();
421
413
 
422
414
  if (isShared && env?.SHARED_EXPORT) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "export-runtime",
3
- "version": "0.0.21",
3
+ "version": "0.0.23",
4
4
  "description": "Cloudflare Workers ESM Export Framework Runtime",
5
5
  "keywords": [
6
6
  "cloudflare",
package/rpc.js CHANGED
@@ -155,25 +155,20 @@ export function createRpcDispatcher(moduleMap) {
155
155
 
156
156
  clearAll() {
157
157
  closed = true;
158
- // Cancel all active iterators
159
- for (const iter of iterators.values()) {
160
- try {
161
- if (iter?.return) iter.return(undefined);
162
- } catch {}
163
- }
164
- // Cancel all active streams
165
- for (const entry of streams.values()) {
166
- try {
167
- if (entry.reader) {
168
- entry.reader.cancel();
169
- } else if (entry.stream) {
170
- entry.stream.cancel();
171
- }
172
- } catch {}
173
- }
158
+ // Synchronously clear all maps to prevent further access
159
+ const iters = [...iterators.values()];
160
+ const strms = [...streams.values()];
174
161
  instances.clear();
175
162
  iterators.clear();
176
163
  streams.clear();
164
+
165
+ // Cancel iterators and streams without awaiting (fire and forget)
166
+ for (const iter of iters) {
167
+ try { iter?.return?.(); } catch {}
168
+ }
169
+ for (const entry of strms) {
170
+ try { (entry.reader || entry.stream)?.cancel?.(); } catch {}
171
+ }
177
172
  },
178
173
  };
179
174
  }