Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@bytecodealliance/preview2-shim

Package Overview
Dependencies
Maintainers
3
Versions
36
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@bytecodealliance/preview2-shim - npm Package Compare versions

Comparing version 0.0.17 to 0.0.18

types/interfaces/wasi-io-poll.d.ts

4

lib/browser/index.js
import * as clocks from "./clocks.js";
import * as filesystem from "./filesystem.js";
import * as http from "./http.js";
import * as io from "./io.js";
import * as logging from "./logging.js";
import * as io from "../common/io.js";
import * as poll from "./poll.js";

@@ -16,3 +15,2 @@ import * as random from "./random.js";

io,
logging,
poll,

@@ -19,0 +17,0 @@ random,

@@ -1,6 +0,9 @@

export class IgnoreStream {
read (_len) {
return [new Uint8Array([]), 'ended'];
let id = 0;
class Error {
constructor (msg) {
this.msg = msg;
}
write (_bytes) {
toDebugString () {
return this.msg;
}

@@ -10,111 +13,154 @@ }

/**
* @typedef {{ read: (len: number) => [Uint8Array, 'open' | 'ended'], drop?: () => {} }} ReadableStream
* @typedef {{ write: (buf: Uint8Array) {}, drop?: () => {}, flush?: () => {}, check?: () => BigInt }} WriteableStream
*/
* @typedef {{
* read?: (len: BigInt) => Uint8Array,
* blockingRead: (len: BigInt) => Uint8Array,
* skip?: (len: BigInt) => BigInt,
* blockingSkip?: (len: BigInt) => BigInt,
* subscribe: () => void,
* drop: () => void,
* }} InputStreamHandler
*
* @typedef {{
* checkWrite?: () -> BigInt,
* write: (buf: Uint8Array) => BigInt,
* blockingWriteAndFlush?: (buf: Uint8Array) => void,
* flush?: () => void,
* blockingFlush: () => void,
* writeZeroes?: (len: BigInt) => void,
* blockingWriteZeroes?: (len: BigInt) => void,
* blockingWriteZeroesAndFlush?: (len: BigInt) => void,
* splice?: (src: InputStream, len: BigInt) => BigInt,
* blockingSplice?: (src: InputStream, len: BigInt) => BigInt,
* forward?: (src: InputStream) => void,
* subscribe?: () => void,
* drop: () => void,
* }} OutputStreamHandler
*
**/
// NOTE: pending asyncify work, all stream methods are synchronous and blocking
export class Io {
constructor (
stdout = new IgnoreStream(),
stderr = new IgnoreStream(),
stdin = new IgnoreStream()
) {
this.streamCnt = 3;
this.streamEntries = {
0: stdin,
1: stdout,
2: stderr
class InputStream {
/**
* @param {InputStreamHandler} handler
*/
constructor (handler) {
if (!handler)
console.trace('no handler');
this.id = ++id;
this.handler = handler;
}
read(len) {
if (this.handler.read)
return this.handler.read(len);
return this.handler.blockingRead.call(this, len);
}
blockingRead(len) {
return this.handler.blockingRead.call(this, len);
}
skip(len) {
if (this.handler.skip)
return this.handler.skip.call(this, len);
if (this.handler.read) {
const bytes = this.handler.read.call(this, len);
return BigInt(bytes.byteLength);
}
const io = this;
this.streams = {
read(s, len) {
return io.getStream(s).read(len);
},
blockingRead(s, len) {
return io.getStream(s).read(len);
},
skip(s, _len) {
console.log(`[streams] Skip ${s}`);
},
blockingSkip(s, _len) {
console.log(`[streams] Blocking skip ${s}`);
},
subscribeToInputStream(s) {
console.log(`[streams] Subscribe to input stream ${s}`);
},
dropInputStream(s) {
io.dropStream(s);
},
checkWrite(s) {
return io.getStream(s).check() || 1000_000n;
},
write(s, buf) {
io.getStream(s).write(buf);
},
blockingWriteAndFlush(s, buf) {
const stream = io.getStream(s);
stream.write(buf);
if (stream.flush)
stream.flush();
},
flush(s) {
const stream = io.getStream(s);
if (stream.flush)
stream.flush();
},
blockingFlush(s) {
const stream = io.getStream(s);
if (stream.flush)
stream.flush();
},
writeZeroes(s, _len) {
console.log(`[streams] Write zeroes ${s}`);
},
blockingWriteZeroes(s, _len) {
console.log(`[streams] Blocking write zeroes ${s}`);
},
splice(s, _src, _len) {
console.log(`[streams] Splice ${s}`);
},
blockingSplice(s, _src, _len) {
console.log(`[streams] Blocking splice ${s}`);
},
forward(s, _src) {
console.log(`[streams] Forward ${s}`);
},
subscribeToOutputStream(s) {
console.log(`[streams] Subscribe to output stream ${s}`);
},
dropOutputStream(s) {
io.dropStream(s);
}
};
return this.blockingSkip.call(this, len);
}
blockingSkip(len) {
if (this.handler.blockingSkip)
return this.handler.blockingSkip.call(this, len);
const bytes = this.handler.blockingRead.call(this, len);
return BigInt(bytes.byteLength);
}
subscribe() {
console.log(`[streams] Subscribe to input stream ${this.id}`);
}
drop () {
if (this.handler.drop)
this.handler.drop.call(this);
}
}
class OutputStream {
/**
*
* @param {ReadableStream | WriteableStream} stream
* @returns {number}
* @param {OutputStreamHandler} handler
*/
createStream (stream) {
this.streamEntries[this.streamCnt] = stream;
return this.streamCnt++;
constructor (handler) {
if (!handler)
console.trace('no handler');
this.id = ++id;
this.open = true;
this.handler = handler;
}
/**
* @param {number} sid
* @returns {ReadableStream | WriteableStream}
*/
getStream (sid) {
const stream = this.streamEntries[sid];
if (!stream) throw new Error();
return stream;
checkWrite(len) {
if (!this.open)
return 0n;
if (this.handler.checkWrite)
return this.handler.checkWrite.call(this, len);
return 1_000_000n;
}
dropStream (sid) {
const stream = this.streamEntries[sid];
if (stream.drop) stream.drop();
delete this.streamEntries[sid];
write(buf) {
this.handler.write.call(this, buf);
}
blockingWriteAndFlush(buf) {
/// Perform a write of up to 4096 bytes, and then flush the stream. Block
/// until all of these operations are complete, or an error occurs.
///
/// This is a convenience wrapper around the use of `check-write`,
/// `subscribe`, `write`, and `flush`, and is implemented with the
/// following pseudo-code:
///
/// ```text
/// let pollable = this.subscribe();
/// while !contents.is_empty() {
/// // Wait for the stream to become writable
/// poll-one(pollable);
/// let Ok(n) = this.check-write(); // eliding error handling
/// let len = min(n, contents.len());
/// let (chunk, rest) = contents.split_at(len);
/// this.write(chunk ); // eliding error handling
/// contents = rest;
/// }
/// this.flush();
/// // Wait for completion of `flush`
/// poll-one(pollable);
/// // Check for any errors that arose during `flush`
/// let _ = this.check-write(); // eliding error handling
/// ```
this.handler.write.call(this, buf);
}
flush() {
if (this.handler.flush)
this.handler.flush.call(this);
}
blockingFlush() {
this.open = true;
}
writeZeroes(len) {
this.write.call(this, new Uint8Array(Number(len)));
}
blockingWriteZeroes(len) {
this.blockingWrite.call(this, new Uint8Array(Number(len)));
}
blockingWriteZeroesAndFlush(len) {
this.blockingWriteAndFlush.call(this, new Uint8Array(Number(len)));
}
splice(src, len) {
const spliceLen = Math.min(len, this.checkWrite.call(this));
const bytes = src.read(spliceLen);
this.write.call(this, bytes);
return bytes.byteLength;
}
blockingSplice(_src, _len) {
console.log(`[streams] Blocking splice ${this.id}`);
}
forward(_src) {
console.log(`[streams] Forward ${this.id}`);
}
subscribe() {
console.log(`[streams] Subscribe to output stream ${this.id}`);
}
drop() {
}
}
export const streams = { Error, InputStream, OutputStream };
import { argv, env, cwd } from 'node:process';
import { streams } from '../common/io.js';
const { InputStream, OutputStream } = streams;

@@ -23,5 +25,38 @@ let _env = Object.entries(env), _args = argv, _cwd = cwd();

const stdinStream = new InputStream({
blockingRead (_len) {
// TODO
},
subscribe () {
// TODO
},
drop () {
// TODO
}
});
const stdoutStream = new OutputStream({
write (contents) {
process.stdout.write(contents);
},
blockingFlush () {
},
drop () {
}
});
const stderrStream = new OutputStream({
write (contents) {
process.stderr.write(contents);
},
blockingFlush () {
},
drop () {
}
});
export const stdin = {
InputStream,
getStdin () {
return 0;
return stdinStream;
}

@@ -31,4 +66,5 @@ };

export const stdout = {
OutputStream,
getStdout () {
return 1;
return stdoutStream;
}

@@ -38,8 +74,17 @@ };

export const stderr = {
OutputStream,
getStderr () {
return 2;
return stderrStream;
}
};
class TerminalInput {}
class TerminalOutput {}
const terminalStdoutInstance = new TerminalOutput();
const terminalStderrInstance = new TerminalOutput();
const terminalStdinInstance = new TerminalInput();
export const terminalInput = {
TerminalInput,
dropTerminalInput () {}

@@ -49,2 +94,3 @@ };

export const terminalOutput = {
TerminalOutput,
dropTerminalOutput () {}

@@ -54,4 +100,5 @@ };

export const terminalStderr = {
TerminalOutput,
getTerminalStderr () {
return 0;
return terminalStderrInstance;
}

@@ -61,4 +108,5 @@ };

export const terminalStdin = {
TerminalInput,
getTerminalStdin () {
return 1;
return terminalStdinInstance;
}

@@ -68,5 +116,6 @@ };

export const terminalStdout = {
TerminalOutput,
getTerminalStdout () {
return 2;
return terminalStdoutInstance;
}
};

@@ -1,62 +0,10 @@

import { _io } from './io.js';
import { streams } from '../common/io.js';
import { environment } from './cli.js';
import { constants, readSync, openSync, opendirSync, closeSync, fstatSync, lstatSync, statSync, writeSync } from 'node:fs';
import { constants, readSync, openSync, opendirSync, closeSync, fstatSync, lstatSync, statSync, writeSync, mkdirSync } from 'node:fs';
import { platform } from 'node:process';
const { InputStream, OutputStream, Error: StreamError } = streams;
const isWindows = platform === 'win32';
class ReadableFileStream {
constructor (hostFd, position) {
this.hostFd = hostFd;
this.position = Number(position);
}
read (len) {
const buf = new Uint8Array(Number(len));
const bytesRead = readSync(this.hostFd, buf, 0, buf.byteLength, this.position);
this.position += bytesRead;
if (bytesRead < buf.byteLength)
return [new Uint8Array(buf.buffer, 0, bytesRead), bytesRead === 0 ? 'ended' : 'open'];
return [buf, 'open'];
}
}
class WriteableFileStream {
constructor (hostFd, position) {
this.hostFd = hostFd;
this.position = Number(position);
}
write (contents) {
let totalWritten = 0;
while (totalWritten !== contents.byteLength) {
const bytesWritten = writeSync(this.hostFd, contents, null, null, this.position);
totalWritten += bytesWritten;
contents = new Uint8Array(contents.buffer, bytesWritten);
}
this.position += contents.byteLength;
}
}
class DirStream {
constructor (dir) {
this.dir = dir;
}
read () {
let entry;
try {
entry = this.dir.readSync();
} catch (e) {
throw convertFsError(e);
}
if (entry === null) {
return null;
}
const name = entry.name;
const type = lookupType(entry);
return { name, type };
}
drop () {
this.dir.closeSync();
}
}
const nsMagnitude = 1_000_000_000_000n;

@@ -89,14 +37,7 @@ function nsToDateTime (ns) {

* @typedef {
* { stream: number } |
* { hostPreopen: string } |
* { fullPath: string, fd: number }
* } Descriptor
* } DescriptorProps
*/
export class FileSystem {
getDescriptor (fd) {
const descriptor = this.descriptors[fd];
if (!descriptor) throw 'bad-descriptor';
return descriptor;
}
// Note: This should implement per-segment semantics of openAt, but we cannot currently

@@ -107,3 +48,3 @@ // due to the lack of support for openat() in Node.js.

// TODO: support followSymlinks
getFullPath (fd, subpath, _followSymlinks) {
getFullPath (descriptor, subpath, _followSymlinks) {
if (subpath.indexOf('\\') !== -1)

@@ -120,3 +61,3 @@ subpath = subpath.replace(/\\/g, '/');

throw 'no-entry';
fd = bestPreopenMatch[0];
descriptor = bestPreopenMatch[0];
subpath = subpath.slice(bestPreopenMatch[1]);

@@ -128,3 +69,2 @@ if (subpath[0] === '/')

subpath = subpath.slice(subpath[1] === '/' ? 2 : 1);
const descriptor = this.getDescriptor(fd);
if (descriptor.hostPreopen)

@@ -137,106 +77,157 @@ return descriptor.hostPreopen + (descriptor.hostPreopen.endsWith('/') ? '' : '/') + subpath;

*
* @param {import('./io.js').Io} io
* @param {[string, string][]} preopens
* @param {import('./cli.js').environment} environment
* @returns
*/
constructor (io, preopens, environment) {
constructor (preopens, environment) {
const fs = this;
this.cwd = environment.initialCwd();
// io always has streams 0, 1, 2 as stdio streams
this.descriptorCnt = 3;
class FileInputStream extends InputStream {
constructor (hostFd, position) {
super({
blockingRead (len) {
const buf = new Uint8Array(Number(len));
try {
var bytesRead = readSync(this.hostFd, buf, 0, buf.byteLength, this.position);
} catch (e) {
throw { tag: 'last-operation-failed', val: new StreamError(e.message) };
}
this.position += bytesRead;
if (bytesRead < buf.byteLength) {
if (bytesRead === 0)
throw { tag: 'closed' };
return new Uint8Array(buf.buffer, 0, bytesRead);
}
return buf;
},
subscribe () {
// TODO
},
drop () {
// TODO
}
});
this.hostFd = hostFd;
this.position = Number(position);
}
}
class FileOutputStream extends OutputStream {
constructor (hostFd, position) {
super({
write (contents) {
let totalWritten = 0;
while (totalWritten !== contents.byteLength) {
const bytesWritten = writeSync(this.hostFd, contents, null, null, this.position);
totalWritten += bytesWritten;
contents = new Uint8Array(contents.buffer, bytesWritten);
}
this.position += contents.byteLength;
},
blockingFlush () {
},
drop () {
}
});
this.hostFd = hostFd;
this.position = Number(position);
}
}
class DirectoryEntryStream {
constructor (dir) {
this.dir = dir;
}
readDirectoryEntry () {
let entry;
try {
entry = this.dir.readSync();
} catch (e) {
throw convertFsError(e);
}
if (entry === null) {
return null;
}
const name = entry.name;
const type = lookupType(entry);
return { name, type };
}
drop () {
this.dir.closeSync();
}
}
/**
* @type {Record<number, Descriptor>}
* @implements {DescriptorProps}
*/
this.descriptors = {
0: { stream: 0 },
1: { stream: 1 },
2: { stream: 2 },
};
this.preopenEntries = [];
for (const [virtualPath, hostPreopen] of Object.entries(preopens)) {
const preopenEntry = [this.descriptorCnt, virtualPath];
this.preopenEntries.push(preopenEntry);
this.descriptors[this.descriptorCnt++] = { hostPreopen };
}
const fs = this;
this.preopens = {
getDirectories () {
return fs.preopenEntries;
class Descriptor {
constructor () {
this.id = fs.descriptorCnt++;
}
};
this.types = {
readViaStream(fd, offset) {
const descriptor = fs.getDescriptor(fd);
if (descriptor.stream)
return descriptor.stream;
if (descriptor.hostPreopen)
readViaStream(offset) {
if (this.hostPreopen)
throw { tag: 'last-operation-failed', val: new StreamError };
return new FileInputStream(this.fd, offset);
}
writeViaStream(offset) {
if (this.hostPreopen)
throw 'is-directory';
return io.createStream(new ReadableFileStream(descriptor.fd, offset));
},
return new FileOutputStream(this.fd, offset);
}
writeViaStream(fd, offset) {
const descriptor = fs.getDescriptor(fd);
if (descriptor.stream)
return descriptor.stream;
if (descriptor.hostPreopen)
throw 'is-directory';
return io.createStream(new WriteableFileStream(descriptor.fd, offset));
},
appendViaStream() {
console.log(`[filesystem] APPEND STREAM ${this.id}`);
}
appendViaStream(fd) {
console.log(`[filesystem] APPEND STREAM ${fd}`);
},
advise(offset, length, advice) {
console.log(`[filesystem] ADVISE`, this.id, offset, length, advice);
}
advise(fd, offset, length, advice) {
console.log(`[filesystem] ADVISE`, fd, offset, length, advice);
},
syncData() {
console.log(`[filesystem] SYNC DATA ${this.id}`);
}
syncData(fd) {
console.log(`[filesystem] SYNC DATA ${fd}`);
},
getFlags() {
console.log(`[filesystem] FLAGS FOR ${this.id}`);
}
getFlags(fd) {
console.log(`[filesystem] FLAGS FOR ${fd}`);
},
getType(fd) {
const descriptor = fs.getDescriptor(fd);
if (descriptor.stream) return 'fifo';
if (descriptor.hostPreopen) return 'directory';
const stats = fstatSync(descriptor.fd);
getType() {
if (this.hostPreopen) return 'directory';
const stats = fstatSync(this.fd);
return lookupType(stats);
},
}
setFlags(fd, flags) {
console.log(`[filesystem] SET FLAGS ${fd} ${JSON.stringify(flags)}`);
},
setFlags(flags) {
console.log(`[filesystem] SET FLAGS ${this.id} ${JSON.stringify(flags)}`);
}
setSize(fd, size) {
console.log(`[filesystem] SET SIZE`, fd, size);
},
setSize(size) {
console.log(`[filesystem] SET SIZE`, this.id, size);
}
setTimes(fd, dataAccessTimestamp, dataModificationTimestamp) {
console.log(`[filesystem] SET TIMES`, fd, dataAccessTimestamp, dataModificationTimestamp);
},
setTimes(dataAccessTimestamp, dataModificationTimestamp) {
console.log(`[filesystem] SET TIMES`, this.id, dataAccessTimestamp, dataModificationTimestamp);
}
read(fd, length, offset) {
const descriptor = fs.getDescriptor(fd);
if (!descriptor.fullPath) throw 'bad-descriptor';
read(length, offset) {
if (!this.fullPath) throw 'bad-descriptor';
const buf = new Uint8Array(length);
const bytesRead = readSync(descriptor.fd, buf, Number(offset), length, 0);
const bytesRead = readSync(this.fd, buf, Number(offset), length, 0);
const out = new Uint8Array(buf.buffer, 0, bytesRead);
return [out, bytesRead === 0 ? 'ended' : 'open'];
},
}
write(fd, buffer, offset) {
const descriptor = fs.getDescriptor(fd);
if (!descriptor.fullPath) throw 'bad-descriptor';
return BigInt(writeSync(descriptor.fd, buffer, Number(offset), buffer.byteLength - offset, 0));
},
write(buffer, offset) {
if (!this.fullPath) throw 'bad-descriptor';
return BigInt(writeSync(this.fd, buffer, Number(offset), buffer.byteLength - offset, 0));
}
readDirectory(fd) {
const descriptor = fs.getDescriptor(fd);
if (!descriptor.fullPath) throw 'bad-descriptor';
readDirectory() {
if (!this.fullPath) throw 'bad-descriptor';
try {
const dir = opendirSync(isWindows ? descriptor.fullPath.slice(1) : descriptor.fullPath);
return io.createStream(new DirStream(dir));
const dir = opendirSync(isWindows ? this.fullPath.slice(1) : this.fullPath);
return new DirectoryEntryStream(dir);
}

@@ -246,19 +237,23 @@ catch (e) {

}
},
}
sync(fd) {
console.log(`[filesystem] SYNC`, fd);
},
sync() {
console.log(`[filesystem] SYNC`, this.id);
}
createDirectoryAt(fd, path) {
const entry = fs.getOrCreateChildDescriptor(fd, path, { create: true, directory: true });
if (entry.source) throw 'exist';
},
createDirectoryAt(path) {
const fullPath = fs.getFullPath(this, path);
try {
mkdirSync(fullPath);
}
catch (e) {
throw convertFsError(e);
}
}
stat(fd) {
const descriptor = fs.getDescriptor(fd);
if (descriptor.stream || descriptor.hostPreopen) throw 'invalid';
stat() {
if (this.hostPreopen) throw 'invalid';
let stats;
try {
stats = fstatSync(descriptor.fd, { bigint: true });
stats = fstatSync(this.fd, { bigint: true });
}

@@ -277,6 +272,6 @@ catch (e) {

};
},
}
statAt(fd, pathFlags, path) {
const fullPath = fs.getFullPath(fd, path, false);
statAt(pathFlags, path) {
const fullPath = fs.getFullPath(this, path, false);
let stats;

@@ -298,15 +293,14 @@ try {

};
},
}
setTimesAt(fd) {
console.log(`[filesystem] SET TIMES AT`, fd);
},
setTimesAt() {
console.log(`[filesystem] SET TIMES AT`, this.id);
}
linkAt(fd) {
console.log(`[filesystem] LINK AT`, fd);
},
linkAt() {
console.log(`[filesystem] LINK AT`, this.id);
}
openAt(fd, pathFlags, path, openFlags, descriptorFlags, modes) {
const fullPath = fs.getFullPath(fd, path, pathFlags.symlinkFollow);
const childFd = fs.descriptorCnt++;
openAt(pathFlags, path, openFlags, descriptorFlags, modes) {
const fullPath = fs.getFullPath(this, path, pathFlags.symlinkFollow);
let fsOpenFlags = 0x0;

@@ -342,3 +336,3 @@ if (openFlags.create)

const fd = openSync(isWindows ? fullPath.slice(1) : fullPath, fsOpenFlags, fsMode);
fs.descriptors[childFd] = { fullPath, fd };
return Object.assign(new Descriptor(), { fullPath, fd });
}

@@ -348,76 +342,62 @@ catch (e) {

}
return childFd;
},
}
readlinkAt(fd) {
console.log(`[filesystem] READLINK AT`, fd);
},
readlinkAt() {
console.log(`[filesystem] READLINK AT`, this.id);
}
removeDirectoryAt(fd) {
console.log(`[filesystem] REMOVE DIR AT`, fd);
},
removeDirectoryAt() {
console.log(`[filesystem] REMOVE DIR AT`, this.id);
}
renameAt(fd) {
console.log(`[filesystem] RENAME AT`, fd);
},
renameAt() {
console.log(`[filesystem] RENAME AT`, this.id);
}
symlinkAt(fd) {
console.log(`[filesystem] SYMLINK AT`, fd);
},
symlinkAt() {
console.log(`[filesystem] SYMLINK AT`, this.id);
}
unlinkFileAt(fd) {
console.log(`[filesystem] UNLINK FILE AT`, fd);
},
unlinkFileAt() {
console.log(`[filesystem] UNLINK FILE AT`, this.id);
}
changeFilePermissionsAt(fd) {
console.log(`[filesystem] CHANGE FILE PERMISSIONS AT`, fd);
},
changeFilePermissionsAt() {
console.log(`[filesystem] CHANGE FILE PERMISSIONS AT`, this.id);
}
changeDirectoryPermissionsAt(fd) {
console.log(`[filesystem] CHANGE DIR PERMISSIONS AT`, fd);
},
changeDirectoryPermissionsAt() {
console.log(`[filesystem] CHANGE DIR PERMISSIONS AT`, this.id);
}
lockShared(fd) {
console.log(`[filesystem] LOCK SHARED`, fd);
},
lockShared() {
console.log(`[filesystem] LOCK SHARED`, this.id);
}
lockExclusive(fd) {
console.log(`[filesystem] LOCK EXCLUSIVE`, fd);
},
lockExclusive() {
console.log(`[filesystem] LOCK EXCLUSIVE`, this.id);
}
tryLockShared(fd) {
console.log(`[filesystem] TRY LOCK SHARED`, fd);
},
tryLockShared() {
console.log(`[filesystem] TRY LOCK SHARED`, this.id);
}
tryLockExclusive(fd) {
console.log(`[filesystem] TRY LOCK EXCLUSIVE`, fd);
},
tryLockExclusive() {
console.log(`[filesystem] TRY LOCK EXCLUSIVE`, this.id);
}
unlock(fd) {
console.log(`[filesystem] UNLOCK`, fd);
},
unlock() {
console.log(`[filesystem] UNLOCK`, this.id);
}
dropDescriptor(fd) {
const descriptor = fs.getDescriptor(fd);
if (descriptor.fd)
closeSync(descriptor.fd);
delete fs.descriptors[fd];
},
drop() {
if (this.fd)
closeSync(this.fd);
}
readDirectoryEntry(sid) {
return io.getStream(sid).read();
},
dropDirectoryEntryStream(sid) {
io.dropStream(sid);
},
metadataHash(fd) {
const descriptor = fs.getDescriptor(fd);
if (descriptor.stream)
return { upper: 0n, lower: descriptor.stream}
if (descriptor.hostPreopen)
return { upper: 0n, lower: BigInt(fd) };
metadataHash() {
if (this.hostPreopen)
return { upper: 0n, lower: BigInt(this.id) };
try {
const stats = fstatSync(descriptor.fd, { bigint: true });
const stats = fstatSync(this.fd, { bigint: true });
return { upper: stats.mtimeNs, lower: stats.ino };

@@ -428,6 +408,6 @@ }

}
},
}
metadataHashAt(fd, pathFlags, path) {
const fullPath = fs.getFullPath(fd, path, false);
metadataHashAt(pathFlags, path) {
const fullPath = fs.getFullPath(this, path, false);
try {

@@ -441,7 +421,23 @@ const stats = (pathFlags.symlinkFollow ? statSync : lstatSync)(isWindows ? fullPath.slice(1) : fullPath, { bigint: true });

}
}
this.descriptorCnt = 3;
this.preopenEntries = [];
for (const [virtualPath, hostPreopen] of Object.entries(preopens)) {
const preopenEntry = [Object.assign(new Descriptor(), { hostPreopen }), virtualPath];
this.preopenEntries.push(preopenEntry);
}
this.preopens = {
Descriptor,
getDirectories () {
return fs.preopenEntries;
}
};
this.types = {
Descriptor,
};
}
}
const _fs = new FileSystem(_io, { '/': '/' }, environment);
const _fs = new FileSystem({ '/': '/' }, environment);

@@ -448,0 +444,0 @@ export const { preopens, types } = _fs;

import { WasiHttp } from '../http/wasi-http.js';
import { _io } from './io.js';
import { streams } from '../common/io.js';
const http = new WasiHttp(_io);
const http = new WasiHttp(streams);
export const { incomingHandler, outgoingHandler, types } = http;
import * as clocks from "./clocks.js";
import * as filesystem from "./filesystem.js";
import * as http from "./http.js";
import * as io from "./io.js";
import * as logging from "./logging.js";
import * as io from "../common/io.js";
import * as poll from "./poll.js";

@@ -16,3 +15,2 @@ import * as random from "./random.js";

io,
logging,
poll,

@@ -19,0 +17,0 @@ random,

{
"name": "@bytecodealliance/preview2-shim",
"version": "0.0.17",
"version": "0.0.18",
"description": "WASI Preview2 shim for JS environments",

@@ -14,2 +14,6 @@ "author": "Guy Bedford, Eduardo Rodrigues<16357187+eduardomourar@users.noreply.github.com>",

},
"./io": {
"types": "./types/io.d.ts",
"default": "./lib/common/io.js"
},
"./*": {

@@ -16,0 +20,0 @@ "types": "./types/*.d.ts",

export namespace WasiCliTerminalInput {
/**
* Dispose of the specified terminal-input after which it may no longer
* be used.
*/
export function dropTerminalInput(this_: TerminalInput): void;
}
/**
* The input side of a terminal.
*
* This [represents a resource](https://github.com/WebAssembly/WASI/blob/main/docs/WitInWasi.md#Resources).
*/
export type TerminalInput = number;
export namespace WasiCliTerminalOutput {
/**
* Dispose of the specified terminal-output, after which it may no longer
* be used.
*/
export function dropTerminalOutput(this_: TerminalOutput): void;
}
/**
* The output side of a terminal.
*
* This [represents a resource](https://github.com/WebAssembly/WASI/blob/main/docs/WitInWasi.md#Resources).
*/
export type TerminalOutput = number;

@@ -19,3 +19,3 @@ export namespace WasiClocksMonotonicClock {

}
import type { Pollable } from '../interfaces/wasi-poll-poll';
import type { Pollable } from '../interfaces/wasi-io-poll';
export { Pollable };

@@ -22,0 +22,0 @@ /**

@@ -11,12 +11,7 @@ export namespace WasiClocksTimezone {

*/
export function display(this_: Timezone, when: Datetime): TimezoneDisplay;
export function display(when: Datetime): TimezoneDisplay;
/**
* The same as `display`, but only return the UTC offset.
*/
export function utcOffset(this_: Timezone, when: Datetime): number;
/**
* Dispose of the specified input-stream, after which it may no longer
* be used.
*/
export function dropTimezone(this_: Timezone): void;
export function utcOffset(when: Datetime): number;
}

@@ -26,12 +21,2 @@ import type { Datetime } from '../interfaces/wasi-clocks-wall-clock';

/**
* A timezone.
*
* In timezones that recognize daylight saving time, also known as daylight
* time and summer time, the information returned from the functions varies
* over time to reflect these adjustments.
*
* This [represents a resource](https://github.com/WebAssembly/WASI/blob/main/docs/WitInWasi.md#Resources).
*/
export type Timezone = number;
/**
* Information useful for displaying the timezone of a specific `datetime`.

@@ -38,0 +23,0 @@ *

@@ -12,3 +12,3 @@ export namespace WasiFilesystemTypes {

*/
export function readViaStream(this_: Descriptor, offset: Filesize): InputStream;
export { Descriptor };
/**

@@ -22,3 +22,2 @@ * Return a stream for writing to a file, if available.

*/
export function writeViaStream(this_: Descriptor, offset: Filesize): OutputStream;
/**

@@ -32,3 +31,2 @@ * Return a stream for appending to a file, if available.

*/
export function appendViaStream(this_: Descriptor): OutputStream;
/**

@@ -39,3 +37,2 @@ * Provide file advisory information on a descriptor.

*/
export function advise(this_: Descriptor, offset: Filesize, length: Filesize, advice: Advice): void;
/**

@@ -49,3 +46,2 @@ * Synchronize the data of a file to disk.

*/
export function syncData(this_: Descriptor): void;
/**

@@ -59,3 +55,2 @@ * Get flags associated with a descriptor.

*/
export function getFlags(this_: Descriptor): DescriptorFlags;
/**

@@ -73,3 +68,2 @@ * Get the dynamic type of a descriptor.

*/
export function getType(this_: Descriptor): DescriptorType;
/**

@@ -81,3 +75,2 @@ * Adjust the size of an open file. If this increases the file's size, the

*/
export function setSize(this_: Descriptor, size: Filesize): void;
/**

@@ -90,3 +83,2 @@ * Adjust the timestamps of an open file or directory.

*/
export function setTimes(this_: Descriptor, dataAccessTimestamp: NewTimestamp, dataModificationTimestamp: NewTimestamp): void;
/**

@@ -105,3 +97,2 @@ * Read from a descriptor, without using and updating the descriptor's offset.

*/
export function read(this_: Descriptor, length: Filesize, offset: Filesize): [Uint8Array, boolean];
/**

@@ -118,3 +109,2 @@ * Write to a descriptor, without using and updating the descriptor's offset.

*/
export function write(this_: Descriptor, buffer: Uint8Array, offset: Filesize): Filesize;
/**

@@ -131,3 +121,2 @@ * Read directory entries from a directory.

*/
export function readDirectory(this_: Descriptor): DirectoryEntryStream;
/**

@@ -141,3 +130,2 @@ * Synchronize the data and metadata of a file to disk.

*/
export function sync(this_: Descriptor): void;
/**

@@ -148,3 +136,2 @@ * Create a directory.

*/
export function createDirectoryAt(this_: Descriptor, path: string): void;
/**

@@ -161,3 +148,2 @@ * Return the attributes of an open file or directory.

*/
export function stat(this_: Descriptor): DescriptorStat;
/**

@@ -172,3 +158,2 @@ * Return the attributes of a file or directory.

*/
export function statAt(this_: Descriptor, pathFlags: PathFlags, path: string): DescriptorStat;
/**

@@ -182,3 +167,2 @@ * Adjust the timestamps of a file or directory.

*/
export function setTimesAt(this_: Descriptor, pathFlags: PathFlags, path: string, dataAccessTimestamp: NewTimestamp, dataModificationTimestamp: NewTimestamp): void;
/**

@@ -189,3 +173,2 @@ * Create a hard link.

*/
export function linkAt(this_: Descriptor, oldPathFlags: PathFlags, oldPath: string, newDescriptor: Descriptor, newPath: string): void;
/**

@@ -211,3 +194,2 @@ * Open a file or directory.

*/
export function openAt(this_: Descriptor, pathFlags: PathFlags, path: string, openFlags: OpenFlags, flags: DescriptorFlags, modes: Modes): Descriptor;
/**

@@ -221,3 +203,2 @@ * Read the contents of a symbolic link.

*/
export function readlinkAt(this_: Descriptor, path: string): string;
/**

@@ -230,3 +211,2 @@ * Remove a directory.

*/
export function removeDirectoryAt(this_: Descriptor, path: string): void;
/**

@@ -237,3 +217,2 @@ * Rename a filesystem object.

*/
export function renameAt(this_: Descriptor, oldPath: string, newDescriptor: Descriptor, newPath: string): void;
/**

@@ -247,3 +226,2 @@ * Create a symbolic link (also known as a "symlink").

*/
export function symlinkAt(this_: Descriptor, oldPath: string, newPath: string): void;
/**

@@ -261,3 +239,2 @@ * Check accessibility of a filesystem path.

*/
export function accessAt(this_: Descriptor, pathFlags: PathFlags, path: string, type: AccessType): void;
/**

@@ -269,3 +246,2 @@ * Unlink a filesystem object that is not a directory.

*/
export function unlinkFileAt(this_: Descriptor, path: string): void;
/**

@@ -279,3 +255,2 @@ * Change the permissions of a filesystem object that is not a directory.

*/
export function changeFilePermissionsAt(this_: Descriptor, pathFlags: PathFlags, path: string, modes: Modes): void;
/**

@@ -293,3 +268,2 @@ * Change the permissions of a directory.

*/
export function changeDirectoryPermissionsAt(this_: Descriptor, pathFlags: PathFlags, path: string, modes: Modes): void;
/**

@@ -317,3 +291,2 @@ * Request a shared advisory lock for an open file.

*/
export function lockShared(this_: Descriptor): void;
/**

@@ -343,3 +316,2 @@ * Request an exclusive advisory lock for an open file.

*/
export function lockExclusive(this_: Descriptor): void;
/**

@@ -368,3 +340,2 @@ * Request a shared advisory lock for an open file.

*/
export function tryLockShared(this_: Descriptor): void;
/**

@@ -395,3 +366,2 @@ * Request an exclusive advisory lock for an open file.

*/
export function tryLockExclusive(this_: Descriptor): void;
/**

@@ -402,18 +372,3 @@ * Release a shared or exclusive lock on an open file.

*/
export function unlock(this_: Descriptor): void;
/**
* Dispose of the specified `descriptor`, after which it may no longer
* be used.
*/
export function dropDescriptor(this_: Descriptor): void;
/**
* Read a single directory entry from a `directory-entry-stream`.
*/
export function readDirectoryEntry(this_: DirectoryEntryStream): DirectoryEntry | undefined;
/**
* Dispose of the specified `directory-entry-stream`, after which it may no longer
* be used.
*/
export function dropDirectoryEntryStream(this_: DirectoryEntryStream): void;
/**
* Test whether two descriptors refer to the same filesystem object.

@@ -426,3 +381,2 @@ *

*/
export function isSameObject(this_: Descriptor, other: Descriptor): boolean;
/**

@@ -449,3 +403,2 @@ * Return a hash of the metadata associated with a filesystem object referred

*/
export function metadataHash(this_: Descriptor): MetadataHashValue;
/**

@@ -457,3 +410,19 @@ * Return a hash of the metadata associated with a filesystem object referred

*/
export function metadataHashAt(this_: Descriptor, pathFlags: PathFlags, path: string): MetadataHashValue;
/**
* Read a single directory entry from a `directory-entry-stream`.
*/
export { DirectoryEntryStream };
/**
* Attempts to extract a filesystem-related `error-code` from the stream
* `error` provided.
*
* Stream operations which return `stream-error::last-operation-failed`
* have a payload with more information about the operation that failed.
* This payload can be passed through to this function to see if there's
* filesystem-related information about the error to return.
*
* Note that this function is fallible because not all stream-related
* errors are filesystem-related errors.
*/
export function filesystemErrorCode(err: Error): ErrorCode | undefined;
}

@@ -464,2 +433,4 @@ import type { InputStream } from '../interfaces/wasi-io-streams';

export { OutputStream };
import type { Error } from '../interfaces/wasi-io-streams';
export { Error };
import type { Datetime } from '../interfaces/wasi-clocks-wall-clock';

@@ -654,12 +625,21 @@ export { Datetime };

* Last data access timestamp.
*
* If the `option` is none, the platform doesn't maintain an access
* timestamp for this file.
*/
dataAccessTimestamp: Datetime,
dataAccessTimestamp?: Datetime,
/**
* Last data modification timestamp.
*
* If the `option` is none, the platform doesn't maintain a
* modification timestamp for this file.
*/
dataModificationTimestamp: Datetime,
dataModificationTimestamp?: Datetime,
/**
* Last file status change timestamp.
* Last file status-change timestamp.
*
* If the `option` is none, the platform doesn't maintain a
* status-change timestamp for this file.
*/
statusChangeTimestamp: Datetime,
statusChangeTimestamp?: Datetime,
}

@@ -854,10 +834,2 @@ /**

/**
* A descriptor is a reference to a filesystem object, which may be a file,
* directory, named pipe, special file, or other object on which filesystem
* calls may be made.
*
* This [represents a resource](https://github.com/WebAssembly/WASI/blob/main/docs/WitInWasi.md#Resources).
*/
export type Descriptor = number;
/**
* A 128-bit hash value, split into parts because wasm doesn't have a

@@ -876,7 +848,43 @@ * 128-bit integer type.

}
/**
* A stream of directory entries.
*
* This [represents a stream of `dir-entry`](https://github.com/WebAssembly/WASI/blob/main/docs/WitInWasi.md#Streams).
*/
export type DirectoryEntryStream = number;
export class DirectoryEntryStream {
readDirectoryEntry(): DirectoryEntry | undefined;
}
export class Descriptor {
readViaStream(offset: Filesize): InputStream;
writeViaStream(offset: Filesize): OutputStream;
appendViaStream(): OutputStream;
advise(offset: Filesize, length: Filesize, advice: Advice): void;
syncData(): void;
getFlags(): DescriptorFlags;
getType(): DescriptorType;
setSize(size: Filesize): void;
setTimes(dataAccessTimestamp: NewTimestamp, dataModificationTimestamp: NewTimestamp): void;
read(length: Filesize, offset: Filesize): [Uint8Array, boolean];
write(buffer: Uint8Array, offset: Filesize): Filesize;
readDirectory(): DirectoryEntryStream;
sync(): void;
createDirectoryAt(path: string): void;
stat(): DescriptorStat;
statAt(pathFlags: PathFlags, path: string): DescriptorStat;
setTimesAt(pathFlags: PathFlags, path: string, dataAccessTimestamp: NewTimestamp, dataModificationTimestamp: NewTimestamp): void;
linkAt(oldPathFlags: PathFlags, oldPath: string, newDescriptor: Descriptor, newPath: string): void;
openAt(pathFlags: PathFlags, path: string, openFlags: OpenFlags, flags: DescriptorFlags, modes: Modes): Descriptor;
readlinkAt(path: string): string;
removeDirectoryAt(path: string): void;
renameAt(oldPath: string, newDescriptor: Descriptor, newPath: string): void;
symlinkAt(oldPath: string, newPath: string): void;
accessAt(pathFlags: PathFlags, path: string, type: AccessType): void;
unlinkFileAt(path: string): void;
changeFilePermissionsAt(pathFlags: PathFlags, path: string, modes: Modes): void;
changeDirectoryPermissionsAt(pathFlags: PathFlags, path: string, modes: Modes): void;
lockShared(): void;
lockExclusive(): void;
tryLockShared(): void;
tryLockExclusive(): void;
unlock(): void;
isSameObject(other: Descriptor): boolean;
metadataHash(): MetadataHashValue;
metadataHashAt(pathFlags: PathFlags, path: string): MetadataHashValue;
}
export namespace WasiIoStreams {
/**
* Returns a string that's suitable to assist humans in debugging this
* error.
*
* The returned string will change across platforms and hosts which
* means that parsing it, for example, would be a
* platform-compatibility hazard.
*/
export { Error };
/**
* Perform a non-blocking read from the stream.

@@ -10,4 +19,4 @@ *

* empty list and `stream-status:open` indicates no more data is
* available at this time, and that the pollable given by
* `subscribe-to-input-stream` will be ready when more data is available.
* available at this time, and that the pollable given by `subscribe`
* will be ready when more data is available.
*

@@ -27,3 +36,3 @@ * Once a stream has reached the end, subsequent calls to `read` or

*/
export function read(this_: InputStream, len: bigint): [Uint8Array, StreamStatus];
export { InputStream };
/**

@@ -33,3 +42,2 @@ * Read bytes from a stream, after blocking until at least one byte can

*/
export function blockingRead(this_: InputStream, len: bigint): [Uint8Array, StreamStatus];
/**

@@ -49,3 +57,2 @@ * Skip bytes from a stream.

*/
export function skip(this_: InputStream, len: bigint): [bigint, StreamStatus];
/**

@@ -55,3 +62,2 @@ * Skip bytes from a stream, after blocking until at least one byte

*/
export function blockingSkip(this_: InputStream, len: bigint): [bigint, StreamStatus];
/**

@@ -65,13 +71,3 @@ * Create a `pollable` which will resolve once either the specified stream

*/
export function subscribeToInputStream(this_: InputStream): Pollable;
/**
* Dispose of the specified `input-stream`, after which it may no longer
* be used.
* Implementations may trap if this `input-stream` is dropped while child
* `pollable` resources are still alive.
* After this `input-stream` is dropped, implementations may report any
* corresponding `output-stream` has `stream-state.closed`.
*/
export function dropInputStream(this_: InputStream): void;
/**
* Check readiness for writing. This function never blocks.

@@ -83,7 +79,7 @@ *

*
* When this function returns 0 bytes, the `subscribe-to-output-stream`
* pollable will become ready when this function will report at least
* 1 byte, or an error.
* When this function returns 0 bytes, the `subscribe` pollable will
* become ready when this function will report at least 1 byte, or an
* error.
*/
export function checkWrite(this_: OutputStream): bigint;
export { OutputStream };
/**

@@ -98,3 +94,2 @@ * Perform a write. This function never blocks.

*/
export function write(this_: OutputStream, contents: Uint8Array): void;
/**

@@ -105,24 +100,23 @@ * Perform a write of up to 4096 bytes, and then flush the stream. Block

* This is a convenience wrapper around the use of `check-write`,
* `subscribe-to-output-stream`, `write`, and `flush`, and is implemented
* with the following pseudo-code:
* `subscribe`, `write`, and `flush`, and is implemented with the
* following pseudo-code:
*
* ```text
* let pollable = subscribe-to-output-stream(this);
* let pollable = this.subscribe();
* while !contents.is_empty() {
* // Wait for the stream to become writable
* poll-oneoff(pollable);
* let Ok(n) = check-write(this); // eliding error handling
* poll-one(pollable);
* let Ok(n) = this.check-write(); // eliding error handling
* let len = min(n, contents.len());
* let (chunk, rest) = contents.split_at(len);
* write(this, chunk); // eliding error handling
* this.write(chunk ); // eliding error handling
* contents = rest;
* }
* flush(this);
* this.flush();
* // Wait for completion of `flush`
* poll-oneoff(pollable);
* poll-one(pollable);
* // Check for any errors that arose during `flush`
* let _ = check-write(this); // eliding error handling
* let _ = this.check-write(); // eliding error handling
* ```
*/
export function blockingWriteAndFlush(this_: OutputStream, contents: Uint8Array): void;
/**

@@ -137,6 +131,5 @@ * Request to flush buffered output. This function never blocks.

* writes (`check-write` will return `ok(0)`) until the flush has
* completed. The `subscribe-to-output-stream` pollable will become ready
* when the flush has completed and the stream can accept more writes.
* completed. The `subscribe` pollable will become ready when the
* flush has completed and the stream can accept more writes.
*/
export function flush(this_: OutputStream): void;
/**

@@ -146,3 +139,2 @@ * Request to flush buffered output, and block until flush completes

*/
export function blockingFlush(this_: OutputStream): void;
/**

@@ -160,3 +152,2 @@ * Create a `pollable` which will resolve once the output-stream

*/
export function subscribeToOutputStream(this_: OutputStream): Pollable;
/**

@@ -170,118 +161,107 @@ * Write zeroes to a stream.

*/
export function writeZeroes(this_: OutputStream, len: bigint): void;
/**
* Read from one stream and write to another.
* Perform a write of up to 4096 zeroes, and then flush the stream.
* Block until all of these operations are complete, or an error
* occurs.
*
* This function returns the number of bytes transferred; it may be less
* than `len`.
* This is a convenience wrapper around the use of `check-write`,
* `subscribe`, `write-zeroes`, and `flush`, and is implemented with
* the following pseudo-code:
*
* Unlike other I/O functions, this function blocks until all the data
* read from the input stream has been written to the output stream.
*/
export function splice(this_: OutputStream, src: InputStream, len: bigint): [bigint, StreamStatus];
* ```text
* let pollable = this.subscribe();
* while num_zeroes != 0 {
* // Wait for the stream to become writable
* poll-one(pollable);
* let Ok(n) = this.check-write(); // eliding error handling
* let len = min(n, num_zeroes);
* this.write-zeroes(len); // eliding error handling
* num_zeroes -= len;
* }
* this.flush();
* // Wait for completion of `flush`
* poll-one(pollable);
* // Check for any errors that arose during `flush`
* let _ = this.check-write(); // eliding error handling
* ```
*/
/**
* Read from one stream and write to another.
*
* This function returns the number of bytes transferred; it may be less
* than `len`.
*
* Unlike other I/O functions, this function blocks until all the data
* read from the input stream has been written to the output stream.
*/
/**
* Read from one stream and write to another, with blocking.
*
* This is similar to `splice`, except that it blocks until at least
* one byte can be read.
*/
/**
* Forward the entire contents of an input stream to an output stream.
*
* This function repeatedly reads from the input stream and writes
* the data to the output stream, until the end of the input stream
* is reached, or an error is encountered.
*
* Unlike other I/O functions, this function blocks until the end
* of the input stream is seen and all the data has been written to
* the output stream.
*
* This function returns the number of bytes transferred, and the status of
* the output stream.
*/
}
import type { Pollable } from '../interfaces/wasi-io-poll';
export { Pollable };
/**
* Read from one stream and write to another, with blocking.
*
* This is similar to `splice`, except that it blocks until at least
* one byte can be read.
* An error for input-stream and output-stream operations.
*/
export function blockingSplice(this_: OutputStream, src: InputStream, len: bigint): [bigint, StreamStatus];
export type StreamError = StreamErrorLastOperationFailed | StreamErrorClosed;
/**
* Forward the entire contents of an input stream to an output stream.
* The last operation (a write or flush) failed before completion.
*
* This function repeatedly reads from the input stream and writes
* the data to the output stream, until the end of the input stream
* is reached, or an error is encountered.
*
* Unlike other I/O functions, this function blocks until the end
* of the input stream is seen and all the data has been written to
* the output stream.
*
* This function returns the number of bytes transferred, and the status of
* the output stream.
* More information is available in the `error` payload.
*/
export function forward(this_: OutputStream, src: InputStream): [bigint, StreamStatus];
export interface StreamErrorLastOperationFailed {
tag: 'last-operation-failed',
val: Error,
}
/**
* Dispose of the specified `output-stream`, after which it may no longer
* be used.
* Implementations may trap if this `output-stream` is dropped while
* child `pollable` resources are still alive.
* After this `output-stream` is dropped, implementations may report any
* corresponding `input-stream` has `stream-state.closed`.
* The stream is closed: no more input will be accepted by the
* stream. A closed output-stream will return this error on all
* future operations.
*/
export function dropOutputStream(this_: OutputStream): void;
}
import type { Pollable } from '../interfaces/wasi-poll-poll';
export { Pollable };
/**
* Streams provide a sequence of data and then end; once they end, they
* no longer provide any further data.
*
* For example, a stream reading from a file ends when the stream reaches
* the end of the file. For another example, a stream reading from a
* socket ends when the socket is closed.
* # Variants
*
* ## `"open"`
*
* The stream is open and may produce further data.
* ## `"ended"`
*
* When reading, this indicates that the stream will not produce
* further data.
* When writing, this indicates that the stream will no longer be read.
* Further writes are still permitted.
*/
export type StreamStatus = 'open' | 'ended';
/**
* An input bytestream. In the future, this will be replaced by handle
* types.
*
* `input-stream`s are *non-blocking* to the extent practical on underlying
* platforms. I/O operations always return promptly; if fewer bytes are
* promptly available than requested, they return the number of bytes promptly
* available, which could even be zero. To wait for data to be available,
* use the `subscribe-to-input-stream` function to obtain a `pollable` which
* can be polled for using `wasi:poll/poll.poll_oneoff`.
*
* And at present, it is a `u32` instead of being an actual handle, until
* the wit-bindgen implementation of handles and resources is ready.
*
* This [represents a resource](https://github.com/WebAssembly/WASI/blob/main/docs/WitInWasi.md#Resources).
*/
export type InputStream = number;
/**
* An output bytestream. In the future, this will be replaced by handle
* types.
*
* `output-stream`s are *non-blocking* to the extent practical on
* underlying platforms. Except where specified otherwise, I/O operations also
* always return promptly, after the number of bytes that can be written
* promptly, which could even be zero. To wait for the stream to be ready to
* accept data, the `subscribe-to-output-stream` function to obtain a
* `pollable` which can be polled for using `wasi:poll`.
*
* And at present, it is a `u32` instead of being an actual handle, until
* the wit-bindgen implementation of handles and resources is ready.
*
* This [represents a resource](https://github.com/WebAssembly/WASI/blob/main/docs/WitInWasi.md#Resources).
*/
export type OutputStream = number;
/**
* An error for output-stream operations.
*
* Contrary to input-streams, a closed output-stream is reported using
* an error.
* # Variants
*
* ## `"last-operation-failed"`
*
* The last operation (a write or flush) failed before completion.
* ## `"closed"`
*
* The stream is closed: no more input will be accepted by the
* stream. A closed output-stream will return this error on all
* future operations.
*/
export type WriteError = 'last-operation-failed' | 'closed';
export interface StreamErrorClosed {
tag: 'closed',
}
export class OutputStream {
checkWrite(): bigint;
write(contents: Uint8Array): void;
blockingWriteAndFlush(contents: Uint8Array): void;
flush(): void;
blockingFlush(): void;
subscribe(): Pollable;
writeZeroes(len: bigint): void;
blockingWriteZeroesAndFlush(len: bigint): void;
splice(src: InputStream, len: bigint): bigint;
blockingSplice(src: InputStream, len: bigint): bigint;
forward(src: InputStream): bigint;
}
export class Error {
toDebugString(): string;
}
export class InputStream {
read(len: bigint): Uint8Array;
blockingRead(len: bigint): Uint8Array;
skip(len: bigint): bigint;
blockingSkip(len: bigint): bigint;
subscribe(): Pollable;
}
export namespace WasiRandomRandom {
/**
* Return `len` cryptographically-secure pseudo-random bytes.
* Return `len` cryptographically-secure random or pseudo-random bytes.
*
* This function must produce data from an adequately seeded
* cryptographically-secure pseudo-random number generator (CSPRNG), so it
* must not block, from the perspective of the calling program, and the
* returned data is always unpredictable.
* This function must produce data at least as cryptographically secure and
* fast as an adequately seeded cryptographically-secure pseudo-random
* number generator (CSPRNG). It must not block, from the perspective of
* the calling program, under any circumstances, including on the first
* request and on requests for numbers of bytes. The returned data must
* always be unpredictable.
*
* This function must always return fresh pseudo-random data. Deterministic
* environments must omit this function, rather than implementing it with
* deterministic data.
* This function must always return fresh data. Deterministic environments
* must omit this function, rather than implementing it with deterministic
* data.
*/
export function getRandomBytes(len: bigint): Uint8Array;
/**
* Return a cryptographically-secure pseudo-random `u64` value.
* Return a cryptographically-secure random or pseudo-random `u64` value.
*
* This function returns the same type of pseudo-random data as
* `get-random-bytes`, represented as a `u64`.
* This function returns the same type of data as `get-random-bytes`,
* represented as a `u64`.
*/
export function getRandomU64(): bigint;
}

@@ -24,5 +24,5 @@ export namespace WasiSocketsIpNameLookup {

* # Typical errors
* - `invalid-name`: `name` is a syntactically invalid domain name.
* - `invalid-name`: `name` is an IP address.
* - `address-family-not-supported`: The specified `address-family` is not supported. (EAI_FAMILY)
* - `invalid-argument`: `name` is a syntactically invalid domain name.
* - `invalid-argument`: `name` is an IP address.
* - `not-supported`: The specified `address-family` is not supported. (EAI_FAMILY)
*

@@ -42,3 +42,2 @@ * # References:

* addresses have been exhausted, this function returns `none`.
* After which, you should release the stream with `drop-resolve-address-stream`.
*

@@ -53,10 +52,4 @@ * This function never returns IPv4-mapped IPv6 addresses.

*/
export function resolveNextAddress(this_: ResolveAddressStream): IpAddress | undefined;
export { ResolveAddressStream };
/**
* Dispose of the specified `resolve-address-stream`, after which it may no longer be used.
*
* Note: this function is scheduled to be removed when Resources are natively supported in Wit.
*/
export function dropResolveAddressStream(this_: ResolveAddressStream): void;
/**
* Create a `pollable` which will resolve once the stream is ready for I/O.

@@ -67,5 +60,4 @@ *

*/
export function subscribe(this_: ResolveAddressStream): Pollable;
}
import type { Pollable } from '../interfaces/wasi-poll-poll';
import type { Pollable } from '../interfaces/wasi-io-poll';
export { Pollable };

@@ -80,2 +72,6 @@ import type { Network } from '../interfaces/wasi-sockets-network';

export { IpAddressFamily };
export type ResolveAddressStream = number;
export class ResolveAddressStream {
resolveNextAddress(): IpAddress | undefined;
subscribe(): Pollable;
}
export namespace WasiSocketsNetwork {
/**
* Dispose of the specified `network`, after which it may no longer be used.
*
* Note: this function is scheduled to be removed when Resources are natively supported in Wit.
*/
export function dropNetwork(this_: Network): void;
}
/**
* An opaque resource that represents access to (a subset of) the network.
* This enables context-based security for networking.
* There is no need for this to map 1:1 to a physical network interface.
*
* FYI, In the future this will be replaced by handle types.
*/
export type Network = number;
/**
* Error codes.

@@ -27,2 +13,3 @@ *

* - `out-of-memory`
* - `concurrency-conflict`
*

@@ -45,2 +32,7 @@ * See each individual API for what the POSIX equivalents are. They sometimes differ per API.

* POSIX equivalent: EOPNOTSUPP
* ## `"invalid-argument"`
*
* One of the arguments is invalid.
*
* POSIX equivalent: EINVAL
* ## `"out-of-memory"`

@@ -57,2 +49,4 @@ *

* This operation is incompatible with another asynchronous operation that is already in progress.
*
* POSIX equivalent: EALREADY
* ## `"not-in-progress"`

@@ -70,35 +64,8 @@ *

* Note: this is scheduled to be removed when `future`s are natively supported.
* ## `"address-family-not-supported"`
* ## `"invalid-state"`
*
* The specified address-family is not supported.
* ## `"address-family-mismatch"`
*
* An IPv4 address was passed to an IPv6 resource, or vice versa.
* ## `"invalid-remote-address"`
*
* The socket address is not a valid remote address. E.g. the IP address is set to INADDR_ANY, or the port is set to 0.
* ## `"ipv4-only-operation"`
*
* The operation is only supported on IPv4 resources.
* ## `"ipv6-only-operation"`
*
* The operation is only supported on IPv6 resources.
* The operation is not valid in the socket's current state.
* ## `"new-socket-limit"`
*
* A new socket resource could not be created because of a system limit.
* ## `"already-attached"`
*
* The socket is already attached to another network.
* ## `"already-bound"`
*
* The socket is already bound.
* ## `"already-connected"`
*
* The socket is already in the Connection state.
* ## `"not-bound"`
*
* The socket is not bound to any local address.
* ## `"not-connected"`
*
* The socket is not in the Connection state.
* ## `"address-not-bindable"`

@@ -109,15 +76,6 @@ *

*
* A bind operation failed because the provided address is already in use.
* ## `"ephemeral-ports-exhausted"`
*
* A bind operation failed because there are no ephemeral ports available.
* A bind operation failed because the provided address is already in use or because there are no ephemeral ports available.
* ## `"remote-unreachable"`
*
* The remote address is not reachable
* ## `"already-listening"`
*
* The socket is already in the Listener state.
* ## `"not-listening"`
*
* The socket is already in the Listener state.
* ## `"connection-refused"`

@@ -129,7 +87,7 @@ *

* The connection was reset.
* ## `"connection-aborted"`
*
* A connection was aborted.
* ## `"datagram-too-large"`
*
* ## `"invalid-name"`
*
* The provided name is a syntactically invalid domain name.
* ## `"name-unresolvable"`

@@ -145,3 +103,3 @@ *

*/
export type ErrorCode = 'unknown' | 'access-denied' | 'not-supported' | 'out-of-memory' | 'timeout' | 'concurrency-conflict' | 'not-in-progress' | 'would-block' | 'address-family-not-supported' | 'address-family-mismatch' | 'invalid-remote-address' | 'ipv4-only-operation' | 'ipv6-only-operation' | 'new-socket-limit' | 'already-attached' | 'already-bound' | 'already-connected' | 'not-bound' | 'not-connected' | 'address-not-bindable' | 'address-in-use' | 'ephemeral-ports-exhausted' | 'remote-unreachable' | 'already-listening' | 'not-listening' | 'connection-refused' | 'connection-reset' | 'datagram-too-large' | 'invalid-name' | 'name-unresolvable' | 'temporary-resolver-failure' | 'permanent-resolver-failure';
export type ErrorCode = 'unknown' | 'access-denied' | 'not-supported' | 'invalid-argument' | 'out-of-memory' | 'timeout' | 'concurrency-conflict' | 'not-in-progress' | 'would-block' | 'invalid-state' | 'new-socket-limit' | 'address-not-bindable' | 'address-in-use' | 'remote-unreachable' | 'connection-refused' | 'connection-reset' | 'connection-aborted' | 'datagram-too-large' | 'name-unresolvable' | 'temporary-resolver-failure' | 'permanent-resolver-failure';
/**

@@ -148,0 +106,0 @@ * # Variants

@@ -14,5 +14,4 @@ export namespace WasiSocketsTcpCreateSocket {

* # Typical errors
* - `not-supported`: The host does not support TCP sockets. (EOPNOTSUPP)
* - `address-family-not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT)
* - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE)
* - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT)
* - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE)
*

@@ -19,0 +18,0 @@ * # References

@@ -15,8 +15,9 @@ export namespace WasiSocketsTcp {

* # Typical `start` errors
* - `address-family-mismatch`: The `local-address` has the wrong address family. (EINVAL)
* - `already-bound`: The socket is already bound. (EINVAL)
* - `concurrency-conflict`: Another `bind`, `connect` or `listen` operation is already in progress. (EALREADY)
* - `invalid-argument`: The `local-address` has the wrong address family. (EAFNOSUPPORT, EFAULT on Windows)
* - `invalid-argument`: `local-address` is not a unicast address. (EINVAL)
* - `invalid-argument`: `local-address` is an IPv4-mapped IPv6 address, but the socket has `ipv6-only` enabled. (EINVAL)
* - `invalid-state`: The socket is already bound. (EINVAL)
*
* # Typical `finish` errors
* - `ephemeral-ports-exhausted`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows)
* - `address-in-use`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows)
* - `address-in-use`: Address is already in use. (EADDRINUSE)

@@ -33,4 +34,3 @@ * - `address-not-bindable`: `local-address` is not an address that the `network` can bind to. (EADDRNOTAVAIL)

*/
export function startBind(this_: TcpSocket, network: Network, localAddress: IpSocketAddress): void;
export function finishBind(this_: TcpSocket): void;
export { TcpSocket };
/**

@@ -43,10 +43,21 @@ * Connect to a remote endpoint.

*
* POSIX mentions:
* > If connect() fails, the state of the socket is unspecified. Conforming applications should
* > close the file descriptor and create a new socket before attempting to reconnect.
*
* WASI prescribes the following behavior:
* - If `connect` fails because an input/state validation error, the socket should remain usable.
* - If a connection was actually attempted but failed, the socket should become unusable for further network communication.
* Besides `drop`, any method after such a failure may return an error.
*
* # Typical `start` errors
* - `address-family-mismatch`: The `remote-address` has the wrong address family. (EAFNOSUPPORT)
* - `invalid-remote-address`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EADDRNOTAVAIL on Windows)
* - `invalid-remote-address`: The port in `remote-address` is set to 0. (EADDRNOTAVAIL on Windows)
* - `already-attached`: The socket is already attached to a different network. The `network` passed to `connect` must be identical to the one passed to `bind`.
* - `already-connected`: The socket is already in the Connection state. (EISCONN)
* - `already-listening`: The socket is already in the Listener state. (EOPNOTSUPP, EINVAL on Windows)
* - `concurrency-conflict`: Another `bind`, `connect` or `listen` operation is already in progress. (EALREADY)
* - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT)
* - `invalid-argument`: `remote-address` is not a unicast address. (EINVAL, ENETUNREACH on Linux, EAFNOSUPPORT on MacOS)
* - `invalid-argument`: `remote-address` is an IPv4-mapped IPv6 address, but the socket has `ipv6-only` enabled. (EINVAL, EADDRNOTAVAIL on Illumos)
* - `invalid-argument`: `remote-address` is a non-IPv4-mapped IPv6 address, but the socket was bound to a specific IPv4-mapped IPv6 address. (or vice versa)
* - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EADDRNOTAVAIL on Windows)
* - `invalid-argument`: The port in `remote-address` is set to 0. (EADDRNOTAVAIL on Windows)
* - `invalid-argument`: The socket is already attached to a different network. The `network` passed to `connect` must be identical to the one passed to `bind`.
* - `invalid-state`: The socket is already in the Connection state. (EISCONN)
* - `invalid-state`: The socket is already in the Listener state. (EOPNOTSUPP, EINVAL on Windows)
*

@@ -57,4 +68,5 @@ * # Typical `finish` errors

* - `connection-reset`: The connection was reset. (ECONNRESET)
* - `connection-aborted`: The connection was aborted. (ECONNABORTED)
* - `remote-unreachable`: The remote address is not reachable. (EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN)
* - `ephemeral-ports-exhausted`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD)
* - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD)
* - `not-in-progress`: A `connect` operation is not in progress.

@@ -69,10 +81,3 @@ * - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN)

*/
export function startConnect(this_: TcpSocket, network: Network, remoteAddress: IpSocketAddress): void;
/**
* Note: the returned `input-stream` and `output-stream` are child
* resources of the `tcp-socket`. Implementations may trap if the
* `tcp-socket` is dropped before both of these streams are dropped.
*/
export function finishConnect(this_: TcpSocket): [InputStream, OutputStream];
/**
* Start listening for new connections.

@@ -87,9 +92,8 @@ *

* # Typical `start` errors
* - `not-bound`: The socket is not bound to any local address. (EDESTADDRREQ)
* - `already-connected`: The socket is already in the Connection state. (EISCONN, EINVAL on BSD)
* - `already-listening`: The socket is already in the Listener state.
* - `concurrency-conflict`: Another `bind`, `connect` or `listen` operation is already in progress. (EINVAL on BSD)
* - `invalid-state`: The socket is not bound to any local address. (EDESTADDRREQ)
* - `invalid-state`: The socket is already in the Connection state. (EISCONN, EINVAL on BSD)
* - `invalid-state`: The socket is already in the Listener state.
*
* # Typical `finish` errors
* - `ephemeral-ports-exhausted`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE)
* - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE)
* - `not-in-progress`: A `listen` operation is not in progress.

@@ -104,8 +108,13 @@ * - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN)

*/
export function startListen(this_: TcpSocket): void;
export function finishListen(this_: TcpSocket): void;
/**
* Accept a new client socket.
*
* The returned socket is bound and in the Connection state.
* The returned socket is bound and in the Connection state. The following properties are inherited from the listener socket:
* - `address-family`
* - `ipv6-only`
* - `keep-alive`
* - `no-delay`
* - `unicast-hop-limit`
* - `receive-buffer-size`
* - `send-buffer-size`
*

@@ -115,12 +124,8 @@ * On success, this function returns the newly accepted client socket along with

*
* Note: the returned `input-stream` and `output-stream` are child
* resources of the returned `tcp-socket`. Implementations may trap if the
* `tcp-socket` is dropped before its child streams are dropped.
*
* # Typical errors
* - `not-listening`: Socket is not in the Listener state. (EINVAL)
* - `would-block`: No pending connections at the moment. (EWOULDBLOCK, EAGAIN)
* - `invalid-state`: Socket is not in the Listener state. (EINVAL)
* - `would-block`: No pending connections at the moment. (EWOULDBLOCK, EAGAIN)
* - `connection-aborted`: An incoming connection was pending, but was terminated by the client before this listener could accept it. (ECONNABORTED)
* - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE)
*
* Host implementations must skip over transient errors returned by the native accept syscall.
*
* # References

@@ -132,8 +137,13 @@ * - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html>

*/
export function accept(this_: TcpSocket): [TcpSocket, InputStream, OutputStream];
/**
* Get the bound local address.
*
* POSIX mentions:
* > If the socket has not been bound to a local name, the value
* > stored in the object pointed to by `address` is unspecified.
*
* WASI is stricter and requires `local-address` to return `invalid-state` when the socket hasn't been bound yet.
*
* # Typical errors
* - `not-bound`: The socket is not bound to any local address.
* - `invalid-state`: The socket is not bound to any local address.
*

@@ -146,8 +156,7 @@ * # References

*/
export function localAddress(this_: TcpSocket): IpSocketAddress;
/**
* Get the bound remote address.
* Get the remote address.
*
* # Typical errors
* - `not-connected`: The socket is not connected to a remote address. (ENOTCONN)
* - `invalid-state`: The socket is not connected to a remote address. (ENOTCONN)
*

@@ -160,3 +169,2 @@ * # References

*/
export function remoteAddress(this_: TcpSocket): IpSocketAddress;
/**

@@ -167,3 +175,2 @@ * Whether this is a IPv4 or IPv6 socket.

*/
export function addressFamily(this_: TcpSocket): IpAddressFamily;
/**

@@ -175,9 +182,6 @@ * Whether IPv4 compatibility (dual-stack) mode is disabled or not.

* # Typical errors
* - `ipv6-only-operation`: (get/set) `this` socket is an IPv4 socket.
* - `already-bound`: (set) The socket is already bound.
* - `invalid-state`: (set) The socket is already bound.
* - `not-supported`: (get/set) `this` socket is an IPv4 socket.
* - `not-supported`: (set) Host does not support dual-stack sockets. (Implementations are not required to.)
* - `concurrency-conflict`: (set) A `bind`, `connect` or `listen` operation is already in progress. (EALREADY)
*/
export function ipv6Only(this_: TcpSocket): boolean;
export function setIpv6Only(this_: TcpSocket, value: boolean): void;
/**

@@ -187,22 +191,13 @@ * Hints the desired listen queue size. Implementations are free to ignore this.

* # Typical errors
* - `already-connected`: (set) The socket is already in the Connection state.
* - `concurrency-conflict`: (set) A `bind`, `connect` or `listen` operation is already in progress. (EALREADY)
* - `not-supported`: (set) The platform does not support changing the backlog size after the initial listen.
* - `invalid-state`: (set) The socket is already in the Connection state.
*/
export function setListenBacklogSize(this_: TcpSocket, value: bigint): void;
/**
* Equivalent to the SO_KEEPALIVE socket option.
*
* # Typical errors
* - `concurrency-conflict`: (set) A `bind`, `connect` or `listen` operation is already in progress. (EALREADY)
*/
export function keepAlive(this_: TcpSocket): boolean;
export function setKeepAlive(this_: TcpSocket, value: boolean): void;
/**
* Equivalent to the TCP_NODELAY socket option.
*
* # Typical errors
* - `concurrency-conflict`: (set) A `bind`, `connect` or `listen` operation is already in progress. (EALREADY)
* The default value is `false`.
*/
export function noDelay(this_: TcpSocket): boolean;
export function setNoDelay(this_: TcpSocket, value: boolean): void;
/**

@@ -212,8 +207,6 @@ * Equivalent to the IP_TTL & IPV6_UNICAST_HOPS socket options.

* # Typical errors
* - `already-connected`: (set) The socket is already in the Connection state.
* - `already-listening`: (set) The socket is already in the Listener state.
* - `concurrency-conflict`: (set) A `bind`, `connect` or `listen` operation is already in progress. (EALREADY)
* - `invalid-argument`: (set) The TTL value must be 1 or higher.
* - `invalid-state`: (set) The socket is already in the Connection state.
* - `invalid-state`: (set) The socket is already in the Listener state.
*/
export function unicastHopLimit(this_: TcpSocket): number;
export function setUnicastHopLimit(this_: TcpSocket, value: number): void;
/**

@@ -232,21 +225,11 @@ * The kernel buffer space reserved for sends/receives on this socket.

* # Typical errors
* - `already-connected`: (set) The socket is already in the Connection state.
* - `already-listening`: (set) The socket is already in the Listener state.
* - `concurrency-conflict`: (set) A `bind`, `connect` or `listen` operation is already in progress. (EALREADY)
* - `invalid-state`: (set) The socket is already in the Connection state.
* - `invalid-state`: (set) The socket is already in the Listener state.
*/
export function receiveBufferSize(this_: TcpSocket): bigint;
export function setReceiveBufferSize(this_: TcpSocket, value: bigint): void;
export function sendBufferSize(this_: TcpSocket): bigint;
export function setSendBufferSize(this_: TcpSocket, value: bigint): void;
/**
* Create a `pollable` which will resolve once the socket is ready for I/O.
*
* The created `pollable` is a child resource of the `tcp-socket`.
* Implementations may trap if the `tcp-socket` is dropped before all
* derived `pollable`s created with this function are dropped.
*
* Note: this function is here for WASI Preview2 only.
* It's planned to be removed when `future` is natively supported in Preview3.
*/
export function subscribe(this_: TcpSocket): Pollable;
/**

@@ -265,3 +248,3 @@ * Initiate a graceful shutdown.

* # Typical errors
* - `not-connected`: The socket is not in the Connection state. (ENOTCONN)
* - `invalid-state`: The socket is not in the Connection state. (ENOTCONN)
*

@@ -274,11 +257,2 @@ * # References

*/
export function shutdown(this_: TcpSocket, shutdownType: ShutdownType): void;
/**
* Dispose of the specified `tcp-socket`, after which it may no longer be used.
*
* Similar to the POSIX `close` function.
*
* Note: this function is scheduled to be removed when Resources are natively supported in Wit.
*/
export function dropTcpSocket(this_: TcpSocket): void;
}

@@ -289,3 +263,3 @@ import type { InputStream } from '../interfaces/wasi-io-streams';

export { OutputStream };
import type { Pollable } from '../interfaces/wasi-poll-poll';
import type { Pollable } from '../interfaces/wasi-io-poll';
export { Pollable };

@@ -301,6 +275,2 @@ import type { Network } from '../interfaces/wasi-sockets-network';

/**
* A TCP socket handle.
*/
export type TcpSocket = number;
/**
* # Variants

@@ -319,1 +289,29 @@ *

export type ShutdownType = 'receive' | 'send' | 'both';
export class TcpSocket {
startBind(network: Network, localAddress: IpSocketAddress): void;
finishBind(): void;
startConnect(network: Network, remoteAddress: IpSocketAddress): void;
finishConnect(): [InputStream, OutputStream];
startListen(): void;
finishListen(): void;
accept(): [TcpSocket, InputStream, OutputStream];
localAddress(): IpSocketAddress;
remoteAddress(): IpSocketAddress;
addressFamily(): IpAddressFamily;
ipv6Only(): boolean;
setIpv6Only(value: boolean): void;
setListenBacklogSize(value: bigint): void;
keepAlive(): boolean;
setKeepAlive(value: boolean): void;
noDelay(): boolean;
setNoDelay(value: boolean): void;
unicastHopLimit(): number;
setUnicastHopLimit(value: number): void;
receiveBufferSize(): bigint;
setReceiveBufferSize(value: bigint): void;
sendBufferSize(): bigint;
setSendBufferSize(value: bigint): void;
subscribe(): Pollable;
shutdown(shutdownType: ShutdownType): void;
}

@@ -14,5 +14,4 @@ export namespace WasiSocketsUdpCreateSocket {

* # Typical errors
* - `not-supported`: The host does not support UDP sockets. (EOPNOTSUPP)
* - `address-family-not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT)
* - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE)
* - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT)
* - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE)
*

@@ -19,0 +18,0 @@ * # References:

@@ -14,8 +14,7 @@ export namespace WasiSocketsUdp {

* # Typical `start` errors
* - `address-family-mismatch`: The `local-address` has the wrong address family. (EINVAL)
* - `already-bound`: The socket is already bound. (EINVAL)
* - `concurrency-conflict`: Another `bind` or `connect` operation is already in progress. (EALREADY)
* - `invalid-argument`: The `local-address` has the wrong address family. (EAFNOSUPPORT, EFAULT on Windows)
* - `invalid-state`: The socket is already bound. (EINVAL)
*
* # Typical `finish` errors
* - `ephemeral-ports-exhausted`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows)
* - `address-in-use`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows)
* - `address-in-use`: Address is already in use. (EADDRINUSE)

@@ -32,4 +31,3 @@ * - `address-not-bindable`: `local-address` is not an address that the `network` can bind to. (EADDRNOTAVAIL)

*/
export function startBind(this_: UdpSocket, network: Network, localAddress: IpSocketAddress): void;
export function finishBind(this_: UdpSocket): void;
export { UdpSocket };
/**

@@ -49,10 +47,10 @@ * Set the destination address.

* # Typical `start` errors
* - `address-family-mismatch`: The `remote-address` has the wrong address family. (EAFNOSUPPORT)
* - `invalid-remote-address`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EDESTADDRREQ, EADDRNOTAVAIL)
* - `invalid-remote-address`: The port in `remote-address` is set to 0. (EDESTADDRREQ, EADDRNOTAVAIL)
* - `already-attached`: The socket is already bound to a different network. The `network` passed to `connect` must be identical to the one passed to `bind`.
* - `concurrency-conflict`: Another `bind` or `connect` operation is already in progress. (EALREADY)
* - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT)
* - `invalid-argument`: `remote-address` is a non-IPv4-mapped IPv6 address, but the socket was bound to a specific IPv4-mapped IPv6 address. (or vice versa)
* - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EDESTADDRREQ, EADDRNOTAVAIL)
* - `invalid-argument`: The port in `remote-address` is set to 0. (EDESTADDRREQ, EADDRNOTAVAIL)
* - `invalid-argument`: The socket is already bound to a different network. The `network` passed to `connect` must be identical to the one passed to `bind`.
*
* # Typical `finish` errors
* - `ephemeral-ports-exhausted`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD)
* - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD)
* - `not-in-progress`: A `connect` operation is not in progress.

@@ -67,4 +65,2 @@ * - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN)

*/
export function startConnect(this_: UdpSocket, network: Network, remoteAddress: IpSocketAddress): void;
export function finishConnect(this_: UdpSocket): void;
/**

@@ -78,3 +74,3 @@ * Receive messages on the socket.

* # Typical errors
* - `not-bound`: The socket is not bound to any local address. (EINVAL)
* - `invalid-state`: The socket is not bound to any local address. (EINVAL)
* - `remote-unreachable`: The remote address is not reachable. (ECONNREFUSED, ECONNRESET, ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN)

@@ -93,3 +89,2 @@ * - `would-block`: There is no pending data available to be read at the moment. (EWOULDBLOCK, EAGAIN)

*/
export function receive(this_: UdpSocket, maxResults: bigint): Datagram[];
/**

@@ -111,7 +106,8 @@ * Send messages on the socket.

* # Typical errors
* - `address-family-mismatch`: The `remote-address` has the wrong address family. (EAFNOSUPPORT)
* - `invalid-remote-address`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EDESTADDRREQ, EADDRNOTAVAIL)
* - `invalid-remote-address`: The port in `remote-address` is set to 0. (EDESTADDRREQ, EADDRNOTAVAIL)
* - `already-connected`: The socket is in "connected" mode and the `datagram.remote-address` does not match the address passed to `connect`. (EISCONN)
* - `not-bound`: The socket is not bound to any local address. Unlike POSIX, this function does not perform an implicit bind.
* - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT)
* - `invalid-argument`: `remote-address` is a non-IPv4-mapped IPv6 address, but the socket was bound to a specific IPv4-mapped IPv6 address. (or vice versa)
* - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EDESTADDRREQ, EADDRNOTAVAIL)
* - `invalid-argument`: The port in `remote-address` is set to 0. (EDESTADDRREQ, EADDRNOTAVAIL)
* - `invalid-argument`: The socket is in "connected" mode and the `datagram.remote-address` does not match the address passed to `connect`. (EISCONN)
* - `invalid-state`: The socket is not bound to any local address. Unlike POSIX, this function does not perform an implicit bind.
* - `remote-unreachable`: The remote address is not reachable. (ECONNREFUSED, ECONNRESET, ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN)

@@ -131,8 +127,13 @@ * - `datagram-too-large`: The datagram is too large. (EMSGSIZE)

*/
export function send(this_: UdpSocket, datagrams: Datagram[]): bigint;
/**
* Get the current bound address.
*
* POSIX mentions:
* > If the socket has not been bound to a local name, the value
* > stored in the object pointed to by `address` is unspecified.
*
* WASI is stricter and requires `local-address` to return `invalid-state` when the socket hasn't been bound yet.
*
* # Typical errors
* - `not-bound`: The socket is not bound to any local address.
* - `invalid-state`: The socket is not bound to any local address.
*

@@ -145,3 +146,2 @@ * # References

*/
export function localAddress(this_: UdpSocket): IpSocketAddress;
/**

@@ -151,3 +151,3 @@ * Get the address set with `connect`.

* # Typical errors
* - `not-connected`: The socket is not connected to a remote address. (ENOTCONN)
* - `invalid-state`: The socket is not connected to a remote address. (ENOTCONN)
*

@@ -160,3 +160,2 @@ * # References

*/
export function remoteAddress(this_: UdpSocket): IpSocketAddress;
/**

@@ -167,3 +166,2 @@ * Whether this is a IPv4 or IPv6 socket.

*/
export function addressFamily(this_: UdpSocket): IpAddressFamily;
/**

@@ -175,17 +173,9 @@ * Whether IPv4 compatibility (dual-stack) mode is disabled or not.

* # Typical errors
* - `ipv6-only-operation`: (get/set) `this` socket is an IPv4 socket.
* - `already-bound`: (set) The socket is already bound.
* - `not-supported`: (get/set) `this` socket is an IPv4 socket.
* - `invalid-state`: (set) The socket is already bound.
* - `not-supported`: (set) Host does not support dual-stack sockets. (Implementations are not required to.)
* - `concurrency-conflict`: (set) Another `bind` or `connect` operation is already in progress. (EALREADY)
*/
export function ipv6Only(this_: UdpSocket): boolean;
export function setIpv6Only(this_: UdpSocket, value: boolean): void;
/**
* Equivalent to the IP_TTL & IPV6_UNICAST_HOPS socket options.
*
* # Typical errors
* - `concurrency-conflict`: (set) Another `bind` or `connect` operation is already in progress. (EALREADY)
*/
export function unicastHopLimit(this_: UdpSocket): number;
export function setUnicastHopLimit(this_: UdpSocket, value: number): void;
/**

@@ -202,10 +192,3 @@ * The kernel buffer space reserved for sends/receives on this socket.

* Equivalent to the SO_RCVBUF and SO_SNDBUF socket options.
*
* # Typical errors
* - `concurrency-conflict`: (set) Another `bind` or `connect` operation is already in progress. (EALREADY)
*/
export function receiveBufferSize(this_: UdpSocket): bigint;
export function setReceiveBufferSize(this_: UdpSocket, value: bigint): void;
export function sendBufferSize(this_: UdpSocket): bigint;
export function setSendBufferSize(this_: UdpSocket, value: bigint): void;
/**

@@ -217,11 +200,4 @@ * Create a `pollable` which will resolve once the socket is ready for I/O.

*/
export function subscribe(this_: UdpSocket): Pollable;
/**
* Dispose of the specified `udp-socket`, after which it may no longer be used.
*
* Note: this function is scheduled to be removed when Resources are natively supported in Wit.
*/
export function dropUdpSocket(this_: UdpSocket): void;
}
import type { Pollable } from '../interfaces/wasi-poll-poll';
import type { Pollable } from '../interfaces/wasi-io-poll';
export { Pollable };

@@ -236,6 +212,2 @@ import type { Network } from '../interfaces/wasi-sockets-network';

export { IpAddressFamily };
/**
* A UDP socket handle.
*/
export type UdpSocket = number;
export interface Datagram {

@@ -245,1 +217,22 @@ data: Uint8Array,

}
export class UdpSocket {
startBind(network: Network, localAddress: IpSocketAddress): void;
finishBind(): void;
startConnect(network: Network, remoteAddress: IpSocketAddress): void;
finishConnect(): void;
receive(maxResults: bigint): Datagram[];
send(datagrams: Datagram[]): bigint;
localAddress(): IpSocketAddress;
remoteAddress(): IpSocketAddress;
addressFamily(): IpAddressFamily;
ipv6Only(): boolean;
setIpv6Only(value: boolean): void;
unicastHopLimit(): number;
setUnicastHopLimit(value: number): void;
receiveBufferSize(): bigint;
setReceiveBufferSize(value: bigint): void;
sendBufferSize(): bigint;
setSendBufferSize(value: bigint): void;
subscribe(): Pollable;
}

@@ -16,4 +16,4 @@ import { WasiCliEnvironment } from './interfaces/wasi-cli-environment';

import { WasiFilesystemTypes } from './interfaces/wasi-filesystem-types';
import { WasiIoPoll } from './interfaces/wasi-io-poll';
import { WasiIoStreams } from './interfaces/wasi-io-streams';
import { WasiPollPoll } from './interfaces/wasi-poll-poll';
import { WasiRandomInsecure } from './interfaces/wasi-random-insecure';

@@ -20,0 +20,0 @@ import { WasiRandomInsecureSeed } from './interfaces/wasi-random-insecure-seed';

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc