@ricsam/isolate-client 0.1.5 → 0.1.7
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/README.md +89 -0
- package/dist/cjs/connection.cjs +80 -26
- package/dist/cjs/connection.cjs.map +3 -3
- package/dist/cjs/index.cjs +2 -4
- package/dist/cjs/index.cjs.map +3 -3
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/types.cjs +2 -4
- package/dist/cjs/types.cjs.map +1 -1
- package/dist/mjs/connection.mjs +79 -24
- package/dist/mjs/connection.mjs.map +3 -3
- package/dist/mjs/index.mjs +1 -2
- package/dist/mjs/index.mjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/types.mjs +1 -2
- package/dist/mjs/types.mjs.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/types.d.ts +14 -0
- package/package.json +1 -1
package/dist/mjs/connection.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
// @bun
|
|
2
1
|
// packages/isolate-client/src/connection.ts
|
|
3
|
-
import { connect as netConnect } from "net";
|
|
2
|
+
import { connect as netConnect } from "node:net";
|
|
4
3
|
import {
|
|
5
4
|
createFrameParser,
|
|
6
5
|
buildFrame,
|
|
@@ -24,7 +23,8 @@ async function connect(options = {}) {
|
|
|
24
23
|
nextStreamId: 1,
|
|
25
24
|
connected: true,
|
|
26
25
|
streamResponses: new Map,
|
|
27
|
-
uploadStreams: new Map
|
|
26
|
+
uploadStreams: new Map,
|
|
27
|
+
moduleSourceCache: new Map
|
|
28
28
|
};
|
|
29
29
|
const parser = createFrameParser();
|
|
30
30
|
socket.on("data", (data) => {
|
|
@@ -39,15 +39,38 @@ async function connect(options = {}) {
|
|
|
39
39
|
socket.on("close", () => {
|
|
40
40
|
state.connected = false;
|
|
41
41
|
for (const [, pending] of state.pendingRequests) {
|
|
42
|
+
if (pending.timeoutId) {
|
|
43
|
+
clearTimeout(pending.timeoutId);
|
|
44
|
+
}
|
|
42
45
|
pending.reject(new Error("Connection closed"));
|
|
43
46
|
}
|
|
44
47
|
state.pendingRequests.clear();
|
|
48
|
+
for (const [, receiver] of state.streamResponses) {
|
|
49
|
+
receiver.state = "errored";
|
|
50
|
+
receiver.error = new Error("Connection closed");
|
|
51
|
+
const resolvers = receiver.pullResolvers.splice(0);
|
|
52
|
+
for (const resolver of resolvers) {
|
|
53
|
+
resolver();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
state.streamResponses.clear();
|
|
57
|
+
for (const [, session] of state.uploadStreams) {
|
|
58
|
+
session.state = "closed";
|
|
59
|
+
if (session.creditResolver) {
|
|
60
|
+
session.creditResolver();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
state.uploadStreams.clear();
|
|
45
64
|
});
|
|
46
65
|
socket.on("error", (err) => {
|
|
47
66
|
console.error("Socket error:", err);
|
|
48
67
|
});
|
|
49
68
|
return {
|
|
50
69
|
createRuntime: (runtimeOptions) => createRuntime(state, runtimeOptions),
|
|
70
|
+
createNamespace: (id) => ({
|
|
71
|
+
id,
|
|
72
|
+
createRuntime: (runtimeOptions) => createRuntime(state, runtimeOptions, id)
|
|
73
|
+
}),
|
|
51
74
|
close: async () => {
|
|
52
75
|
state.connected = false;
|
|
53
76
|
socket.destroy();
|
|
@@ -150,23 +173,35 @@ function handleMessage(message, state) {
|
|
|
150
173
|
metadata: msg.metadata,
|
|
151
174
|
controller: null,
|
|
152
175
|
state: "active",
|
|
153
|
-
pendingChunks: []
|
|
176
|
+
pendingChunks: [],
|
|
177
|
+
pullResolvers: [],
|
|
178
|
+
controllerFinalized: false
|
|
154
179
|
};
|
|
155
180
|
const readableStream = new ReadableStream({
|
|
156
181
|
start(controller) {
|
|
157
182
|
receiver.controller = controller;
|
|
158
183
|
},
|
|
159
184
|
pull(_controller) {
|
|
185
|
+
if (receiver.controllerFinalized) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
160
188
|
while (receiver.pendingChunks.length > 0) {
|
|
161
189
|
const chunk = receiver.pendingChunks.shift();
|
|
162
190
|
receiver.controller.enqueue(chunk);
|
|
163
191
|
}
|
|
164
192
|
if (receiver.state === "closed") {
|
|
165
|
-
receiver.
|
|
166
|
-
|
|
193
|
+
if (!receiver.controllerFinalized) {
|
|
194
|
+
receiver.controllerFinalized = true;
|
|
195
|
+
receiver.controller.close();
|
|
196
|
+
}
|
|
197
|
+
return Promise.resolve();
|
|
167
198
|
}
|
|
168
199
|
if (receiver.state === "errored") {
|
|
169
|
-
|
|
200
|
+
if (!receiver.controllerFinalized && receiver.error) {
|
|
201
|
+
receiver.controllerFinalized = true;
|
|
202
|
+
receiver.controller.error(receiver.error);
|
|
203
|
+
}
|
|
204
|
+
return Promise.resolve();
|
|
170
205
|
}
|
|
171
206
|
sendMessage(state.socket, {
|
|
172
207
|
type: MessageType.STREAM_PULL,
|
|
@@ -174,17 +209,23 @@ function handleMessage(message, state) {
|
|
|
174
209
|
maxBytes: STREAM_DEFAULT_CREDIT
|
|
175
210
|
});
|
|
176
211
|
return new Promise((resolve) => {
|
|
177
|
-
receiver.
|
|
212
|
+
receiver.pullResolvers.push(resolve);
|
|
178
213
|
});
|
|
179
214
|
},
|
|
180
215
|
cancel(_reason) {
|
|
181
|
-
receiver.state = "
|
|
216
|
+
receiver.state = "closed";
|
|
217
|
+
receiver.controllerFinalized = true;
|
|
218
|
+
const resolvers = receiver.pullResolvers.splice(0);
|
|
219
|
+
for (const resolver of resolvers) {
|
|
220
|
+
resolver();
|
|
221
|
+
}
|
|
182
222
|
sendMessage(state.socket, {
|
|
183
223
|
type: MessageType.STREAM_ERROR,
|
|
184
224
|
streamId: msg.streamId,
|
|
185
225
|
error: "Stream cancelled by consumer"
|
|
186
226
|
});
|
|
187
227
|
state.streamResponses.delete(msg.streamId);
|
|
228
|
+
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
188
229
|
}
|
|
189
230
|
});
|
|
190
231
|
state.streamResponses.set(msg.streamId, receiver);
|
|
@@ -211,10 +252,9 @@ function handleMessage(message, state) {
|
|
|
211
252
|
const msg = message;
|
|
212
253
|
const receiver = state.streamResponses.get(msg.streamId);
|
|
213
254
|
if (receiver && receiver.state === "active") {
|
|
214
|
-
if (receiver.
|
|
255
|
+
if (receiver.pullResolvers.length > 0) {
|
|
215
256
|
receiver.controller.enqueue(msg.chunk);
|
|
216
|
-
const resolver = receiver.
|
|
217
|
-
receiver.pullResolver = undefined;
|
|
257
|
+
const resolver = receiver.pullResolvers.shift();
|
|
218
258
|
resolver();
|
|
219
259
|
} else {
|
|
220
260
|
receiver.pendingChunks.push(msg.chunk);
|
|
@@ -231,10 +271,12 @@ function handleMessage(message, state) {
|
|
|
231
271
|
const chunk = receiver.pendingChunks.shift();
|
|
232
272
|
receiver.controller.enqueue(chunk);
|
|
233
273
|
}
|
|
234
|
-
receiver.
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
274
|
+
if (!receiver.controllerFinalized) {
|
|
275
|
+
receiver.controllerFinalized = true;
|
|
276
|
+
receiver.controller.close();
|
|
277
|
+
}
|
|
278
|
+
const resolvers = receiver.pullResolvers.splice(0);
|
|
279
|
+
for (const resolver of resolvers) {
|
|
238
280
|
resolver();
|
|
239
281
|
}
|
|
240
282
|
state.streamResponses.delete(msg.streamId);
|
|
@@ -263,10 +305,13 @@ function handleMessage(message, state) {
|
|
|
263
305
|
const receiver = state.streamResponses.get(msg.streamId);
|
|
264
306
|
if (receiver) {
|
|
265
307
|
receiver.state = "errored";
|
|
266
|
-
receiver.
|
|
267
|
-
|
|
268
|
-
const
|
|
269
|
-
receiver.
|
|
308
|
+
receiver.error = new Error(msg.error);
|
|
309
|
+
while (receiver.pendingChunks.length > 0) {
|
|
310
|
+
const chunk = receiver.pendingChunks.shift();
|
|
311
|
+
receiver.controller.enqueue(chunk);
|
|
312
|
+
}
|
|
313
|
+
const resolvers = receiver.pullResolvers.splice(0);
|
|
314
|
+
for (const resolver of resolvers) {
|
|
270
315
|
resolver();
|
|
271
316
|
}
|
|
272
317
|
state.streamResponses.delete(msg.streamId);
|
|
@@ -326,7 +371,7 @@ function sendRequest(state, message, timeout = DEFAULT_TIMEOUT) {
|
|
|
326
371
|
sendMessage(state.socket, message);
|
|
327
372
|
});
|
|
328
373
|
}
|
|
329
|
-
async function createRuntime(state, options = {}) {
|
|
374
|
+
async function createRuntime(state, options = {}, namespaceId) {
|
|
330
375
|
const callbacks = {};
|
|
331
376
|
if (options.console) {
|
|
332
377
|
callbacks.console = registerConsoleCallbacks(state, options.console);
|
|
@@ -449,11 +494,13 @@ async function createRuntime(state, options = {}) {
|
|
|
449
494
|
memoryLimitMB: options.memoryLimitMB,
|
|
450
495
|
cwd: options.cwd,
|
|
451
496
|
callbacks,
|
|
452
|
-
testEnvironment: testEnvironmentOption
|
|
497
|
+
testEnvironment: testEnvironmentOption,
|
|
498
|
+
namespaceId
|
|
453
499
|
}
|
|
454
500
|
};
|
|
455
501
|
const result = await sendRequest(state, request);
|
|
456
502
|
const isolateId = result.isolateId;
|
|
503
|
+
const reused = result.reused ?? false;
|
|
457
504
|
const wsCommandCallbacks = new Set;
|
|
458
505
|
isolateWsCallbacks.set(isolateId, wsCommandCallbacks);
|
|
459
506
|
const fetchHandle = {
|
|
@@ -697,6 +744,7 @@ async function createRuntime(state, options = {}) {
|
|
|
697
744
|
return {
|
|
698
745
|
id: isolateId,
|
|
699
746
|
isolateId,
|
|
747
|
+
reused,
|
|
700
748
|
fetch: fetchHandle,
|
|
701
749
|
timers: timersHandle,
|
|
702
750
|
console: consoleHandle,
|
|
@@ -830,7 +878,14 @@ function registerFsCallbacks(state, callbacks) {
|
|
|
830
878
|
function registerModuleLoaderCallback(state, callback) {
|
|
831
879
|
const callbackId = state.nextCallbackId++;
|
|
832
880
|
state.callbacks.set(callbackId, async (moduleName) => {
|
|
833
|
-
|
|
881
|
+
const specifier = moduleName;
|
|
882
|
+
const cached = state.moduleSourceCache.get(specifier);
|
|
883
|
+
if (cached !== undefined) {
|
|
884
|
+
return cached;
|
|
885
|
+
}
|
|
886
|
+
const source = await callback(specifier);
|
|
887
|
+
state.moduleSourceCache.set(specifier, source);
|
|
888
|
+
return source;
|
|
834
889
|
});
|
|
835
890
|
return { callbackId, name: "moduleLoader", type: "async" };
|
|
836
891
|
}
|
|
@@ -1159,4 +1214,4 @@ export {
|
|
|
1159
1214
|
connect
|
|
1160
1215
|
};
|
|
1161
1216
|
|
|
1162
|
-
//# debugId=
|
|
1217
|
+
//# debugId=CF03E0FFB61C218564756E2164756E21
|