Skip to main content
Module

std/wasi/snapshot_preview1.ts

Deno standard library
Go to Latest
File
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525
/* eslint-disable */
import { resolve } from "../path/mod.ts";
const CLOCKID_REALTIME = 0;const CLOCKID_MONOTONIC = 1;const CLOCKID_PROCESS_CPUTIME_ID = 2;const CLOCKID_THREAD_CPUTIME_ID = 3;
const ERRNO_SUCCESS = 0;const ERRNO_2BIG = 1;const ERRNO_ACCES = 2;const ERRNO_ADDRINUSE = 3;const ERRNO_ADDRNOTAVAIL = 4;const ERRNO_AFNOSUPPORT = 5;const ERRNO_AGAIN = 6;const ERRNO_ALREADY = 7;const ERRNO_BADF = 8;const ERRNO_BADMSG = 9;const ERRNO_BUSY = 10;const ERRNO_CANCELED = 11;const ERRNO_CHILD = 12;const ERRNO_CONNABORTED = 13;const ERRNO_CONNREFUSED = 14;const ERRNO_CONNRESET = 15;const ERRNO_DEADLK = 16;const ERRNO_DESTADDRREQ = 17;const ERRNO_DOM = 18;const ERRNO_DQUOT = 19;const ERRNO_EXIST = 20;const ERRNO_FAULT = 21;const ERRNO_FBIG = 22;const ERRNO_HOSTUNREACH = 23;const ERRNO_IDRM = 24;const ERRNO_ILSEQ = 25;const ERRNO_INPROGRESS = 26;const ERRNO_INTR = 27;const ERRNO_INVAL = 28;const ERRNO_IO = 29;const ERRNO_ISCONN = 30;const ERRNO_ISDIR = 31;const ERRNO_LOOP = 32;const ERRNO_MFILE = 33;const ERRNO_MLINK = 34;const ERRNO_MSGSIZE = 35;const ERRNO_MULTIHOP = 36;const ERRNO_NAMETOOLONG = 37;const ERRNO_NETDOWN = 38;const ERRNO_NETRESET = 39;const ERRNO_NETUNREACH = 40;const ERRNO_NFILE = 41;const ERRNO_NOBUFS = 42;const ERRNO_NODEV = 43;const ERRNO_NOENT = 44;const ERRNO_NOEXEC = 45;const ERRNO_NOLCK = 46;const ERRNO_NOLINK = 47;const ERRNO_NOMEM = 48;const ERRNO_NOMSG = 49;const ERRNO_NOPROTOOPT = 50;const ERRNO_NOSPC = 51;const ERRNO_NOSYS = 52;const ERRNO_NOTCONN = 53;const ERRNO_NOTDIR = 54;const ERRNO_NOTEMPTY = 55;const ERRNO_NOTRECOVERABLE = 56;const ERRNO_NOTSOCK = 57;const ERRNO_NOTSUP = 58;const ERRNO_NOTTY = 59;const ERRNO_NXIO = 60;const ERRNO_OVERFLOW = 61;const ERRNO_OWNERDEAD = 62;const ERRNO_PERM = 63;const ERRNO_PIPE = 64;const ERRNO_PROTO = 65;const ERRNO_PROTONOSUPPORT = 66;const ERRNO_PROTOTYPE = 67;const ERRNO_RANGE = 68;const ERRNO_ROFS = 69;const ERRNO_SPIPE = 70;const ERRNO_SRCH = 71;const ERRNO_STALE = 72;const ERRNO_TIMEDOUT = 73;const ERRNO_TXTBSY = 74;const ERRNO_XDEV = 75;const ERRNO_NOTCAPABLE = 76;
const RIGHTS_FD_DATASYNC = 0x0000000000000001n;const RIGHTS_FD_READ = 0x0000000000000002n;const RIGHTS_FD_SEEK = 0x0000000000000004n;const RIGHTS_FD_FDSTAT_SET_FLAGS = 0x0000000000000008n;const RIGHTS_FD_SYNC = 0x0000000000000010n;const RIGHTS_FD_TELL = 0x0000000000000020n;const RIGHTS_FD_WRITE = 0x0000000000000040n;const RIGHTS_FD_ADVISE = 0x0000000000000080n;const RIGHTS_FD_ALLOCATE = 0x0000000000000100n;const RIGHTS_PATH_CREATE_DIRECTORY = 0x0000000000000200n;const RIGHTS_PATH_CREATE_FILE = 0x0000000000000400n;const RIGHTS_PATH_LINK_SOURCE = 0x0000000000000800n;const RIGHTS_PATH_LINK_TARGET = 0x0000000000001000n;const RIGHTS_PATH_OPEN = 0x0000000000002000n;const RIGHTS_FD_READDIR = 0x0000000000004000n;const RIGHTS_PATH_READLINK = 0x0000000000008000n;const RIGHTS_PATH_RENAME_SOURCE = 0x0000000000010000n;const RIGHTS_PATH_RENAME_TARGET = 0x0000000000020000n;const RIGHTS_PATH_FILESTAT_GET = 0x0000000000040000n;const RIGHTS_PATH_FILESTAT_SET_SIZE = 0x0000000000080000n;const RIGHTS_PATH_FILESTAT_SET_TIMES = 0x0000000000100000n;const RIGHTS_FD_FILESTAT_GET = 0x0000000000200000n;const RIGHTS_FD_FILESTAT_SET_SIZE = 0x0000000000400000n;const RIGHTS_FD_FILESTAT_SET_TIMES = 0x0000000000800000n;const RIGHTS_PATH_SYMLINK = 0x0000000001000000n;const RIGHTS_PATH_REMOVE_DIRECTORY = 0x0000000002000000n;const RIGHTS_PATH_UNLINK_FILE = 0x0000000004000000n;const RIGHTS_POLL_FD_READWRITE = 0x0000000008000000n;const RIGHTS_SOCK_SHUTDOWN = 0x0000000010000000n;
const WHENCE_SET = 0;const WHENCE_CUR = 1;const WHENCE_END = 2;
const FILETYPE_UNKNOWN = 0;const FILETYPE_BLOCK_DEVICE = 1;const FILETYPE_CHARACTER_DEVICE = 2;const FILETYPE_DIRECTORY = 3;const FILETYPE_REGULAR_FILE = 4;const FILETYPE_SOCKET_DGRAM = 5;const FILETYPE_SOCKET_STREAM = 6;const FILETYPE_SYMBOLIC_LINK = 7;
const ADVICE_NORMAL = 0;const ADVICE_SEQUENTIAL = 1;const ADVICE_RANDOM = 2;const ADVICE_WILLNEED = 3;const ADVICE_DONTNEED = 4;const ADVICE_NOREUSE = 5;
const FDFLAGS_APPEND = 0x0001;const FDFLAGS_DSYNC = 0x0002;const FDFLAGS_NONBLOCK = 0x0004;const FDFLAGS_RSYNC = 0x0008;const FDFLAGS_SYNC = 0x0010;
const FSTFLAGS_ATIM = 0x0001;const FSTFLAGS_ATIM_NOW = 0x0002;const FSTFLAGS_MTIM = 0x0004;const FSTFLAGS_MTIM_NOW = 0x0008;
const LOOKUPFLAGS_SYMLINK_FOLLOW = 0x0001;
const OFLAGS_CREAT = 0x0001;const OFLAGS_DIRECTORY = 0x0002;const OFLAGS_EXCL = 0x0004;const OFLAGS_TRUNC = 0x0008;
const EVENTTYPE_CLOCK = 0;const EVENTTYPE_FD_READ = 1;const EVENTTYPE_FD_WRITE = 2;
const EVENTRWFLAGS_FD_READWRITE_HANGUP = 1;const SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME = 1;
const SIGNAL_NONE = 0;const SIGNAL_HUP = 1;const SIGNAL_INT = 2;const SIGNAL_QUIT = 3;const SIGNAL_ILL = 4;const SIGNAL_TRAP = 5;const SIGNAL_ABRT = 6;const SIGNAL_BUS = 7;const SIGNAL_FPE = 8;const SIGNAL_KILL = 9;const SIGNAL_USR1 = 10;const SIGNAL_SEGV = 11;const SIGNAL_USR2 = 12;const SIGNAL_PIPE = 13;const SIGNAL_ALRM = 14;const SIGNAL_TERM = 15;const SIGNAL_CHLD = 16;const SIGNAL_CONT = 17;const SIGNAL_STOP = 18;const SIGNAL_TSTP = 19;const SIGNAL_TTIN = 20;const SIGNAL_TTOU = 21;const SIGNAL_URG = 22;const SIGNAL_XCPU = 23;const SIGNAL_XFSZ = 24;const SIGNAL_VTALRM = 25;const SIGNAL_PROF = 26;const SIGNAL_WINCH = 27;const SIGNAL_POLL = 28;const SIGNAL_PWR = 29;const SIGNAL_SYS = 30;
const RIFLAGS_RECV_PEEK = 0x0001;const RIFLAGS_RECV_WAITALL = 0x0002;
const ROFLAGS_RECV_DATA_TRUNCATED = 0x0001;
const SDFLAGS_RD = 0x0001;const SDFLAGS_WR = 0x0002;
const PREOPENTYPE_DIR = 0;
const clock_res_realtime = function (): bigint { return BigInt(1e6);};
const clock_res_monotonic = function (): bigint { return BigInt(1e3);};
const clock_res_process = clock_res_monotonic;const clock_res_thread = clock_res_monotonic;
const clock_time_realtime = function (): bigint { return BigInt(Date.now()) * BigInt(1e6);};
const clock_time_monotonic = function (): bigint { const t = performance.now(); const s = Math.trunc(t); const ms = Math.floor((t - s) * 1e3);
return BigInt(s) * BigInt(1e9) + BigInt(ms) * BigInt(1e6);};
const clock_time_process = clock_time_monotonic;const clock_time_thread = clock_time_monotonic;
function errno(err: Error) { switch (err.name) { case "NotFound": return ERRNO_NOENT;
case "PermissionDenied": return ERRNO_ACCES;
case "ConnectionRefused": return ERRNO_CONNREFUSED;
case "ConnectionReset": return ERRNO_CONNRESET;
case "ConnectionAborted": return ERRNO_CONNABORTED;
case "NotConnected": return ERRNO_NOTCONN;
case "AddrInUse": return ERRNO_ADDRINUSE;
case "AddrNotAvailable": return ERRNO_ADDRNOTAVAIL;
case "BrokenPipe": return ERRNO_PIPE;
case "InvalidData": return ERRNO_INVAL;
case "TimedOut": return ERRNO_TIMEDOUT;
case "Interrupted": return ERRNO_INTR;
case "BadResource": return ERRNO_BADF;
case "Busy": return ERRNO_BUSY;
default: return ERRNO_INVAL; }}
export interface ModuleOptions { args?: string[]; env?: { [key: string]: string | undefined }; preopens?: { [key: string]: string }; memory?: WebAssembly.Memory;}
export default class Module { args: string[]; env: { [key: string]: string | undefined }; memory: WebAssembly.Memory;
// deno-lint-ignore no-explicit-any fds: any[];
// deno-lint-ignore no-explicit-any exports: { [key: string]: any };
constructor(options: ModuleOptions) { this.args = options.args ? options.args : []; this.env = options.env ? options.env : {}; this.memory = options.memory!;
this.fds = [ { type: FILETYPE_CHARACTER_DEVICE, handle: Deno.stdin, }, { type: FILETYPE_CHARACTER_DEVICE, handle: Deno.stdout, }, { type: FILETYPE_CHARACTER_DEVICE, handle: Deno.stderr, }, ];
if (options.preopens) { for (const [vpath, path] of Object.entries(options.preopens)) { const type = FILETYPE_DIRECTORY; const entries = Array.from(Deno.readDirSync(path));
const entry = { type, entries, path, vpath, };
this.fds.push(entry); } }
this.exports = { args_get: (argv_ptr: number, argv_buf_ptr: number): number => { const args = this.args; const text = new TextEncoder(); const heap = new Uint8Array(this.memory.buffer); const view = new DataView(this.memory.buffer);
for (let arg of args) { view.setUint32(argv_ptr, argv_buf_ptr, true); argv_ptr += 4;
const data = text.encode(`${arg}\0`); heap.set(data, argv_buf_ptr); argv_buf_ptr += data.length; }
return ERRNO_SUCCESS; },
args_sizes_get: (argc_out: number, argv_buf_size_out: number): number => { const args = this.args; const text = new TextEncoder(); const view = new DataView(this.memory.buffer);
view.setUint32(argc_out, args.length, true); view.setUint32( argv_buf_size_out, args.reduce(function (acc, arg) { return acc + text.encode(`${arg}\0`).length; }, 0), true, );
return ERRNO_SUCCESS; },
environ_get: (environ_ptr: number, environ_buf_ptr: number): number => { const entries = Object.entries(this.env); const text = new TextEncoder(); const heap = new Uint8Array(this.memory.buffer); const view = new DataView(this.memory.buffer);
for (let [key, value] of entries) { view.setUint32(environ_ptr, environ_buf_ptr, true); environ_ptr += 4;
const data = text.encode(`${key}=${value}\0`); heap.set(data, environ_buf_ptr); environ_buf_ptr += data.length; }
return ERRNO_SUCCESS; },
environ_sizes_get: ( environc_out: number, environ_buf_size_out: number, ): number => { const entries = Object.entries(this.env); const text = new TextEncoder(); const view = new DataView(this.memory.buffer);
view.setUint32(environc_out, entries.length, true); view.setUint32( environ_buf_size_out, entries.reduce(function (acc, [key, value]) { return acc + text.encode(`${key}=${value}\0`).length; }, 0), true, );
return ERRNO_SUCCESS; },
clock_res_get: (id: number, resolution_out: number): number => { const view = new DataView(this.memory.buffer);
switch (id) { case CLOCKID_REALTIME: view.setBigUint64(resolution_out, clock_res_realtime(), true); break;
case CLOCKID_MONOTONIC: view.setBigUint64(resolution_out, clock_res_monotonic(), true); break;
case CLOCKID_PROCESS_CPUTIME_ID: view.setBigUint64(resolution_out, clock_res_process(), true); break;
case CLOCKID_THREAD_CPUTIME_ID: view.setBigUint64(resolution_out, clock_res_thread(), true); break;
default: return ERRNO_INVAL; }
return ERRNO_SUCCESS; },
clock_time_get: ( id: number, precision: bigint, time_out: number, ): number => { const view = new DataView(this.memory.buffer);
switch (id) { case CLOCKID_REALTIME: view.setBigUint64(time_out, clock_time_realtime(), true); break;
case CLOCKID_MONOTONIC: view.setBigUint64(time_out, clock_time_monotonic(), true); break;
case CLOCKID_PROCESS_CPUTIME_ID: view.setBigUint64(time_out, clock_time_process(), true); break;
case CLOCKID_THREAD_CPUTIME_ID: view.setBigUint64(time_out, clock_time_thread(), true); break;
default: return ERRNO_INVAL; }
return ERRNO_SUCCESS; },
fd_advise: ( fd: number, offset: bigint, len: bigint, advice: number, ): number => { return ERRNO_NOSYS; },
fd_allocate: (fd: number, offset: bigint, len: bigint): number => { return ERRNO_NOSYS; },
fd_close: (fd: number): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (entry.handle) { entry.handle.close(); }
delete this.fds[fd];
return ERRNO_SUCCESS; },
fd_datasync: (fd: number): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
try { Deno.fdatasyncSync(entry.handle.rid); } catch (err) { return errno(err); }
return ERRNO_SUCCESS; },
fd_fdstat_get: (fd: number, stat_out: number): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
const view = new DataView(this.memory.buffer); view.setUint8(stat_out, entry.type); view.setUint16(stat_out + 4, 0, true); // TODO view.setBigUint64(stat_out + 8, 0n, true); // TODO view.setBigUint64(stat_out + 16, 0n, true); // TODO
return ERRNO_SUCCESS; },
fd_fdstat_set_flags: (fd: number, flags: number): number => { return ERRNO_NOSYS; },
fd_fdstat_set_rights: ( fd: number, fs_rights_base: bigint, fs_rights_inheriting: bigint, ): number => { return ERRNO_NOSYS; },
fd_filestat_get: (fd: number, buf_out: number): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
const view = new DataView(this.memory.buffer);
try { const info = Deno.fstatSync(entry.handle.rid);
if (entry.type === undefined) { switch (true) { case info.isFile: entry.type = FILETYPE_REGULAR_FILE; break;
case info.isDirectory: entry.type = FILETYPE_DIRECTORY; break;
case info.isSymlink: entry.type = FILETYPE_SYMBOLIC_LINK; break;
default: entry.type = FILETYPE_UNKNOWN; break; } }
view.setBigUint64(buf_out, BigInt(info.dev ? info.dev : 0), true); buf_out += 8;
view.setBigUint64(buf_out, BigInt(info.ino ? info.ino : 0), true); buf_out += 8;
view.setUint8(buf_out, entry.type); buf_out += 8;
view.setUint32(buf_out, Number(info.nlink), true); buf_out += 8;
view.setBigUint64(buf_out, BigInt(info.size), true); buf_out += 8;
view.setBigUint64( buf_out, BigInt(info.atime ? info.atime.getTime() * 1e6 : 0), true, ); buf_out += 8;
view.setBigUint64( buf_out, BigInt(info.mtime ? info.mtime.getTime() * 1e6 : 0), true, ); buf_out += 8;
view.setBigUint64( buf_out, BigInt(info.birthtime ? info.birthtime.getTime() * 1e6 : 0), true, ); buf_out += 8; } catch (err) { return errno(err); }
return ERRNO_SUCCESS; },
fd_filestat_set_size: (fd: number, size: bigint): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
try { Deno.ftruncateSync(entry.handle.rid, Number(size)); } catch (err) { return errno(err); }
return ERRNO_SUCCESS; },
fd_filestat_set_times: ( fd: number, atim: bigint, mtim: bigint, fst_flags: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.path) { return ERRNO_INVAL; }
if ((fst_flags & FSTFLAGS_ATIM_NOW) == FSTFLAGS_ATIM_NOW) { atim = BigInt(Date.now() * 1e6); }
if ((fst_flags & FSTFLAGS_MTIM_NOW) == FSTFLAGS_MTIM_NOW) { mtim = BigInt(Date.now() * 1e6); }
try { Deno.utimeSync(entry.path, Number(atim), Number(mtim)); } catch (err) { return errno(err); }
return ERRNO_SUCCESS; },
fd_pread: ( fd: number, iovs_ptr: number, iovs_len: number, offset: bigint, nread_out: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
const seek = entry.handle.seekSync(0, Deno.SeekMode.Current); const view = new DataView(this.memory.buffer);
let nread = 0; for (let i = 0; i < iovs_len; i++) { const data_ptr = view.getUint32(iovs_ptr, true); iovs_ptr += 4;
const data_len = view.getUint32(iovs_ptr, true); iovs_ptr += 4;
const data = new Uint8Array(this.memory.buffer, data_ptr, data_len); nread += entry.handle.readSync(data); }
entry.handle.seekSync(seek, Deno.SeekMode.Start); view.setUint32(nread_out, nread, true);
return ERRNO_SUCCESS; },
fd_prestat_get: (fd: number, buf_out: number): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.vpath) { return ERRNO_BADF; }
const view = new DataView(this.memory.buffer); view.setUint8(buf_out, PREOPENTYPE_DIR); view.setUint32( buf_out + 4, new TextEncoder().encode(entry.vpath).byteLength, true, );
return ERRNO_SUCCESS; },
fd_prestat_dir_name: ( fd: number, path_ptr: number, path_len: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.vpath) { return ERRNO_BADF; }
const data = new Uint8Array(this.memory.buffer, path_ptr, path_len); data.set(new TextEncoder().encode(entry.vpath));
return ERRNO_SUCCESS; },
fd_pwrite: ( fd: number, iovs_ptr: number, iovs_len: number, offset: bigint, nwritten_out: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
const seek = entry.handle.seekSync(0, Deno.SeekMode.Current); const view = new DataView(this.memory.buffer);
let nwritten = 0; for (let i = 0; i < iovs_len; i++) { const data_ptr = view.getUint32(iovs_ptr, true); iovs_ptr += 4;
const data_len = view.getUint32(iovs_ptr, true); iovs_ptr += 4;
const data = new Uint8Array(this.memory.buffer, data_ptr, data_len); nwritten += entry.handle.writeSync(data); }
entry.handle.seekSync(seek, Deno.SeekMode.Start); view.setUint32(nwritten_out, nwritten, true);
return ERRNO_SUCCESS; },
fd_read: ( fd: number, iovs_ptr: number, iovs_len: number, nread_out: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
const view = new DataView(this.memory.buffer);
let nread = 0; for (let i = 0; i < iovs_len; i++) { const data_ptr = view.getUint32(iovs_ptr, true); iovs_ptr += 4;
const data_len = view.getUint32(iovs_ptr, true); iovs_ptr += 4;
const data = new Uint8Array(this.memory.buffer, data_ptr, data_len); nread += entry.handle.readSync(data); }
view.setUint32(nread_out, nread, true);
return ERRNO_SUCCESS; },
fd_readdir: ( fd: number, buf_ptr: number, buf_len: number, cookie: bigint, bufused_out: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
const heap = new Uint8Array(this.memory.buffer); const view = new DataView(this.memory.buffer);
let bufused = 0;
try { const entries = Array.from(Deno.readDirSync(entry.path)); for (let i = Number(cookie); i < entries.length; i++) { const name_data = new TextEncoder().encode(entries[i].name);
const entry_info = Deno.statSync( resolve(entry.path, entries[i].name), ); const entry_data = new Uint8Array(24 + name_data.byteLength); const entry_view = new DataView(entry_data.buffer);
entry_view.setBigUint64(0, BigInt(i + 1), true); entry_view.setBigUint64( 8, BigInt(entry_info.ino ? entry_info.ino : 0), true, ); entry_view.setUint32(16, name_data.byteLength, true);
switch (true) { case entries[i].isFile: var type = FILETYPE_REGULAR_FILE; break;
case entries[i].isDirectory: var type = FILETYPE_REGULAR_FILE; break;
case entries[i].isSymlink: var type = FILETYPE_SYMBOLIC_LINK; break;
default: var type = FILETYPE_REGULAR_FILE; break; }
entry_view.setUint8(20, type); entry_data.set(name_data, 24);
const data = entry_data.slice( 0, Math.min(entry_data.length, buf_len - bufused), ); heap.set(data, buf_ptr + bufused); bufused += data.byteLength; } } catch (err) { return errno(err); }
view.setUint32(bufused_out, bufused, true);
return ERRNO_SUCCESS; },
fd_renumber: (fd: number, to: number): number => { if (!this.fds[fd]) { return ERRNO_BADF; }
if (!this.fds[to]) { return ERRNO_BADF; }
this.fds[to].handle.close(); this.fds[to] = this.fds[fd]; delete this.fds[fd];
return ERRNO_SUCCESS; },
fd_seek: ( fd: number, offset: bigint, whence: number, newoffset_out: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
const view = new DataView(this.memory.buffer);
try { // FIXME Deno does not support seeking with big integers
const newoffset = entry.handle.seekSync(Number(offset), whence); view.setBigUint64(newoffset_out, BigInt(newoffset), true); } catch (err) { return ERRNO_INVAL; }
return ERRNO_SUCCESS; },
fd_sync: (fd: number): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
try { Deno.fsyncSync(entry.handle.rid); } catch (err) { return errno(err); }
return ERRNO_SUCCESS; },
fd_tell: (fd: number, offset_out: number): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
const view = new DataView(this.memory.buffer);
try { const offset = entry.handle.seekSync(0, Deno.SeekMode.Current); view.setBigUint64(offset_out, offset, true); } catch (err) { return ERRNO_INVAL; }
return ERRNO_SUCCESS; },
fd_write: ( fd: number, iovs_ptr: number, iovs_len: number, nwritten_out: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
const view = new DataView(this.memory.buffer);
let nwritten = 0; for (let i = 0; i < iovs_len; i++) { const data_ptr = view.getUint32(iovs_ptr, true); iovs_ptr += 4;
const data_len = view.getUint32(iovs_ptr, true); iovs_ptr += 4;
nwritten += entry.handle.writeSync( new Uint8Array(this.memory.buffer, data_ptr, data_len), ); }
view.setUint32(nwritten_out, nwritten, true);
return ERRNO_SUCCESS; },
path_create_directory: ( fd: number, path_ptr: number, path_len: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.path) { return ERRNO_INVAL; }
const text = new TextDecoder(); const data = new Uint8Array(this.memory.buffer, path_ptr, path_len); const path = resolve(entry.path, text.decode(data));
try { Deno.mkdirSync(path); } catch (err) { return errno(err); }
return ERRNO_SUCCESS; },
path_filestat_get: ( fd: number, flags: number, path_ptr: number, path_len: number, buf_out: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.path) { return ERRNO_INVAL; }
const text = new TextDecoder(); const data = new Uint8Array(this.memory.buffer, path_ptr, path_len); const path = resolve(entry.path, text.decode(data));
const view = new DataView(this.memory.buffer);
try { const info = (flags & LOOKUPFLAGS_SYMLINK_FOLLOW) != 0 ? Deno.statSync(path) : Deno.lstatSync(path);
view.setBigUint64(buf_out, BigInt(info.dev ? info.dev : 0), true); buf_out += 8;
view.setBigUint64(buf_out, BigInt(info.ino ? info.ino : 0), true); buf_out += 8;
switch (true) { case info.isFile: view.setUint8(buf_out, FILETYPE_REGULAR_FILE); buf_out += 8; break;
case info.isDirectory: view.setUint8(buf_out, FILETYPE_DIRECTORY); buf_out += 8; break;
case info.isSymlink: view.setUint8(buf_out, FILETYPE_SYMBOLIC_LINK); buf_out += 8; break;
default: view.setUint8(buf_out, FILETYPE_UNKNOWN); buf_out += 8; break; }
view.setUint32(buf_out, Number(info.nlink), true); buf_out += 8;
view.setBigUint64(buf_out, BigInt(info.size), true); buf_out += 8;
view.setBigUint64( buf_out, BigInt(info.atime ? info.atime.getTime() * 1e6 : 0), true, ); buf_out += 8;
view.setBigUint64( buf_out, BigInt(info.mtime ? info.mtime.getTime() * 1e6 : 0), true, ); buf_out += 8;
view.setBigUint64( buf_out, BigInt(info.birthtime ? info.birthtime.getTime() * 1e6 : 0), true, ); buf_out += 8; } catch (err) { return errno(err); }
return ERRNO_SUCCESS; },
path_filestat_set_times: ( fd: number, flags: number, path_ptr: number, path_len: number, atim: bigint, mtim: bigint, fst_flags: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.path) { return ERRNO_INVAL; }
const text = new TextDecoder(); const data = new Uint8Array(this.memory.buffer, path_ptr, path_len); const path = resolve(entry.path, text.decode(data));
if ((fst_flags & FSTFLAGS_ATIM_NOW) == FSTFLAGS_ATIM_NOW) { atim = BigInt(Date.now()) * BigInt(1e6); }
if ((fst_flags & FSTFLAGS_MTIM_NOW) == FSTFLAGS_MTIM_NOW) { mtim = BigInt(Date.now()) * BigInt(1e6); }
try { Deno.utimeSync(path, Number(atim), Number(mtim)); } catch (err) { return errno(err); }
return ERRNO_SUCCESS; },
path_link: ( old_fd: number, old_flags: number, old_path_ptr: number, old_path_len: number, new_fd: number, new_path_ptr: number, new_path_len: number, ): number => { const old_entry = this.fds[old_fd]; const new_entry = this.fds[new_fd]; if (!old_entry || !new_entry) { return ERRNO_BADF; }
if (!old_entry.path || !new_entry.path) { return ERRNO_INVAL; }
const text = new TextDecoder(); const old_data = new Uint8Array( this.memory.buffer, old_path_ptr, old_path_len, ); const old_path = resolve(old_entry.path, text.decode(old_data)); const new_data = new Uint8Array( this.memory.buffer, new_path_ptr, new_path_len, ); const new_path = resolve(new_entry.path, text.decode(new_data));
try { Deno.linkSync(old_path, new_path); } catch (err) { return errno(err); }
return ERRNO_SUCCESS; },
path_open: ( fd: number, dirflags: number, path_ptr: number, path_len: number, oflags: number, fs_rights_base: bigint, fs_rights_inherting: bigint, fdflags: number, opened_fd_out: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.path) { return ERRNO_INVAL; }
const text = new TextDecoder(); const data = new Uint8Array(this.memory.buffer, path_ptr, path_len); const path = resolve(entry.path, text.decode(data));
if ((oflags & OFLAGS_DIRECTORY) !== 0) { // XXX (caspervonb) this isn't ideal as we can't get a rid for the // directory this way so there's no native fstat but Deno.open // doesn't work with directories on windows so we'll have to work // around it for now. try { const entries = Array.from(Deno.readDirSync(path)); const opened_fd = this.fds.push({ entries, path, }) - 1;
const view = new DataView(this.memory.buffer); view.setUint32(opened_fd_out, opened_fd, true); } catch (err) { return errno(err); }
return ERRNO_SUCCESS; }
const options = { read: false, write: false, append: false, truncate: false, create: false, createNew: false, };
if ((oflags & OFLAGS_CREAT) !== 0) { options.create = true; options.write = true; }
if ((oflags & OFLAGS_EXCL) !== 0) { options.createNew = true; }
if ((oflags & OFLAGS_TRUNC) !== 0) { options.truncate = true; options.write = true; }
const read = ( RIGHTS_FD_READ | RIGHTS_FD_READDIR );
if ((fs_rights_base & read) != 0n) { options.read = true; }
const write = ( RIGHTS_FD_DATASYNC | RIGHTS_FD_WRITE | RIGHTS_FD_ALLOCATE | RIGHTS_FD_FILESTAT_SET_SIZE );
if ((fs_rights_base & write) != 0n) { options.write = true; }
if ((fdflags & FDFLAGS_APPEND) != 0) { options.append = true; }
if ((fdflags & FDFLAGS_DSYNC) != 0) { // TODO (caspervonb) review if we can emulate this. }
if ((fdflags & FDFLAGS_NONBLOCK) != 0) { // TODO (caspervonb) review if we can emulate this. }
if ((fdflags & FDFLAGS_RSYNC) != 0) { // TODO (caspervonb) review if we can emulate this. }
if ((fdflags & FDFLAGS_SYNC) != 0) { // TODO (caspervonb) review if we can emulate this. }
if (!options.read && !options.write && !options.truncate) { options.read = true; }
try { const handle = Deno.openSync(path, options); const opened_fd = this.fds.push({ handle, path, }) - 1;
const view = new DataView(this.memory.buffer); view.setUint32(opened_fd_out, opened_fd, true); } catch (err) { return errno(err); }
return ERRNO_SUCCESS; },
path_readlink: ( fd: number, path_ptr: number, path_len: number, buf_ptr: number, buf_len: number, bufused_out: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.path) { return ERRNO_INVAL; }
const view = new DataView(this.memory.buffer); const heap = new Uint8Array(this.memory.buffer);
const data = new Uint8Array(this.memory.buffer, path_ptr, path_len); const path = resolve(entry.path, new TextDecoder().decode(data));
try { const link = Deno.readLinkSync(path); const data = new TextEncoder().encode(link); heap.set(new Uint8Array(data, 0, buf_len), buf_ptr);
const bufused = Math.min(data.byteLength, buf_len); view.setUint32(bufused_out, bufused, true); } catch (err) { return errno(err); }
return ERRNO_SUCCESS; },
path_remove_directory: ( fd: number, path_ptr: number, path_len: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.path) { return ERRNO_INVAL; }
const text = new TextDecoder(); const data = new Uint8Array(this.memory.buffer, path_ptr, path_len); const path = resolve(entry.path, text.decode(data));
try { if (!Deno.statSync(path).isDirectory) { return ERRNO_NOTDIR; }
Deno.removeSync(path); } catch (err) { return errno(err); }
return ERRNO_SUCCESS; },
path_rename: ( fd: number, old_path_ptr: number, old_path_len: number, new_fd: number, new_path_ptr: number, new_path_len: number, ): number => { const old_entry = this.fds[fd]; const new_entry = this.fds[new_fd]; if (!old_entry || !new_entry) { return ERRNO_BADF; }
if (!old_entry.path || !new_entry.path) { return ERRNO_INVAL; }
const text = new TextDecoder(); const old_data = new Uint8Array( this.memory.buffer, old_path_ptr, old_path_len, ); const old_path = resolve(old_entry.path, text.decode(old_data)); const new_data = new Uint8Array( this.memory.buffer, new_path_ptr, new_path_len, ); const new_path = resolve(new_entry.path, text.decode(new_data));
try { Deno.renameSync(old_path, new_path); } catch (err) { return errno(err); }
return ERRNO_SUCCESS; },
path_symlink: ( old_path_ptr: number, old_path_len: number, fd: number, new_path_ptr: number, new_path_len: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.path) { return ERRNO_INVAL; }
const text = new TextDecoder(); const old_data = new Uint8Array( this.memory.buffer, old_path_ptr, old_path_len, ); const old_path = text.decode(old_data); const new_data = new Uint8Array( this.memory.buffer, new_path_ptr, new_path_len, ); const new_path = resolve(entry.path, text.decode(new_data));
try { Deno.symlinkSync(old_path, new_path); } catch (err) { return errno(err); }
return ERRNO_SUCCESS; },
path_unlink_file: ( fd: number, path_ptr: number, path_len: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.path) { return ERRNO_INVAL; }
const text = new TextDecoder(); const data = new Uint8Array(this.memory.buffer, path_ptr, path_len); const path = resolve(entry.path, text.decode(data));
try { Deno.removeSync(path); } catch (err) { return errno(err); }
return ERRNO_SUCCESS; },
poll_oneoff: ( in_ptr: number, out_ptr: number, nsubscriptions: number, nevents_out: number, ): number => { return ERRNO_NOSYS; },
proc_exit: (rval: number): never => { Deno.exit(rval); },
proc_raise: (sig: number): number => { return ERRNO_NOSYS; },
sched_yield: (): number => { return ERRNO_SUCCESS; },
random_get: (buf_ptr: number, buf_len: number): number => { const buffer = new Uint8Array(this.memory.buffer, buf_ptr, buf_len); crypto.getRandomValues(buffer);
return ERRNO_SUCCESS; },
sock_recv: ( fd: number, ri_data_ptr: number, ri_data_len: number, ri_flags: number, ro_datalen_out: number, ro_flags_out: number, ): number => { return ERRNO_NOSYS; },
sock_send: ( fd: number, si_data_ptr: number, si_data_len: number, si_flags: number, so_datalen_out: number, ): number => { return ERRNO_NOSYS; },
sock_shutdown: (fd: number, how: number): number => { return ERRNO_NOSYS; }, }; }}