@ricsam/isolate-fetch 0.1.8 → 0.1.10
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/dist/cjs/index.cjs +120 -9
- package/dist/cjs/index.cjs.map +3 -3
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/stream-state.cjs +2 -4
- package/dist/cjs/stream-state.cjs.map +2 -2
- package/dist/mjs/index.mjs +119 -7
- package/dist/mjs/index.mjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/stream-state.mjs +1 -2
- package/dist/mjs/stream-state.mjs.map +2 -2
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
(function(exports, require, module, __filename, __dirname) {var __create = Object.create;
|
|
1
|
+
var __create = Object.create;
|
|
3
2
|
var __getProtoOf = Object.getPrototypeOf;
|
|
4
3
|
var __defProp = Object.defineProperty;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -51,6 +50,7 @@ var import_isolated_vm = __toESM(require("isolated-vm"));
|
|
|
51
50
|
var import_isolate_core = require("@ricsam/isolate-core");
|
|
52
51
|
var import_stream_state = require("./stream-state.cjs");
|
|
53
52
|
var instanceStateMap = new WeakMap;
|
|
53
|
+
var passthruBodies = new WeakMap;
|
|
54
54
|
var nextInstanceId = 1;
|
|
55
55
|
function getInstanceStateMapForContext(context) {
|
|
56
56
|
let map = instanceStateMap.get(context);
|
|
@@ -60,6 +60,14 @@ function getInstanceStateMapForContext(context) {
|
|
|
60
60
|
}
|
|
61
61
|
return map;
|
|
62
62
|
}
|
|
63
|
+
function getPassthruBodiesForContext(context) {
|
|
64
|
+
let map = passthruBodies.get(context);
|
|
65
|
+
if (!map) {
|
|
66
|
+
map = new Map;
|
|
67
|
+
passthruBodies.set(context, map);
|
|
68
|
+
}
|
|
69
|
+
return map;
|
|
70
|
+
}
|
|
63
71
|
var headersCode = `
|
|
64
72
|
(function() {
|
|
65
73
|
class Headers {
|
|
@@ -648,8 +656,12 @@ function setupResponse(context, stateMap) {
|
|
|
648
656
|
// Mark as needing async Blob handling - will be read in constructor
|
|
649
657
|
return { __isBlob: true, blob: body };
|
|
650
658
|
}
|
|
651
|
-
// Handle
|
|
652
|
-
if (body instanceof
|
|
659
|
+
// Handle HostBackedReadableStream specially - preserve streamId
|
|
660
|
+
if (body instanceof HostBackedReadableStream) {
|
|
661
|
+
return { __isHostStream: true, stream: body, streamId: body._getStreamId() };
|
|
662
|
+
}
|
|
663
|
+
// Handle native ReadableStream
|
|
664
|
+
if (body instanceof ReadableStream) {
|
|
653
665
|
return { __isStream: true, stream: body };
|
|
654
666
|
}
|
|
655
667
|
// Try to convert to string
|
|
@@ -704,7 +716,27 @@ function setupResponse(context, stateMap) {
|
|
|
704
716
|
return;
|
|
705
717
|
}
|
|
706
718
|
|
|
707
|
-
// Handle
|
|
719
|
+
// Handle HostBackedReadableStream - reuse existing streamId for pass-through
|
|
720
|
+
if (preparedBody && preparedBody.__isHostStream) {
|
|
721
|
+
// Reuse the existing streamId to preserve the pass-through body mapping
|
|
722
|
+
this.#streamId = preparedBody.streamId;
|
|
723
|
+
const status = init.status ?? 200;
|
|
724
|
+
const statusText = init.statusText ?? '';
|
|
725
|
+
const headers = new Headers(init.headers);
|
|
726
|
+
const headersArray = Array.from(headers.entries());
|
|
727
|
+
|
|
728
|
+
this.#instanceId = __Response_constructStreaming(
|
|
729
|
+
this.#streamId,
|
|
730
|
+
status,
|
|
731
|
+
statusText,
|
|
732
|
+
headersArray
|
|
733
|
+
);
|
|
734
|
+
this.#headers = headers;
|
|
735
|
+
// Don't pump - the body is already backed by this streamId
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
// Handle native ReadableStream body
|
|
708
740
|
if (preparedBody && preparedBody.__isStream) {
|
|
709
741
|
this.#streamId = __Stream_create();
|
|
710
742
|
const status = init.status ?? 200;
|
|
@@ -1385,7 +1417,8 @@ function setupRequest(context, stateMap) {
|
|
|
1385
1417
|
`;
|
|
1386
1418
|
context.evalSync(requestCode);
|
|
1387
1419
|
}
|
|
1388
|
-
|
|
1420
|
+
var FETCH_STREAM_THRESHOLD = 64 * 1024;
|
|
1421
|
+
function setupFetchFunction(context, stateMap, streamRegistry, options) {
|
|
1389
1422
|
const global = context.global;
|
|
1390
1423
|
const fetchRef = new import_isolated_vm.default.Reference(async (url, method, headersJson, bodyJson, signalAborted) => {
|
|
1391
1424
|
if (signalAborted) {
|
|
@@ -1401,6 +1434,69 @@ function setupFetchFunction(context, stateMap, options) {
|
|
|
1401
1434
|
});
|
|
1402
1435
|
const onFetch = options?.onFetch ?? fetch;
|
|
1403
1436
|
const nativeResponse = await onFetch(nativeRequest);
|
|
1437
|
+
const contentLength = nativeResponse.headers.get("content-length");
|
|
1438
|
+
const knownSize = contentLength ? parseInt(contentLength, 10) : null;
|
|
1439
|
+
const isCallbackStream = nativeResponse.__isCallbackStream;
|
|
1440
|
+
const isNetworkResponse = nativeResponse.url && (nativeResponse.url.startsWith("http://") || nativeResponse.url.startsWith("https://"));
|
|
1441
|
+
const shouldStream = nativeResponse.body && (isCallbackStream || isNetworkResponse && (knownSize === null || knownSize > FETCH_STREAM_THRESHOLD));
|
|
1442
|
+
if (shouldStream && nativeResponse.body) {
|
|
1443
|
+
if (isCallbackStream) {
|
|
1444
|
+
const streamId2 = streamRegistry.create();
|
|
1445
|
+
const passthruMap = getPassthruBodiesForContext(context);
|
|
1446
|
+
passthruMap.set(streamId2, nativeResponse.body);
|
|
1447
|
+
const instanceId3 = nextInstanceId++;
|
|
1448
|
+
const state3 = {
|
|
1449
|
+
status: nativeResponse.status,
|
|
1450
|
+
statusText: nativeResponse.statusText,
|
|
1451
|
+
headers: Array.from(nativeResponse.headers.entries()),
|
|
1452
|
+
body: new Uint8Array(0),
|
|
1453
|
+
bodyUsed: false,
|
|
1454
|
+
type: "default",
|
|
1455
|
+
url: nativeResponse.url,
|
|
1456
|
+
redirected: nativeResponse.redirected,
|
|
1457
|
+
streamId: streamId2
|
|
1458
|
+
};
|
|
1459
|
+
stateMap.set(instanceId3, state3);
|
|
1460
|
+
return instanceId3;
|
|
1461
|
+
}
|
|
1462
|
+
const streamId = streamRegistry.create();
|
|
1463
|
+
const instanceId2 = nextInstanceId++;
|
|
1464
|
+
const state2 = {
|
|
1465
|
+
status: nativeResponse.status,
|
|
1466
|
+
statusText: nativeResponse.statusText,
|
|
1467
|
+
headers: Array.from(nativeResponse.headers.entries()),
|
|
1468
|
+
body: new Uint8Array(0),
|
|
1469
|
+
bodyUsed: false,
|
|
1470
|
+
type: "default",
|
|
1471
|
+
url: nativeResponse.url,
|
|
1472
|
+
redirected: nativeResponse.redirected,
|
|
1473
|
+
streamId
|
|
1474
|
+
};
|
|
1475
|
+
stateMap.set(instanceId2, state2);
|
|
1476
|
+
const reader = nativeResponse.body.getReader();
|
|
1477
|
+
(async () => {
|
|
1478
|
+
try {
|
|
1479
|
+
while (true) {
|
|
1480
|
+
const { done, value } = await reader.read();
|
|
1481
|
+
if (done) {
|
|
1482
|
+
streamRegistry.close(streamId);
|
|
1483
|
+
break;
|
|
1484
|
+
}
|
|
1485
|
+
if (value) {
|
|
1486
|
+
while (streamRegistry.isQueueFull(streamId)) {
|
|
1487
|
+
await new Promise((r) => setTimeout(r, 1));
|
|
1488
|
+
}
|
|
1489
|
+
streamRegistry.push(streamId, value);
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
} catch (err) {
|
|
1493
|
+
streamRegistry.error(streamId, err);
|
|
1494
|
+
} finally {
|
|
1495
|
+
reader.releaseLock();
|
|
1496
|
+
}
|
|
1497
|
+
})();
|
|
1498
|
+
return instanceId2;
|
|
1499
|
+
}
|
|
1404
1500
|
const responseBody = await nativeResponse.arrayBuffer();
|
|
1405
1501
|
const responseBodyArray = Array.from(new Uint8Array(responseBody));
|
|
1406
1502
|
const instanceId = nextInstanceId++;
|
|
@@ -1574,7 +1670,7 @@ async function setupFetch(context, options) {
|
|
|
1574
1670
|
context.evalSync(hostBackedStreamCode);
|
|
1575
1671
|
setupResponse(context, stateMap);
|
|
1576
1672
|
setupRequest(context, stateMap);
|
|
1577
|
-
setupFetchFunction(context, stateMap, options);
|
|
1673
|
+
setupFetchFunction(context, stateMap, streamRegistry, options);
|
|
1578
1674
|
const serveState = {
|
|
1579
1675
|
pendingUpgrade: null,
|
|
1580
1676
|
activeConnections: new Map
|
|
@@ -1637,6 +1733,22 @@ async function setupFetch(context, options) {
|
|
|
1637
1733
|
if (!responseState) {
|
|
1638
1734
|
throw new Error("Response state not found");
|
|
1639
1735
|
}
|
|
1736
|
+
if (responseState.streamId !== null) {
|
|
1737
|
+
const passthruMap = getPassthruBodiesForContext(context);
|
|
1738
|
+
const passthruBody = passthruMap.get(responseState.streamId);
|
|
1739
|
+
if (passthruBody) {
|
|
1740
|
+
passthruMap.delete(responseState.streamId);
|
|
1741
|
+
const responseHeaders2 = new Headers(responseState.headers);
|
|
1742
|
+
const status2 = responseState.status === 101 ? 200 : responseState.status;
|
|
1743
|
+
const response2 = new Response(passthruBody, {
|
|
1744
|
+
status: status2,
|
|
1745
|
+
statusText: responseState.statusText,
|
|
1746
|
+
headers: responseHeaders2
|
|
1747
|
+
});
|
|
1748
|
+
response2._originalStatus = responseState.status;
|
|
1749
|
+
return response2;
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1640
1752
|
if (responseState.streamId !== null) {
|
|
1641
1753
|
const responseStreamId = responseState.streamId;
|
|
1642
1754
|
let streamDone = false;
|
|
@@ -1817,6 +1929,5 @@ async function setupFetch(context, options) {
|
|
|
1817
1929
|
}
|
|
1818
1930
|
};
|
|
1819
1931
|
}
|
|
1820
|
-
})
|
|
1821
1932
|
|
|
1822
|
-
//# debugId=
|
|
1933
|
+
//# debugId=D2829934F58098A764756E2164756E21
|