@bytecodealliance/preview2-shim 0.25.0 → 0.26.1
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 +3 -5
- package/dist/common/instantiation.js +11 -0
- package/dist/nodejs/filesystem.d.ts +1 -2
- package/dist/nodejs/filesystem.js +109 -95
- package/dist/nodejs/http.d.ts +4 -55
- package/dist/nodejs/http.js +11 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -107,8 +107,7 @@ const shim = new WASIShim({
|
|
|
107
107
|
```
|
|
108
108
|
|
|
109
109
|
This keeps permission prompts, handle acquisition, persistence, and synchronization policy in
|
|
110
|
-
application code.
|
|
111
|
-
`fetch` capability.
|
|
110
|
+
application code. `sandbox.enableNetwork: false` denies raw TCP, UDP, DNS, and outbound HTTP.
|
|
112
111
|
|
|
113
112
|
Deterministic in-memory transports are available for components that act as servers and for tests:
|
|
114
113
|
|
|
@@ -240,9 +239,8 @@ const component = await instantiate(loader, sandboxedShim.getImportObject());
|
|
|
240
239
|
- The direct preopen functions (`_setPreopens`, `_clearPreopens`, etc.) modify global state and
|
|
241
240
|
affect all components not using `WASIShim` with explicit configuration. For isolation, prefer
|
|
242
241
|
using `WASIShim` with the `sandbox` option containing `preopens` and `env`.
|
|
243
|
-
- When `sandbox.enableNetwork: false`,
|
|
244
|
-
network
|
|
245
|
-
namespace when the embedding must deny it as well.
|
|
242
|
+
- When `sandbox.enableNetwork: false`, socket operations and outbound HTTP receive instance-local
|
|
243
|
+
denied network capabilities.
|
|
246
244
|
|
|
247
245
|
[jco]: https://www.npmjs.com/package/@bytecodealliance/jco
|
|
248
246
|
|
|
@@ -180,6 +180,17 @@ export class WASIShim {
|
|
|
180
180
|
};
|
|
181
181
|
}
|
|
182
182
|
this.#http = shims?.http ?? wasi.http;
|
|
183
|
+
if (sandbox?.enableNetwork === false) {
|
|
184
|
+
this.#http = {
|
|
185
|
+
...this.#http,
|
|
186
|
+
outgoingHandler: {
|
|
187
|
+
...this.#http.outgoingHandler,
|
|
188
|
+
handle() {
|
|
189
|
+
throw "access-denied";
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
}
|
|
183
194
|
if (shims?.incomingHandler) {
|
|
184
195
|
if (!this.#http.createIncomingHandler) {
|
|
185
196
|
throw new TypeError("the selected HTTP shim does not support Web incoming handlers");
|
|
@@ -95,11 +95,10 @@ export declare function _setPreopens(preopens: any): void;
|
|
|
95
95
|
export declare function _addPreopen(virtualPath: any, hostPreopen: any): void;
|
|
96
96
|
/**
|
|
97
97
|
* Clear all preopens, giving the guest no filesystem access.
|
|
98
|
-
* Call this immediately after import to disable default full filesystem access.
|
|
99
98
|
*
|
|
100
99
|
* @example
|
|
101
100
|
* import { _clearPreopens } from '@bytecodealliance/preview2-shim/filesystem';
|
|
102
|
-
* _clearPreopens();
|
|
101
|
+
* _clearPreopens();
|
|
103
102
|
*/
|
|
104
103
|
export declare function _clearPreopens(): void;
|
|
105
104
|
/**
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { earlyDispose, inputStreamCreate, ioCall, outputStreamCreate, registerDispose, } from "../io/worker-io.js";
|
|
2
2
|
import { FILE, FILESYSTEM_DESCRIPTOR_ADVISE, FILESYSTEM_DESCRIPTOR_CLOSE, FILESYSTEM_DESCRIPTOR_GET_TYPE, FILESYSTEM_DESCRIPTOR_METADATA_HASH, FILESYSTEM_DESCRIPTOR_OPEN, FILESYSTEM_DESCRIPTOR_READ, FILESYSTEM_DESCRIPTOR_SET_SIZE, FILESYSTEM_DESCRIPTOR_SET_TIMES, FILESYSTEM_DESCRIPTOR_STAT, FILESYSTEM_DESCRIPTOR_SYNC, FILESYSTEM_DESCRIPTOR_SYNC_DATA, FILESYSTEM_DESCRIPTOR_WRITE, INPUT_STREAM_CREATE, OUTPUT_STREAM_CREATE, } from "../io/calls.js";
|
|
3
3
|
import { constants, linkSync, lstatSync, lutimesSync, mkdirSync, opendirSync, readlinkSync, realpathSync, renameSync, rmdirSync, statSync, symlinkSync, unlinkSync, utimesSync, } from "node:fs";
|
|
4
|
+
import { posix, win32 } from "node:path";
|
|
4
5
|
import { platform } from "node:process";
|
|
5
6
|
const symbolDispose = Symbol.dispose || Symbol.for("dispose");
|
|
6
7
|
const isWindows = platform === "win32";
|
|
7
8
|
const isMac = platform === "darwin";
|
|
9
|
+
const hostPath = isWindows ? win32 : posix;
|
|
10
|
+
const MAX_SYMLINKS = 40;
|
|
11
|
+
function normalizeHostPath(path) {
|
|
12
|
+
return isWindows ? path.replace(/\\/g, "/") : path;
|
|
13
|
+
}
|
|
8
14
|
const nsMagnitude = 1000000000n;
|
|
9
15
|
function nsToDateTime(ns) {
|
|
10
16
|
const seconds = ns / nsMagnitude;
|
|
@@ -226,7 +232,7 @@ class Descriptor {
|
|
|
226
232
|
}
|
|
227
233
|
}
|
|
228
234
|
createDirectoryAt(path) {
|
|
229
|
-
const fullPath = this.#getFullPath(path);
|
|
235
|
+
const fullPath = this.#getFullPath(path, false);
|
|
230
236
|
try {
|
|
231
237
|
mkdirSync(fullPath);
|
|
232
238
|
}
|
|
@@ -256,7 +262,7 @@ class Descriptor {
|
|
|
256
262
|
};
|
|
257
263
|
}
|
|
258
264
|
statAt(pathFlags, path) {
|
|
259
|
-
const fullPath = this.#getFullPath(path);
|
|
265
|
+
const fullPath = this.#getFullPath(path, pathFlags.symlinkFollow);
|
|
260
266
|
let stats;
|
|
261
267
|
try {
|
|
262
268
|
stats = (pathFlags.symlinkFollow ? statSync : lstatSync)(fullPath, {
|
|
@@ -277,7 +283,7 @@ class Descriptor {
|
|
|
277
283
|
};
|
|
278
284
|
}
|
|
279
285
|
setTimesAt(pathFlags, path, dataAccessTimestamp, dataModificationTimestamp) {
|
|
280
|
-
const fullPath = this.#getFullPath(path);
|
|
286
|
+
const fullPath = this.#getFullPath(path, pathFlags.symlinkFollow);
|
|
281
287
|
let stats;
|
|
282
288
|
if (dataAccessTimestamp.tag === "no-change" ||
|
|
283
289
|
dataModificationTimestamp.tag === "no-change") {
|
|
@@ -288,7 +294,7 @@ class Descriptor {
|
|
|
288
294
|
if (!pathFlags.symlinkFollow && !lutimesSync) {
|
|
289
295
|
throw new Error("Changing the timestamps of symlinks isn't supported");
|
|
290
296
|
}
|
|
291
|
-
let metadataSetFn = pathFlags.symlinkFollow ?
|
|
297
|
+
let metadataSetFn = pathFlags.symlinkFollow ? utimesSync : lutimesSync;
|
|
292
298
|
try {
|
|
293
299
|
metadataSetFn(fullPath, atime / 1000, mtime / 1000);
|
|
294
300
|
}
|
|
@@ -297,42 +303,21 @@ class Descriptor {
|
|
|
297
303
|
}
|
|
298
304
|
}
|
|
299
305
|
linkAt(oldPathFlags, oldPath, newDescriptor, newPath) {
|
|
300
|
-
const oldFullPath = this.#getFullPath(oldPath);
|
|
301
|
-
const newFullPath = newDescriptor.#getFullPath(newPath);
|
|
306
|
+
const oldFullPath = this.#getFullPath(oldPath, oldPathFlags.symlinkFollow);
|
|
307
|
+
const newFullPath = newDescriptor.#getFullPath(newPath, false);
|
|
302
308
|
// Windows doesn't automatically fail on trailing slashes
|
|
303
309
|
if (isWindows && newFullPath.endsWith("/")) {
|
|
304
310
|
throw "no-entry";
|
|
305
311
|
}
|
|
306
312
|
try {
|
|
307
|
-
|
|
308
|
-
// Resolve only this operation's source, propagating resolution errors
|
|
309
|
-
// instead of silently hard-linking a dangling or cyclic symlink.
|
|
310
|
-
let source = oldFullPath;
|
|
311
|
-
if (oldPathFlags.symlinkFollow) {
|
|
312
|
-
source = realpathSync(source);
|
|
313
|
-
// realpath strips trailing slashes; keep the caller's directory
|
|
314
|
-
// requirement so a regular-file source ending in '/' still fails.
|
|
315
|
-
if (oldFullPath.endsWith("/")) {
|
|
316
|
-
// Windows may ignore a trailing slash even in linkSync.
|
|
317
|
-
if (!statSync(source).isDirectory()) {
|
|
318
|
-
throw "not-directory";
|
|
319
|
-
}
|
|
320
|
-
if (!source.endsWith("/")) {
|
|
321
|
-
source += "/";
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
linkSync(source, newFullPath);
|
|
313
|
+
linkSync(oldFullPath, newFullPath);
|
|
326
314
|
}
|
|
327
315
|
catch (e) {
|
|
328
316
|
throw convertFsError(e);
|
|
329
317
|
}
|
|
330
318
|
}
|
|
331
319
|
openAt(pathFlags, path, openFlags, descriptorFlags) {
|
|
332
|
-
|
|
333
|
-
throw "access";
|
|
334
|
-
}
|
|
335
|
-
const fullPath = this.#getFullPath(path);
|
|
320
|
+
const fullPath = this.#getFullPath(path, pathFlags.symlinkFollow);
|
|
336
321
|
let fsOpenFlags = 0x0;
|
|
337
322
|
if (openFlags.create) {
|
|
338
323
|
fsOpenFlags |= constants.O_CREAT;
|
|
@@ -426,16 +411,17 @@ class Descriptor {
|
|
|
426
411
|
}
|
|
427
412
|
}
|
|
428
413
|
readlinkAt(path) {
|
|
429
|
-
const fullPath = this.#getFullPath(path);
|
|
414
|
+
const fullPath = this.#getFullPath(path, false);
|
|
430
415
|
try {
|
|
431
|
-
|
|
416
|
+
const target = readlinkSync(fullPath);
|
|
417
|
+
return isWindows ? target.replace(/\\/g, "/") : target;
|
|
432
418
|
}
|
|
433
419
|
catch (e) {
|
|
434
420
|
throw convertFsError(e);
|
|
435
421
|
}
|
|
436
422
|
}
|
|
437
423
|
removeDirectoryAt(path) {
|
|
438
|
-
const fullPath = this.#getFullPath(path);
|
|
424
|
+
const fullPath = this.#getFullPath(path, false);
|
|
439
425
|
try {
|
|
440
426
|
rmdirSync(fullPath);
|
|
441
427
|
}
|
|
@@ -447,8 +433,8 @@ class Descriptor {
|
|
|
447
433
|
}
|
|
448
434
|
}
|
|
449
435
|
renameAt(oldPath, newDescriptor, newPath) {
|
|
450
|
-
const oldFullPath = this.#getFullPath(oldPath);
|
|
451
|
-
const newFullPath = newDescriptor.#getFullPath(newPath);
|
|
436
|
+
const oldFullPath = this.#getFullPath(oldPath, false);
|
|
437
|
+
const newFullPath = newDescriptor.#getFullPath(newPath, false);
|
|
452
438
|
try {
|
|
453
439
|
renameSync(oldFullPath, newFullPath);
|
|
454
440
|
}
|
|
@@ -460,7 +446,7 @@ class Descriptor {
|
|
|
460
446
|
}
|
|
461
447
|
}
|
|
462
448
|
symlinkAt(target, path) {
|
|
463
|
-
const fullPath = this.#getFullPath(path);
|
|
449
|
+
const fullPath = this.#getFullPath(path, false);
|
|
464
450
|
if (target.startsWith("/")) {
|
|
465
451
|
throw "not-permitted";
|
|
466
452
|
}
|
|
@@ -489,7 +475,7 @@ class Descriptor {
|
|
|
489
475
|
}
|
|
490
476
|
}
|
|
491
477
|
unlinkFileAt(path) {
|
|
492
|
-
const fullPath = this.#getFullPath(path);
|
|
478
|
+
const fullPath = this.#getFullPath(path, false);
|
|
493
479
|
try {
|
|
494
480
|
if (fullPath.endsWith("/")) {
|
|
495
481
|
let isDir = false;
|
|
@@ -531,7 +517,7 @@ class Descriptor {
|
|
|
531
517
|
}
|
|
532
518
|
}
|
|
533
519
|
metadataHashAt(pathFlags, path) {
|
|
534
|
-
const fullPath = this.#getFullPath(path);
|
|
520
|
+
const fullPath = this.#getFullPath(path, pathFlags.symlinkFollow);
|
|
535
521
|
try {
|
|
536
522
|
const stats = (pathFlags.symlinkFollow ? statSync : lstatSync)(fullPath, {
|
|
537
523
|
bigint: true,
|
|
@@ -542,70 +528,100 @@ class Descriptor {
|
|
|
542
528
|
throw convertFsError(e);
|
|
543
529
|
}
|
|
544
530
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
if (subpath.indexOf("\\") !== -1) {
|
|
549
|
-
subpath = subpath.replace(/\\/g, "/");
|
|
550
|
-
}
|
|
551
|
-
if (subpath.indexOf("//") !== -1) {
|
|
552
|
-
subpath = subpath.replace(/\/\/+/g, "/");
|
|
553
|
-
}
|
|
554
|
-
if (subpath[0] === "/") {
|
|
531
|
+
#getFullPath(subpath, followFinalSymlink) {
|
|
532
|
+
subpath = subpath.replace(/\\/g, "/").replace(/\/\/+/g, "/");
|
|
533
|
+
if (subpath.startsWith("/")) {
|
|
555
534
|
throw "not-permitted";
|
|
556
535
|
}
|
|
557
|
-
|
|
536
|
+
const trailingSlash = subpath.endsWith("/");
|
|
558
537
|
const segments = [];
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
// busy reading a segment - only terminate on '/'
|
|
562
|
-
if (segmentIndex !== -1) {
|
|
563
|
-
if (subpath[i] === "/") {
|
|
564
|
-
segments.push(subpath.slice(segmentIndex, i + 1));
|
|
565
|
-
segmentIndex = -1;
|
|
566
|
-
}
|
|
538
|
+
for (const segment of subpath.split("/")) {
|
|
539
|
+
if (segment === "" || segment === ".") {
|
|
567
540
|
continue;
|
|
568
541
|
}
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
if (subpath[i + 1] === "." &&
|
|
573
|
-
(subpath[i + 2] === "/" || i + 2 === subpath.length)) {
|
|
574
|
-
if (segments.pop() === undefined) {
|
|
575
|
-
throw "not-permitted";
|
|
576
|
-
}
|
|
577
|
-
i += 2;
|
|
578
|
-
continue;
|
|
542
|
+
if (segment === "..") {
|
|
543
|
+
if (segments.pop() === undefined) {
|
|
544
|
+
throw "not-permitted";
|
|
579
545
|
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
546
|
+
}
|
|
547
|
+
else {
|
|
548
|
+
segments.push(segment);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
const base = this.#hostPreopen ?? this.#fullPath;
|
|
552
|
+
// The default Windows preopen intentionally represents every drive and
|
|
553
|
+
// UNC share, so there is no narrower host boundary to enforce.
|
|
554
|
+
if (isWindows && this.#hostPreopen === "//") {
|
|
555
|
+
const normalized = segments.join("/");
|
|
556
|
+
const fullPath = /^[a-zA-Z]:\//.test(normalized)
|
|
557
|
+
? `//?/${normalized}`
|
|
558
|
+
: `//${normalized}`;
|
|
559
|
+
return trailingSlash && normalized ? `${fullPath}/` : fullPath;
|
|
560
|
+
}
|
|
561
|
+
let baseResolved;
|
|
562
|
+
try {
|
|
563
|
+
baseResolved = normalizeHostPath(realpathSync(base));
|
|
564
|
+
}
|
|
565
|
+
catch (error) {
|
|
566
|
+
throw convertFsError(error);
|
|
567
|
+
}
|
|
568
|
+
let current = baseResolved;
|
|
569
|
+
let pending = [...segments];
|
|
570
|
+
let followedSymlinks = 0;
|
|
571
|
+
while (pending.length > 0) {
|
|
572
|
+
const segment = pending.shift();
|
|
573
|
+
const candidate = normalizeHostPath(hostPath.join(current, segment));
|
|
574
|
+
let stats;
|
|
575
|
+
try {
|
|
576
|
+
stats = lstatSync(candidate);
|
|
577
|
+
}
|
|
578
|
+
catch (error) {
|
|
579
|
+
if (error.code === "ENOENT") {
|
|
580
|
+
const unresolved = normalizeHostPath(hostPath.join(candidate, ...pending));
|
|
581
|
+
return trailingSlash ? `${unresolved}/` : unresolved;
|
|
584
582
|
}
|
|
583
|
+
throw convertFsError(error);
|
|
584
|
+
}
|
|
585
|
+
const isFinal = pending.length === 0;
|
|
586
|
+
if (!stats.isSymbolicLink() || (isFinal && !followFinalSymlink && !trailingSlash)) {
|
|
587
|
+
current = candidate;
|
|
588
|
+
continue;
|
|
589
|
+
}
|
|
590
|
+
if (++followedSymlinks > MAX_SYMLINKS) {
|
|
591
|
+
throw "loop";
|
|
592
|
+
}
|
|
593
|
+
let target;
|
|
594
|
+
try {
|
|
595
|
+
target = readlinkSync(candidate);
|
|
596
|
+
}
|
|
597
|
+
catch (error) {
|
|
598
|
+
throw convertFsError(error);
|
|
585
599
|
}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
600
|
+
let targetSegments;
|
|
601
|
+
if (hostPath.isAbsolute(target)) {
|
|
602
|
+
throw "not-permitted";
|
|
589
603
|
}
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
604
|
+
else {
|
|
605
|
+
const relativeCurrent = hostPath.relative(baseResolved, current);
|
|
606
|
+
targetSegments = relativeCurrent ? relativeCurrent.split(hostPath.sep) : [];
|
|
607
|
+
for (const targetSegment of target.replace(/\\/g, "/").split("/")) {
|
|
608
|
+
if (targetSegment === "" || targetSegment === ".") {
|
|
609
|
+
continue;
|
|
610
|
+
}
|
|
611
|
+
if (targetSegment === "..") {
|
|
612
|
+
if (targetSegments.pop() === undefined) {
|
|
613
|
+
throw "not-permitted";
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
else {
|
|
617
|
+
targetSegments.push(targetSegment);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
pending = [...targetSegments, ...pending];
|
|
622
|
+
current = baseResolved;
|
|
623
|
+
}
|
|
624
|
+
return trailingSlash && current !== baseResolved ? `${current}/` : current;
|
|
609
625
|
}
|
|
610
626
|
}
|
|
611
627
|
const descriptorCreatePreopen = Descriptor._createPreopen;
|
|
@@ -654,7 +670,6 @@ export const preopens = {
|
|
|
654
670
|
return preopenEntries;
|
|
655
671
|
},
|
|
656
672
|
};
|
|
657
|
-
_addPreopen("/", isWindows ? "//" : "/");
|
|
658
673
|
export const types = {
|
|
659
674
|
Descriptor,
|
|
660
675
|
DirectoryEntryStream,
|
|
@@ -693,11 +708,10 @@ export function _addPreopen(virtualPath, hostPreopen) {
|
|
|
693
708
|
}
|
|
694
709
|
/**
|
|
695
710
|
* Clear all preopens, giving the guest no filesystem access.
|
|
696
|
-
* Call this immediately after import to disable default full filesystem access.
|
|
697
711
|
*
|
|
698
712
|
* @example
|
|
699
713
|
* import { _clearPreopens } from '@bytecodealliance/preview2-shim/filesystem';
|
|
700
|
-
* _clearPreopens();
|
|
714
|
+
* _clearPreopens();
|
|
701
715
|
*/
|
|
702
716
|
export function _clearPreopens() {
|
|
703
717
|
preopenEntries = [];
|
package/dist/nodejs/http.d.ts
CHANGED
|
@@ -1,31 +1,7 @@
|
|
|
1
1
|
import type { types as TypesNamespace } from "../../types/http.js";
|
|
2
|
-
import {
|
|
2
|
+
import { Pollable } from "../../types/interfaces/wasi-io-streams.js";
|
|
3
3
|
declare const symbolDispose: symbol;
|
|
4
4
|
export declare const _forbiddenHeaders: Set<string>;
|
|
5
|
-
declare class OutgoingRequest implements TypesNamespace.OutgoingRequest {
|
|
6
|
-
#private;
|
|
7
|
-
[symbolDispose]: () => void;
|
|
8
|
-
constructor(headers: any);
|
|
9
|
-
body(): OutgoingBody;
|
|
10
|
-
method(): TypesNamespace.Method;
|
|
11
|
-
setMethod(method: any): void;
|
|
12
|
-
pathWithQuery(): string | undefined;
|
|
13
|
-
setPathWithQuery(pathWithQuery: any): void;
|
|
14
|
-
scheme(): TypesNamespace.Scheme | undefined;
|
|
15
|
-
setScheme(scheme: any): void;
|
|
16
|
-
authority(): string | undefined;
|
|
17
|
-
setAuthority(authority: any): void;
|
|
18
|
-
headers(): Fields;
|
|
19
|
-
static _handle(request: any, options: any): FutureIncomingResponse;
|
|
20
|
-
}
|
|
21
|
-
declare class OutgoingBody implements TypesNamespace.OutgoingBody {
|
|
22
|
-
#private;
|
|
23
|
-
[symbolDispose]: () => void;
|
|
24
|
-
write(): OutputStream;
|
|
25
|
-
static finish(body: OutgoingBody, trailers: Fields | undefined): void;
|
|
26
|
-
static _outputStreamId(outgoingBody: any): any;
|
|
27
|
-
static _create(contentLength: any): OutgoingBody;
|
|
28
|
-
}
|
|
29
5
|
declare class FutureIncomingResponse implements TypesNamespace.FutureIncomingResponse {
|
|
30
6
|
#private;
|
|
31
7
|
[symbolDispose]: () => void;
|
|
@@ -33,42 +9,15 @@ declare class FutureIncomingResponse implements TypesNamespace.FutureIncomingRes
|
|
|
33
9
|
get(): any;
|
|
34
10
|
static _create(method: any, scheme: any, authority: any, pathWithQuery: any, headers: any, body: any, connectTimeout: any, betweenBytesTimeout: any, firstByteTimeout: any): FutureIncomingResponse;
|
|
35
11
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* @param {[string, Uint8Array[][]][]} entries
|
|
40
|
-
*/
|
|
41
|
-
static fromList(entries: any): Fields;
|
|
42
|
-
get(name: any): TypesNamespace.FieldValue[];
|
|
43
|
-
/**
|
|
44
|
-
* WIT spec (https://github.com/WebAssembly/WASI/blob/91bb44c3c3a9b1e09187db23c85fa844d1fd6b15/proposals/http/wit/types.wit#L215-L223):
|
|
45
|
-
*
|
|
46
|
-
* > Set all of the values for a name. Clears any existing values for that
|
|
47
|
-
* > name, if they have been set.
|
|
48
|
-
* >
|
|
49
|
-
* > Fails with `header-error.immutable` if the `fields` are immutable.
|
|
50
|
-
* >
|
|
51
|
-
* > Fails with `header-error.invalid-syntax` if the `field-name` or any of
|
|
52
|
-
* > the `field-value`s are syntactically invalid.
|
|
53
|
-
*
|
|
54
|
-
* The existing-branch splice/reuse is an allocation optimization — values are cleared, not retained.
|
|
55
|
-
*/
|
|
56
|
-
set(name: any, values: any): void;
|
|
57
|
-
has(name: any): boolean;
|
|
58
|
-
delete(name: any): void;
|
|
59
|
-
append(name: any, value: any): void;
|
|
60
|
-
entries(): [string, TypesNamespace.FieldValue][];
|
|
61
|
-
clone(): Fields;
|
|
62
|
-
static _lock(fields: any): any;
|
|
63
|
-
static _fromEntriesChecked(entries: any): Fields;
|
|
64
|
-
}
|
|
12
|
+
/** Deny outbound HTTP for the process-global HTTP namespace. */
|
|
13
|
+
export declare function _denyHttp(): void;
|
|
65
14
|
export declare const outgoingHandler: {
|
|
66
15
|
/**
|
|
67
16
|
* @param {OutgoingRequest} request
|
|
68
17
|
* @param {RequestOptions | undefined} options
|
|
69
18
|
* @returns {FutureIncomingResponse}
|
|
70
19
|
*/
|
|
71
|
-
handle:
|
|
20
|
+
handle(request: any, options: any): FutureIncomingResponse;
|
|
72
21
|
};
|
|
73
22
|
export declare const types: typeof TypesNamespace;
|
|
74
23
|
export declare class HTTPServer {
|
package/dist/nodejs/http.js
CHANGED
|
@@ -546,13 +546,23 @@ delete Fields._lock;
|
|
|
546
546
|
const fieldsFromEntriesChecked = Fields._fromEntriesChecked;
|
|
547
547
|
// @ts-expect-error - Deleting static method
|
|
548
548
|
delete Fields._fromEntriesChecked;
|
|
549
|
+
let httpEnabled = true;
|
|
550
|
+
/** Deny outbound HTTP for the process-global HTTP namespace. */
|
|
551
|
+
export function _denyHttp() {
|
|
552
|
+
httpEnabled = false;
|
|
553
|
+
}
|
|
549
554
|
export const outgoingHandler = {
|
|
550
555
|
/**
|
|
551
556
|
* @param {OutgoingRequest} request
|
|
552
557
|
* @param {RequestOptions | undefined} options
|
|
553
558
|
* @returns {FutureIncomingResponse}
|
|
554
559
|
*/
|
|
555
|
-
handle
|
|
560
|
+
handle(request, options) {
|
|
561
|
+
if (!httpEnabled) {
|
|
562
|
+
throw "access-denied";
|
|
563
|
+
}
|
|
564
|
+
return outgoingRequestHandle(request, options);
|
|
565
|
+
},
|
|
556
566
|
};
|
|
557
567
|
function httpErrorCode(err) {
|
|
558
568
|
if (err.payload) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bytecodealliance/preview2-shim",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.1",
|
|
4
4
|
"description": "WASI Preview2 shim for JS environments",
|
|
5
5
|
"homepage": "https://github.com/bytecodealliance/jco#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"@bytecodealliance/jco": "1.25.2",
|
|
69
69
|
"@types/node": "^24.12.4",
|
|
70
70
|
"mime": "^4.0.7",
|
|
71
|
-
"puppeteer": "^25.
|
|
71
|
+
"puppeteer": "^25.12.0",
|
|
72
72
|
"rolldown": "^1.2.4",
|
|
73
73
|
"typescript": "7.0.2",
|
|
74
74
|
"vitest": "^4.1.11"
|