Skip to content

Commit 6392c62

Browse files
Merge pull request #5 from uswriting/mfs
feat: memory file system
2 parents df2d317 + fba33d3 commit 6392c62

File tree

4 files changed

+1146
-286
lines changed

4 files changed

+1146
-286
lines changed

src/abi.ts

+200-147
Original file line numberDiff line numberDiff line change
@@ -1,156 +1,209 @@
11
export class WASIAbi {
2-
/**
3-
* No error occurred. System call completed successfully.
4-
*/
5-
static readonly WASI_ESUCCESS = 0;
6-
7-
/**
8-
* Bad file descriptor.
9-
*/
10-
static readonly WASI_ERRNO_BADF = 8;
11-
12-
/**
13-
* Function not supported.
14-
*/
15-
static readonly WASI_ENOSYS = 52;
16-
17-
/**
18-
* The clock measuring real time. Time value zero corresponds with 1970-01-01T00:00:00Z.
19-
*/
20-
static readonly WASI_CLOCK_REALTIME = 0;
21-
/**
22-
* The store-wide monotonic clock, which is defined as a clock measuring real time,
23-
* whose value cannot be adjusted and which cannot have negative clock jumps.
24-
* The epoch of this clock is undefined. The absolute time value of this clock therefore has no meaning.
25-
*/
26-
static readonly WASI_CLOCK_MONOTONIC = 1;
27-
28-
/**
29-
* The file descriptor or file refers to a character device inode.
30-
*/
31-
static readonly WASI_FILETYPE_CHARACTER_DEVICE = 2;
32-
33-
static readonly IMPORT_FUNCTIONS = [
34-
"args_get",
35-
"args_sizes_get",
36-
37-
"clock_res_get",
38-
"clock_time_get",
39-
40-
"environ_get",
41-
"environ_sizes_get",
42-
43-
"fd_advise",
44-
"fd_allocate",
45-
"fd_close",
46-
"fd_datasync",
47-
"fd_fdstat_get",
48-
"fd_fdstat_set_flags",
49-
"fd_fdstat_set_rights",
50-
"fd_filestat_get",
51-
"fd_filestat_set_size",
52-
"fd_filestat_set_times",
53-
"fd_pread",
54-
"fd_prestat_dir_name",
55-
"fd_prestat_get",
56-
"fd_pwrite",
57-
"fd_read",
58-
"fd_readdir",
59-
"fd_renumber",
60-
"fd_seek",
61-
"fd_sync",
62-
"fd_tell",
63-
"fd_write",
64-
65-
"path_create_directory",
66-
"path_filestat_get",
67-
"path_filestat_set_times",
68-
"path_link",
69-
"path_open",
70-
"path_readlink",
71-
"path_remove_directory",
72-
"path_rename",
73-
"path_symlink",
74-
"path_unlink_file",
75-
76-
"poll_oneoff",
77-
78-
"proc_exit",
79-
"proc_raise",
80-
81-
"random_get",
82-
83-
"sched_yield",
84-
85-
"sock_accept",
86-
"sock_recv",
87-
"sock_send",
88-
"sock_shutdown",
89-
]
90-
91-
private encoder: TextEncoder;
92-
93-
constructor() {
94-
this.encoder = new TextEncoder();
95-
}
96-
97-
writeString(memory: DataView, value: string, offset: number): number {
98-
const bytes = this.encoder.encode(value);
99-
const buffer = new Uint8Array(memory.buffer, offset, bytes.length);
100-
buffer.set(bytes);
101-
return bytes.length;
102-
}
103-
byteLength(value: string): number {
104-
return this.encoder.encode(value).length;
105-
}
106-
107-
108-
private static readonly iovec_t = {
109-
size: 8,
110-
bufferOffset: 0,
111-
lengthOffset: 4,
112-
}
113-
114-
iovViews(memory: DataView, iovs: number, iovsLen: number): Uint8Array[] {
115-
const iovsBuffers: Uint8Array[] = [];
116-
let iovsOffset = iovs;
117-
118-
for (let i = 0; i < iovsLen; i++) {
119-
const offset = memory.getUint32(iovsOffset + WASIAbi.iovec_t.bufferOffset, true);
120-
const len = memory.getUint32(iovsOffset + WASIAbi.iovec_t.lengthOffset, true);
121-
122-
iovsBuffers.push(new Uint8Array(memory.buffer, offset, len));
123-
iovsOffset += WASIAbi.iovec_t.size;
124-
}
125-
return iovsBuffers;
126-
}
127-
128-
writeFilestat(memory: DataView, ptr: number, filetype: number): void {
129-
memory.setBigUint64(ptr, /* dev */ BigInt(0), true);
130-
memory.setBigUint64(ptr + 8, /* ino */ BigInt(0), true);
131-
memory.setUint8(ptr + 16, filetype);
132-
memory.setUint32(ptr + 24, /* nlink */ 0, true);
133-
memory.setBigUint64(ptr + 32, /* size */ BigInt(0), true);
134-
memory.setBigUint64(ptr + 40, /* atim */ BigInt(0), true);
135-
memory.setBigUint64(ptr + 48, /* mtim */ BigInt(0), true);
136-
}
137-
138-
writeFdstat(memory: DataView, ptr: number, filetype: number, flags: number): void {
139-
memory.setUint8(ptr, filetype);
140-
memory.setUint16(ptr + 2, flags, true);
141-
memory.setBigUint64(ptr + 8, /* rights_base */ BigInt(0), true);
142-
memory.setBigUint64(ptr + 16, /* rights_inheriting */ BigInt(0), true);
2+
/**
3+
* No error occurred. System call completed successfully.
4+
*/
5+
static readonly WASI_ESUCCESS = 0;
6+
7+
/**
8+
* Bad file descriptor.
9+
*/
10+
static readonly WASI_ERRNO_BADF = 8;
11+
12+
/**
13+
* Function not supported.
14+
*/
15+
static readonly WASI_ENOSYS = 52;
16+
17+
/**
18+
* The clock measuring real time. Time value zero corresponds with 1970-01-01T00:00:00Z.
19+
*/
20+
static readonly WASI_CLOCK_REALTIME = 0;
21+
/**
22+
* The store-wide monotonic clock, which is defined as a clock measuring real time,
23+
* whose value cannot be adjusted and which cannot have negative clock jumps.
24+
* The epoch of this clock is undefined. The absolute time value of this clock therefore has no meaning.
25+
*/
26+
static readonly WASI_CLOCK_MONOTONIC = 1;
27+
28+
/**
29+
* The file descriptor or file refers to a directory.
30+
*/
31+
static readonly WASI_ERRNO_ISDIR = 31;
32+
/**
33+
* Invalid argument.
34+
*/
35+
static readonly WASI_ERRNO_INVAL = 28;
36+
/**
37+
* Not a directory or a symbolic link to a directory.
38+
*/
39+
static readonly WASI_ERRNO_NOTDIR = 54;
40+
/**
41+
* No such file or directory.
42+
*/
43+
static readonly WASI_ERRNO_NOENT = 44;
44+
/**
45+
* File exists.
46+
*/
47+
static readonly WASI_ERRNO_EXIST = 20;
48+
/**
49+
* I/O error.
50+
*/
51+
static readonly WASI_ERRNO_IO = 29;
52+
53+
/**
54+
* The file descriptor or file refers to a character device inode.
55+
*/
56+
static readonly WASI_FILETYPE_CHARACTER_DEVICE = 2;
57+
/**
58+
* The file descriptor or file refers to a directory inode.
59+
*/
60+
static readonly WASI_FILETYPE_DIRECTORY = 3;
61+
/**
62+
* The file descriptor or file refers to a regular file inode.
63+
*/
64+
static readonly WASI_FILETYPE_REGULAR_FILE = 4;
65+
66+
static readonly IMPORT_FUNCTIONS = [
67+
"args_get",
68+
"args_sizes_get",
69+
70+
"clock_res_get",
71+
"clock_time_get",
72+
73+
"environ_get",
74+
"environ_sizes_get",
75+
76+
"fd_advise",
77+
"fd_allocate",
78+
"fd_close",
79+
"fd_datasync",
80+
"fd_fdstat_get",
81+
"fd_fdstat_set_flags",
82+
"fd_fdstat_set_rights",
83+
"fd_filestat_get",
84+
"fd_filestat_set_size",
85+
"fd_filestat_set_times",
86+
"fd_pread",
87+
"fd_prestat_dir_name",
88+
"fd_prestat_get",
89+
"fd_pwrite",
90+
"fd_read",
91+
"fd_readdir",
92+
"fd_renumber",
93+
"fd_seek",
94+
"fd_sync",
95+
"fd_tell",
96+
"fd_write",
97+
98+
"path_create_directory",
99+
"path_filestat_get",
100+
"path_filestat_set_times",
101+
"path_link",
102+
"path_open",
103+
"path_readlink",
104+
"path_remove_directory",
105+
"path_rename",
106+
"path_symlink",
107+
"path_unlink_file",
108+
109+
"poll_oneoff",
110+
111+
"proc_exit",
112+
"proc_raise",
113+
114+
"random_get",
115+
116+
"sched_yield",
117+
118+
"sock_accept",
119+
"sock_recv",
120+
"sock_send",
121+
"sock_shutdown",
122+
];
123+
124+
private encoder: TextEncoder;
125+
private decoder: TextDecoder;
126+
127+
constructor() {
128+
this.encoder = new TextEncoder();
129+
this.decoder = new TextDecoder();
130+
}
131+
132+
writeString(memory: DataView, value: string, offset: number): number {
133+
const bytes = this.encoder.encode(value);
134+
const buffer = new Uint8Array(memory.buffer, offset, bytes.length);
135+
buffer.set(bytes);
136+
return bytes.length;
137+
}
138+
139+
readString(memory: DataView, ptr: number, len: number): string {
140+
const buffer = new Uint8Array(memory.buffer, ptr, len);
141+
return this.decoder.decode(buffer);
142+
}
143+
144+
byteLength(value: string): number {
145+
return this.encoder.encode(value).length;
146+
}
147+
148+
private static readonly iovec_t = {
149+
size: 8,
150+
bufferOffset: 0,
151+
lengthOffset: 4,
152+
};
153+
154+
iovViews(memory: DataView, iovs: number, iovsLen: number): Uint8Array[] {
155+
const iovsBuffers: Uint8Array[] = [];
156+
let iovsOffset = iovs;
157+
158+
for (let i = 0; i < iovsLen; i++) {
159+
const offset = memory.getUint32(
160+
iovsOffset + WASIAbi.iovec_t.bufferOffset,
161+
true
162+
);
163+
const len = memory.getUint32(
164+
iovsOffset + WASIAbi.iovec_t.lengthOffset,
165+
true
166+
);
167+
168+
iovsBuffers.push(new Uint8Array(memory.buffer, offset, len));
169+
iovsOffset += WASIAbi.iovec_t.size;
143170
}
171+
return iovsBuffers;
172+
}
173+
174+
writeFilestat(memory: DataView, ptr: number, filetype: number): void {
175+
memory.setBigUint64(ptr, /* dev */ BigInt(0), true);
176+
memory.setBigUint64(ptr + 8, /* ino */ BigInt(0), true);
177+
memory.setUint8(ptr + 16, filetype);
178+
memory.setUint32(ptr + 24, /* nlink */ 0, true);
179+
memory.setBigUint64(ptr + 32, /* size */ BigInt(0), true);
180+
memory.setBigUint64(ptr + 40, /* atim */ BigInt(0), true);
181+
memory.setBigUint64(ptr + 48, /* mtim */ BigInt(0), true);
182+
}
183+
184+
writeFdstat(
185+
memory: DataView,
186+
ptr: number,
187+
filetype: number,
188+
flags: number
189+
): void {
190+
memory.setUint8(ptr, filetype);
191+
memory.setUint16(ptr + 2, flags, true);
192+
memory.setBigUint64(ptr + 8, /* rights_base */ BigInt(0), true);
193+
memory.setBigUint64(ptr + 16, /* rights_inheriting */ BigInt(0), true);
194+
}
144195
}
145196

146197
/**
147198
* An exception that is thrown when the process exits.
148199
**/
149200
export class WASIProcExit {
150-
constructor(public readonly code: number) { }
151-
152-
/** @deprecated Use 'code' instead.
153-
* Has been renamed to have loose compatibility
154-
* with other implementations **/
155-
get exitCode() { return this.code; }
201+
constructor(public readonly code: number) {}
202+
203+
/** @deprecated Use 'code' instead.
204+
* Has been renamed to have loose compatibility
205+
* with other implementations **/
206+
get exitCode() {
207+
return this.code;
208+
}
156209
}

0 commit comments

Comments
 (0)