@live-codes/pascal-wasm 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +501 -0
- package/README.md +278 -0
- package/THIRD-PARTY-NOTICES.md +48 -0
- package/assets/pas2js.wasm +0 -0
- package/assets/rtl/Rtl.BrowserLoadHelper.pas +179 -0
- package/assets/rtl/browserconsole.pas +190 -0
- package/assets/rtl/classes.pas +11371 -0
- package/assets/rtl/js.pas +2211 -0
- package/assets/rtl/manifest.json +19 -0
- package/assets/rtl/math.pas +903 -0
- package/assets/rtl/p2jsres.pp +334 -0
- package/assets/rtl/rtl.js +1563 -0
- package/assets/rtl/rtlconsts.pas +97 -0
- package/assets/rtl/simplelinkedlist.pas +152 -0
- package/assets/rtl/system.pas +1166 -0
- package/assets/rtl/sysutils.pas +8959 -0
- package/assets/rtl/types.pas +2296 -0
- package/assets/rtl/typinfo.pas +1680 -0
- package/assets/rtl/web.pas +3586 -0
- package/assets/rtl/weborworker.pas +2101 -0
- package/dist/pascal-wasm.iife.min.js +6 -0
- package/dist/pascal-wasm.iife.min.js.map +7 -0
- package/package.json +54 -0
- package/src/assets.js +119 -0
- package/src/compiler.js +142 -0
- package/src/config.js +24 -0
- package/src/iife.js +27 -0
- package/src/index.js +130 -0
- package/src/vendor/browser_wasi_shim/debug.js +1 -0
- package/src/vendor/browser_wasi_shim/fd.js +1 -0
- package/src/vendor/browser_wasi_shim/fs_mem.js +1 -0
- package/src/vendor/browser_wasi_shim/fs_opfs.js +1 -0
- package/src/vendor/browser_wasi_shim/index.js +1 -0
- package/src/vendor/browser_wasi_shim/strace.js +1 -0
- package/src/vendor/browser_wasi_shim/wasi.js +1 -0
- package/src/vendor/browser_wasi_shim/wasi_defs.js +1 -0
- package/types/index.d.ts +89 -0
package/src/config.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Package-wide defaults, settable with `configure()`. Useful where options
|
|
2
|
+
// cannot be passed per call — most notably in a classic worker, where the bundle
|
|
3
|
+
// is loaded with `importScripts()` and only a global API is available.
|
|
4
|
+
|
|
5
|
+
const config = {
|
|
6
|
+
baseUrl: null,
|
|
7
|
+
flags: [],
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Set defaults for every subsequent compile.
|
|
12
|
+
*
|
|
13
|
+
* @param {object} [options]
|
|
14
|
+
* @param {string|URL} [options.baseUrl] Where `pas2js.wasm` and `rtl/` live.
|
|
15
|
+
* @param {string[]} [options.flags] Extra compiler options to always pass.
|
|
16
|
+
*/
|
|
17
|
+
export function configure(options = {}) {
|
|
18
|
+
if (options.baseUrl !== undefined) config.baseUrl = options.baseUrl;
|
|
19
|
+
if (options.flags !== undefined) config.flags = [...options.flags];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function getConfig() {
|
|
23
|
+
return config;
|
|
24
|
+
}
|
package/src/iife.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Classic-script entry point, built into `dist/pascal-wasm.iife.min.js`.
|
|
2
|
+
//
|
|
3
|
+
// Exposes the same API as the ES module on a global named `pascalWasm`, so it
|
|
4
|
+
// can be pulled into a non-module worker:
|
|
5
|
+
//
|
|
6
|
+
// importScripts('…/pascal-wasm.iife.min.js');
|
|
7
|
+
// pascalWasm.configure({ baseUrl: '…/assets/' });
|
|
8
|
+
// pascalWasm.compile('begin Writeln(42) end.').then(console.log);
|
|
9
|
+
//
|
|
10
|
+
// This build has no module URL to resolve the assets against, so `baseUrl` is
|
|
11
|
+
// required — see `assets.js`.
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
compile,
|
|
15
|
+
createCompiler,
|
|
16
|
+
defaultBaseUrl,
|
|
17
|
+
configure,
|
|
18
|
+
parseDiagnostics,
|
|
19
|
+
} from './index.js';
|
|
20
|
+
|
|
21
|
+
globalThis.pascalWasm = {
|
|
22
|
+
compile,
|
|
23
|
+
createCompiler,
|
|
24
|
+
defaultBaseUrl,
|
|
25
|
+
configure,
|
|
26
|
+
parseDiagnostics,
|
|
27
|
+
};
|
package/src/index.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// @live-codes/pascal-wasm — the Free Pascal `pas2js` compiler compiled to
|
|
2
|
+
// WebAssembly, for use in browsers and Web Workers. Compilation happens entirely
|
|
3
|
+
// on the client; nothing is sent to a server.
|
|
4
|
+
//
|
|
5
|
+
// import { compile } from '@live-codes/pascal-wasm';
|
|
6
|
+
//
|
|
7
|
+
// const { js, diagnostics } = await compile('begin Writeln(42) end.');
|
|
8
|
+
|
|
9
|
+
import { defaultBaseUrl, loadAssets } from './assets.js';
|
|
10
|
+
import { configure, getConfig } from './config.js';
|
|
11
|
+
import { runCompiler } from './compiler.js';
|
|
12
|
+
|
|
13
|
+
export { configure, defaultBaseUrl };
|
|
14
|
+
|
|
15
|
+
// One compiler per asset location: loading is expensive (a ~9 MB binary) and the
|
|
16
|
+
// result is reusable, so `compile()` shares it across calls.
|
|
17
|
+
const compilers = new Map();
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Create a reusable compiler.
|
|
21
|
+
*
|
|
22
|
+
* @param {import('../types/index.d.ts').CompilerOptions} [options]
|
|
23
|
+
* @returns {Promise<import('../types/index.d.ts').Compiler>}
|
|
24
|
+
*/
|
|
25
|
+
export async function createCompiler(options = {}) {
|
|
26
|
+
const key = cacheKey(options);
|
|
27
|
+
let pending = compilers.get(key);
|
|
28
|
+
if (!pending) {
|
|
29
|
+
pending = loadAssets(options);
|
|
30
|
+
compilers.set(key, pending);
|
|
31
|
+
// Never cache a failed load.
|
|
32
|
+
pending.catch(() => compilers.delete(key));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const assets = await pending;
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
baseUrl: assets.baseUrl,
|
|
39
|
+
compile: (source, compileOptions = {}) => {
|
|
40
|
+
const { flags, ...rest } = compileOptions;
|
|
41
|
+
return runCompiler({
|
|
42
|
+
source,
|
|
43
|
+
wasm: assets.wasm,
|
|
44
|
+
rtl: assets.rtl,
|
|
45
|
+
...rest,
|
|
46
|
+
flags: mergeFlags(flags),
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
version: async () => {
|
|
50
|
+
const { diagnostics } = await runCompiler({
|
|
51
|
+
wasm: assets.wasm,
|
|
52
|
+
rtl: assets.rtl,
|
|
53
|
+
flags: ['-iV'], // write the short compiler version and halt
|
|
54
|
+
});
|
|
55
|
+
return diagnostics.trim();
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Compile a single program, reusing a shared compiler.
|
|
62
|
+
*
|
|
63
|
+
* @param {string} source
|
|
64
|
+
* @param {import('../types/index.d.ts').CompileOptions} [options]
|
|
65
|
+
* @returns {Promise<import('../types/index.d.ts').CompileResult>}
|
|
66
|
+
*/
|
|
67
|
+
export async function compile(source, options = {}) {
|
|
68
|
+
const compiler = await createCompiler(options);
|
|
69
|
+
return compiler.compile(source, options);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Turn the compiler's text output into structured messages.
|
|
74
|
+
*
|
|
75
|
+
* Lines look like `main.pp(5,11) Error: identifier not found "x"`, alongside
|
|
76
|
+
* informational chatter which is ignored.
|
|
77
|
+
*
|
|
78
|
+
* @param {string} diagnostics
|
|
79
|
+
* @returns {import('../types/index.d.ts').DiagnosticMessage[]}
|
|
80
|
+
*/
|
|
81
|
+
export function parseDiagnostics(diagnostics) {
|
|
82
|
+
const messages = [];
|
|
83
|
+
for (const raw of String(diagnostics ?? '').split('\n')) {
|
|
84
|
+
const line = raw.trim();
|
|
85
|
+
if (!line) continue;
|
|
86
|
+
|
|
87
|
+
const located = /^(.*?)\((\d+),(\d+)\)\s+(Error|Warning|Hint|Note)\s*:\s*(.*)$/.exec(line);
|
|
88
|
+
if (located) {
|
|
89
|
+
messages.push({
|
|
90
|
+
file: located[1],
|
|
91
|
+
line: Number(located[2]),
|
|
92
|
+
column: Number(located[3]),
|
|
93
|
+
severity: located[4].toLowerCase(),
|
|
94
|
+
message: located[5],
|
|
95
|
+
});
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const fatal = /^Fatal\s*:\s*(.*)$/.exec(line);
|
|
100
|
+
if (fatal) {
|
|
101
|
+
messages.push({
|
|
102
|
+
file: null,
|
|
103
|
+
line: null,
|
|
104
|
+
column: null,
|
|
105
|
+
severity: 'fatal',
|
|
106
|
+
message: fatal[1],
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return messages;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Options passed per compile are appended to the configured defaults. */
|
|
114
|
+
function mergeFlags(flags) {
|
|
115
|
+
const { flags: configured } = getConfig();
|
|
116
|
+
if (!configured.length) return flags ?? [];
|
|
117
|
+
return [...configured, ...(flags ?? [])];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function cacheKey({ baseUrl, wasmUrl, rtlUrl }) {
|
|
121
|
+
let key = baseUrl;
|
|
122
|
+
if (!key) {
|
|
123
|
+
try {
|
|
124
|
+
key = defaultBaseUrl().href;
|
|
125
|
+
} catch {
|
|
126
|
+
key = 'default';
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return [key, wasmUrl ?? '', rtlUrl ?? ''].join('|');
|
|
130
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
let Debug=class Debug{enable(enabled){this.log=createLogger(enabled===undefined?true:enabled,this.prefix)}get enabled(){return this.isEnabled}constructor(isEnabled){this.isEnabled=isEnabled;this.prefix="wasi:";this.enable(isEnabled)}};function createLogger(enabled,prefix){if(enabled){const a=console.log.bind(console,"%c%s","color: #265BA0",prefix);return a}else{return()=>{}}}export const debug=new Debug(false);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import*as wasi from"./wasi_defs.js";export class Fd{fd_allocate(offset,len){return wasi.ERRNO_NOTSUP}fd_close(){return 0}fd_fdstat_get(){return{ret:wasi.ERRNO_NOTSUP,fdstat:null}}fd_fdstat_set_flags(flags){return wasi.ERRNO_NOTSUP}fd_fdstat_set_rights(fs_rights_base,fs_rights_inheriting){return wasi.ERRNO_NOTSUP}fd_filestat_get(){return{ret:wasi.ERRNO_NOTSUP,filestat:null}}fd_filestat_set_size(size){return wasi.ERRNO_NOTSUP}fd_filestat_set_times(atim,mtim,fst_flags){return wasi.ERRNO_NOTSUP}fd_pread(size,offset){return{ret:wasi.ERRNO_NOTSUP,data:new Uint8Array}}fd_prestat_get(){return{ret:wasi.ERRNO_NOTSUP,prestat:null}}fd_pwrite(data,offset){return{ret:wasi.ERRNO_NOTSUP,nwritten:0}}fd_read(size){return{ret:wasi.ERRNO_NOTSUP,data:new Uint8Array}}fd_readdir_single(cookie){return{ret:wasi.ERRNO_NOTSUP,dirent:null}}fd_seek(offset,whence){return{ret:wasi.ERRNO_NOTSUP,offset:0n}}fd_sync(){return 0}fd_tell(){return{ret:wasi.ERRNO_NOTSUP,offset:0n}}fd_write(data){return{ret:wasi.ERRNO_NOTSUP,nwritten:0}}path_create_directory(path){return wasi.ERRNO_NOTSUP}path_filestat_get(flags,path){return{ret:wasi.ERRNO_NOTSUP,filestat:null}}path_filestat_set_times(flags,path,atim,mtim,fst_flags){return wasi.ERRNO_NOTSUP}path_link(path,inode,allow_dir){return wasi.ERRNO_NOTSUP}path_unlink(path){return{ret:wasi.ERRNO_NOTSUP,inode_obj:null}}path_lookup(path,dirflags){return{ret:wasi.ERRNO_NOTSUP,inode_obj:null}}path_open(dirflags,path,oflags,fs_rights_base,fs_rights_inheriting,fd_flags){return{ret:wasi.ERRNO_NOTDIR,fd_obj:null}}path_readlink(path){return{ret:wasi.ERRNO_NOTSUP,data:null}}path_remove_directory(path){return wasi.ERRNO_NOTSUP}path_rename(old_path,new_fd,new_path){return wasi.ERRNO_NOTSUP}path_unlink_file(path){return wasi.ERRNO_NOTSUP}}export class Inode{static issue_ino(){return Inode.next_ino++}static root_ino(){return 0n}constructor(){this.ino=Inode.issue_ino()}}Inode.next_ino=1n;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{debug}from"./debug.js";import*as wasi from"./wasi_defs.js";import{Fd,Inode}from"./fd.js";export class OpenFile extends Fd{fd_allocate(offset,len){if(this.file.size>offset+len){}else{const new_data=new Uint8Array(Number(offset+len));new_data.set(this.file.data,0);this.file.data=new_data}return wasi.ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new wasi.Fdstat(wasi.FILETYPE_REGULAR_FILE,0)}}fd_filestat_set_size(size){if(this.file.size>size){this.file.data=new Uint8Array(this.file.data.buffer.slice(0,Number(size)))}else{const new_data=new Uint8Array(Number(size));new_data.set(this.file.data,0);this.file.data=new_data}return wasi.ERRNO_SUCCESS}fd_read(size){const slice=this.file.data.slice(Number(this.file_pos),Number(this.file_pos+BigInt(size)));this.file_pos+=BigInt(slice.length);return{ret:0,data:slice}}fd_pread(size,offset){const slice=this.file.data.slice(Number(offset),Number(offset+BigInt(size)));return{ret:0,data:slice}}fd_seek(offset,whence){let calculated_offset;switch(whence){case wasi.WHENCE_SET:calculated_offset=offset;break;case wasi.WHENCE_CUR:calculated_offset=this.file_pos+offset;break;case wasi.WHENCE_END:calculated_offset=BigInt(this.file.data.byteLength)+offset;break;default:return{ret:wasi.ERRNO_INVAL,offset:0n}}if(calculated_offset<0){return{ret:wasi.ERRNO_INVAL,offset:0n}}this.file_pos=calculated_offset;return{ret:0,offset:this.file_pos}}fd_tell(){return{ret:0,offset:this.file_pos}}fd_write(data){if(this.file.readonly)return{ret:wasi.ERRNO_BADF,nwritten:0};if(this.file_pos+BigInt(data.byteLength)>this.file.size){const old=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(data.byteLength)));this.file.data.set(old)}this.file.data.set(data,Number(this.file_pos));this.file_pos+=BigInt(data.byteLength);return{ret:0,nwritten:data.byteLength}}fd_pwrite(data,offset){if(this.file.readonly)return{ret:wasi.ERRNO_BADF,nwritten:0};if(offset+BigInt(data.byteLength)>this.file.size){const old=this.file.data;this.file.data=new Uint8Array(Number(offset+BigInt(data.byteLength)));this.file.data.set(old)}this.file.data.set(data,Number(offset));return{ret:0,nwritten:data.byteLength}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(file){super();this.file_pos=0n;this.file=file}}export class OpenDirectory extends Fd{fd_seek(offset,whence){return{ret:wasi.ERRNO_BADF,offset:0n}}fd_tell(){return{ret:wasi.ERRNO_BADF,offset:0n}}fd_allocate(offset,len){return wasi.ERRNO_BADF}fd_fdstat_get(){return{ret:0,fdstat:new wasi.Fdstat(wasi.FILETYPE_DIRECTORY,0)}}fd_readdir_single(cookie){if(debug.enabled){debug.log("readdir_single",cookie);debug.log(cookie,this.dir.contents.keys())}if(cookie==0n){return{ret:wasi.ERRNO_SUCCESS,dirent:new wasi.Dirent(1n,this.dir.ino,".",wasi.FILETYPE_DIRECTORY)}}else if(cookie==1n){return{ret:wasi.ERRNO_SUCCESS,dirent:new wasi.Dirent(2n,this.dir.parent_ino(),"..",wasi.FILETYPE_DIRECTORY)}}if(cookie>=BigInt(this.dir.contents.size)+2n){return{ret:0,dirent:null}}const[name,entry]=Array.from(this.dir.contents.entries())[Number(cookie-2n)];return{ret:0,dirent:new wasi.Dirent(cookie+1n,entry.ino,name,entry.stat().filetype)}}path_filestat_get(flags,path_str){const{ret:path_err,path}=Path.from(path_str);if(path==null){return{ret:path_err,filestat:null}}const{ret,entry}=this.dir.get_entry_for_path(path);if(entry==null){return{ret,filestat:null}}return{ret:0,filestat:entry.stat()}}path_lookup(path_str,dirflags){const{ret:path_ret,path}=Path.from(path_str);if(path==null){return{ret:path_ret,inode_obj:null}}const{ret,entry}=this.dir.get_entry_for_path(path);if(entry==null){return{ret,inode_obj:null}}return{ret:wasi.ERRNO_SUCCESS,inode_obj:entry}}path_open(dirflags,path_str,oflags,fs_rights_base,fs_rights_inheriting,fd_flags){const{ret:path_ret,path}=Path.from(path_str);if(path==null){return{ret:path_ret,fd_obj:null}}let{ret,entry}=this.dir.get_entry_for_path(path);if(entry==null){if(ret!=wasi.ERRNO_NOENT){return{ret,fd_obj:null}}if((oflags&wasi.OFLAGS_CREAT)==wasi.OFLAGS_CREAT){const{ret,entry:new_entry}=this.dir.create_entry_for_path(path_str,(oflags&wasi.OFLAGS_DIRECTORY)==wasi.OFLAGS_DIRECTORY);if(new_entry==null){return{ret,fd_obj:null}}entry=new_entry}else{return{ret:wasi.ERRNO_NOENT,fd_obj:null}}}else if((oflags&wasi.OFLAGS_EXCL)==wasi.OFLAGS_EXCL){return{ret:wasi.ERRNO_EXIST,fd_obj:null}}if((oflags&wasi.OFLAGS_DIRECTORY)==wasi.OFLAGS_DIRECTORY&&entry.stat().filetype!==wasi.FILETYPE_DIRECTORY){return{ret:wasi.ERRNO_NOTDIR,fd_obj:null}}return entry.path_open(oflags,fs_rights_base,fd_flags)}path_create_directory(path){return this.path_open(0,path,wasi.OFLAGS_CREAT|wasi.OFLAGS_DIRECTORY,0n,0n,0).ret}path_link(path_str,inode,allow_dir){const{ret:path_ret,path}=Path.from(path_str);if(path==null){return path_ret}if(path.is_dir){return wasi.ERRNO_NOENT}const{ret:parent_ret,parent_entry,filename,entry}=this.dir.get_parent_dir_and_entry_for_path(path,true);if(parent_entry==null||filename==null){return parent_ret}if(entry!=null){const source_is_dir=inode.stat().filetype==wasi.FILETYPE_DIRECTORY;const target_is_dir=entry.stat().filetype==wasi.FILETYPE_DIRECTORY;if(source_is_dir&&target_is_dir){if(allow_dir&&entry instanceof Directory){if(entry.contents.size==0){}else{return wasi.ERRNO_NOTEMPTY}}else{return wasi.ERRNO_EXIST}}else if(source_is_dir&&!target_is_dir){return wasi.ERRNO_NOTDIR}else if(!source_is_dir&&target_is_dir){return wasi.ERRNO_ISDIR}else if(inode.stat().filetype==wasi.FILETYPE_REGULAR_FILE&&entry.stat().filetype==wasi.FILETYPE_REGULAR_FILE){}else{return wasi.ERRNO_EXIST}}if(!allow_dir&&inode.stat().filetype==wasi.FILETYPE_DIRECTORY){return wasi.ERRNO_PERM}parent_entry.contents.set(filename,inode);return wasi.ERRNO_SUCCESS}path_unlink(path_str){const{ret:path_ret,path}=Path.from(path_str);if(path==null){return{ret:path_ret,inode_obj:null}}const{ret:parent_ret,parent_entry,filename,entry}=this.dir.get_parent_dir_and_entry_for_path(path,true);if(parent_entry==null||filename==null){return{ret:parent_ret,inode_obj:null}}if(entry==null){return{ret:wasi.ERRNO_NOENT,inode_obj:null}}parent_entry.contents.delete(filename);return{ret:wasi.ERRNO_SUCCESS,inode_obj:entry}}path_unlink_file(path_str){const{ret:path_ret,path}=Path.from(path_str);if(path==null){return path_ret}const{ret:parent_ret,parent_entry,filename,entry}=this.dir.get_parent_dir_and_entry_for_path(path,false);if(parent_entry==null||filename==null||entry==null){return parent_ret}if(entry.stat().filetype===wasi.FILETYPE_DIRECTORY){return wasi.ERRNO_ISDIR}parent_entry.contents.delete(filename);return wasi.ERRNO_SUCCESS}path_remove_directory(path_str){const{ret:path_ret,path}=Path.from(path_str);if(path==null){return path_ret}const{ret:parent_ret,parent_entry,filename,entry}=this.dir.get_parent_dir_and_entry_for_path(path,false);if(parent_entry==null||filename==null||entry==null){return parent_ret}if(!(entry instanceof Directory)||entry.stat().filetype!==wasi.FILETYPE_DIRECTORY){return wasi.ERRNO_NOTDIR}if(entry.contents.size!==0){return wasi.ERRNO_NOTEMPTY}if(!parent_entry.contents.delete(filename)){return wasi.ERRNO_NOENT}return wasi.ERRNO_SUCCESS}fd_filestat_get(){return{ret:0,filestat:this.dir.stat()}}fd_filestat_set_size(size){return wasi.ERRNO_BADF}fd_read(size){return{ret:wasi.ERRNO_BADF,data:new Uint8Array}}fd_pread(size,offset){return{ret:wasi.ERRNO_BADF,data:new Uint8Array}}fd_write(data){return{ret:wasi.ERRNO_BADF,nwritten:0}}fd_pwrite(data,offset){return{ret:wasi.ERRNO_BADF,nwritten:0}}constructor(dir){super();this.dir=dir}}export class PreopenDirectory extends OpenDirectory{fd_prestat_get(){return{ret:0,prestat:wasi.Prestat.dir(this.prestat_name)}}constructor(name,contents){super(new Directory(contents));this.prestat_name=name}}export class File extends Inode{path_open(oflags,fs_rights_base,fd_flags){if(this.readonly&&(fs_rights_base&BigInt(wasi.RIGHTS_FD_WRITE))==BigInt(wasi.RIGHTS_FD_WRITE)){return{ret:wasi.ERRNO_PERM,fd_obj:null}}if((oflags&wasi.OFLAGS_TRUNC)==wasi.OFLAGS_TRUNC){if(this.readonly)return{ret:wasi.ERRNO_PERM,fd_obj:null};this.data=new Uint8Array([])}const file=new OpenFile(this);if(fd_flags&wasi.FDFLAGS_APPEND)file.fd_seek(0n,wasi.WHENCE_END);return{ret:wasi.ERRNO_SUCCESS,fd_obj:file}}get size(){return BigInt(this.data.byteLength)}stat(){return new wasi.Filestat(this.ino,wasi.FILETYPE_REGULAR_FILE,this.size)}constructor(data,options){super();this.data=new Uint8Array(data);this.readonly=!!options?.readonly}}let Path=class Path{static from(path){const self=new Path;self.is_dir=path.endsWith("/");if(path.startsWith("/")){return{ret:wasi.ERRNO_NOTCAPABLE,path:null}}if(path.includes("\x00")){return{ret:wasi.ERRNO_INVAL,path:null}}for(const component of path.split("/")){if(component===""||component==="."){continue}if(component===".."){if(self.parts.pop()==undefined){return{ret:wasi.ERRNO_NOTCAPABLE,path:null}}continue}self.parts.push(component)}return{ret:wasi.ERRNO_SUCCESS,path:self}}to_path_string(){let s=this.parts.join("/");if(this.is_dir){s+="/"}return s}constructor(){this.parts=[];this.is_dir=false}};export class Directory extends Inode{parent_ino(){if(this.parent==null){return Inode.root_ino()}return this.parent.ino}path_open(oflags,fs_rights_base,fd_flags){return{ret:wasi.ERRNO_SUCCESS,fd_obj:new OpenDirectory(this)}}stat(){return new wasi.Filestat(this.ino,wasi.FILETYPE_DIRECTORY,0n)}get_entry_for_path(path){let entry=this;for(const component of path.parts){if(!(entry instanceof Directory)){return{ret:wasi.ERRNO_NOTDIR,entry:null}}const child=entry.contents.get(component);if(child!==undefined){entry=child}else{debug.log(component);return{ret:wasi.ERRNO_NOENT,entry:null}}}if(path.is_dir){if(entry.stat().filetype!=wasi.FILETYPE_DIRECTORY){return{ret:wasi.ERRNO_NOTDIR,entry:null}}}return{ret:wasi.ERRNO_SUCCESS,entry}}get_parent_dir_and_entry_for_path(path,allow_undefined){const filename=path.parts.pop();if(filename===undefined){return{ret:wasi.ERRNO_INVAL,parent_entry:null,filename:null,entry:null}}const{ret:entry_ret,entry:parent_entry}=this.get_entry_for_path(path);if(parent_entry==null){return{ret:entry_ret,parent_entry:null,filename:null,entry:null}}if(!(parent_entry instanceof Directory)){return{ret:wasi.ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}}const entry=parent_entry.contents.get(filename);if(entry===undefined){if(!allow_undefined){return{ret:wasi.ERRNO_NOENT,parent_entry:null,filename:null,entry:null}}else{return{ret:wasi.ERRNO_SUCCESS,parent_entry,filename,entry:null}}}if(path.is_dir){if(entry.stat().filetype!=wasi.FILETYPE_DIRECTORY){return{ret:wasi.ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}}}return{ret:wasi.ERRNO_SUCCESS,parent_entry,filename,entry}}create_entry_for_path(path_str,is_dir){const{ret:path_ret,path}=Path.from(path_str);if(path==null){return{ret:path_ret,entry:null}}let{ret:parent_ret,parent_entry,filename,entry}=this.get_parent_dir_and_entry_for_path(path,true);if(parent_entry==null||filename==null){return{ret:parent_ret,entry:null}}if(entry!=null){return{ret:wasi.ERRNO_EXIST,entry:null}}debug.log("create",path);let new_child;if(!is_dir){new_child=new File(new ArrayBuffer(0))}else{new_child=new Directory(new Map)}parent_entry.contents.set(filename,new_child);entry=new_child;return{ret:wasi.ERRNO_SUCCESS,entry}}constructor(contents){super();this.parent=null;if(contents instanceof Array){this.contents=new Map(contents)}else{this.contents=contents}for(const entry of this.contents.values()){if(entry instanceof Directory){entry.parent=this}}}}export class ConsoleStdout extends Fd{fd_filestat_get(){const filestat=new wasi.Filestat(this.ino,wasi.FILETYPE_CHARACTER_DEVICE,BigInt(0));return{ret:0,filestat}}fd_fdstat_get(){const fdstat=new wasi.Fdstat(wasi.FILETYPE_CHARACTER_DEVICE,0);fdstat.fs_rights_base=BigInt(wasi.RIGHTS_FD_WRITE);return{ret:0,fdstat}}fd_write(data){this.write(data);return{ret:0,nwritten:data.byteLength}}static lineBuffered(write){const dec=new TextDecoder("utf-8",{fatal:false});let line_buf="";return new ConsoleStdout(buffer=>{line_buf+=dec.decode(buffer,{stream:true});const lines=line_buf.split("\n");for(const[i,line]of lines.entries()){if(i<lines.length-1){write(line)}else{line_buf=line}}})}constructor(write){super();this.ino=Inode.issue_ino();this.write=write}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import*as wasi from"./wasi_defs.js";import{Fd,Inode}from"./fd.js";export class SyncOPFSFile extends Inode{path_open(oflags,fs_rights_base,fd_flags){if(this.readonly&&(fs_rights_base&BigInt(wasi.RIGHTS_FD_WRITE))==BigInt(wasi.RIGHTS_FD_WRITE)){return{ret:wasi.ERRNO_PERM,fd_obj:null}}if((oflags&wasi.OFLAGS_TRUNC)==wasi.OFLAGS_TRUNC){if(this.readonly)return{ret:wasi.ERRNO_PERM,fd_obj:null};this.handle.truncate(0)}const file=new OpenSyncOPFSFile(this);if(fd_flags&wasi.FDFLAGS_APPEND)file.fd_seek(0n,wasi.WHENCE_END);return{ret:wasi.ERRNO_SUCCESS,fd_obj:file}}get size(){return BigInt(this.handle.getSize())}stat(){return new wasi.Filestat(this.ino,wasi.FILETYPE_REGULAR_FILE,this.size)}constructor(handle,options){super();this.handle=handle;this.readonly=!!options?.readonly}}export class OpenSyncOPFSFile extends Fd{fd_allocate(offset,len){if(BigInt(this.file.handle.getSize())>offset+len){}else{this.file.handle.truncate(Number(offset+len))}return wasi.ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new wasi.Fdstat(wasi.FILETYPE_REGULAR_FILE,0)}}fd_filestat_get(){return{ret:0,filestat:new wasi.Filestat(this.ino,wasi.FILETYPE_REGULAR_FILE,BigInt(this.file.handle.getSize()))}}fd_filestat_set_size(size){this.file.handle.truncate(Number(size));return wasi.ERRNO_SUCCESS}fd_read(size){const buf=new Uint8Array(size);const n=this.file.handle.read(buf,{at:Number(this.position)});this.position+=BigInt(n);return{ret:0,data:buf.slice(0,n)}}fd_seek(offset,whence){let calculated_offset;switch(whence){case wasi.WHENCE_SET:calculated_offset=BigInt(offset);break;case wasi.WHENCE_CUR:calculated_offset=this.position+BigInt(offset);break;case wasi.WHENCE_END:calculated_offset=BigInt(this.file.handle.getSize())+BigInt(offset);break;default:return{ret:wasi.ERRNO_INVAL,offset:0n}}if(calculated_offset<0){return{ret:wasi.ERRNO_INVAL,offset:0n}}this.position=calculated_offset;return{ret:wasi.ERRNO_SUCCESS,offset:this.position}}fd_write(data){if(this.file.readonly)return{ret:wasi.ERRNO_BADF,nwritten:0};const n=this.file.handle.write(data,{at:Number(this.position)});this.position+=BigInt(n);return{ret:wasi.ERRNO_SUCCESS,nwritten:n}}fd_sync(){this.file.handle.flush();return wasi.ERRNO_SUCCESS}constructor(file){super();this.position=0n;this.file=file;this.ino=Inode.issue_ino()}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import WASI,{WASIProcExit}from"./wasi.js";export{WASI,WASIProcExit};export{Fd,Inode}from"./fd.js";export{File,Directory,OpenFile,OpenDirectory,PreopenDirectory,ConsoleStdout}from"./fs_mem.js";export{SyncOPFSFile,OpenSyncOPFSFile}from"./fs_opfs.js";export{strace}from"./strace.js";export*as wasi from"./wasi_defs.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function strace(imports,no_trace){return new Proxy(imports,{get(target,prop,receiver){const f=Reflect.get(target,prop,receiver);if(no_trace.includes(prop)){return f}return function(...args){console.log(prop,"(",...args,")");const result=Reflect.apply(f,receiver,args);console.log(" =",result);return result}}})}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import*as wasi from"./wasi_defs.js";import{debug}from"./debug.js";export class WASIProcExit extends Error{constructor(code){super("exit with exit code "+code);this.code=code}}let WASI=class WASI{start(instance){this.inst=instance;try{instance.exports._start();return 0}catch(e){if(e instanceof WASIProcExit){return e.code}else{throw e}}}initialize(instance){this.inst=instance;if(instance.exports._initialize){instance.exports._initialize()}}constructor(args,env,fds,options={}){this.args=[];this.env=[];this.fds=[];debug.enable(options.debug);this.args=args;this.env=env;this.fds=fds;const self=this;this.wasiImport={args_sizes_get(argc,argv_buf_size){const buffer=new DataView(self.inst.exports.memory.buffer);buffer.setUint32(argc,self.args.length,true);let buf_size=0;for(const arg of self.args){buf_size+=arg.length+1}buffer.setUint32(argv_buf_size,buf_size,true);debug.log(buffer.getUint32(argc,true),buffer.getUint32(argv_buf_size,true));return 0},args_get(argv,argv_buf){const buffer=new DataView(self.inst.exports.memory.buffer);const buffer8=new Uint8Array(self.inst.exports.memory.buffer);const orig_argv_buf=argv_buf;for(let i=0;i<self.args.length;i++){buffer.setUint32(argv,argv_buf,true);argv+=4;const arg=new TextEncoder().encode(self.args[i]);buffer8.set(arg,argv_buf);buffer.setUint8(argv_buf+arg.length,0);argv_buf+=arg.length+1}if(debug.enabled){debug.log(new TextDecoder("utf-8").decode(buffer8.slice(orig_argv_buf,argv_buf)))}return 0},environ_sizes_get(environ_count,environ_size){const buffer=new DataView(self.inst.exports.memory.buffer);buffer.setUint32(environ_count,self.env.length,true);let buf_size=0;for(const environ of self.env){buf_size+=new TextEncoder().encode(environ).length+1}buffer.setUint32(environ_size,buf_size,true);debug.log(buffer.getUint32(environ_count,true),buffer.getUint32(environ_size,true));return 0},environ_get(environ,environ_buf){const buffer=new DataView(self.inst.exports.memory.buffer);const buffer8=new Uint8Array(self.inst.exports.memory.buffer);const orig_environ_buf=environ_buf;for(let i=0;i<self.env.length;i++){buffer.setUint32(environ,environ_buf,true);environ+=4;const e=new TextEncoder().encode(self.env[i]);buffer8.set(e,environ_buf);buffer.setUint8(environ_buf+e.length,0);environ_buf+=e.length+1}if(debug.enabled){debug.log(new TextDecoder("utf-8").decode(buffer8.slice(orig_environ_buf,environ_buf)))}return 0},clock_res_get(id,res_ptr){let resolutionValue;switch(id){case wasi.CLOCKID_MONOTONIC:{resolutionValue=5000n;break}case wasi.CLOCKID_REALTIME:{resolutionValue=1000000n;break}default:return wasi.ERRNO_NOSYS}const view=new DataView(self.inst.exports.memory.buffer);view.setBigUint64(res_ptr,resolutionValue,true);return wasi.ERRNO_SUCCESS},clock_time_get(id,precision,time){const buffer=new DataView(self.inst.exports.memory.buffer);if(id===wasi.CLOCKID_REALTIME){buffer.setBigUint64(time,BigInt(new Date().getTime())*1000000n,true)}else if(id==wasi.CLOCKID_MONOTONIC){let monotonic_time;try{monotonic_time=BigInt(Math.round(performance.now()*1e6))}catch(e){monotonic_time=0n}buffer.setBigUint64(time,monotonic_time,true)}else{buffer.setBigUint64(time,0n,true)}return 0},fd_advise(fd,offset,len,advice){if(self.fds[fd]!=undefined){return wasi.ERRNO_SUCCESS}else{return wasi.ERRNO_BADF}},fd_allocate(fd,offset,len){if(self.fds[fd]!=undefined){return self.fds[fd].fd_allocate(offset,len)}else{return wasi.ERRNO_BADF}},fd_close(fd){if(self.fds[fd]!=undefined){const ret=self.fds[fd].fd_close();self.fds[fd]=undefined;return ret}else{return wasi.ERRNO_BADF}},fd_datasync(fd){if(self.fds[fd]!=undefined){return self.fds[fd].fd_sync()}else{return wasi.ERRNO_BADF}},fd_fdstat_get(fd,fdstat_ptr){if(self.fds[fd]!=undefined){const{ret,fdstat}=self.fds[fd].fd_fdstat_get();if(fdstat!=null){fdstat.write_bytes(new DataView(self.inst.exports.memory.buffer),fdstat_ptr)}return ret}else{return wasi.ERRNO_BADF}},fd_fdstat_set_flags(fd,flags){if(self.fds[fd]!=undefined){return self.fds[fd].fd_fdstat_set_flags(flags)}else{return wasi.ERRNO_BADF}},fd_fdstat_set_rights(fd,fs_rights_base,fs_rights_inheriting){if(self.fds[fd]!=undefined){return self.fds[fd].fd_fdstat_set_rights(fs_rights_base,fs_rights_inheriting)}else{return wasi.ERRNO_BADF}},fd_filestat_get(fd,filestat_ptr){if(self.fds[fd]!=undefined){const{ret,filestat}=self.fds[fd].fd_filestat_get();if(filestat!=null){filestat.write_bytes(new DataView(self.inst.exports.memory.buffer),filestat_ptr)}return ret}else{return wasi.ERRNO_BADF}},fd_filestat_set_size(fd,size){if(self.fds[fd]!=undefined){return self.fds[fd].fd_filestat_set_size(size)}else{return wasi.ERRNO_BADF}},fd_filestat_set_times(fd,atim,mtim,fst_flags){if(self.fds[fd]!=undefined){return self.fds[fd].fd_filestat_set_times(atim,mtim,fst_flags)}else{return wasi.ERRNO_BADF}},fd_pread(fd,iovs_ptr,iovs_len,offset,nread_ptr){const buffer=new DataView(self.inst.exports.memory.buffer);const buffer8=new Uint8Array(self.inst.exports.memory.buffer);if(self.fds[fd]!=undefined){const iovecs=wasi.Iovec.read_bytes_array(buffer,iovs_ptr,iovs_len);let nread=0;for(const iovec of iovecs){const{ret,data}=self.fds[fd].fd_pread(iovec.buf_len,offset);if(ret!=wasi.ERRNO_SUCCESS){buffer.setUint32(nread_ptr,nread,true);return ret}buffer8.set(data,iovec.buf);nread+=data.length;offset+=BigInt(data.length);if(data.length!=iovec.buf_len){break}}buffer.setUint32(nread_ptr,nread,true);return wasi.ERRNO_SUCCESS}else{return wasi.ERRNO_BADF}},fd_prestat_get(fd,buf_ptr){const buffer=new DataView(self.inst.exports.memory.buffer);if(self.fds[fd]!=undefined){const{ret,prestat}=self.fds[fd].fd_prestat_get();if(prestat!=null){prestat.write_bytes(buffer,buf_ptr)}return ret}else{return wasi.ERRNO_BADF}},fd_prestat_dir_name(fd,path_ptr,path_len){if(self.fds[fd]!=undefined){const{ret,prestat}=self.fds[fd].fd_prestat_get();if(prestat==null){return ret}const prestat_dir_name=prestat.inner.pr_name;const buffer8=new Uint8Array(self.inst.exports.memory.buffer);buffer8.set(prestat_dir_name.slice(0,path_len),path_ptr);return prestat_dir_name.byteLength>path_len?wasi.ERRNO_NAMETOOLONG:wasi.ERRNO_SUCCESS}else{return wasi.ERRNO_BADF}},fd_pwrite(fd,iovs_ptr,iovs_len,offset,nwritten_ptr){const buffer=new DataView(self.inst.exports.memory.buffer);const buffer8=new Uint8Array(self.inst.exports.memory.buffer);if(self.fds[fd]!=undefined){const iovecs=wasi.Ciovec.read_bytes_array(buffer,iovs_ptr,iovs_len);let nwritten=0;for(const iovec of iovecs){const data=buffer8.slice(iovec.buf,iovec.buf+iovec.buf_len);const{ret,nwritten:nwritten_part}=self.fds[fd].fd_pwrite(data,offset);if(ret!=wasi.ERRNO_SUCCESS){buffer.setUint32(nwritten_ptr,nwritten,true);return ret}nwritten+=nwritten_part;offset+=BigInt(nwritten_part);if(nwritten_part!=data.byteLength){break}}buffer.setUint32(nwritten_ptr,nwritten,true);return wasi.ERRNO_SUCCESS}else{return wasi.ERRNO_BADF}},fd_read(fd,iovs_ptr,iovs_len,nread_ptr){const buffer=new DataView(self.inst.exports.memory.buffer);const buffer8=new Uint8Array(self.inst.exports.memory.buffer);if(self.fds[fd]!=undefined){const iovecs=wasi.Iovec.read_bytes_array(buffer,iovs_ptr,iovs_len);let nread=0;for(const iovec of iovecs){const{ret,data}=self.fds[fd].fd_read(iovec.buf_len);if(ret!=wasi.ERRNO_SUCCESS){buffer.setUint32(nread_ptr,nread,true);return ret}buffer8.set(data,iovec.buf);nread+=data.length;if(data.length!=iovec.buf_len){break}}buffer.setUint32(nread_ptr,nread,true);return wasi.ERRNO_SUCCESS}else{return wasi.ERRNO_BADF}},fd_readdir(fd,buf,buf_len,cookie,bufused_ptr){const buffer=new DataView(self.inst.exports.memory.buffer);const buffer8=new Uint8Array(self.inst.exports.memory.buffer);if(self.fds[fd]!=undefined){let bufused=0;while(true){const{ret,dirent}=self.fds[fd].fd_readdir_single(cookie);if(ret!=0){buffer.setUint32(bufused_ptr,bufused,true);return ret}if(dirent==null){break}if(buf_len-bufused<dirent.head_length()){bufused=buf_len;break}const head_bytes=new ArrayBuffer(dirent.head_length());dirent.write_head_bytes(new DataView(head_bytes),0);buffer8.set(new Uint8Array(head_bytes).slice(0,Math.min(head_bytes.byteLength,buf_len-bufused)),buf);buf+=dirent.head_length();bufused+=dirent.head_length();if(buf_len-bufused<dirent.name_length()){bufused=buf_len;break}dirent.write_name_bytes(buffer8,buf,buf_len-bufused);buf+=dirent.name_length();bufused+=dirent.name_length();cookie=dirent.d_next}buffer.setUint32(bufused_ptr,bufused,true);return 0}else{return wasi.ERRNO_BADF}},fd_renumber(fd,to){if(self.fds[fd]!=undefined&&self.fds[to]!=undefined){const ret=self.fds[to].fd_close();if(ret!=0){return ret}self.fds[to]=self.fds[fd];self.fds[fd]=undefined;return 0}else{return wasi.ERRNO_BADF}},fd_seek(fd,offset,whence,offset_out_ptr){const buffer=new DataView(self.inst.exports.memory.buffer);if(self.fds[fd]!=undefined){const{ret,offset:offset_out}=self.fds[fd].fd_seek(offset,whence);buffer.setBigInt64(offset_out_ptr,offset_out,true);return ret}else{return wasi.ERRNO_BADF}},fd_sync(fd){if(self.fds[fd]!=undefined){return self.fds[fd].fd_sync()}else{return wasi.ERRNO_BADF}},fd_tell(fd,offset_ptr){const buffer=new DataView(self.inst.exports.memory.buffer);if(self.fds[fd]!=undefined){const{ret,offset}=self.fds[fd].fd_tell();buffer.setBigUint64(offset_ptr,offset,true);return ret}else{return wasi.ERRNO_BADF}},fd_write(fd,iovs_ptr,iovs_len,nwritten_ptr){const buffer=new DataView(self.inst.exports.memory.buffer);const buffer8=new Uint8Array(self.inst.exports.memory.buffer);if(self.fds[fd]!=undefined){const iovecs=wasi.Ciovec.read_bytes_array(buffer,iovs_ptr,iovs_len);let nwritten=0;for(const iovec of iovecs){const data=buffer8.slice(iovec.buf,iovec.buf+iovec.buf_len);const{ret,nwritten:nwritten_part}=self.fds[fd].fd_write(data);if(ret!=wasi.ERRNO_SUCCESS){buffer.setUint32(nwritten_ptr,nwritten,true);return ret}nwritten+=nwritten_part;if(nwritten_part!=data.byteLength){break}}buffer.setUint32(nwritten_ptr,nwritten,true);return wasi.ERRNO_SUCCESS}else{return wasi.ERRNO_BADF}},path_create_directory(fd,path_ptr,path_len){const buffer8=new Uint8Array(self.inst.exports.memory.buffer);if(self.fds[fd]!=undefined){const path=new TextDecoder("utf-8").decode(buffer8.slice(path_ptr,path_ptr+path_len));return self.fds[fd].path_create_directory(path)}else{return wasi.ERRNO_BADF}},path_filestat_get(fd,flags,path_ptr,path_len,filestat_ptr){const buffer=new DataView(self.inst.exports.memory.buffer);const buffer8=new Uint8Array(self.inst.exports.memory.buffer);if(self.fds[fd]!=undefined){const path=new TextDecoder("utf-8").decode(buffer8.slice(path_ptr,path_ptr+path_len));const{ret,filestat}=self.fds[fd].path_filestat_get(flags,path);if(filestat!=null){filestat.write_bytes(buffer,filestat_ptr)}return ret}else{return wasi.ERRNO_BADF}},path_filestat_set_times(fd,flags,path_ptr,path_len,atim,mtim,fst_flags){const buffer8=new Uint8Array(self.inst.exports.memory.buffer);if(self.fds[fd]!=undefined){const path=new TextDecoder("utf-8").decode(buffer8.slice(path_ptr,path_ptr+path_len));return self.fds[fd].path_filestat_set_times(flags,path,atim,mtim,fst_flags)}else{return wasi.ERRNO_BADF}},path_link(old_fd,old_flags,old_path_ptr,old_path_len,new_fd,new_path_ptr,new_path_len){const buffer8=new Uint8Array(self.inst.exports.memory.buffer);if(self.fds[old_fd]!=undefined&&self.fds[new_fd]!=undefined){const old_path=new TextDecoder("utf-8").decode(buffer8.slice(old_path_ptr,old_path_ptr+old_path_len));const new_path=new TextDecoder("utf-8").decode(buffer8.slice(new_path_ptr,new_path_ptr+new_path_len));const{ret,inode_obj}=self.fds[old_fd].path_lookup(old_path,old_flags);if(inode_obj==null){return ret}return self.fds[new_fd].path_link(new_path,inode_obj,false)}else{return wasi.ERRNO_BADF}},path_open(fd,dirflags,path_ptr,path_len,oflags,fs_rights_base,fs_rights_inheriting,fd_flags,opened_fd_ptr){const buffer=new DataView(self.inst.exports.memory.buffer);const buffer8=new Uint8Array(self.inst.exports.memory.buffer);if(self.fds[fd]!=undefined){const path=new TextDecoder("utf-8").decode(buffer8.slice(path_ptr,path_ptr+path_len));debug.log(path);const{ret,fd_obj}=self.fds[fd].path_open(dirflags,path,oflags,fs_rights_base,fs_rights_inheriting,fd_flags);if(ret!=0){return ret}self.fds.push(fd_obj);const opened_fd=self.fds.length-1;buffer.setUint32(opened_fd_ptr,opened_fd,true);return 0}else{return wasi.ERRNO_BADF}},path_readlink(fd,path_ptr,path_len,buf_ptr,buf_len,nread_ptr){const buffer=new DataView(self.inst.exports.memory.buffer);const buffer8=new Uint8Array(self.inst.exports.memory.buffer);if(self.fds[fd]!=undefined){const path=new TextDecoder("utf-8").decode(buffer8.slice(path_ptr,path_ptr+path_len));debug.log(path);const{ret,data}=self.fds[fd].path_readlink(path);if(data!=null){const data_buf=new TextEncoder().encode(data);if(data_buf.length>buf_len){buffer.setUint32(nread_ptr,0,true);return wasi.ERRNO_BADF}buffer8.set(data_buf,buf_ptr);buffer.setUint32(nread_ptr,data_buf.length,true)}return ret}else{return wasi.ERRNO_BADF}},path_remove_directory(fd,path_ptr,path_len){const buffer8=new Uint8Array(self.inst.exports.memory.buffer);if(self.fds[fd]!=undefined){const path=new TextDecoder("utf-8").decode(buffer8.slice(path_ptr,path_ptr+path_len));return self.fds[fd].path_remove_directory(path)}else{return wasi.ERRNO_BADF}},path_rename(fd,old_path_ptr,old_path_len,new_fd,new_path_ptr,new_path_len){const buffer8=new Uint8Array(self.inst.exports.memory.buffer);if(self.fds[fd]!=undefined&&self.fds[new_fd]!=undefined){const old_path=new TextDecoder("utf-8").decode(buffer8.slice(old_path_ptr,old_path_ptr+old_path_len));const new_path=new TextDecoder("utf-8").decode(buffer8.slice(new_path_ptr,new_path_ptr+new_path_len));let{ret,inode_obj}=self.fds[fd].path_unlink(old_path);if(inode_obj==null){return ret}ret=self.fds[new_fd].path_link(new_path,inode_obj,true);if(ret!=wasi.ERRNO_SUCCESS){if(self.fds[fd].path_link(old_path,inode_obj,true)!=wasi.ERRNO_SUCCESS){throw"path_link should always return success when relinking an inode back to the original place"}}return ret}else{return wasi.ERRNO_BADF}},path_symlink(old_path_ptr,old_path_len,fd,new_path_ptr,new_path_len){const buffer8=new Uint8Array(self.inst.exports.memory.buffer);if(self.fds[fd]!=undefined){const old_path=new TextDecoder("utf-8").decode(buffer8.slice(old_path_ptr,old_path_ptr+old_path_len));const new_path=new TextDecoder("utf-8").decode(buffer8.slice(new_path_ptr,new_path_ptr+new_path_len));return wasi.ERRNO_NOTSUP}else{return wasi.ERRNO_BADF}},path_unlink_file(fd,path_ptr,path_len){const buffer8=new Uint8Array(self.inst.exports.memory.buffer);if(self.fds[fd]!=undefined){const path=new TextDecoder("utf-8").decode(buffer8.slice(path_ptr,path_ptr+path_len));return self.fds[fd].path_unlink_file(path)}else{return wasi.ERRNO_BADF}},poll_oneoff(in_ptr,out_ptr,nsubscriptions){if(nsubscriptions===0){return wasi.ERRNO_INVAL}if(nsubscriptions>1){debug.log("poll_oneoff: only a single subscription is supported");return wasi.ERRNO_NOTSUP}const buffer=new DataView(self.inst.exports.memory.buffer);const s=wasi.Subscription.read_bytes(buffer,in_ptr);const eventtype=s.eventtype;const clockid=s.clockid;const timeout=s.timeout;if(eventtype!==wasi.EVENTTYPE_CLOCK){debug.log("poll_oneoff: only clock subscriptions are supported");return wasi.ERRNO_NOTSUP}let getNow=undefined;if(clockid===wasi.CLOCKID_MONOTONIC){getNow=()=>BigInt(Math.round(performance.now()*1e6))}else if(clockid===wasi.CLOCKID_REALTIME){getNow=()=>BigInt(new Date().getTime())*1000000n}else{return wasi.ERRNO_INVAL}const endTime=(s.flags&wasi.SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME)!==0?timeout:getNow()+timeout;while(endTime>getNow()){}const event=new wasi.Event(s.userdata,wasi.ERRNO_SUCCESS,eventtype);event.write_bytes(buffer,out_ptr);return wasi.ERRNO_SUCCESS},proc_exit(exit_code){throw new WASIProcExit(exit_code)},proc_raise(sig){throw"raised signal "+sig},sched_yield(){},random_get(buf,buf_len){const buffer8=new Uint8Array(self.inst.exports.memory.buffer).subarray(buf,buf+buf_len);if("crypto"in globalThis&&(typeof SharedArrayBuffer==="undefined"||!(self.inst.exports.memory.buffer instanceof SharedArrayBuffer))){for(let i=0;i<buf_len;i+=65536){crypto.getRandomValues(buffer8.subarray(i,i+65536))}}else{for(let i=0;i<buf_len;i++){buffer8[i]=Math.random()*256|0}}},sock_recv(fd,ri_data,ri_flags){throw"sockets not supported"},sock_send(fd,si_data,si_flags){throw"sockets not supported"},sock_shutdown(fd,how){throw"sockets not supported"},sock_accept(fd,flags){throw"sockets not supported"}}}};export{WASI as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const FD_STDIN=0;export const FD_STDOUT=1;export const FD_STDERR=2;export const CLOCKID_REALTIME=0;export const CLOCKID_MONOTONIC=1;export const CLOCKID_PROCESS_CPUTIME_ID=2;export const CLOCKID_THREAD_CPUTIME_ID=3;export const ERRNO_SUCCESS=0;export const ERRNO_2BIG=1;export const ERRNO_ACCES=2;export const ERRNO_ADDRINUSE=3;export const ERRNO_ADDRNOTAVAIL=4;export const ERRNO_AFNOSUPPORT=5;export const ERRNO_AGAIN=6;export const ERRNO_ALREADY=7;export const ERRNO_BADF=8;export const ERRNO_BADMSG=9;export const ERRNO_BUSY=10;export const ERRNO_CANCELED=11;export const ERRNO_CHILD=12;export const ERRNO_CONNABORTED=13;export const ERRNO_CONNREFUSED=14;export const ERRNO_CONNRESET=15;export const ERRNO_DEADLK=16;export const ERRNO_DESTADDRREQ=17;export const ERRNO_DOM=18;export const ERRNO_DQUOT=19;export const ERRNO_EXIST=20;export const ERRNO_FAULT=21;export const ERRNO_FBIG=22;export const ERRNO_HOSTUNREACH=23;export const ERRNO_IDRM=24;export const ERRNO_ILSEQ=25;export const ERRNO_INPROGRESS=26;export const ERRNO_INTR=27;export const ERRNO_INVAL=28;export const ERRNO_IO=29;export const ERRNO_ISCONN=30;export const ERRNO_ISDIR=31;export const ERRNO_LOOP=32;export const ERRNO_MFILE=33;export const ERRNO_MLINK=34;export const ERRNO_MSGSIZE=35;export const ERRNO_MULTIHOP=36;export const ERRNO_NAMETOOLONG=37;export const ERRNO_NETDOWN=38;export const ERRNO_NETRESET=39;export const ERRNO_NETUNREACH=40;export const ERRNO_NFILE=41;export const ERRNO_NOBUFS=42;export const ERRNO_NODEV=43;export const ERRNO_NOENT=44;export const ERRNO_NOEXEC=45;export const ERRNO_NOLCK=46;export const ERRNO_NOLINK=47;export const ERRNO_NOMEM=48;export const ERRNO_NOMSG=49;export const ERRNO_NOPROTOOPT=50;export const ERRNO_NOSPC=51;export const ERRNO_NOSYS=52;export const ERRNO_NOTCONN=53;export const ERRNO_NOTDIR=54;export const ERRNO_NOTEMPTY=55;export const ERRNO_NOTRECOVERABLE=56;export const ERRNO_NOTSOCK=57;export const ERRNO_NOTSUP=58;export const ERRNO_NOTTY=59;export const ERRNO_NXIO=60;export const ERRNO_OVERFLOW=61;export const ERRNO_OWNERDEAD=62;export const ERRNO_PERM=63;export const ERRNO_PIPE=64;export const ERRNO_PROTO=65;export const ERRNO_PROTONOSUPPORT=66;export const ERRNO_PROTOTYPE=67;export const ERRNO_RANGE=68;export const ERRNO_ROFS=69;export const ERRNO_SPIPE=70;export const ERRNO_SRCH=71;export const ERRNO_STALE=72;export const ERRNO_TIMEDOUT=73;export const ERRNO_TXTBSY=74;export const ERRNO_XDEV=75;export const ERRNO_NOTCAPABLE=76;export const RIGHTS_FD_DATASYNC=1<<0;export const RIGHTS_FD_READ=1<<1;export const RIGHTS_FD_SEEK=1<<2;export const RIGHTS_FD_FDSTAT_SET_FLAGS=1<<3;export const RIGHTS_FD_SYNC=1<<4;export const RIGHTS_FD_TELL=1<<5;export const RIGHTS_FD_WRITE=1<<6;export const RIGHTS_FD_ADVISE=1<<7;export const RIGHTS_FD_ALLOCATE=1<<8;export const RIGHTS_PATH_CREATE_DIRECTORY=1<<9;export const RIGHTS_PATH_CREATE_FILE=1<<10;export const RIGHTS_PATH_LINK_SOURCE=1<<11;export const RIGHTS_PATH_LINK_TARGET=1<<12;export const RIGHTS_PATH_OPEN=1<<13;export const RIGHTS_FD_READDIR=1<<14;export const RIGHTS_PATH_READLINK=1<<15;export const RIGHTS_PATH_RENAME_SOURCE=1<<16;export const RIGHTS_PATH_RENAME_TARGET=1<<17;export const RIGHTS_PATH_FILESTAT_GET=1<<18;export const RIGHTS_PATH_FILESTAT_SET_SIZE=1<<19;export const RIGHTS_PATH_FILESTAT_SET_TIMES=1<<20;export const RIGHTS_FD_FILESTAT_GET=1<<21;export const RIGHTS_FD_FILESTAT_SET_SIZE=1<<22;export const RIGHTS_FD_FILESTAT_SET_TIMES=1<<23;export const RIGHTS_PATH_SYMLINK=1<<24;export const RIGHTS_PATH_REMOVE_DIRECTORY=1<<25;export const RIGHTS_PATH_UNLINK_FILE=1<<26;export const RIGHTS_POLL_FD_READWRITE=1<<27;export const RIGHTS_SOCK_SHUTDOWN=1<<28;export class Iovec{static read_bytes(view,ptr){const iovec=new Iovec;iovec.buf=view.getUint32(ptr,true);iovec.buf_len=view.getUint32(ptr+4,true);return iovec}static read_bytes_array(view,ptr,len){const iovecs=[];for(let i=0;i<len;i++){iovecs.push(Iovec.read_bytes(view,ptr+8*i))}return iovecs}}export class Ciovec{static read_bytes(view,ptr){const iovec=new Ciovec;iovec.buf=view.getUint32(ptr,true);iovec.buf_len=view.getUint32(ptr+4,true);return iovec}static read_bytes_array(view,ptr,len){const iovecs=[];for(let i=0;i<len;i++){iovecs.push(Ciovec.read_bytes(view,ptr+8*i))}return iovecs}}export const WHENCE_SET=0;export const WHENCE_CUR=1;export const WHENCE_END=2;export const FILETYPE_UNKNOWN=0;export const FILETYPE_BLOCK_DEVICE=1;export const FILETYPE_CHARACTER_DEVICE=2;export const FILETYPE_DIRECTORY=3;export const FILETYPE_REGULAR_FILE=4;export const FILETYPE_SOCKET_DGRAM=5;export const FILETYPE_SOCKET_STREAM=6;export const FILETYPE_SYMBOLIC_LINK=7;export class Dirent{head_length(){return 24}name_length(){return this.dir_name.byteLength}write_head_bytes(view,ptr){view.setBigUint64(ptr,this.d_next,true);view.setBigUint64(ptr+8,this.d_ino,true);view.setUint32(ptr+16,this.dir_name.length,true);view.setUint8(ptr+20,this.d_type)}write_name_bytes(view8,ptr,buf_len){view8.set(this.dir_name.slice(0,Math.min(this.dir_name.byteLength,buf_len)),ptr)}constructor(next_cookie,d_ino,name,type){const encoded_name=new TextEncoder().encode(name);this.d_next=next_cookie;this.d_ino=d_ino;this.d_namlen=encoded_name.byteLength;this.d_type=type;this.dir_name=encoded_name}}export const ADVICE_NORMAL=0;export const ADVICE_SEQUENTIAL=1;export const ADVICE_RANDOM=2;export const ADVICE_WILLNEED=3;export const ADVICE_DONTNEED=4;export const ADVICE_NOREUSE=5;export const FDFLAGS_APPEND=1<<0;export const FDFLAGS_DSYNC=1<<1;export const FDFLAGS_NONBLOCK=1<<2;export const FDFLAGS_RSYNC=1<<3;export const FDFLAGS_SYNC=1<<4;export class Fdstat{write_bytes(view,ptr){view.setUint8(ptr,this.fs_filetype);view.setUint16(ptr+2,this.fs_flags,true);view.setBigUint64(ptr+8,this.fs_rights_base,true);view.setBigUint64(ptr+16,this.fs_rights_inherited,true)}constructor(filetype,flags){this.fs_rights_base=0n;this.fs_rights_inherited=0n;this.fs_filetype=filetype;this.fs_flags=flags}}export const FSTFLAGS_ATIM=1<<0;export const FSTFLAGS_ATIM_NOW=1<<1;export const FSTFLAGS_MTIM=1<<2;export const FSTFLAGS_MTIM_NOW=1<<3;export const OFLAGS_CREAT=1<<0;export const OFLAGS_DIRECTORY=1<<1;export const OFLAGS_EXCL=1<<2;export const OFLAGS_TRUNC=1<<3;export class Filestat{write_bytes(view,ptr){view.setBigUint64(ptr,this.dev,true);view.setBigUint64(ptr+8,this.ino,true);view.setUint8(ptr+16,this.filetype);view.setBigUint64(ptr+24,this.nlink,true);view.setBigUint64(ptr+32,this.size,true);view.setBigUint64(ptr+38,this.atim,true);view.setBigUint64(ptr+46,this.mtim,true);view.setBigUint64(ptr+52,this.ctim,true)}constructor(ino,filetype,size){this.dev=0n;this.nlink=0n;this.atim=0n;this.mtim=0n;this.ctim=0n;this.ino=ino;this.filetype=filetype;this.size=size}}export const EVENTTYPE_CLOCK=0;export const EVENTTYPE_FD_READ=1;export const EVENTTYPE_FD_WRITE=2;export const EVENTRWFLAGS_FD_READWRITE_HANGUP=1<<0;export const SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME=1<<0;export class Subscription{static read_bytes(view,ptr){return new Subscription(view.getBigUint64(ptr,true),view.getUint8(ptr+8),view.getUint32(ptr+16,true),view.getBigUint64(ptr+24,true),view.getUint16(ptr+36,true))}constructor(userdata,eventtype,clockid,timeout,flags){this.userdata=userdata;this.eventtype=eventtype;this.clockid=clockid;this.timeout=timeout;this.flags=flags}}export class Event{write_bytes(view,ptr){view.setBigUint64(ptr,this.userdata,true);view.setUint16(ptr+8,this.error,true);view.setUint8(ptr+10,this.eventtype)}constructor(userdata,error,eventtype){this.userdata=userdata;this.error=error;this.eventtype=eventtype}}export const SIGNAL_NONE=0;export const SIGNAL_HUP=1;export const SIGNAL_INT=2;export const SIGNAL_QUIT=3;export const SIGNAL_ILL=4;export const SIGNAL_TRAP=5;export const SIGNAL_ABRT=6;export const SIGNAL_BUS=7;export const SIGNAL_FPE=8;export const SIGNAL_KILL=9;export const SIGNAL_USR1=10;export const SIGNAL_SEGV=11;export const SIGNAL_USR2=12;export const SIGNAL_PIPE=13;export const SIGNAL_ALRM=14;export const SIGNAL_TERM=15;export const SIGNAL_CHLD=16;export const SIGNAL_CONT=17;export const SIGNAL_STOP=18;export const SIGNAL_TSTP=19;export const SIGNAL_TTIN=20;export const SIGNAL_TTOU=21;export const SIGNAL_URG=22;export const SIGNAL_XCPU=23;export const SIGNAL_XFSZ=24;export const SIGNAL_VTALRM=25;export const SIGNAL_PROF=26;export const SIGNAL_WINCH=27;export const SIGNAL_POLL=28;export const SIGNAL_PWR=29;export const SIGNAL_SYS=30;export const RIFLAGS_RECV_PEEK=1<<0;export const RIFLAGS_RECV_WAITALL=1<<1;export const ROFLAGS_RECV_DATA_TRUNCATED=1<<0;export const SDFLAGS_RD=1<<0;export const SDFLAGS_WR=1<<1;export const PREOPENTYPE_DIR=0;export class PrestatDir{write_bytes(view,ptr){view.setUint32(ptr,this.pr_name.byteLength,true)}constructor(name){this.pr_name=new TextEncoder().encode(name)}}export class Prestat{static dir(name){const prestat=new Prestat;prestat.tag=PREOPENTYPE_DIR;prestat.inner=new PrestatDir(name);return prestat}write_bytes(view,ptr){view.setUint32(ptr,this.tag,true);this.inner.write_bytes(view,ptr+4)}}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
export interface CompilerOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Directory holding `pas2js.wasm` and `rtl/`.
|
|
4
|
+
*
|
|
5
|
+
* Defaults to the assets shipped alongside this package, resolved from the
|
|
6
|
+
* module's own URL. The classic-script (IIFE) build has no module URL, so it
|
|
7
|
+
* requires this to be passed in.
|
|
8
|
+
*/
|
|
9
|
+
baseUrl?: string | URL;
|
|
10
|
+
/** Override the compiler binary location. */
|
|
11
|
+
wasmUrl?: string | URL;
|
|
12
|
+
/** Override the RTL directory location. */
|
|
13
|
+
rtlUrl?: string | URL;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface CompileOptions extends CompilerOptions {
|
|
17
|
+
/** Extra pas2js command-line options, e.g. `['-O2', '-Mdelphi']`. */
|
|
18
|
+
flags?: string[];
|
|
19
|
+
/** Extra units by filename, placed on the compiler's search path. */
|
|
20
|
+
units?: Record<string, string | Uint8Array> | Map<string, string | Uint8Array>;
|
|
21
|
+
/** Emit a source map mapping the generated JavaScript back to the Pascal. */
|
|
22
|
+
sourceMap?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface CompileResult {
|
|
26
|
+
/** Process exit code; non-zero means compilation failed. */
|
|
27
|
+
exitCode: number;
|
|
28
|
+
/** Generated JavaScript, or `null` when compilation failed. */
|
|
29
|
+
js: string | null;
|
|
30
|
+
/** Source map for `js`, or `null` unless `sourceMap` was requested. */
|
|
31
|
+
sourceMap: string | null;
|
|
32
|
+
/** Raw compiler output (progress chatter plus diagnostics). */
|
|
33
|
+
diagnostics: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface Compiler {
|
|
37
|
+
/** Where the assets were loaded from. */
|
|
38
|
+
readonly baseUrl: URL;
|
|
39
|
+
compile(source: string, options?: CompileOptions): Promise<CompileResult>;
|
|
40
|
+
/** The compiler's own version string, e.g. `"3.3.1"`. */
|
|
41
|
+
version(): Promise<string>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface DiagnosticMessage {
|
|
45
|
+
file: string | null;
|
|
46
|
+
line: number | null;
|
|
47
|
+
column: number | null;
|
|
48
|
+
severity: 'error' | 'warning' | 'hint' | 'note' | 'fatal';
|
|
49
|
+
message: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface ConfigureOptions {
|
|
53
|
+
/** Where `pas2js.wasm` and `rtl/` live, for every subsequent compile. */
|
|
54
|
+
baseUrl?: string | URL;
|
|
55
|
+
/** Compiler options to always pass, prepended to each call's `flags`. */
|
|
56
|
+
flags?: string[];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export declare function createCompiler(options?: CompilerOptions): Promise<Compiler>;
|
|
60
|
+
|
|
61
|
+
export declare function compile(
|
|
62
|
+
source: string,
|
|
63
|
+
options?: CompileOptions,
|
|
64
|
+
): Promise<CompileResult>;
|
|
65
|
+
|
|
66
|
+
export declare function parseDiagnostics(diagnostics: string): DiagnosticMessage[];
|
|
67
|
+
|
|
68
|
+
/** Set package-wide defaults — the way to configure the classic-script build. */
|
|
69
|
+
export declare function configure(options?: ConfigureOptions): void;
|
|
70
|
+
|
|
71
|
+
/** The asset location that will be used when none is given explicitly. */
|
|
72
|
+
export declare function defaultBaseUrl(): URL;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The API exposed on `globalThis.pascalWasm` by the IIFE build
|
|
76
|
+
* (`dist/pascal-wasm.iife.min.js`), for classic scripts and non-module workers.
|
|
77
|
+
*/
|
|
78
|
+
export interface PascalWasmGlobal {
|
|
79
|
+
compile: typeof compile;
|
|
80
|
+
createCompiler: typeof createCompiler;
|
|
81
|
+
parseDiagnostics: typeof parseDiagnostics;
|
|
82
|
+
configure: typeof configure;
|
|
83
|
+
defaultBaseUrl: typeof defaultBaseUrl;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
declare global {
|
|
87
|
+
// eslint-disable-next-line no-var
|
|
88
|
+
var pascalWasm: PascalWasmGlobal;
|
|
89
|
+
}
|