From 93229ee98e0265e759760574a1107f6a2c3c004c Mon Sep 17 00:00:00 2001 From: George Thomas Date: Mon, 2 Jun 2025 10:12:10 +0100 Subject: [PATCH] chore(primer-miso): vendor JS dependencies This was created by running: ```sh curl https://cdn.jsdelivr.net/npm/@bjorn3/browser_wasi_shim@0.3.0/dist/debug.js -o primer-miso/frontend/debug.js curl https://cdn.jsdelivr.net/npm/@bjorn3/browser_wasi_shim@0.3.0/dist/fd.js -o primer-miso/frontend/fd.js curl https://cdn.jsdelivr.net/npm/@bjorn3/browser_wasi_shim@0.3.0/dist/fs_mem.js -o primer-miso/frontend/fs_mem.js curl https://cdn.jsdelivr.net/npm/@bjorn3/browser_wasi_shim@0.3.0/dist/fs_opfs.js -o primer-miso/frontend/fs_opfs.js curl https://cdn.jsdelivr.net/npm/@bjorn3/browser_wasi_shim@0.3.0/dist/index.js -o primer-miso/frontend/browser_wasi_shim.js curl https://cdn.jsdelivr.net/npm/@bjorn3/browser_wasi_shim@0.3.0/dist/strace.js -o primer-miso/frontend/strace.js curl https://cdn.jsdelivr.net/npm/@bjorn3/browser_wasi_shim@0.3.0/dist/wasi_defs.js -o primer-miso/frontend/wasi_defs.js curl https://cdn.jsdelivr.net/npm/@bjorn3/browser_wasi_shim@0.3.0/dist/wasi.js -o primer-miso/frontend/wasi.js curl https://cdn.jsdelivr.net/npm/@bjorn3/browser_wasi_shim@0.3.0/dist/wasi.js -o primer-miso/frontend/wasi.js ``` Signed-off-by: George Thomas --- primer-miso/frontend/browser_wasi_shim.js | 1 + primer-miso/frontend/debug.js | 1 + primer-miso/frontend/fd.js | 1 + primer-miso/frontend/fs_mem.js | 1 + primer-miso/frontend/fs_opfs.js | 1 + primer-miso/frontend/index.js | 2 +- primer-miso/frontend/strace.js | 1 + primer-miso/frontend/wasi.js | 1 + primer-miso/frontend/wasi_defs.js | 1 + 9 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 primer-miso/frontend/browser_wasi_shim.js create mode 100644 primer-miso/frontend/debug.js create mode 100644 primer-miso/frontend/fd.js create mode 100644 primer-miso/frontend/fs_mem.js create mode 100644 primer-miso/frontend/fs_opfs.js create mode 100644 primer-miso/frontend/strace.js create mode 100644 primer-miso/frontend/wasi.js create mode 100644 primer-miso/frontend/wasi_defs.js diff --git a/primer-miso/frontend/browser_wasi_shim.js b/primer-miso/frontend/browser_wasi_shim.js new file mode 100644 index 000000000..ee618558c --- /dev/null +++ b/primer-miso/frontend/browser_wasi_shim.js @@ -0,0 +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"; \ No newline at end of file diff --git a/primer-miso/frontend/debug.js b/primer-miso/frontend/debug.js new file mode 100644 index 000000000..b7e03accb --- /dev/null +++ b/primer-miso/frontend/debug.js @@ -0,0 +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); \ No newline at end of file diff --git a/primer-miso/frontend/fd.js b/primer-miso/frontend/fd.js new file mode 100644 index 000000000..7e0526b18 --- /dev/null +++ b/primer-miso/frontend/fd.js @@ -0,0 +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{} \ No newline at end of file diff --git a/primer-miso/frontend/fs_mem.js b/primer-miso/frontend/fs_mem.js new file mode 100644 index 000000000..21393d0d7 --- /dev/null +++ b/primer-miso/frontend/fs_mem.js @@ -0,0 +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,".",wasi.FILETYPE_DIRECTORY)}}else if(cookie==1n){return{ret:wasi.ERRNO_SUCCESS,dirent:new wasi.Dirent(2n,"..",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,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(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{path_open(oflags,fs_rights_base,fd_flags){return{ret:wasi.ERRNO_SUCCESS,fd_obj:new OpenDirectory(this)}}stat(){return new wasi.Filestat(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();if(contents instanceof Array){this.contents=new Map(contents)}else{this.contents=contents}}}export class ConsoleStdout extends Fd{fd_filestat_get(){const filestat=new wasi.Filestat(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(ioffset+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(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}} \ No newline at end of file diff --git a/primer-miso/frontend/index.js b/primer-miso/frontend/index.js index b188b7f11..70d8603ca 100644 --- a/primer-miso/frontend/index.js +++ b/primer-miso/frontend/index.js @@ -1,4 +1,4 @@ -import { WASI, OpenFile, File, ConsoleStdout } from "https://cdn.jsdelivr.net/npm/@bjorn3/browser_wasi_shim@0.3.0/dist/index.js"; +import { WASI, OpenFile, File, ConsoleStdout } from "./browser_wasi_shim.js"; import ghc_wasm_jsffi from "./ghc_wasm_jsffi.js"; const args = []; diff --git a/primer-miso/frontend/strace.js b/primer-miso/frontend/strace.js new file mode 100644 index 000000000..a7573568f --- /dev/null +++ b/primer-miso/frontend/strace.js @@ -0,0 +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}}})} \ No newline at end of file diff --git a/primer-miso/frontend/wasi.js b/primer-miso/frontend/wasi.js new file mode 100644 index 000000000..c1a49d485 --- /dev/null +++ b/primer-miso/frontend/wasi.js @@ -0,0 +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;ipath_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-bufusedbuf_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_,out,nsubscriptions){throw"async io not supported"},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);for(let i=0;i