jsg 0.1.2 → 0.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/README.md +91 -15
- data/exe/jsg +3 -95
- data/lib/jsg/cli.rb +110 -0
- data/lib/jsg/version.rb +1 -1
- data/lib/jsg.rb +211 -0
- data/sig/jsg.rbs +1 -1
- data/template/Gemfile +6 -5
- data/template/assets/browser.script.iife.js +244 -145
- data/template/index.html.erb +6 -22
- data/template/src/main.rb +9 -2
- metadata +17 -26
- data/.idea/.gitignore +0 -8
- data/.idea/jsg.iml +0 -94
- data/.idea/misc.xml +0 -4
- data/.idea/modules.xml +0 -8
- data/.idea/vcs.xml +0 -6
- data/.rspec +0 -3
- data/.rubocop.yml +0 -8
- data/Rakefile +0 -12
- data/jsg.rb +0 -198
|
@@ -1264,8 +1264,7 @@ Licensed under the Apache License 2.0 https://www.openssl.org/source/license.htm
|
|
|
1264
1264
|
https://github.com/kateinoigakukun/wasi-vfs
|
|
1265
1265
|
|
|
1266
1266
|
```
|
|
1267
|
-
|
|
1268
|
-
Licensed under the MIT License
|
|
1267
|
+
Licensed under the Apache License v2.0 with LLVM Exceptions
|
|
1269
1268
|
```
|
|
1270
1269
|
|
|
1271
1270
|
---
|
|
@@ -1309,7 +1308,7 @@ SOFTWARE.
|
|
|
1309
1308
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
1310
1309
|
PERFORMANCE OF THIS SOFTWARE.
|
|
1311
1310
|
***************************************************************************** */
|
|
1312
|
-
/* global Reflect, Promise, SuppressedError, Symbol */
|
|
1311
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
1313
1312
|
|
|
1314
1313
|
|
|
1315
1314
|
function __values(o) {
|
|
@@ -1337,15 +1336,15 @@ SOFTWARE.
|
|
|
1337
1336
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
1338
1337
|
};
|
|
1339
1338
|
|
|
1340
|
-
const CLOCKID_REALTIME=0;const CLOCKID_MONOTONIC=1;const ERRNO_SUCCESS=0;const ERRNO_BADF=8;const ERRNO_EXIST=20;const ERRNO_INVAL=28;const ERRNO_ISDIR=31;const ERRNO_NAMETOOLONG=37;const ERRNO_NOENT=44;const ERRNO_NOSYS=52;const ERRNO_NOTDIR=54;const ERRNO_NOTEMPTY=55;const ERRNO_NOTSUP=58;const ERRNO_PERM=63;const ERRNO_NOTCAPABLE=76;const RIGHTS_FD_WRITE=1<<6;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}}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}}const WHENCE_SET=0;const WHENCE_CUR=1;const WHENCE_END=2;const FILETYPE_DIRECTORY=3;const FILETYPE_REGULAR_FILE=4;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,name,type){
|
|
1339
|
+
const CLOCKID_REALTIME=0;const CLOCKID_MONOTONIC=1;const ERRNO_SUCCESS=0;const ERRNO_BADF=8;const ERRNO_EXIST=20;const ERRNO_INVAL=28;const ERRNO_ISDIR=31;const ERRNO_NAMETOOLONG=37;const ERRNO_NOENT=44;const ERRNO_NOSYS=52;const ERRNO_NOTDIR=54;const ERRNO_NOTEMPTY=55;const ERRNO_NOTSUP=58;const ERRNO_PERM=63;const ERRNO_NOTCAPABLE=76;const RIGHTS_FD_WRITE=1<<6;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}}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}}const WHENCE_SET=0;const WHENCE_CUR=1;const WHENCE_END=2;const FILETYPE_DIRECTORY=3;const FILETYPE_REGULAR_FILE=4;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;}}const FDFLAGS_APPEND=1<<0;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;}}const OFLAGS_CREAT=1<<0;const OFLAGS_DIRECTORY=1<<1;const OFLAGS_EXCL=1<<2;const OFLAGS_TRUNC=1<<3;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;}}const EVENTTYPE_CLOCK=0;const SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME=1<<0;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;}}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;}}const PREOPENTYPE_DIR=0;class PrestatDir{write_bytes(view,ptr){view.setUint32(ptr,this.pr_name.byteLength,true);}constructor(name){this.pr_name=new TextEncoder().encode(name);}}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);}}
|
|
1341
1340
|
|
|
1342
1341
|
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 ()=>{}}}const debug=new Debug(false);
|
|
1343
1342
|
|
|
1344
|
-
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+=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 CLOCKID_MONOTONIC:{resolutionValue=5000n;break}case CLOCKID_REALTIME:{resolutionValue=1000000n;break}default:return ERRNO_NOSYS}const view=new DataView(self.inst.exports.memory.buffer);view.setBigUint64(res_ptr,resolutionValue,true);return ERRNO_SUCCESS},clock_time_get(id,precision,time){const buffer=new DataView(self.inst.exports.memory.buffer);if(id===CLOCKID_REALTIME){buffer.setBigUint64(time,BigInt(new Date().getTime())*1000000n,true);}else if(id==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 ERRNO_SUCCESS}else {return ERRNO_BADF}},fd_allocate(fd,offset,len){if(self.fds[fd]!=undefined){return self.fds[fd].fd_allocate(offset,len)}else {return 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 ERRNO_BADF}},fd_datasync(fd){if(self.fds[fd]!=undefined){return self.fds[fd].fd_sync()}else {return 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 ERRNO_BADF}},fd_fdstat_set_flags(fd,flags){if(self.fds[fd]!=undefined){return self.fds[fd].fd_fdstat_set_flags(flags)}else {return 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 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 ERRNO_BADF}},fd_filestat_set_size(fd,size){if(self.fds[fd]!=undefined){return self.fds[fd].fd_filestat_set_size(size)}else {return 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 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=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!=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 ERRNO_SUCCESS}else {return 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 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?ERRNO_NAMETOOLONG:ERRNO_SUCCESS}else {return 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=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!=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 ERRNO_SUCCESS}else {return 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=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!=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 ERRNO_SUCCESS}else {return 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 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 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 ERRNO_BADF}},fd_sync(fd){if(self.fds[fd]!=undefined){return self.fds[fd].fd_sync()}else {return 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 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=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!=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 ERRNO_SUCCESS}else {return 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 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 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 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 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 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 ERRNO_BADF}buffer8.set(data_buf,buf_ptr);buffer.setUint32(nread_ptr,data_buf.length,true);}return ret}else {return 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 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!=ERRNO_SUCCESS){if(self.fds[fd].path_link(old_path,inode_obj,true)!=ERRNO_SUCCESS){throw "path_link should always return success when relinking an inode back to the original place"}}return ret}else {return 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){new TextDecoder("utf-8").decode(buffer8.slice(old_path_ptr,old_path_ptr+old_path_len));new TextDecoder("utf-8").decode(buffer8.slice(new_path_ptr,new_path_ptr+new_path_len));return ERRNO_NOTSUP}else {return 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 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<buf_len;i++){buffer8[buf+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"}};}};
|
|
1343
|
+
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 CLOCKID_MONOTONIC:{resolutionValue=5000n;break}case CLOCKID_REALTIME:{resolutionValue=1000000n;break}default:return ERRNO_NOSYS}const view=new DataView(self.inst.exports.memory.buffer);view.setBigUint64(res_ptr,resolutionValue,true);return ERRNO_SUCCESS},clock_time_get(id,precision,time){const buffer=new DataView(self.inst.exports.memory.buffer);if(id===CLOCKID_REALTIME){buffer.setBigUint64(time,BigInt(new Date().getTime())*1000000n,true);}else if(id==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 ERRNO_SUCCESS}else {return ERRNO_BADF}},fd_allocate(fd,offset,len){if(self.fds[fd]!=undefined){return self.fds[fd].fd_allocate(offset,len)}else {return 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 ERRNO_BADF}},fd_datasync(fd){if(self.fds[fd]!=undefined){return self.fds[fd].fd_sync()}else {return 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 ERRNO_BADF}},fd_fdstat_set_flags(fd,flags){if(self.fds[fd]!=undefined){return self.fds[fd].fd_fdstat_set_flags(flags)}else {return 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 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 ERRNO_BADF}},fd_filestat_set_size(fd,size){if(self.fds[fd]!=undefined){return self.fds[fd].fd_filestat_set_size(size)}else {return 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 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=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!=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 ERRNO_SUCCESS}else {return 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 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?ERRNO_NAMETOOLONG:ERRNO_SUCCESS}else {return 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=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!=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 ERRNO_SUCCESS}else {return 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=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!=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 ERRNO_SUCCESS}else {return 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 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 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 ERRNO_BADF}},fd_sync(fd){if(self.fds[fd]!=undefined){return self.fds[fd].fd_sync()}else {return 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 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=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!=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 ERRNO_SUCCESS}else {return 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 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 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 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 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 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 ERRNO_BADF}buffer8.set(data_buf,buf_ptr);buffer.setUint32(nread_ptr,data_buf.length,true);}return ret}else {return 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 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!=ERRNO_SUCCESS){if(self.fds[fd].path_link(old_path,inode_obj,true)!=ERRNO_SUCCESS){throw "path_link should always return success when relinking an inode back to the original place"}}return ret}else {return 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){new TextDecoder("utf-8").decode(buffer8.slice(old_path_ptr,old_path_ptr+old_path_len));new TextDecoder("utf-8").decode(buffer8.slice(new_path_ptr,new_path_ptr+new_path_len));return ERRNO_NOTSUP}else {return 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 ERRNO_BADF}},poll_oneoff(in_ptr,out_ptr,nsubscriptions){if(nsubscriptions===0){return ERRNO_INVAL}if(nsubscriptions>1){debug.log("poll_oneoff: only a single subscription is supported");return ERRNO_NOTSUP}const buffer=new DataView(self.inst.exports.memory.buffer);const s=Subscription.read_bytes(buffer,in_ptr);const eventtype=s.eventtype;const clockid=s.clockid;const timeout=s.timeout;if(eventtype!==EVENTTYPE_CLOCK){debug.log("poll_oneoff: only clock subscriptions are supported");return ERRNO_NOTSUP}let getNow=undefined;if(clockid===CLOCKID_MONOTONIC){getNow=()=>BigInt(Math.round(performance.now()*1e6));}else if(clockid===CLOCKID_REALTIME){getNow=()=>BigInt(new Date().getTime())*1000000n;}else {return ERRNO_INVAL}const endTime=(s.flags&SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME)!==0?timeout:getNow()+timeout;while(endTime>getNow()){}const event=new Event(s.userdata,ERRNO_SUCCESS,eventtype);event.write_bytes(buffer,out_ptr);return 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"}};}};
|
|
1345
1344
|
|
|
1346
|
-
class Fd{fd_allocate(offset,len){return ERRNO_NOTSUP}fd_close(){return 0}fd_fdstat_get(){return {ret:ERRNO_NOTSUP,fdstat:null}}fd_fdstat_set_flags(flags){return ERRNO_NOTSUP}fd_fdstat_set_rights(fs_rights_base,fs_rights_inheriting){return ERRNO_NOTSUP}fd_filestat_get(){return {ret:ERRNO_NOTSUP,filestat:null}}fd_filestat_set_size(size){return ERRNO_NOTSUP}fd_filestat_set_times(atim,mtim,fst_flags){return ERRNO_NOTSUP}fd_pread(size,offset){return {ret:ERRNO_NOTSUP,data:new Uint8Array}}fd_prestat_get(){return {ret:ERRNO_NOTSUP,prestat:null}}fd_pwrite(data,offset){return {ret:ERRNO_NOTSUP,nwritten:0}}fd_read(size){return {ret:ERRNO_NOTSUP,data:new Uint8Array}}fd_readdir_single(cookie){return {ret:ERRNO_NOTSUP,dirent:null}}fd_seek(offset,whence){return {ret:ERRNO_NOTSUP,offset:0n}}fd_sync(){return 0}fd_tell(){return {ret:ERRNO_NOTSUP,offset:0n}}fd_write(data){return {ret:ERRNO_NOTSUP,nwritten:0}}path_create_directory(path){return ERRNO_NOTSUP}path_filestat_get(flags,path){return {ret:ERRNO_NOTSUP,filestat:null}}path_filestat_set_times(flags,path,atim,mtim,fst_flags){return ERRNO_NOTSUP}path_link(path,inode,allow_dir){return ERRNO_NOTSUP}path_unlink(path){return {ret:ERRNO_NOTSUP,inode_obj:null}}path_lookup(path,dirflags){return {ret:ERRNO_NOTSUP,inode_obj:null}}path_open(dirflags,path,oflags,fs_rights_base,fs_rights_inheriting,fd_flags){return {ret:ERRNO_NOTDIR,fd_obj:null}}path_readlink(path){return {ret:ERRNO_NOTSUP,data:null}}path_remove_directory(path){return ERRNO_NOTSUP}path_rename(old_path,new_fd,new_path){return ERRNO_NOTSUP}path_unlink_file(path){return ERRNO_NOTSUP}}class Inode{}
|
|
1345
|
+
class Fd{fd_allocate(offset,len){return ERRNO_NOTSUP}fd_close(){return 0}fd_fdstat_get(){return {ret:ERRNO_NOTSUP,fdstat:null}}fd_fdstat_set_flags(flags){return ERRNO_NOTSUP}fd_fdstat_set_rights(fs_rights_base,fs_rights_inheriting){return ERRNO_NOTSUP}fd_filestat_get(){return {ret:ERRNO_NOTSUP,filestat:null}}fd_filestat_set_size(size){return ERRNO_NOTSUP}fd_filestat_set_times(atim,mtim,fst_flags){return ERRNO_NOTSUP}fd_pread(size,offset){return {ret:ERRNO_NOTSUP,data:new Uint8Array}}fd_prestat_get(){return {ret:ERRNO_NOTSUP,prestat:null}}fd_pwrite(data,offset){return {ret:ERRNO_NOTSUP,nwritten:0}}fd_read(size){return {ret:ERRNO_NOTSUP,data:new Uint8Array}}fd_readdir_single(cookie){return {ret:ERRNO_NOTSUP,dirent:null}}fd_seek(offset,whence){return {ret:ERRNO_NOTSUP,offset:0n}}fd_sync(){return 0}fd_tell(){return {ret:ERRNO_NOTSUP,offset:0n}}fd_write(data){return {ret:ERRNO_NOTSUP,nwritten:0}}path_create_directory(path){return ERRNO_NOTSUP}path_filestat_get(flags,path){return {ret:ERRNO_NOTSUP,filestat:null}}path_filestat_set_times(flags,path,atim,mtim,fst_flags){return ERRNO_NOTSUP}path_link(path,inode,allow_dir){return ERRNO_NOTSUP}path_unlink(path){return {ret:ERRNO_NOTSUP,inode_obj:null}}path_lookup(path,dirflags){return {ret:ERRNO_NOTSUP,inode_obj:null}}path_open(dirflags,path,oflags,fs_rights_base,fs_rights_inheriting,fd_flags){return {ret:ERRNO_NOTDIR,fd_obj:null}}path_readlink(path){return {ret:ERRNO_NOTSUP,data:null}}path_remove_directory(path){return ERRNO_NOTSUP}path_rename(old_path,new_fd,new_path){return ERRNO_NOTSUP}path_unlink_file(path){return ERRNO_NOTSUP}}class Inode{static issue_ino(){return Inode.next_ino++}static root_ino(){return 0n}constructor(){this.ino=Inode.issue_ino();}}Inode.next_ino=1n;
|
|
1347
1346
|
|
|
1348
|
-
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 ERRNO_SUCCESS}fd_fdstat_get(){return {ret:0,fdstat:new Fdstat(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 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 WHENCE_SET:calculated_offset=offset;break;case WHENCE_CUR:calculated_offset=this.file_pos+offset;break;case WHENCE_END:calculated_offset=BigInt(this.file.data.byteLength)+offset;break;default:return {ret:ERRNO_INVAL,offset:0n}}if(calculated_offset<0){return {ret: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: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: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;}}class OpenDirectory extends Fd{fd_seek(offset,whence){return {ret:ERRNO_BADF,offset:0n}}fd_tell(){return {ret:ERRNO_BADF,offset:0n}}fd_allocate(offset,len){return ERRNO_BADF}fd_fdstat_get(){return {ret:0,fdstat:new Fdstat(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:ERRNO_SUCCESS,dirent:new Dirent(1n,".",FILETYPE_DIRECTORY)}}else if(cookie==1n){return {ret:ERRNO_SUCCESS,dirent:new Dirent(2n,"..",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 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: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!=ERRNO_NOENT){return {ret,fd_obj:null}}if((oflags&OFLAGS_CREAT)==OFLAGS_CREAT){const{ret,entry:new_entry}=this.dir.create_entry_for_path(path_str,(oflags&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY);if(new_entry==null){return {ret,fd_obj:null}}entry=new_entry;}else {return {ret:ERRNO_NOENT,fd_obj:null}}}else if((oflags&OFLAGS_EXCL)==OFLAGS_EXCL){return {ret:ERRNO_EXIST,fd_obj:null}}if((oflags&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY&&entry.stat().filetype!==FILETYPE_DIRECTORY){return {ret: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,OFLAGS_CREAT|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 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==FILETYPE_DIRECTORY;const target_is_dir=entry.stat().filetype==FILETYPE_DIRECTORY;if(source_is_dir&&target_is_dir){if(allow_dir&&entry instanceof Directory){if(entry.contents.size==0);else {return ERRNO_NOTEMPTY}}else {return ERRNO_EXIST}}else if(source_is_dir&&!target_is_dir){return ERRNO_NOTDIR}else if(!source_is_dir&&target_is_dir){return ERRNO_ISDIR}else if(inode.stat().filetype==FILETYPE_REGULAR_FILE&&entry.stat().filetype==FILETYPE_REGULAR_FILE);else {return ERRNO_EXIST}}if(!allow_dir&&inode.stat().filetype==FILETYPE_DIRECTORY){return ERRNO_PERM}parent_entry.contents.set(filename,inode);return 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:ERRNO_NOENT,inode_obj:null}}parent_entry.contents.delete(filename);return {ret: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===FILETYPE_DIRECTORY){return ERRNO_ISDIR}parent_entry.contents.delete(filename);return 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!==FILETYPE_DIRECTORY){return ERRNO_NOTDIR}if(entry.contents.size!==0){return ERRNO_NOTEMPTY}if(!parent_entry.contents.delete(filename)){return ERRNO_NOENT}return ERRNO_SUCCESS}fd_filestat_get(){return {ret:0,filestat:this.dir.stat()}}fd_filestat_set_size(size){return ERRNO_BADF}fd_read(size){return {ret:ERRNO_BADF,data:new Uint8Array}}fd_pread(size,offset){return {ret:ERRNO_BADF,data:new Uint8Array}}fd_write(data){return {ret:ERRNO_BADF,nwritten:0}}fd_pwrite(data,offset){return {ret:ERRNO_BADF,nwritten:0}}constructor(dir){super();this.dir=dir;}}class PreopenDirectory extends OpenDirectory{fd_prestat_get(){return {ret:0,prestat:Prestat.dir(this.prestat_name)}}constructor(name,contents){super(new Directory(contents));this.prestat_name=name;}}class File extends Inode{path_open(oflags,fs_rights_base,fd_flags){if(this.readonly&&(fs_rights_base&BigInt(RIGHTS_FD_WRITE))==BigInt(RIGHTS_FD_WRITE)){return {ret:ERRNO_PERM,fd_obj:null}}if((oflags&OFLAGS_TRUNC)==OFLAGS_TRUNC){if(this.readonly)return {ret:ERRNO_PERM,fd_obj:null};this.data=new Uint8Array([]);}const file=new OpenFile(this);if(fd_flags&FDFLAGS_APPEND)file.fd_seek(0n,WHENCE_END);return {ret:ERRNO_SUCCESS,fd_obj:file}}get size(){return BigInt(this.data.byteLength)}stat(){return new Filestat(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:ERRNO_NOTCAPABLE,path:null}}if(path.includes("\x00")){return {ret:ERRNO_INVAL,path:null}}for(const component of path.split("/")){if(component===""||component==="."){continue}if(component===".."){if(self.parts.pop()==undefined){return {ret:ERRNO_NOTCAPABLE,path:null}}continue}self.parts.push(component);}return {ret: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;}};class Directory extends Inode{path_open(oflags,fs_rights_base,fd_flags){return {ret:ERRNO_SUCCESS,fd_obj:new OpenDirectory(this)}}stat(){return new Filestat(FILETYPE_DIRECTORY,0n)}get_entry_for_path(path){let entry=this;for(const component of path.parts){if(!(entry instanceof Directory)){return {ret:ERRNO_NOTDIR,entry:null}}const child=entry.contents.get(component);if(child!==undefined){entry=child;}else {debug.log(component);return {ret:ERRNO_NOENT,entry:null}}}if(path.is_dir){if(entry.stat().filetype!=FILETYPE_DIRECTORY){return {ret:ERRNO_NOTDIR,entry:null}}}return {ret:ERRNO_SUCCESS,entry}}get_parent_dir_and_entry_for_path(path,allow_undefined){const filename=path.parts.pop();if(filename===undefined){return {ret: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:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}}const entry=parent_entry.contents.get(filename);if(entry===undefined){if(!allow_undefined){return {ret:ERRNO_NOENT,parent_entry:null,filename:null,entry:null}}else {return {ret:ERRNO_SUCCESS,parent_entry,filename,entry:null}}}if(path.is_dir){if(entry.stat().filetype!=FILETYPE_DIRECTORY){return {ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}}}return {ret: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: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:ERRNO_SUCCESS,entry}}constructor(contents){super();if(contents instanceof Array){this.contents=new Map(contents);}else {this.contents=contents;}}}
|
|
1347
|
+
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 ERRNO_SUCCESS}fd_fdstat_get(){return {ret:0,fdstat:new Fdstat(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 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 WHENCE_SET:calculated_offset=offset;break;case WHENCE_CUR:calculated_offset=this.file_pos+offset;break;case WHENCE_END:calculated_offset=BigInt(this.file.data.byteLength)+offset;break;default:return {ret:ERRNO_INVAL,offset:0n}}if(calculated_offset<0){return {ret: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: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: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;}}class OpenDirectory extends Fd{fd_seek(offset,whence){return {ret:ERRNO_BADF,offset:0n}}fd_tell(){return {ret:ERRNO_BADF,offset:0n}}fd_allocate(offset,len){return ERRNO_BADF}fd_fdstat_get(){return {ret:0,fdstat:new Fdstat(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:ERRNO_SUCCESS,dirent:new Dirent(1n,this.dir.ino,".",FILETYPE_DIRECTORY)}}else if(cookie==1n){return {ret:ERRNO_SUCCESS,dirent:new Dirent(2n,this.dir.parent_ino(),"..",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 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: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!=ERRNO_NOENT){return {ret,fd_obj:null}}if((oflags&OFLAGS_CREAT)==OFLAGS_CREAT){const{ret,entry:new_entry}=this.dir.create_entry_for_path(path_str,(oflags&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY);if(new_entry==null){return {ret,fd_obj:null}}entry=new_entry;}else {return {ret:ERRNO_NOENT,fd_obj:null}}}else if((oflags&OFLAGS_EXCL)==OFLAGS_EXCL){return {ret:ERRNO_EXIST,fd_obj:null}}if((oflags&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY&&entry.stat().filetype!==FILETYPE_DIRECTORY){return {ret: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,OFLAGS_CREAT|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 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==FILETYPE_DIRECTORY;const target_is_dir=entry.stat().filetype==FILETYPE_DIRECTORY;if(source_is_dir&&target_is_dir){if(allow_dir&&entry instanceof Directory){if(entry.contents.size==0);else {return ERRNO_NOTEMPTY}}else {return ERRNO_EXIST}}else if(source_is_dir&&!target_is_dir){return ERRNO_NOTDIR}else if(!source_is_dir&&target_is_dir){return ERRNO_ISDIR}else if(inode.stat().filetype==FILETYPE_REGULAR_FILE&&entry.stat().filetype==FILETYPE_REGULAR_FILE);else {return ERRNO_EXIST}}if(!allow_dir&&inode.stat().filetype==FILETYPE_DIRECTORY){return ERRNO_PERM}parent_entry.contents.set(filename,inode);return 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:ERRNO_NOENT,inode_obj:null}}parent_entry.contents.delete(filename);return {ret: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===FILETYPE_DIRECTORY){return ERRNO_ISDIR}parent_entry.contents.delete(filename);return 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!==FILETYPE_DIRECTORY){return ERRNO_NOTDIR}if(entry.contents.size!==0){return ERRNO_NOTEMPTY}if(!parent_entry.contents.delete(filename)){return ERRNO_NOENT}return ERRNO_SUCCESS}fd_filestat_get(){return {ret:0,filestat:this.dir.stat()}}fd_filestat_set_size(size){return ERRNO_BADF}fd_read(size){return {ret:ERRNO_BADF,data:new Uint8Array}}fd_pread(size,offset){return {ret:ERRNO_BADF,data:new Uint8Array}}fd_write(data){return {ret:ERRNO_BADF,nwritten:0}}fd_pwrite(data,offset){return {ret:ERRNO_BADF,nwritten:0}}constructor(dir){super();this.dir=dir;}}class PreopenDirectory extends OpenDirectory{fd_prestat_get(){return {ret:0,prestat:Prestat.dir(this.prestat_name)}}constructor(name,contents){super(new Directory(contents));this.prestat_name=name;}}class File extends Inode{path_open(oflags,fs_rights_base,fd_flags){if(this.readonly&&(fs_rights_base&BigInt(RIGHTS_FD_WRITE))==BigInt(RIGHTS_FD_WRITE)){return {ret:ERRNO_PERM,fd_obj:null}}if((oflags&OFLAGS_TRUNC)==OFLAGS_TRUNC){if(this.readonly)return {ret:ERRNO_PERM,fd_obj:null};this.data=new Uint8Array([]);}const file=new OpenFile(this);if(fd_flags&FDFLAGS_APPEND)file.fd_seek(0n,WHENCE_END);return {ret:ERRNO_SUCCESS,fd_obj:file}}get size(){return BigInt(this.data.byteLength)}stat(){return new Filestat(this.ino,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:ERRNO_NOTCAPABLE,path:null}}if(path.includes("\x00")){return {ret:ERRNO_INVAL,path:null}}for(const component of path.split("/")){if(component===""||component==="."){continue}if(component===".."){if(self.parts.pop()==undefined){return {ret:ERRNO_NOTCAPABLE,path:null}}continue}self.parts.push(component);}return {ret: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;}};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:ERRNO_SUCCESS,fd_obj:new OpenDirectory(this)}}stat(){return new Filestat(this.ino,FILETYPE_DIRECTORY,0n)}get_entry_for_path(path){let entry=this;for(const component of path.parts){if(!(entry instanceof Directory)){return {ret:ERRNO_NOTDIR,entry:null}}const child=entry.contents.get(component);if(child!==undefined){entry=child;}else {debug.log(component);return {ret:ERRNO_NOENT,entry:null}}}if(path.is_dir){if(entry.stat().filetype!=FILETYPE_DIRECTORY){return {ret:ERRNO_NOTDIR,entry:null}}}return {ret:ERRNO_SUCCESS,entry}}get_parent_dir_and_entry_for_path(path,allow_undefined){const filename=path.parts.pop();if(filename===undefined){return {ret: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:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}}const entry=parent_entry.contents.get(filename);if(entry===undefined){if(!allow_undefined){return {ret:ERRNO_NOENT,parent_entry:null,filename:null,entry:null}}else {return {ret:ERRNO_SUCCESS,parent_entry,filename,entry:null}}}if(path.is_dir){if(entry.stat().filetype!=FILETYPE_DIRECTORY){return {ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}}}return {ret: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: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: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;}}}}
|
|
1349
1348
|
|
|
1350
1349
|
/**
|
|
1351
1350
|
* Create a console printer that can be used as an overlay of WASI imports.
|
|
@@ -1438,7 +1437,9 @@ SOFTWARE.
|
|
|
1438
1437
|
const fs_filetypePtr = fdstat + 0;
|
|
1439
1438
|
view.setUint8(fs_filetypePtr, 2); // FILETYPE_CHARACTER_DEVICE
|
|
1440
1439
|
const fs_rights_basePtr = fdstat + 8;
|
|
1441
|
-
|
|
1440
|
+
// See https://github.com/WebAssembly/WASI/blob/v0.2.0/legacy/preview1/docs.md#record-members
|
|
1441
|
+
const RIGHTS_FD_WRITE = 1 << 6;
|
|
1442
|
+
view.setBigUint64(fs_rights_basePtr, BigInt(RIGHTS_FD_WRITE), true);
|
|
1442
1443
|
return 0;
|
|
1443
1444
|
};
|
|
1444
1445
|
},
|
|
@@ -1525,38 +1526,23 @@ SOFTWARE.
|
|
|
1525
1526
|
class RbAbiGuest {
|
|
1526
1527
|
constructor() {
|
|
1527
1528
|
this._resource0_slab = new Slab();
|
|
1528
|
-
this._resource1_slab = new Slab();
|
|
1529
1529
|
}
|
|
1530
1530
|
addToImports(imports) {
|
|
1531
1531
|
if (!("canonical_abi" in imports))
|
|
1532
1532
|
imports["canonical_abi"] = {};
|
|
1533
|
-
imports.canonical_abi['resource_drop_rb-
|
|
1533
|
+
imports.canonical_abi['resource_drop_rb-abi-value'] = i => {
|
|
1534
1534
|
this._resource0_slab.remove(i).drop();
|
|
1535
1535
|
};
|
|
1536
|
-
imports.canonical_abi['resource_clone_rb-
|
|
1536
|
+
imports.canonical_abi['resource_clone_rb-abi-value'] = i => {
|
|
1537
1537
|
const obj = this._resource0_slab.get(i);
|
|
1538
1538
|
return this._resource0_slab.insert(obj.clone());
|
|
1539
1539
|
};
|
|
1540
|
-
imports.canonical_abi['resource_get_rb-iseq'] = i => {
|
|
1541
|
-
return this._resource0_slab.get(i)._wasm_val;
|
|
1542
|
-
};
|
|
1543
|
-
imports.canonical_abi['resource_new_rb-iseq'] = i => {
|
|
1544
|
-
this._registry0;
|
|
1545
|
-
return this._resource0_slab.insert(new RbIseq(i, this));
|
|
1546
|
-
};
|
|
1547
|
-
imports.canonical_abi['resource_drop_rb-abi-value'] = i => {
|
|
1548
|
-
this._resource1_slab.remove(i).drop();
|
|
1549
|
-
};
|
|
1550
|
-
imports.canonical_abi['resource_clone_rb-abi-value'] = i => {
|
|
1551
|
-
const obj = this._resource1_slab.get(i);
|
|
1552
|
-
return this._resource1_slab.insert(obj.clone());
|
|
1553
|
-
};
|
|
1554
1540
|
imports.canonical_abi['resource_get_rb-abi-value'] = i => {
|
|
1555
|
-
return this.
|
|
1541
|
+
return this._resource0_slab.get(i)._wasm_val;
|
|
1556
1542
|
};
|
|
1557
1543
|
imports.canonical_abi['resource_new_rb-abi-value'] = i => {
|
|
1558
|
-
this.
|
|
1559
|
-
return this.
|
|
1544
|
+
this._registry0;
|
|
1545
|
+
return this._resource0_slab.insert(new RbAbiValue(i, this));
|
|
1560
1546
|
};
|
|
1561
1547
|
}
|
|
1562
1548
|
async instantiate(module, imports) {
|
|
@@ -1577,32 +1563,12 @@ SOFTWARE.
|
|
|
1577
1563
|
this.instance = instance;
|
|
1578
1564
|
}
|
|
1579
1565
|
this._exports = this.instance.exports;
|
|
1580
|
-
this._registry0 = new FinalizationRegistry(this._exports['canonical_abi_drop_rb-
|
|
1581
|
-
this._registry1 = new FinalizationRegistry(this._exports['canonical_abi_drop_rb-abi-value']);
|
|
1566
|
+
this._registry0 = new FinalizationRegistry(this._exports['canonical_abi_drop_rb-abi-value']);
|
|
1582
1567
|
}
|
|
1583
1568
|
rubyShowVersion() {
|
|
1584
1569
|
this._exports['ruby-show-version: func() -> ()']();
|
|
1585
1570
|
}
|
|
1586
|
-
rubyInit() {
|
|
1587
|
-
this._exports['ruby-init: func() -> ()']();
|
|
1588
|
-
}
|
|
1589
|
-
rubySysinit(arg0) {
|
|
1590
|
-
const memory = this._exports.memory;
|
|
1591
|
-
const realloc = this._exports["cabi_realloc"];
|
|
1592
|
-
const vec1 = arg0;
|
|
1593
|
-
const len1 = vec1.length;
|
|
1594
|
-
const result1 = realloc(0, 0, 4, len1 * 8);
|
|
1595
|
-
for (let i = 0; i < vec1.length; i++) {
|
|
1596
|
-
const e = vec1[i];
|
|
1597
|
-
const base = result1 + i * 8;
|
|
1598
|
-
const ptr0 = utf8_encode(e, realloc, memory);
|
|
1599
|
-
const len0 = UTF8_ENCODED_LEN;
|
|
1600
|
-
data_view(memory).setInt32(base + 4, len0, true);
|
|
1601
|
-
data_view(memory).setInt32(base + 0, ptr0, true);
|
|
1602
|
-
}
|
|
1603
|
-
this._exports['ruby-sysinit: func(args: list<string>) -> ()'](result1, len1);
|
|
1604
|
-
}
|
|
1605
|
-
rubyOptions(arg0) {
|
|
1571
|
+
rubyInit(arg0) {
|
|
1606
1572
|
const memory = this._exports.memory;
|
|
1607
1573
|
const realloc = this._exports["cabi_realloc"];
|
|
1608
1574
|
const vec1 = arg0;
|
|
@@ -1616,15 +1582,7 @@ SOFTWARE.
|
|
|
1616
1582
|
data_view(memory).setInt32(base + 4, len0, true);
|
|
1617
1583
|
data_view(memory).setInt32(base + 0, ptr0, true);
|
|
1618
1584
|
}
|
|
1619
|
-
|
|
1620
|
-
return this._resource0_slab.remove(ret);
|
|
1621
|
-
}
|
|
1622
|
-
rubyScript(arg0) {
|
|
1623
|
-
const memory = this._exports.memory;
|
|
1624
|
-
const realloc = this._exports["cabi_realloc"];
|
|
1625
|
-
const ptr0 = utf8_encode(arg0, realloc, memory);
|
|
1626
|
-
const len0 = UTF8_ENCODED_LEN;
|
|
1627
|
-
this._exports['ruby-script: func(name: string) -> ()'](ptr0, len0);
|
|
1585
|
+
this._exports['ruby-init: func(args: list<string>) -> ()'](result1, len1);
|
|
1628
1586
|
}
|
|
1629
1587
|
rubyInitLoadpath() {
|
|
1630
1588
|
this._exports['ruby-init-loadpath: func() -> ()']();
|
|
@@ -1635,7 +1593,7 @@ SOFTWARE.
|
|
|
1635
1593
|
const ptr0 = utf8_encode(arg0, realloc, memory);
|
|
1636
1594
|
const len0 = UTF8_ENCODED_LEN;
|
|
1637
1595
|
const ret = this._exports['rb-eval-string-protect: func(str: string) -> tuple<handle<rb-abi-value>, s32>'](ptr0, len0);
|
|
1638
|
-
return [this.
|
|
1596
|
+
return [this._resource0_slab.remove(data_view(memory).getInt32(ret + 0, true)), data_view(memory).getInt32(ret + 4, true)];
|
|
1639
1597
|
}
|
|
1640
1598
|
rbFuncallvProtect(arg0, arg1, arg2) {
|
|
1641
1599
|
const memory = this._exports.memory;
|
|
@@ -1652,10 +1610,10 @@ SOFTWARE.
|
|
|
1652
1610
|
const obj1 = e;
|
|
1653
1611
|
if (!(obj1 instanceof RbAbiValue))
|
|
1654
1612
|
throw new TypeError('expected instance of RbAbiValue');
|
|
1655
|
-
data_view(memory).setInt32(base + 0, this.
|
|
1613
|
+
data_view(memory).setInt32(base + 0, this._resource0_slab.insert(obj1.clone()), true);
|
|
1656
1614
|
}
|
|
1657
|
-
const ret = this._exports['rb-funcallv-protect: func(recv: handle<rb-abi-value>, mid: u32, args: list<handle<rb-abi-value>>) -> tuple<handle<rb-abi-value>, s32>'](this.
|
|
1658
|
-
return [this.
|
|
1615
|
+
const ret = this._exports['rb-funcallv-protect: func(recv: handle<rb-abi-value>, mid: u32, args: list<handle<rb-abi-value>>) -> tuple<handle<rb-abi-value>, s32>'](this._resource0_slab.insert(obj0.clone()), to_uint32(arg1), result2, len2);
|
|
1616
|
+
return [this._resource0_slab.remove(data_view(memory).getInt32(ret + 0, true)), data_view(memory).getInt32(ret + 4, true)];
|
|
1659
1617
|
}
|
|
1660
1618
|
rbIntern(arg0) {
|
|
1661
1619
|
const memory = this._exports.memory;
|
|
@@ -1667,7 +1625,7 @@ SOFTWARE.
|
|
|
1667
1625
|
}
|
|
1668
1626
|
rbErrinfo() {
|
|
1669
1627
|
const ret = this._exports['rb-errinfo: func() -> handle<rb-abi-value>']();
|
|
1670
|
-
return this.
|
|
1628
|
+
return this._resource0_slab.remove(ret);
|
|
1671
1629
|
}
|
|
1672
1630
|
rbClearErrinfo() {
|
|
1673
1631
|
this._exports['rb-clear-errinfo: func() -> ()']();
|
|
@@ -1677,7 +1635,7 @@ SOFTWARE.
|
|
|
1677
1635
|
const obj0 = arg0;
|
|
1678
1636
|
if (!(obj0 instanceof RbAbiValue))
|
|
1679
1637
|
throw new TypeError('expected instance of RbAbiValue');
|
|
1680
|
-
const ret = this._exports['rstring-ptr: func(value: handle<rb-abi-value>) -> string'](this.
|
|
1638
|
+
const ret = this._exports['rstring-ptr: func(value: handle<rb-abi-value>) -> string'](this._resource0_slab.insert(obj0.clone()));
|
|
1681
1639
|
const ptr1 = data_view(memory).getInt32(ret + 0, true);
|
|
1682
1640
|
const len1 = data_view(memory).getInt32(ret + 4, true);
|
|
1683
1641
|
const result1 = UTF8_DECODER.decode(new Uint8Array(memory.buffer, ptr1, len1));
|
|
@@ -1703,7 +1661,7 @@ SOFTWARE.
|
|
|
1703
1661
|
return bool0 == 0 ? false : (bool0 == 1 ? true : throw_invalid_bool());
|
|
1704
1662
|
}
|
|
1705
1663
|
}
|
|
1706
|
-
class
|
|
1664
|
+
class RbAbiValue {
|
|
1707
1665
|
constructor(wasm_val, obj) {
|
|
1708
1666
|
this._wasm_val = wasm_val;
|
|
1709
1667
|
this._obj = obj;
|
|
@@ -1719,30 +1677,6 @@ SOFTWARE.
|
|
|
1719
1677
|
if (this._refcnt !== 0)
|
|
1720
1678
|
return;
|
|
1721
1679
|
this._obj._registry0.unregister(this);
|
|
1722
|
-
const dtor = this._obj._exports['canonical_abi_drop_rb-iseq'];
|
|
1723
|
-
const wasm_val = this._wasm_val;
|
|
1724
|
-
delete this._obj;
|
|
1725
|
-
delete this._refcnt;
|
|
1726
|
-
delete this._wasm_val;
|
|
1727
|
-
dtor(wasm_val);
|
|
1728
|
-
}
|
|
1729
|
-
}
|
|
1730
|
-
class RbAbiValue {
|
|
1731
|
-
constructor(wasm_val, obj) {
|
|
1732
|
-
this._wasm_val = wasm_val;
|
|
1733
|
-
this._obj = obj;
|
|
1734
|
-
this._refcnt = 1;
|
|
1735
|
-
obj._registry1.register(this, wasm_val, this);
|
|
1736
|
-
}
|
|
1737
|
-
clone() {
|
|
1738
|
-
this._refcnt += 1;
|
|
1739
|
-
return this;
|
|
1740
|
-
}
|
|
1741
|
-
drop() {
|
|
1742
|
-
this._refcnt -= 1;
|
|
1743
|
-
if (this._refcnt !== 0)
|
|
1744
|
-
return;
|
|
1745
|
-
this._obj._registry1.unregister(this);
|
|
1746
1680
|
const dtor = this._obj._exports['canonical_abi_drop_rb-abi-value'];
|
|
1747
1681
|
const wasm_val = this._wasm_val;
|
|
1748
1682
|
delete this._obj;
|
|
@@ -2044,17 +1978,8 @@ SOFTWARE.
|
|
|
2044
1978
|
rubyShowVersion() {
|
|
2045
1979
|
this.underlying.rubyShowVersion();
|
|
2046
1980
|
}
|
|
2047
|
-
rubyInit() {
|
|
2048
|
-
this.underlying.rubyInit();
|
|
2049
|
-
}
|
|
2050
|
-
rubySysinit(args) {
|
|
2051
|
-
this.underlying.rubySysinit(args);
|
|
2052
|
-
}
|
|
2053
|
-
rubyOptions(args) {
|
|
2054
|
-
this.underlying.rubyOptions(args);
|
|
2055
|
-
}
|
|
2056
|
-
rubyScript(name) {
|
|
2057
|
-
this.underlying.rubyScript(name);
|
|
1981
|
+
rubyInit(args) {
|
|
1982
|
+
this.underlying.rubyInit(args);
|
|
2058
1983
|
}
|
|
2059
1984
|
rubyInitLoadpath() {
|
|
2060
1985
|
this.underlying.rubyInitLoadpath();
|
|
@@ -2099,24 +2024,124 @@ SOFTWARE.
|
|
|
2099
2024
|
|
|
2100
2025
|
/**
|
|
2101
2026
|
* A Ruby VM instance
|
|
2102
|
-
*
|
|
2103
|
-
* @
|
|
2104
|
-
*
|
|
2105
|
-
* const wasi = new WASI();
|
|
2106
|
-
* const vm = new RubyVM();
|
|
2107
|
-
* const imports = {
|
|
2108
|
-
* wasi_snapshot_preview1: wasi.wasiImport,
|
|
2109
|
-
* };
|
|
2110
|
-
*
|
|
2111
|
-
* vm.addToImports(imports);
|
|
2112
|
-
*
|
|
2113
|
-
* const instance = await WebAssembly.instantiate(rubyModule, imports);
|
|
2114
|
-
* await vm.setInstance(instance);
|
|
2115
|
-
* wasi.initialize(instance);
|
|
2116
|
-
* vm.initialize();
|
|
2117
|
-
*
|
|
2027
|
+
* @see {@link RubyVM.instantiateComponent} and {@link RubyVM.instantiateModule} to create a new instance
|
|
2028
|
+
* @category Essentials
|
|
2118
2029
|
*/
|
|
2119
2030
|
class RubyVM {
|
|
2031
|
+
/**
|
|
2032
|
+
* Instantiate a Ruby VM with the given WebAssembly Core module with WASI Preview 1 implementation.
|
|
2033
|
+
*
|
|
2034
|
+
* @param options The options to instantiate the Ruby VM
|
|
2035
|
+
* @returns A promise that resolves to the Ruby VM instance and the WebAssembly instance
|
|
2036
|
+
* @category Essentials
|
|
2037
|
+
*
|
|
2038
|
+
* @example
|
|
2039
|
+
*
|
|
2040
|
+
* import { WASI } from "@bjorn3/browser_wasi_shim";
|
|
2041
|
+
* const wasip1 = new WASI([], [], []);
|
|
2042
|
+
* const module = await WebAssembly.compile("./path/to/ruby.wasm");
|
|
2043
|
+
* const { vm } = await RubyVM.instantiateModule({ module, wasip1 });
|
|
2044
|
+
*
|
|
2045
|
+
*/
|
|
2046
|
+
static async instantiateModule(options) {
|
|
2047
|
+
var _a, _b;
|
|
2048
|
+
const { module, wasip1 } = options;
|
|
2049
|
+
const vm = new RubyVM();
|
|
2050
|
+
const imports = {
|
|
2051
|
+
wasi_snapshot_preview1: wasip1.wasiImport,
|
|
2052
|
+
};
|
|
2053
|
+
vm.addToImports(imports);
|
|
2054
|
+
(_a = options.addToImports) === null || _a === void 0 ? void 0 : _a.call(options, imports);
|
|
2055
|
+
const instance = await WebAssembly.instantiate(module, imports);
|
|
2056
|
+
try {
|
|
2057
|
+
await vm.setInstance(instance);
|
|
2058
|
+
}
|
|
2059
|
+
catch (e) {
|
|
2060
|
+
console.error("Failed to instantiate Ruby VM. Please make sure that you have added `gem \"js\"` to your Gemfile.");
|
|
2061
|
+
throw e;
|
|
2062
|
+
}
|
|
2063
|
+
(_b = options.setMemory) === null || _b === void 0 ? void 0 : _b.call(options, instance.exports.memory);
|
|
2064
|
+
wasip1.initialize(instance);
|
|
2065
|
+
vm.initialize(options.args);
|
|
2066
|
+
return { vm, instance };
|
|
2067
|
+
}
|
|
2068
|
+
/**
|
|
2069
|
+
* Instantiate a Ruby VM with the given WebAssembly component with WASI Preview 2 implementation.
|
|
2070
|
+
*
|
|
2071
|
+
* @param options The options to instantiate the Ruby VM
|
|
2072
|
+
* @returns A promise that resolves to the Ruby VM instance
|
|
2073
|
+
* @category Essentials
|
|
2074
|
+
*
|
|
2075
|
+
* @example
|
|
2076
|
+
*
|
|
2077
|
+
* // First, you need to transpile the Ruby component to a JavaScript module using jco.
|
|
2078
|
+
* // $ jco transpile --no-wasi-shim --instantiation --valid-lifting-optimization ./ruby.component.wasm -o ./component
|
|
2079
|
+
* // Then, you can instantiate the Ruby VM with the component:
|
|
2080
|
+
*
|
|
2081
|
+
* import * as wasip2 from "@bytecodealliance/preview2-shim"
|
|
2082
|
+
* import fs from "fs/promises";
|
|
2083
|
+
* import path from "path";
|
|
2084
|
+
*
|
|
2085
|
+
* const { instantiate } = await import("./component/ruby.component.js");
|
|
2086
|
+
* const getCoreModule = async (relativePath) => {
|
|
2087
|
+
* const buffer = await fs.readFile(path.join("./component", relativePath));
|
|
2088
|
+
* return WebAssembly.compile(buffer);
|
|
2089
|
+
* }
|
|
2090
|
+
*
|
|
2091
|
+
* const { vm } = await RubyVM.instantiateComponent({
|
|
2092
|
+
* instantiate, getCoreModule, wasip2,
|
|
2093
|
+
* });
|
|
2094
|
+
*
|
|
2095
|
+
*/
|
|
2096
|
+
static async instantiateComponent(options) {
|
|
2097
|
+
let initComponent;
|
|
2098
|
+
if ("getCoreModule" in options) {
|
|
2099
|
+
// A convenience overload to instantiate with "instantiate" function generated by jco
|
|
2100
|
+
initComponent = async (jsRuntime) => {
|
|
2101
|
+
const { instantiate, getCoreModule, wasip2 } = options;
|
|
2102
|
+
const { cli, clocks, filesystem, io, random, sockets, http } = wasip2;
|
|
2103
|
+
const environment = options.env ? Object.assign(Object.assign({}, cli.environment), { getEnvironment: () => {
|
|
2104
|
+
var _a;
|
|
2105
|
+
return Array.from(new Map([
|
|
2106
|
+
...cli.environment.getEnvironment(),
|
|
2107
|
+
...Object.entries((_a = options.env) !== null && _a !== void 0 ? _a : {}),
|
|
2108
|
+
]).entries());
|
|
2109
|
+
} }) : cli.environment;
|
|
2110
|
+
const importObject = {
|
|
2111
|
+
"ruby:js/js-runtime": jsRuntime,
|
|
2112
|
+
"wasi:cli/environment": environment,
|
|
2113
|
+
"wasi:cli/exit": cli.exit,
|
|
2114
|
+
"wasi:cli/stderr": cli.stderr,
|
|
2115
|
+
"wasi:cli/stdin": cli.stdin,
|
|
2116
|
+
"wasi:cli/stdout": cli.stdout,
|
|
2117
|
+
"wasi:cli/terminal-input": cli.terminalInput,
|
|
2118
|
+
"wasi:cli/terminal-output": cli.terminalOutput,
|
|
2119
|
+
"wasi:cli/terminal-stderr": cli.terminalStderr,
|
|
2120
|
+
"wasi:cli/terminal-stdin": cli.terminalStdin,
|
|
2121
|
+
"wasi:cli/terminal-stdout": cli.terminalStdout,
|
|
2122
|
+
"wasi:clocks/monotonic-clock": clocks.monotonicClock,
|
|
2123
|
+
"wasi:clocks/wall-clock": clocks.wallClock,
|
|
2124
|
+
"wasi:filesystem/preopens": filesystem.preopens,
|
|
2125
|
+
"wasi:filesystem/types": filesystem.types,
|
|
2126
|
+
"wasi:io/error": io.error,
|
|
2127
|
+
"wasi:io/poll": io.poll,
|
|
2128
|
+
"wasi:io/streams": io.streams,
|
|
2129
|
+
"wasi:random/random": random.random,
|
|
2130
|
+
"wasi:sockets/tcp": sockets.tcp,
|
|
2131
|
+
"wasi:http/types": http.types,
|
|
2132
|
+
"wasi:http/incoming-handler": http.incomingHandler,
|
|
2133
|
+
"wasi:http/outgoing-handler": http.outgoingHandler,
|
|
2134
|
+
};
|
|
2135
|
+
const component = await instantiate(getCoreModule, importObject, options.instantiateCore);
|
|
2136
|
+
return component.rubyRuntime;
|
|
2137
|
+
};
|
|
2138
|
+
}
|
|
2139
|
+
else {
|
|
2140
|
+
initComponent = options.instantiate;
|
|
2141
|
+
}
|
|
2142
|
+
const vm = await this._instantiate({}, initComponent);
|
|
2143
|
+
return { vm };
|
|
2144
|
+
}
|
|
2120
2145
|
constructor(binding) {
|
|
2121
2146
|
this.instance = null;
|
|
2122
2147
|
this.interfaceState = {
|
|
@@ -2165,7 +2190,7 @@ SOFTWARE.
|
|
|
2165
2190
|
this.transport = new JsValueTransport();
|
|
2166
2191
|
this.exceptionFormatter = new RbExceptionFormatter();
|
|
2167
2192
|
}
|
|
2168
|
-
static async _instantiate(
|
|
2193
|
+
static async _instantiate(options, initComponent) {
|
|
2169
2194
|
const binding = new ComponentBinding();
|
|
2170
2195
|
const vm = new RubyVM(binding);
|
|
2171
2196
|
class JsAbiValue {
|
|
@@ -2193,13 +2218,30 @@ SOFTWARE.
|
|
|
2193
2218
|
* Initialize the Ruby VM with the given command line arguments
|
|
2194
2219
|
* @param args The command line arguments to pass to Ruby. Must be
|
|
2195
2220
|
* an array of strings starting with the Ruby program name.
|
|
2221
|
+
* @category Low-level initialization
|
|
2196
2222
|
*/
|
|
2197
2223
|
initialize(args = ["ruby.wasm", "-EUTF-8", "-e_=0"]) {
|
|
2198
2224
|
const c_args = args.map((arg) => arg + "\0");
|
|
2199
|
-
this.guest.rubyInit();
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2225
|
+
this.guest.rubyInit(c_args);
|
|
2226
|
+
try {
|
|
2227
|
+
this.eval(`
|
|
2228
|
+
# Require Bundler standalone setup
|
|
2229
|
+
if File.exist?("/bundle/bundler/setup.rb")
|
|
2230
|
+
# Some ruby-head + ruby.wasm revisions return from rubyInit with a partial
|
|
2231
|
+
# Gem module: Gem is defined, but RubyGems is not loaded yet and its API
|
|
2232
|
+
# helpers are still missing. Bundler standalone treats defined?(Gem) as
|
|
2233
|
+
# sufficient, so load RubyGems explicitly before requiring its setup file.
|
|
2234
|
+
require "rubygems" if defined?(Gem) && !Gem.respond_to?(:ruby_api_version)
|
|
2235
|
+
require "/bundle/bundler/setup.rb"
|
|
2236
|
+
elsif File.exist?("/bundle/setup.rb")
|
|
2237
|
+
# For non-CM builds, which doesn't use Bundler's standalone mode
|
|
2238
|
+
require "/bundle/setup.rb"
|
|
2239
|
+
end
|
|
2240
|
+
`);
|
|
2241
|
+
}
|
|
2242
|
+
catch (e) {
|
|
2243
|
+
console.warn("Failed to load /bundle/setup", e);
|
|
2244
|
+
}
|
|
2203
2245
|
}
|
|
2204
2246
|
/**
|
|
2205
2247
|
* Set a given instance to interact JavaScript and Ruby's
|
|
@@ -2209,6 +2251,7 @@ SOFTWARE.
|
|
|
2209
2251
|
* @param instance The WebAssembly instance to interact with. Must
|
|
2210
2252
|
* be instantiated from a Ruby built with JS extension, and built
|
|
2211
2253
|
* with Reactor ABI instead of command line.
|
|
2254
|
+
* @category Low-level initialization
|
|
2212
2255
|
*/
|
|
2213
2256
|
async setInstance(instance) {
|
|
2214
2257
|
this.instance = instance;
|
|
@@ -2218,6 +2261,7 @@ SOFTWARE.
|
|
|
2218
2261
|
* Add intrinsic import entries, which is necessary to interact JavaScript
|
|
2219
2262
|
* and Ruby's WebAssembly instance.
|
|
2220
2263
|
* @param imports The import object to add to the WebAssembly instance
|
|
2264
|
+
* @category Low-level initialization
|
|
2221
2265
|
*/
|
|
2222
2266
|
addToImports(imports) {
|
|
2223
2267
|
this.guest.addToImports(imports);
|
|
@@ -2423,6 +2467,7 @@ SOFTWARE.
|
|
|
2423
2467
|
* Runs a string of Ruby code from JavaScript
|
|
2424
2468
|
* @param code The Ruby code to run
|
|
2425
2469
|
* @returns the result of the last expression
|
|
2470
|
+
* @category Essentials
|
|
2426
2471
|
*
|
|
2427
2472
|
* @example
|
|
2428
2473
|
* vm.eval("puts 'hello world'");
|
|
@@ -2438,6 +2483,7 @@ SOFTWARE.
|
|
|
2438
2483
|
* Returns a promise that resolves when execution completes.
|
|
2439
2484
|
* @param code The Ruby code to run
|
|
2440
2485
|
* @returns a promise that resolves to the result of the last expression
|
|
2486
|
+
* @category Essentials
|
|
2441
2487
|
*
|
|
2442
2488
|
* @example
|
|
2443
2489
|
* const text = await vm.evalAsync(`
|
|
@@ -2520,6 +2566,7 @@ SOFTWARE.
|
|
|
2520
2566
|
}
|
|
2521
2567
|
/**
|
|
2522
2568
|
* A RbValue is an object that represents a value in Ruby
|
|
2569
|
+
* @category Essentials
|
|
2523
2570
|
*/
|
|
2524
2571
|
class RbValue {
|
|
2525
2572
|
/**
|
|
@@ -2821,18 +2868,16 @@ SOFTWARE.
|
|
|
2821
2868
|
new PreopenDirectory("/", new Map()),
|
|
2822
2869
|
];
|
|
2823
2870
|
const wasi = new WASI(args, env, fds, { debug: false });
|
|
2824
|
-
const vm = new RubyVM();
|
|
2825
|
-
const imports = {
|
|
2826
|
-
wasi_snapshot_preview1: wasi.wasiImport,
|
|
2827
|
-
};
|
|
2828
|
-
vm.addToImports(imports);
|
|
2829
2871
|
const printer = ((_b = options.consolePrint) !== null && _b !== void 0 ? _b : true) ? consolePrinter() : undefined;
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2872
|
+
const { vm, instance } = await RubyVM.instantiateModule({
|
|
2873
|
+
module: rubyModule, wasip1: wasi,
|
|
2874
|
+
addToImports: (imports) => {
|
|
2875
|
+
printer === null || printer === void 0 ? void 0 : printer.addToImports(imports);
|
|
2876
|
+
},
|
|
2877
|
+
setMemory: (memory) => {
|
|
2878
|
+
printer === null || printer === void 0 ? void 0 : printer.setMemory(memory);
|
|
2879
|
+
}
|
|
2880
|
+
});
|
|
2836
2881
|
return {
|
|
2837
2882
|
vm,
|
|
2838
2883
|
wasi,
|
|
@@ -2840,10 +2885,17 @@ SOFTWARE.
|
|
|
2840
2885
|
};
|
|
2841
2886
|
};
|
|
2842
2887
|
|
|
2888
|
+
/**
|
|
2889
|
+
* The main entry point of `<script type="text/ruby">`-based scripting with WebAssembly Core Module.
|
|
2890
|
+
*/
|
|
2843
2891
|
const main$1 = async (pkg, options) => {
|
|
2892
|
+
const scriptEnv = parseDataEnv(document.currentScript);
|
|
2844
2893
|
const response = fetch(`assets/ruby-app.wasm`);
|
|
2845
2894
|
const module = await compileWebAssemblyModule(response);
|
|
2846
|
-
const { vm } = await DefaultRubyVM(module, options);
|
|
2895
|
+
const { vm } = await DefaultRubyVM(module, Object.assign(Object.assign({}, options), { env: Object.assign(Object.assign({}, scriptEnv), void 0 ) }));
|
|
2896
|
+
await mainWithRubyVM(vm);
|
|
2897
|
+
};
|
|
2898
|
+
const mainWithRubyVM = async (vm) => {
|
|
2847
2899
|
vm.printVersion();
|
|
2848
2900
|
globalThis.rubyVM = vm;
|
|
2849
2901
|
// Wait for the text/ruby script tag to be read.
|
|
@@ -2896,6 +2948,53 @@ SOFTWARE.
|
|
|
2896
2948
|
}
|
|
2897
2949
|
return rawEvalStyle;
|
|
2898
2950
|
};
|
|
2951
|
+
/**
|
|
2952
|
+
* Parses the data-env attribute as a JSON object string, for example:
|
|
2953
|
+
* data-env='{"RUBY_BOX":"1","MSG":"hello world"}'
|
|
2954
|
+
*
|
|
2955
|
+
* The parsed value must be a non-null object, not an array. Each key must not
|
|
2956
|
+
* contain "=" or NUL, and each value must be a string.
|
|
2957
|
+
*
|
|
2958
|
+
* JSON is used instead of a shell-like KEY=value list so keys and values can
|
|
2959
|
+
* contain spaces and values can contain "=" without custom escaping rules.
|
|
2960
|
+
*/
|
|
2961
|
+
const parseDataEnv = (tag) => {
|
|
2962
|
+
const rawEnv = tag === null || tag === void 0 ? void 0 : tag.getAttribute("data-env");
|
|
2963
|
+
if (!rawEnv) {
|
|
2964
|
+
return {};
|
|
2965
|
+
}
|
|
2966
|
+
const trimmedEnv = rawEnv.trim();
|
|
2967
|
+
if (!trimmedEnv) {
|
|
2968
|
+
return {};
|
|
2969
|
+
}
|
|
2970
|
+
let parsedEnv;
|
|
2971
|
+
try {
|
|
2972
|
+
parsedEnv = JSON.parse(trimmedEnv);
|
|
2973
|
+
}
|
|
2974
|
+
catch (error) {
|
|
2975
|
+
console.warn(`data-env must be a JSON object string. ${rawEnv} is ignored.`);
|
|
2976
|
+
return {};
|
|
2977
|
+
}
|
|
2978
|
+
if (typeof parsedEnv !== "object" ||
|
|
2979
|
+
parsedEnv === null ||
|
|
2980
|
+
Array.isArray(parsedEnv)) {
|
|
2981
|
+
console.warn(`data-env must be a JSON object string. ${rawEnv} is ignored.`);
|
|
2982
|
+
return {};
|
|
2983
|
+
}
|
|
2984
|
+
return Object.entries(parsedEnv).reduce((env, [key, value]) => {
|
|
2985
|
+
if (key.includes("=") || key.includes("\0")) {
|
|
2986
|
+
console.warn(`data-env key must not contain "=" or NUL. ${key} is ignored.`);
|
|
2987
|
+
return env;
|
|
2988
|
+
}
|
|
2989
|
+
// POSIX environment values may contain arbitrary bytes, but data-env only accepts strings.
|
|
2990
|
+
if (typeof value !== "string") {
|
|
2991
|
+
console.warn(`data-env value for ${key} must be a string. It is ignored.`);
|
|
2992
|
+
return env;
|
|
2993
|
+
}
|
|
2994
|
+
env[key] = value;
|
|
2995
|
+
return env;
|
|
2996
|
+
}, {});
|
|
2997
|
+
};
|
|
2899
2998
|
const loadScriptAsync = async (tag) => {
|
|
2900
2999
|
const evalStyle = deriveEvalStyle(tag);
|
|
2901
3000
|
// Inline comments can be written with the src attribute of the script tag.
|
|
@@ -2925,9 +3024,9 @@ SOFTWARE.
|
|
|
2925
3024
|
}
|
|
2926
3025
|
};
|
|
2927
3026
|
|
|
2928
|
-
var name = "@ruby/
|
|
2929
|
-
var version = "2.
|
|
2930
|
-
var description = "Ruby
|
|
3027
|
+
var name = "@ruby/4.0-wasm-wasi";
|
|
3028
|
+
var version = "2.10.1";
|
|
3029
|
+
var description = "Ruby 4.0 built on WASI";
|
|
2931
3030
|
var main = "./dist/cjs/index.js";
|
|
2932
3031
|
var module = "./dist/esm/index.js";
|
|
2933
3032
|
var exports$1 = {
|
|
@@ -2943,11 +3042,11 @@ SOFTWARE.
|
|
|
2943
3042
|
"import": "./dist/esm/*.js",
|
|
2944
3043
|
require: "./dist/cjs/*.js"
|
|
2945
3044
|
},
|
|
2946
|
-
"
|
|
2947
|
-
browser: "
|
|
2948
|
-
umd: "
|
|
2949
|
-
"import": "
|
|
2950
|
-
require: "
|
|
3045
|
+
"./dist/*.wasm": {
|
|
3046
|
+
browser: "./dist/*.wasm",
|
|
3047
|
+
umd: "./dist/*.wasm",
|
|
3048
|
+
"import": "./dist/*.wasm",
|
|
3049
|
+
require: "./dist/*.wasm"
|
|
2951
3050
|
}
|
|
2952
3051
|
};
|
|
2953
3052
|
var files = [
|
|
@@ -2955,16 +3054,16 @@ SOFTWARE.
|
|
|
2955
3054
|
"README.md"
|
|
2956
3055
|
];
|
|
2957
3056
|
var scripts = {
|
|
2958
|
-
test: "RUBY_NPM_PACKAGE_ROOT=../ruby-
|
|
3057
|
+
test: "RUBY_NPM_PACKAGE_ROOT=../ruby-4.0-wasm-wasi npm -C ../ruby-wasm-wasi run test:run",
|
|
2959
3058
|
"build:deps": "cd ../ruby-wasm-wasi && npm run build",
|
|
2960
3059
|
"build:static:files": "../ruby-wasm-wasi/tools/pack-static-files.sh ./dist",
|
|
2961
|
-
"build:static:compat": "../ruby-wasm-wasi/tools/pack-compat-shim.mjs --dist=./dist --pkg=ruby-
|
|
3060
|
+
"build:static:compat": "../ruby-wasm-wasi/tools/pack-compat-shim.mjs --dist=./dist --pkg=ruby-4.0-wasm-wasi",
|
|
2962
3061
|
"build:static": "npm run build:static:files && npm run build:static:compat",
|
|
2963
3062
|
"build:rollup": "rollup -c rollup.config.mjs",
|
|
2964
3063
|
build: "npm run build:deps && npm run build:static && npm run build:rollup && ../ruby-wasm-wasi/tools/post-build.sh ./dist"
|
|
2965
3064
|
};
|
|
2966
3065
|
var repository = "https://github.com/ruby/ruby.wasm";
|
|
2967
|
-
var homepage = "https://github.com/ruby/ruby.wasm/tree/main/packages/npm-packages/ruby-
|
|
3066
|
+
var homepage = "https://github.com/ruby/ruby.wasm/tree/main/packages/npm-packages/ruby-4.0-wasm-wasi";
|
|
2968
3067
|
var publishConfig = {
|
|
2969
3068
|
access: "public"
|
|
2970
3069
|
};
|