sandboxedjs 0.1.45 → 0.1.47
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 +23 -3
- package/dist/agent.d.cts +1 -1
- package/dist/agent.d.ts +1 -1
- package/dist/{container-CZn9USBQ.d.cts → container-DyRF-bY0.d.cts} +52 -1
- package/dist/{container-CZn9USBQ.d.ts → container-DyRF-bY0.d.ts} +52 -1
- package/dist/index.cjs +295 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +121 -4
- package/dist/index.d.ts +121 -4
- package/dist/index.js +295 -6
- package/dist/index.js.map +1 -1
- package/dist/service-worker.js +347 -8
- package/dist/service-worker.js.map +1 -1
- package/dist/worker-entry.js +133 -1
- package/dist/worker-entry.js.map +1 -1
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -20301,6 +20301,8 @@ var CleanPackageInstaller = class _CleanPackageInstaller {
|
|
|
20301
20301
|
fetcher;
|
|
20302
20302
|
metadata = /* @__PURE__ */ new Map();
|
|
20303
20303
|
tarballs = /* @__PURE__ */ new Map();
|
|
20304
|
+
/** Single-version manifests, for the fields the packument omits. */
|
|
20305
|
+
details = /* @__PURE__ */ new Map();
|
|
20304
20306
|
forCwd(cwd) {
|
|
20305
20307
|
return new _CleanPackageInstaller(this.volume, { ...this.options, cwd });
|
|
20306
20308
|
}
|
|
@@ -20326,10 +20328,17 @@ var CleanPackageInstaller = class _CleanPackageInstaller {
|
|
|
20326
20328
|
const version = resolveVersion(metadata, range);
|
|
20327
20329
|
const manifest = metadata.versions[version];
|
|
20328
20330
|
if (!manifest) throw new Error(`No matching version found for ${name}@${range}`);
|
|
20329
|
-
if (!supportsPlatform(manifest)) {
|
|
20330
|
-
throw new Error(`${name}@${version} is not compatible with linux/x64/glibc`);
|
|
20331
|
-
}
|
|
20332
20331
|
const identity = `${name}@${version}`;
|
|
20332
|
+
if (!supportsPlatform(manifest)) throw new IncompatiblePlatform(identity, "");
|
|
20333
|
+
if (manifest.os?.length || manifest.cpu?.length) {
|
|
20334
|
+
const detail = await this.platformDetail(name, version);
|
|
20335
|
+
if (!platformListAllows(detail.libc, PLATFORM.libc)) {
|
|
20336
|
+
throw new IncompatiblePlatform(identity, ` (needs ${detail.libc?.join(", ")})`);
|
|
20337
|
+
}
|
|
20338
|
+
if (detail.main?.endsWith(".node")) {
|
|
20339
|
+
throw new IncompatiblePlatform(identity, " (native addon; this runtime cannot dlopen)");
|
|
20340
|
+
}
|
|
20341
|
+
}
|
|
20333
20342
|
const target = join(modulesRoot, name);
|
|
20334
20343
|
const installed2 = this.tryReadJson(join(target, "package.json"));
|
|
20335
20344
|
if (installed2?.version === version) return installed2;
|
|
@@ -20351,11 +20360,44 @@ var CleanPackageInstaller = class _CleanPackageInstaller {
|
|
|
20351
20360
|
try {
|
|
20352
20361
|
await this.installAt(dependency, dependencyRange, childRoot, options, nextAncestry);
|
|
20353
20362
|
} catch (error) {
|
|
20363
|
+
if (error instanceof IncompatiblePlatform) continue;
|
|
20354
20364
|
options.onProgress?.(`Skipped optional ${dependency}: ${error instanceof Error ? error.message : String(error)}`);
|
|
20355
20365
|
}
|
|
20356
20366
|
}
|
|
20357
20367
|
return manifest;
|
|
20358
20368
|
}
|
|
20369
|
+
/**
|
|
20370
|
+
* The `libc` and `main` fields, which the abbreviated packument leaves out.
|
|
20371
|
+
*
|
|
20372
|
+
* Fetched per version rather than as a full packument: the single-version
|
|
20373
|
+
* document is a few kilobytes, while the full one for a popular package runs
|
|
20374
|
+
* to megabytes. Only packages that already declare `os` or `cpu` ask for it,
|
|
20375
|
+
* so an ordinary install of pure-JavaScript dependencies makes no extra
|
|
20376
|
+
* requests at all — it is the prebuilt binaries, a handful per project, that
|
|
20377
|
+
* need the answer.
|
|
20378
|
+
*
|
|
20379
|
+
* A failure here is not fatal. Being unable to read `libc` puts the check
|
|
20380
|
+
* back where it was before this existed, which is worth strictly less than
|
|
20381
|
+
* being right and strictly more than refusing to install.
|
|
20382
|
+
*/
|
|
20383
|
+
async platformDetail(name, version) {
|
|
20384
|
+
const key = `${name}@${version}`;
|
|
20385
|
+
let request = this.details.get(key);
|
|
20386
|
+
if (!request) {
|
|
20387
|
+
request = (async () => {
|
|
20388
|
+
try {
|
|
20389
|
+
const encoded = name.startsWith("@") ? name.replace("/", "%2F") : encodeURIComponent(name);
|
|
20390
|
+
const response = await this.fetcher(`${this.registry}/${encoded}/${version}`);
|
|
20391
|
+
if (!response.ok) return {};
|
|
20392
|
+
return await response.json();
|
|
20393
|
+
} catch {
|
|
20394
|
+
return {};
|
|
20395
|
+
}
|
|
20396
|
+
})();
|
|
20397
|
+
this.details.set(key, request);
|
|
20398
|
+
}
|
|
20399
|
+
return request;
|
|
20400
|
+
}
|
|
20359
20401
|
async getMetadata(name) {
|
|
20360
20402
|
let request = this.metadata.get(name);
|
|
20361
20403
|
if (!request) {
|
|
@@ -20423,8 +20465,15 @@ var CleanPackageInstaller = class _CleanPackageInstaller {
|
|
|
20423
20465
|
}
|
|
20424
20466
|
}
|
|
20425
20467
|
};
|
|
20468
|
+
var PLATFORM = { os: "linux", cpu: "x64", libc: "glibc" };
|
|
20469
|
+
var IncompatiblePlatform = class extends Error {
|
|
20470
|
+
constructor(identity, detail) {
|
|
20471
|
+
super(`${identity} is not compatible with ${PLATFORM.os}/${PLATFORM.cpu}/${PLATFORM.libc}${detail}`);
|
|
20472
|
+
this.name = "IncompatiblePlatform";
|
|
20473
|
+
}
|
|
20474
|
+
};
|
|
20426
20475
|
function supportsPlatform(manifest) {
|
|
20427
|
-
return
|
|
20476
|
+
return platformListAllows(manifest.os, PLATFORM.os) && platformListAllows(manifest.cpu, PLATFORM.cpu) && platformListAllows(manifest.libc, PLATFORM.libc);
|
|
20428
20477
|
}
|
|
20429
20478
|
function platformListAllows(values, current) {
|
|
20430
20479
|
if (!values?.length) return true;
|
|
@@ -23472,8 +23521,17 @@ var VirtualIncomingMessage = class extends streamModule4.Readable {
|
|
|
23472
23521
|
httpVersionMajor = 1;
|
|
23473
23522
|
httpVersionMinor = 1;
|
|
23474
23523
|
complete = true;
|
|
23524
|
+
/*
|
|
23525
|
+
* Mutable, and `connection` a getter over it, because an upgraded request
|
|
23526
|
+
* carries a real socket rather than the stub. `emit("upgrade", req, socket)`
|
|
23527
|
+
* hands the same object to both places, and a library that reaches it as
|
|
23528
|
+
* `req.socket` — rather than through the argument — has to find the one it
|
|
23529
|
+
* can actually write to.
|
|
23530
|
+
*/
|
|
23475
23531
|
socket = socketStub();
|
|
23476
|
-
connection
|
|
23532
|
+
get connection() {
|
|
23533
|
+
return this.socket;
|
|
23534
|
+
}
|
|
23477
23535
|
constructor(init) {
|
|
23478
23536
|
super();
|
|
23479
23537
|
this.method = (init.method ?? "GET").toUpperCase();
|
|
@@ -23579,6 +23637,80 @@ var VirtualServerResponse = class extends streamModule4.Writable {
|
|
|
23579
23637
|
return this;
|
|
23580
23638
|
}
|
|
23581
23639
|
};
|
|
23640
|
+
var VirtualSocket = class extends streamModule4.Duplex {
|
|
23641
|
+
remoteAddress = "127.0.0.1";
|
|
23642
|
+
remotePort = 0;
|
|
23643
|
+
localAddress = "127.0.0.1";
|
|
23644
|
+
localPort = 0;
|
|
23645
|
+
encrypted = false;
|
|
23646
|
+
bufferSize = 0;
|
|
23647
|
+
peer;
|
|
23648
|
+
/** Set once the peer is told, so `end()` then `destroy()` reports once. */
|
|
23649
|
+
hungUp = false;
|
|
23650
|
+
constructor(peer) {
|
|
23651
|
+
super({ allowHalfOpen: false });
|
|
23652
|
+
this.peer = peer;
|
|
23653
|
+
}
|
|
23654
|
+
_read() {
|
|
23655
|
+
}
|
|
23656
|
+
_write(chunk, encoding, callback) {
|
|
23657
|
+
const bytes2 = Buffer2.isBuffer(chunk) ? chunk : Buffer2.from(chunk, encoding);
|
|
23658
|
+
try {
|
|
23659
|
+
this.peer?.data(new Uint8Array(bytes2));
|
|
23660
|
+
callback();
|
|
23661
|
+
} catch (error) {
|
|
23662
|
+
callback(error);
|
|
23663
|
+
}
|
|
23664
|
+
}
|
|
23665
|
+
_final(callback) {
|
|
23666
|
+
this.hangUp();
|
|
23667
|
+
callback();
|
|
23668
|
+
}
|
|
23669
|
+
_destroy(error, callback) {
|
|
23670
|
+
this.hangUp();
|
|
23671
|
+
callback(error);
|
|
23672
|
+
}
|
|
23673
|
+
hangUp() {
|
|
23674
|
+
if (this.hungUp) return;
|
|
23675
|
+
this.hungUp = true;
|
|
23676
|
+
try {
|
|
23677
|
+
this.peer?.close();
|
|
23678
|
+
} catch {
|
|
23679
|
+
}
|
|
23680
|
+
this.peer = null;
|
|
23681
|
+
}
|
|
23682
|
+
/** Bytes arriving from the far end. */
|
|
23683
|
+
deliver(bytes2) {
|
|
23684
|
+
if (this.destroyed || this.hungUp) return;
|
|
23685
|
+
this.push(Buffer2.from(bytes2));
|
|
23686
|
+
}
|
|
23687
|
+
/** The far end went away; let the server's stream end cleanly. */
|
|
23688
|
+
peerClosed() {
|
|
23689
|
+
if (this.destroyed) return;
|
|
23690
|
+
this.push(null);
|
|
23691
|
+
}
|
|
23692
|
+
/* The parts of `net.Socket` a WebSocket library reaches for. None of them
|
|
23693
|
+
* mean anything without a kernel, but every one of them is called. */
|
|
23694
|
+
setNoDelay() {
|
|
23695
|
+
return this;
|
|
23696
|
+
}
|
|
23697
|
+
setKeepAlive() {
|
|
23698
|
+
return this;
|
|
23699
|
+
}
|
|
23700
|
+
setTimeout(_milliseconds, callback) {
|
|
23701
|
+
if (callback) this.once("timeout", callback);
|
|
23702
|
+
return this;
|
|
23703
|
+
}
|
|
23704
|
+
destroySoon() {
|
|
23705
|
+
this.end();
|
|
23706
|
+
}
|
|
23707
|
+
ref() {
|
|
23708
|
+
return this;
|
|
23709
|
+
}
|
|
23710
|
+
unref() {
|
|
23711
|
+
return this;
|
|
23712
|
+
}
|
|
23713
|
+
};
|
|
23582
23714
|
var VirtualHttpServer = class extends EventEmitter4 {
|
|
23583
23715
|
constructor(router, owner, listener) {
|
|
23584
23716
|
super();
|
|
@@ -23678,6 +23810,33 @@ var VirtualHttpRouter = class {
|
|
|
23678
23810
|
return { statusCode: 500, statusMessage: "Internal Server Error", headers: {}, body: error instanceof Error ? error.message : String(error) };
|
|
23679
23811
|
}
|
|
23680
23812
|
}
|
|
23813
|
+
/**
|
|
23814
|
+
* Open a connection that leaves HTTP behind — a WebSocket, in practice.
|
|
23815
|
+
*
|
|
23816
|
+
* The counterpart to {@link request}, and the thing whose absence made a dev
|
|
23817
|
+
* server look broken. Every Node WebSocket library is built the same way: it
|
|
23818
|
+
* hands `http.Server` an `upgrade` listener and waits. Nothing here ever
|
|
23819
|
+
* emitted one, so `ws` sat holding a server that could not receive a single
|
|
23820
|
+
* connection, and Vite lost the channel it uses to tell a page to reload —
|
|
23821
|
+
* which is the only way it can recover after re-optimizing dependencies.
|
|
23822
|
+
*
|
|
23823
|
+
* Null means there is nothing to connect to: no server on the port, or a
|
|
23824
|
+
* server that never asked for upgrades. Both are refusals the caller should
|
|
23825
|
+
* report rather than wait out.
|
|
23826
|
+
*/
|
|
23827
|
+
connect(port, init, peer) {
|
|
23828
|
+
const item = this.servers.get(port);
|
|
23829
|
+
if (!item) return null;
|
|
23830
|
+
if (item.server.listenerCount("upgrade") === 0) return null;
|
|
23831
|
+
const request = new VirtualIncomingMessage(init);
|
|
23832
|
+
const socket = new VirtualSocket(peer);
|
|
23833
|
+
request.socket = socket;
|
|
23834
|
+
item.server.emit("upgrade", request, socket, Buffer2.alloc(0));
|
|
23835
|
+
return {
|
|
23836
|
+
send: (bytes2) => socket.deliver(bytes2),
|
|
23837
|
+
close: () => socket.peerClosed()
|
|
23838
|
+
};
|
|
23839
|
+
}
|
|
23681
23840
|
};
|
|
23682
23841
|
var VirtualClientResponse = class extends streamModule4.Readable {
|
|
23683
23842
|
constructor(statusCode, statusMessage, headers, body) {
|
|
@@ -27194,6 +27353,9 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
27194
27353
|
async request(_port, _init = {}) {
|
|
27195
27354
|
return this.router.request(_port, _init);
|
|
27196
27355
|
}
|
|
27356
|
+
connect(port, init, peer) {
|
|
27357
|
+
return this.router.connect(port, init, peer);
|
|
27358
|
+
}
|
|
27197
27359
|
snapshot() {
|
|
27198
27360
|
this.assertActive();
|
|
27199
27361
|
return this.volume.snapshot();
|
|
@@ -27629,6 +27791,15 @@ var WorkerRuntimePod = class _WorkerRuntimePod extends LocalRuntimePod {
|
|
|
27629
27791
|
case "http-response":
|
|
27630
27792
|
this.settleProxied(Number(message.id), message.response);
|
|
27631
27793
|
return;
|
|
27794
|
+
case "ws-data":
|
|
27795
|
+
this.upgraded.get(Number(message.id))?.write(new Uint8Array(message.data));
|
|
27796
|
+
return;
|
|
27797
|
+
case "ws-close": {
|
|
27798
|
+
const socket = this.upgraded.get(Number(message.id));
|
|
27799
|
+
this.upgraded.delete(Number(message.id));
|
|
27800
|
+
socket?.end();
|
|
27801
|
+
return;
|
|
27802
|
+
}
|
|
27632
27803
|
case "child-start":
|
|
27633
27804
|
this.startChild(worker, children, message, ownedChildren);
|
|
27634
27805
|
return;
|
|
@@ -27717,6 +27888,8 @@ var WorkerRuntimePod = class _WorkerRuntimePod extends LocalRuntimePod {
|
|
|
27717
27888
|
// ── HTTP servers living on another thread ─────────────────────────────────
|
|
27718
27889
|
proxies = /* @__PURE__ */ new Map();
|
|
27719
27890
|
waiting = /* @__PURE__ */ new Map();
|
|
27891
|
+
/** Upgraded connections, by the id the Worker knows them as. */
|
|
27892
|
+
upgraded = /* @__PURE__ */ new Map();
|
|
27720
27893
|
nextRequestId = 1;
|
|
27721
27894
|
/**
|
|
27722
27895
|
* Register a stand-in for a server that is actually running in the Worker.
|
|
@@ -27729,6 +27902,9 @@ var WorkerRuntimePod = class _WorkerRuntimePod extends LocalRuntimePod {
|
|
|
27729
27902
|
const server = new VirtualHttpServer(this.router, owner, (request, response) => {
|
|
27730
27903
|
void this.forward(worker, port, request, response);
|
|
27731
27904
|
});
|
|
27905
|
+
server.on("upgrade", (request, socket) => {
|
|
27906
|
+
this.upgrade(worker, port, request, socket);
|
|
27907
|
+
});
|
|
27732
27908
|
try {
|
|
27733
27909
|
server.listen(port);
|
|
27734
27910
|
this.proxies.set(port, server);
|
|
@@ -27759,6 +27935,33 @@ var WorkerRuntimePod = class _WorkerRuntimePod extends LocalRuntimePod {
|
|
|
27759
27935
|
response.writeHead(Number(result.statusCode ?? 200), String(result.statusMessage ?? ""), result.headers ?? {});
|
|
27760
27936
|
response.end(result.body ?? new Uint8Array());
|
|
27761
27937
|
}
|
|
27938
|
+
/**
|
|
27939
|
+
* Tunnel one upgraded connection to the server that actually holds the port.
|
|
27940
|
+
*
|
|
27941
|
+
* Unlike {@link forward} there is no reply to wait for: both ends write
|
|
27942
|
+
* whenever they have something, until one of them stops. The id is what ties
|
|
27943
|
+
* the two directions together across the Worker boundary.
|
|
27944
|
+
*/
|
|
27945
|
+
upgrade(worker, port, request, socket) {
|
|
27946
|
+
const id = this.nextRequestId++;
|
|
27947
|
+
this.upgraded.set(id, socket);
|
|
27948
|
+
socket.on("data", (chunk) => {
|
|
27949
|
+
const bytes2 = new Uint8Array(chunk);
|
|
27950
|
+
worker.postMessage({ type: "ws-data", id, data: bytes2 });
|
|
27951
|
+
});
|
|
27952
|
+
const drop = () => {
|
|
27953
|
+
if (!this.upgraded.delete(id)) return;
|
|
27954
|
+
worker.postMessage({ type: "ws-close", id });
|
|
27955
|
+
};
|
|
27956
|
+
socket.on("close", drop);
|
|
27957
|
+
socket.on("error", drop);
|
|
27958
|
+
worker.postMessage({
|
|
27959
|
+
type: "ws-open",
|
|
27960
|
+
id,
|
|
27961
|
+
port,
|
|
27962
|
+
init: { method: request.method, path: request.url, headers: request.headers }
|
|
27963
|
+
});
|
|
27964
|
+
}
|
|
27762
27965
|
settleProxied(id, response) {
|
|
27763
27966
|
const resolve2 = this.waiting.get(id);
|
|
27764
27967
|
if (!resolve2) return;
|
|
@@ -27771,6 +27974,10 @@ var WorkerRuntimePod = class _WorkerRuntimePod extends LocalRuntimePod {
|
|
|
27771
27974
|
server.close();
|
|
27772
27975
|
this.proxies.delete(port);
|
|
27773
27976
|
}
|
|
27977
|
+
for (const [id, socket] of [...this.upgraded]) {
|
|
27978
|
+
this.upgraded.delete(id);
|
|
27979
|
+
socket.destroy();
|
|
27980
|
+
}
|
|
27774
27981
|
}
|
|
27775
27982
|
teardown() {
|
|
27776
27983
|
for (const { worker, server } of [...this.live]) {
|
|
@@ -28144,6 +28351,29 @@ var Container = class _Container {
|
|
|
28144
28351
|
}
|
|
28145
28352
|
};
|
|
28146
28353
|
}
|
|
28354
|
+
/**
|
|
28355
|
+
* Open a connection to a server inside the container that upgrades out of
|
|
28356
|
+
* HTTP — in practice, a WebSocket.
|
|
28357
|
+
*
|
|
28358
|
+
* The counterpart to {@link request}, and the thing a dev server needs that
|
|
28359
|
+
* a request cannot provide. Bytes go in with `send`, come back through
|
|
28360
|
+
* `peer.data`, and neither side interprets them: the container runs whatever
|
|
28361
|
+
* WebSocket library the program chose, and the caller is responsible for
|
|
28362
|
+
* speaking the protocol it answers with.
|
|
28363
|
+
*
|
|
28364
|
+
* Null means there is nothing to talk to — no server on the port, or one
|
|
28365
|
+
* that never registered an `upgrade` handler. Both are worth reporting
|
|
28366
|
+
* rather than waiting out, because neither resolves on its own.
|
|
28367
|
+
*/
|
|
28368
|
+
connect(port, init = {}, peer) {
|
|
28369
|
+
this.assertActive();
|
|
28370
|
+
if (!this.pod.connect) return null;
|
|
28371
|
+
return this.pod.connect(
|
|
28372
|
+
port,
|
|
28373
|
+
{ method: init.method ?? "GET", path: init.path ?? "/", headers: init.headers ?? {} },
|
|
28374
|
+
peer
|
|
28375
|
+
);
|
|
28376
|
+
}
|
|
28147
28377
|
/**
|
|
28148
28378
|
* Deliver a request whose body is bytes, without letting them become text.
|
|
28149
28379
|
*
|
|
@@ -28715,6 +28945,12 @@ init_arith();
|
|
|
28715
28945
|
init_expand();
|
|
28716
28946
|
init_builtins();
|
|
28717
28947
|
|
|
28948
|
+
// src/preview/ws-client.ts
|
|
28949
|
+
var WS_OPEN = "sandboxedjs:ws-open";
|
|
28950
|
+
var WS_DATA = "sandboxedjs:ws-data";
|
|
28951
|
+
var WS_CLOSE = "sandboxedjs:ws-close";
|
|
28952
|
+
var WS_ERROR = "sandboxedjs:ws-error";
|
|
28953
|
+
|
|
28718
28954
|
// src/preview/register.ts
|
|
28719
28955
|
function serveContainerOn(port, box) {
|
|
28720
28956
|
port.onmessage = async (event) => {
|
|
@@ -28800,7 +29036,7 @@ async function createPreview(box, options = {}) {
|
|
|
28800
29036
|
channel = new MessageChannel();
|
|
28801
29037
|
serveContainerOn(channel.port1, box);
|
|
28802
29038
|
const target = registration.active ?? worker;
|
|
28803
|
-
target.postMessage({ type: "sandboxedjs:connect" }, [channel.port2]);
|
|
29039
|
+
target.postMessage({ type: "sandboxedjs:connect", injectSockets: options.websocket !== false }, [channel.port2]);
|
|
28804
29040
|
};
|
|
28805
29041
|
const onWorkerMessage = (event) => {
|
|
28806
29042
|
const type = event.data?.type;
|
|
@@ -28809,6 +29045,56 @@ async function createPreview(box, options = {}) {
|
|
|
28809
29045
|
};
|
|
28810
29046
|
navigator.serviceWorker.addEventListener("message", onWorkerMessage);
|
|
28811
29047
|
connect();
|
|
29048
|
+
const sockets = /* @__PURE__ */ new Map();
|
|
29049
|
+
const onFrameMessage = (event) => {
|
|
29050
|
+
if (event.origin !== location.origin || !event.source) return;
|
|
29051
|
+
const data = event.data;
|
|
29052
|
+
if (!data || typeof data !== "object") return;
|
|
29053
|
+
if (data.type !== WS_OPEN && data.type !== WS_DATA && data.type !== WS_CLOSE) return;
|
|
29054
|
+
const source = event.source;
|
|
29055
|
+
const id = Number(data.id);
|
|
29056
|
+
const reply = (message, transfer = []) => source.postMessage(message, location.origin, transfer);
|
|
29057
|
+
if (data.type === WS_OPEN) {
|
|
29058
|
+
let table2 = sockets.get(source);
|
|
29059
|
+
if (!table2) sockets.set(source, table2 = /* @__PURE__ */ new Map());
|
|
29060
|
+
let opened = null;
|
|
29061
|
+
try {
|
|
29062
|
+
opened = box.connect(
|
|
29063
|
+
Number(data.port),
|
|
29064
|
+
{ method: "GET", path: data.path ?? "/", headers: data.headers ?? {} },
|
|
29065
|
+
{
|
|
29066
|
+
data: (bytes2) => {
|
|
29067
|
+
const carrier = bytes2.slice().buffer;
|
|
29068
|
+
reply({ type: WS_DATA, id, data: carrier }, [carrier]);
|
|
29069
|
+
},
|
|
29070
|
+
close: () => {
|
|
29071
|
+
table2.delete(id);
|
|
29072
|
+
reply({ type: WS_CLOSE, id });
|
|
29073
|
+
}
|
|
29074
|
+
}
|
|
29075
|
+
);
|
|
29076
|
+
} catch (error) {
|
|
29077
|
+
opened = null;
|
|
29078
|
+
reply({ type: WS_ERROR, id, message: error instanceof Error ? error.message : String(error) });
|
|
29079
|
+
return;
|
|
29080
|
+
}
|
|
29081
|
+
if (!opened) {
|
|
29082
|
+
reply({ type: WS_ERROR, id, message: `Nothing is accepting WebSocket connections on port ${data.port}.` });
|
|
29083
|
+
return;
|
|
29084
|
+
}
|
|
29085
|
+
table2.set(id, opened);
|
|
29086
|
+
return;
|
|
29087
|
+
}
|
|
29088
|
+
const table = sockets.get(source);
|
|
29089
|
+
const socket = table?.get(id);
|
|
29090
|
+
if (!socket) return;
|
|
29091
|
+
if (data.type === WS_DATA) socket.send(new Uint8Array(data.data));
|
|
29092
|
+
else {
|
|
29093
|
+
socket.close();
|
|
29094
|
+
table.delete(id);
|
|
29095
|
+
}
|
|
29096
|
+
};
|
|
29097
|
+
if (typeof window !== "undefined") window.addEventListener("message", onFrameMessage);
|
|
28812
29098
|
const base2 = registration.scope.replace(/\/$/, "");
|
|
28813
29099
|
const urlFor = (port) => `${base2}/__sbx__/${port}/`;
|
|
28814
29100
|
return {
|
|
@@ -28822,6 +29108,9 @@ async function createPreview(box, options = {}) {
|
|
|
28822
29108
|
},
|
|
28823
29109
|
dispose: async () => {
|
|
28824
29110
|
navigator.serviceWorker.removeEventListener("message", onWorkerMessage);
|
|
29111
|
+
if (typeof window !== "undefined") window.removeEventListener("message", onFrameMessage);
|
|
29112
|
+
for (const table of sockets.values()) for (const socket of table.values()) socket.close();
|
|
29113
|
+
sockets.clear();
|
|
28825
29114
|
channel?.port1.close();
|
|
28826
29115
|
channel = null;
|
|
28827
29116
|
await registration.unregister();
|