@ricsam/isolate-fetch 0.1.16 → 0.1.17

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.
@@ -1063,6 +1063,7 @@ function setupRequest(context, stateMap) {
1063
1063
  body,
1064
1064
  bodyUsed: false,
1065
1065
  streamId: null,
1066
+ signalAborted: false,
1066
1067
  mode,
1067
1068
  credentials,
1068
1069
  cache,
@@ -1159,6 +1160,10 @@ function setupRequest(context, stateMap) {
1159
1160
  const state = stateMap.get(instanceId);
1160
1161
  return state?.streamId ?? null;
1161
1162
  }));
1163
+ global.setSync("__Request_get_signalAborted", new import_isolated_vm.default.Callback((instanceId) => {
1164
+ const state = stateMap.get(instanceId);
1165
+ return state?.signalAborted ?? false;
1166
+ }));
1162
1167
  const requestCode = `
1163
1168
  (function() {
1164
1169
  function __decodeError(err) {
@@ -1222,6 +1227,8 @@ function setupRequest(context, stateMap) {
1222
1227
  return result;
1223
1228
  }
1224
1229
 
1230
+ const __requestSignalControllers = new Map();
1231
+
1225
1232
  class Request {
1226
1233
  #instanceId;
1227
1234
  #headers;
@@ -1232,9 +1239,15 @@ function setupRequest(context, stateMap) {
1232
1239
  constructor(input, init = {}) {
1233
1240
  // Handle internal construction from instance ID
1234
1241
  if (typeof input === 'number' && init === null) {
1242
+ const controller = new AbortController();
1243
+ if (__Request_get_signalAborted(input)) {
1244
+ controller.abort();
1245
+ }
1246
+ __requestSignalControllers.set(input, controller);
1247
+
1235
1248
  this.#instanceId = input;
1236
1249
  this.#headers = new Headers(__Request_get_headers(input));
1237
- this.#signal = null;
1250
+ this.#signal = controller.signal;
1238
1251
  this.#streamId = __Request_getStreamId(input);
1239
1252
  return;
1240
1253
  }
@@ -1243,7 +1256,7 @@ function setupRequest(context, stateMap) {
1243
1256
  let method = 'GET';
1244
1257
  let headers;
1245
1258
  let body = null;
1246
- let signal = null;
1259
+ let signal = new AbortController().signal;
1247
1260
  let mode = 'cors';
1248
1261
  let credentials = 'same-origin';
1249
1262
  let cache = 'default';
@@ -1280,6 +1293,11 @@ function setupRequest(context, stateMap) {
1280
1293
  if (init.referrer !== undefined) referrer = init.referrer;
1281
1294
  if (init.integrity !== undefined) integrity = init.integrity;
1282
1295
 
1296
+ // Ensure signal is always a valid AbortSignal
1297
+ if (signal == null) {
1298
+ signal = new AbortController().signal;
1299
+ }
1300
+
1283
1301
  // Validate: body with GET/HEAD
1284
1302
  if (body !== null && (method === 'GET' || method === 'HEAD')) {
1285
1303
  throw new TypeError('Request with GET/HEAD method cannot have body');
@@ -1473,10 +1491,18 @@ function setupRequest(context, stateMap) {
1473
1491
  }
1474
1492
  }
1475
1493
 
1494
+ globalThis.__Request_abortSignalByInstanceId = function(instanceId) {
1495
+ const controller = __requestSignalControllers.get(instanceId);
1496
+ if (controller && !controller.signal.aborted) {
1497
+ controller.abort();
1498
+ }
1499
+ };
1500
+
1476
1501
  globalThis.Request = Request;
1477
1502
  })();
1478
1503
  `;
1479
1504
  context.evalSync(requestCode);
1505
+ return context.evalSync("globalThis.__Request_abortSignalByInstanceId", { reference: true });
1480
1506
  }
1481
1507
  var FETCH_STREAM_THRESHOLD = 64 * 1024;
1482
1508
  function setupFetchFunction(context, stateMap, streamRegistry, options) {
@@ -2134,7 +2160,7 @@ async function setupFetch(context, options) {
2134
2160
  setupStreamCallbacks(context, streamRegistry);
2135
2161
  context.evalSync(hostBackedStreamCode);
2136
2162
  setupResponse(context, stateMap, streamRegistry);
2137
- setupRequest(context, stateMap);
2163
+ const requestAbortSignalRef = setupRequest(context, stateMap);
2138
2164
  setupFetchFunction(context, stateMap, streamRegistry, options);
2139
2165
  const serveState = {
2140
2166
  pendingUpgrade: null,
@@ -2187,8 +2213,11 @@ async function setupFetch(context, options) {
2187
2213
  context.evalSync(`globalThis.__upgradeRegistry__.clear()`);
2188
2214
  serveState.activeConnections.clear();
2189
2215
  serveState.pendingUpgrade = null;
2216
+ try {
2217
+ requestAbortSignalRef.release();
2218
+ } catch {}
2190
2219
  },
2191
- async dispatchRequest(request, _dispatchOptions) {
2220
+ async dispatchRequest(request, dispatchOptions) {
2192
2221
  if (serveState.pendingUpgrade) {
2193
2222
  const oldConnectionId = serveState.pendingUpgrade.connectionId;
2194
2223
  context.evalSync(`globalThis.__upgradeRegistry__.delete("${oldConnectionId}")`);
@@ -2198,8 +2227,12 @@ async function setupFetch(context, options) {
2198
2227
  if (!hasHandler) {
2199
2228
  throw new Error("No serve() handler registered");
2200
2229
  }
2230
+ const forwardedSignal = dispatchOptions?.signal ?? request.signal;
2231
+ const forwardedSignalInitiallyAborted = forwardedSignal?.aborted ?? false;
2201
2232
  let requestStreamId = null;
2233
+ let requestInstanceId = null;
2202
2234
  let streamCleanup = null;
2235
+ let onForwardedSignalAbort;
2203
2236
  const canHaveBody = !["GET", "HEAD"].includes(request.method.toUpperCase());
2204
2237
  if (canHaveBody && request.body) {
2205
2238
  requestStreamId = streamRegistry.create();
@@ -2207,7 +2240,7 @@ async function setupFetch(context, options) {
2207
2240
  }
2208
2241
  try {
2209
2242
  const headersArray = Array.from(request.headers.entries());
2210
- const requestInstanceId = nextInstanceId++;
2243
+ requestInstanceId = nextInstanceId++;
2211
2244
  const requestState = {
2212
2245
  url: request.url,
2213
2246
  method: request.method,
@@ -2215,6 +2248,7 @@ async function setupFetch(context, options) {
2215
2248
  body: null,
2216
2249
  bodyUsed: false,
2217
2250
  streamId: requestStreamId,
2251
+ signalAborted: forwardedSignalInitiallyAborted,
2218
2252
  mode: request.mode,
2219
2253
  credentials: request.credentials,
2220
2254
  cache: request.cache,
@@ -2223,6 +2257,26 @@ async function setupFetch(context, options) {
2223
2257
  integrity: request.integrity
2224
2258
  };
2225
2259
  stateMap.set(requestInstanceId, requestState);
2260
+ if (forwardedSignal && !forwardedSignalInitiallyAborted) {
2261
+ onForwardedSignalAbort = () => {
2262
+ if (requestInstanceId == null)
2263
+ return;
2264
+ const currentState = stateMap.get(requestInstanceId);
2265
+ if (!currentState || currentState.signalAborted) {
2266
+ return;
2267
+ }
2268
+ currentState.signalAborted = true;
2269
+ try {
2270
+ requestAbortSignalRef.applyIgnored(undefined, [requestInstanceId], {
2271
+ arguments: { copy: true }
2272
+ });
2273
+ } catch {}
2274
+ };
2275
+ forwardedSignal.addEventListener("abort", onForwardedSignalAbort, { once: true });
2276
+ if (forwardedSignal.aborted) {
2277
+ onForwardedSignalAbort();
2278
+ }
2279
+ }
2226
2280
  const responseInstanceId = await context.eval(`
2227
2281
  (async function() {
2228
2282
  const request = Request._fromInstanceId(${requestInstanceId});
@@ -2317,6 +2371,9 @@ async function setupFetch(context, options) {
2317
2371
  response._originalStatus = responseState.status;
2318
2372
  return response;
2319
2373
  } finally {
2374
+ if (forwardedSignal && onForwardedSignalAbort) {
2375
+ forwardedSignal.removeEventListener("abort", onForwardedSignalAbort);
2376
+ }
2320
2377
  if (requestStreamId !== null) {
2321
2378
  const startTime = Date.now();
2322
2379
  let streamState = streamRegistry.get(requestStreamId);
@@ -2499,4 +2556,4 @@ async function setupFetch(context, options) {
2499
2556
  };
2500
2557
  }
2501
2558
 
2502
- //# debugId=A475F6C880EAF54E64756E2164756E21
2559
+ //# debugId=930DF43743B8401164756E2164756E21