@ruby/4.0-wasm-wasi 2.8.1-2025-12-30-a

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.
@@ -0,0 +1,1705 @@
1
+ console.warn(`DEPRECATED(ruby-4.0-wasm-wasi): "dist/browser.script.umd" will be moved to "@ruby/wasm-wasi" in the next major release.
2
+ Please replace your \`require('ruby-4.0-wasm-wasi/dist/browser.script.umd');\` with \`require('@ruby/wasm-wasi/dist/browser.script.umd');\``);
3
+
4
+ (function (global, factory) {
5
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
6
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
7
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["ruby-wasm-wasi"] = {}));
8
+ })(this, (function (exports) { 'use strict';
9
+
10
+ /******************************************************************************
11
+ Copyright (c) Microsoft Corporation.
12
+
13
+ Permission to use, copy, modify, and/or distribute this software for any
14
+ purpose with or without fee is hereby granted.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
17
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
19
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22
+ PERFORMANCE OF THIS SOFTWARE.
23
+ ***************************************************************************** */
24
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
25
+
26
+
27
+ function __values(o) {
28
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
29
+ if (m) return m.call(o);
30
+ if (o && typeof o.length === "number") return {
31
+ next: function () {
32
+ if (o && i >= o.length) o = void 0;
33
+ return { value: o && o[i++], done: !o };
34
+ }
35
+ };
36
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
37
+ }
38
+
39
+ function __asyncValues(o) {
40
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
41
+ var m = o[Symbol.asyncIterator], i;
42
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
43
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
44
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
45
+ }
46
+
47
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
48
+ var e = new Error(message);
49
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
50
+ };
51
+
52
+ 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){this.d_ino=0n;const encoded_name=new TextEncoder().encode(name);this.d_next=next_cookie;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(filetype,size){this.dev=0n;this.ino=0n;this.nlink=0n;this.atim=0n;this.mtim=0n;this.ctim=0n;this.filetype=filetype;this.size=size;}}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);}}
53
+
54
+ 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);
55
+
56
+ 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"}};}};
57
+
58
+ 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{}
59
+
60
+ 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;}}}
61
+
62
+ /**
63
+ * Create a console printer that can be used as an overlay of WASI imports.
64
+ * See the example below for how to use it.
65
+ *
66
+ * ```javascript
67
+ * const imports = {
68
+ * "wasi_snapshot_preview1": wasi.wasiImport,
69
+ * }
70
+ * const printer = consolePrinter();
71
+ * printer.addToImports(imports);
72
+ *
73
+ * const instance = await WebAssembly.instantiate(module, imports);
74
+ * printer.setMemory(instance.exports.memory);
75
+ * ```
76
+ *
77
+ * Note that the `stdout` and `stderr` functions are called with text, not
78
+ * bytes. This means that bytes written to stdout/stderr will be decoded as
79
+ * UTF-8 and then passed to the `stdout`/`stderr` functions every time a write
80
+ * occurs without buffering.
81
+ *
82
+ * @param stdout A function that will be called when stdout is written to.
83
+ * Defaults to `console.log`.
84
+ * @param stderr A function that will be called when stderr is written to.
85
+ * Defaults to `console.warn`.
86
+ * @returns An object that can be used as an overlay of WASI imports.
87
+ */
88
+ function consolePrinter({ stdout, stderr, } = {
89
+ stdout: console.log,
90
+ stderr: console.warn,
91
+ }) {
92
+ let memory = undefined;
93
+ let _view = undefined;
94
+ function getMemoryView() {
95
+ if (typeof memory === "undefined") {
96
+ throw new Error("Memory is not set");
97
+ }
98
+ if (_view === undefined || _view.buffer.byteLength === 0) {
99
+ _view = new DataView(memory.buffer);
100
+ }
101
+ return _view;
102
+ }
103
+ const decoder = new TextDecoder();
104
+ return {
105
+ addToImports(imports) {
106
+ const wasiImport = imports.wasi_snapshot_preview1;
107
+ const original_fd_write = wasiImport.fd_write;
108
+ wasiImport.fd_write = (fd, iovs, iovsLen, nwritten) => {
109
+ if (fd !== 1 && fd !== 2) {
110
+ return original_fd_write(fd, iovs, iovsLen, nwritten);
111
+ }
112
+ const view = getMemoryView();
113
+ const buffers = Array.from({ length: iovsLen }, (_, i) => {
114
+ const ptr = iovs + i * 8;
115
+ const buf = view.getUint32(ptr, true);
116
+ const bufLen = view.getUint32(ptr + 4, true);
117
+ return new Uint8Array(memory.buffer, buf, bufLen);
118
+ });
119
+ let written = 0;
120
+ let str = "";
121
+ for (const buffer of buffers) {
122
+ str += decoder.decode(buffer);
123
+ written += buffer.byteLength;
124
+ }
125
+ view.setUint32(nwritten, written, true);
126
+ const log = fd === 1 ? stdout : stderr;
127
+ log(str);
128
+ return 0;
129
+ };
130
+ const original_fd_filestat_get = wasiImport.fd_filestat_get;
131
+ wasiImport.fd_filestat_get = (fd, filestat) => {
132
+ if (fd !== 1 && fd !== 2) {
133
+ return original_fd_filestat_get(fd, filestat);
134
+ }
135
+ const view = getMemoryView();
136
+ const result = original_fd_filestat_get(fd, filestat);
137
+ if (result !== 0) {
138
+ return result;
139
+ }
140
+ const filetypePtr = filestat + 0;
141
+ view.setUint8(filetypePtr, 2); // FILETYPE_CHARACTER_DEVICE
142
+ return 0;
143
+ };
144
+ const original_fd_fdstat_get = wasiImport.fd_fdstat_get;
145
+ wasiImport.fd_fdstat_get = (fd, fdstat) => {
146
+ if (fd !== 1 && fd !== 2) {
147
+ return original_fd_fdstat_get(fd, fdstat);
148
+ }
149
+ const view = getMemoryView();
150
+ const fs_filetypePtr = fdstat + 0;
151
+ view.setUint8(fs_filetypePtr, 2); // FILETYPE_CHARACTER_DEVICE
152
+ const fs_rights_basePtr = fdstat + 8;
153
+ // See https://github.com/WebAssembly/WASI/blob/v0.2.0/legacy/preview1/docs.md#record-members
154
+ const RIGHTS_FD_WRITE = 1 << 6;
155
+ view.setBigUint64(fs_rights_basePtr, BigInt(RIGHTS_FD_WRITE), true);
156
+ return 0;
157
+ };
158
+ },
159
+ setMemory(m) {
160
+ memory = m;
161
+ },
162
+ };
163
+ }
164
+
165
+ let DATA_VIEW = new DataView(new ArrayBuffer());
166
+
167
+ function data_view(mem) {
168
+ if (DATA_VIEW.buffer !== mem.buffer) DATA_VIEW = new DataView(mem.buffer);
169
+ return DATA_VIEW;
170
+ }
171
+
172
+ function to_uint32(val) {
173
+ return val >>> 0;
174
+ }
175
+ const UTF8_DECODER = new TextDecoder('utf-8');
176
+
177
+ const UTF8_ENCODER = new TextEncoder('utf-8');
178
+
179
+ function utf8_encode(s, realloc, memory) {
180
+ if (typeof s !== 'string') throw new TypeError('expected a string');
181
+
182
+ if (s.length === 0) {
183
+ UTF8_ENCODED_LEN = 0;
184
+ return 1;
185
+ }
186
+
187
+ let alloc_len = 0;
188
+ let ptr = 0;
189
+ let writtenTotal = 0;
190
+ while (s.length > 0) {
191
+ ptr = realloc(ptr, alloc_len, 1, alloc_len + s.length);
192
+ alloc_len += s.length;
193
+ const { read, written } = UTF8_ENCODER.encodeInto(
194
+ s,
195
+ new Uint8Array(memory.buffer, ptr + writtenTotal, alloc_len - writtenTotal),
196
+ );
197
+ writtenTotal += written;
198
+ s = s.slice(read);
199
+ }
200
+ if (alloc_len > writtenTotal)
201
+ ptr = realloc(ptr, alloc_len, 1, writtenTotal);
202
+ UTF8_ENCODED_LEN = writtenTotal;
203
+ return ptr;
204
+ }
205
+ let UTF8_ENCODED_LEN = 0;
206
+
207
+ class Slab {
208
+ constructor() {
209
+ this.list = [];
210
+ this.head = 0;
211
+ }
212
+
213
+ insert(val) {
214
+ if (this.head >= this.list.length) {
215
+ this.list.push({
216
+ next: this.list.length + 1,
217
+ val: undefined,
218
+ });
219
+ }
220
+ const ret = this.head;
221
+ const slot = this.list[ret];
222
+ this.head = slot.next;
223
+ slot.next = -1;
224
+ slot.val = val;
225
+ return ret;
226
+ }
227
+
228
+ get(idx) {
229
+ if (idx >= this.list.length)
230
+ throw new RangeError('handle index not valid');
231
+ const slot = this.list[idx];
232
+ if (slot.next === -1)
233
+ return slot.val;
234
+ throw new RangeError('handle index not valid');
235
+ }
236
+
237
+ remove(idx) {
238
+ const ret = this.get(idx); // validate the slot
239
+ const slot = this.list[idx];
240
+ slot.val = undefined;
241
+ slot.next = this.head;
242
+ this.head = idx;
243
+ return ret;
244
+ }
245
+ }
246
+
247
+ function throw_invalid_bool() {
248
+ throw new RangeError("invalid variant discriminant for bool");
249
+ }
250
+
251
+ class RbAbiGuest {
252
+ constructor() {
253
+ this._resource0_slab = new Slab();
254
+ }
255
+ addToImports(imports) {
256
+ if (!("canonical_abi" in imports)) imports["canonical_abi"] = {};
257
+
258
+ imports.canonical_abi['resource_drop_rb-abi-value'] = i => {
259
+ this._resource0_slab.remove(i).drop();
260
+ };
261
+ imports.canonical_abi['resource_clone_rb-abi-value'] = i => {
262
+ const obj = this._resource0_slab.get(i);
263
+ return this._resource0_slab.insert(obj.clone())
264
+ };
265
+ imports.canonical_abi['resource_get_rb-abi-value'] = i => {
266
+ return this._resource0_slab.get(i)._wasm_val;
267
+ };
268
+ imports.canonical_abi['resource_new_rb-abi-value'] = i => {
269
+ this._registry0;
270
+ return this._resource0_slab.insert(new RbAbiValue(i, this));
271
+ };
272
+ }
273
+
274
+ async instantiate(module, imports) {
275
+ imports = imports || {};
276
+ this.addToImports(imports);
277
+
278
+ if (module instanceof WebAssembly.Instance) {
279
+ this.instance = module;
280
+ } else if (module instanceof WebAssembly.Module) {
281
+ this.instance = await WebAssembly.instantiate(module, imports);
282
+ } else if (module instanceof ArrayBuffer || module instanceof Uint8Array) {
283
+ const { instance } = await WebAssembly.instantiate(module, imports);
284
+ this.instance = instance;
285
+ } else {
286
+ const { instance } = await WebAssembly.instantiateStreaming(module, imports);
287
+ this.instance = instance;
288
+ }
289
+ this._exports = this.instance.exports;
290
+ this._registry0 = new FinalizationRegistry(this._exports['canonical_abi_drop_rb-abi-value']);
291
+ }
292
+ rubyShowVersion() {
293
+ this._exports['ruby-show-version: func() -> ()']();
294
+ }
295
+ rubyInit(arg0) {
296
+ const memory = this._exports.memory;
297
+ const realloc = this._exports["cabi_realloc"];
298
+ const vec1 = arg0;
299
+ const len1 = vec1.length;
300
+ const result1 = realloc(0, 0, 4, len1 * 8);
301
+ for (let i = 0; i < vec1.length; i++) {
302
+ const e = vec1[i];
303
+ const base = result1 + i * 8;
304
+ const ptr0 = utf8_encode(e, realloc, memory);
305
+ const len0 = UTF8_ENCODED_LEN;
306
+ data_view(memory).setInt32(base + 4, len0, true);
307
+ data_view(memory).setInt32(base + 0, ptr0, true);
308
+ }
309
+ this._exports['ruby-init: func(args: list<string>) -> ()'](result1, len1);
310
+ }
311
+ rubyInitLoadpath() {
312
+ this._exports['ruby-init-loadpath: func() -> ()']();
313
+ }
314
+ rbEvalStringProtect(arg0) {
315
+ const memory = this._exports.memory;
316
+ const realloc = this._exports["cabi_realloc"];
317
+ const ptr0 = utf8_encode(arg0, realloc, memory);
318
+ const len0 = UTF8_ENCODED_LEN;
319
+ const ret = this._exports['rb-eval-string-protect: func(str: string) -> tuple<handle<rb-abi-value>, s32>'](ptr0, len0);
320
+ return [this._resource0_slab.remove(data_view(memory).getInt32(ret + 0, true)), data_view(memory).getInt32(ret + 4, true)];
321
+ }
322
+ rbFuncallvProtect(arg0, arg1, arg2) {
323
+ const memory = this._exports.memory;
324
+ const realloc = this._exports["cabi_realloc"];
325
+ const obj0 = arg0;
326
+ if (!(obj0 instanceof RbAbiValue)) throw new TypeError('expected instance of RbAbiValue');
327
+ const vec2 = arg2;
328
+ const len2 = vec2.length;
329
+ const result2 = realloc(0, 0, 4, len2 * 4);
330
+ for (let i = 0; i < vec2.length; i++) {
331
+ const e = vec2[i];
332
+ const base = result2 + i * 4;
333
+ const obj1 = e;
334
+ if (!(obj1 instanceof RbAbiValue)) throw new TypeError('expected instance of RbAbiValue');
335
+ data_view(memory).setInt32(base + 0, this._resource0_slab.insert(obj1.clone()), true);
336
+ }
337
+ 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);
338
+ return [this._resource0_slab.remove(data_view(memory).getInt32(ret + 0, true)), data_view(memory).getInt32(ret + 4, true)];
339
+ }
340
+ rbIntern(arg0) {
341
+ const memory = this._exports.memory;
342
+ const realloc = this._exports["cabi_realloc"];
343
+ const ptr0 = utf8_encode(arg0, realloc, memory);
344
+ const len0 = UTF8_ENCODED_LEN;
345
+ const ret = this._exports['rb-intern: func(name: string) -> u32'](ptr0, len0);
346
+ return ret >>> 0;
347
+ }
348
+ rbErrinfo() {
349
+ const ret = this._exports['rb-errinfo: func() -> handle<rb-abi-value>']();
350
+ return this._resource0_slab.remove(ret);
351
+ }
352
+ rbClearErrinfo() {
353
+ this._exports['rb-clear-errinfo: func() -> ()']();
354
+ }
355
+ rstringPtr(arg0) {
356
+ const memory = this._exports.memory;
357
+ const obj0 = arg0;
358
+ if (!(obj0 instanceof RbAbiValue)) throw new TypeError('expected instance of RbAbiValue');
359
+ const ret = this._exports['rstring-ptr: func(value: handle<rb-abi-value>) -> string'](this._resource0_slab.insert(obj0.clone()));
360
+ const ptr1 = data_view(memory).getInt32(ret + 0, true);
361
+ const len1 = data_view(memory).getInt32(ret + 4, true);
362
+ const result1 = UTF8_DECODER.decode(new Uint8Array(memory.buffer, ptr1, len1));
363
+ this._exports["cabi_post_rstring-ptr"](ret);
364
+ return result1;
365
+ }
366
+ rbVmBugreport() {
367
+ this._exports['rb-vm-bugreport: func() -> ()']();
368
+ }
369
+ rbGcEnable() {
370
+ const ret = this._exports['rb-gc-enable: func() -> bool']();
371
+ const bool0 = ret;
372
+ return bool0 == 0 ? false : (bool0 == 1 ? true : throw_invalid_bool());
373
+ }
374
+ rbGcDisable() {
375
+ const ret = this._exports['rb-gc-disable: func() -> bool']();
376
+ const bool0 = ret;
377
+ return bool0 == 0 ? false : (bool0 == 1 ? true : throw_invalid_bool());
378
+ }
379
+ rbSetShouldProhibitRewind(arg0) {
380
+ const ret = this._exports['rb-set-should-prohibit-rewind: func(new-value: bool) -> bool'](arg0 ? 1 : 0);
381
+ const bool0 = ret;
382
+ return bool0 == 0 ? false : (bool0 == 1 ? true : throw_invalid_bool());
383
+ }
384
+ }
385
+
386
+ class RbAbiValue {
387
+ constructor(wasm_val, obj) {
388
+ this._wasm_val = wasm_val;
389
+ this._obj = obj;
390
+ this._refcnt = 1;
391
+ obj._registry0.register(this, wasm_val, this);
392
+ }
393
+
394
+ clone() {
395
+ this._refcnt += 1;
396
+ return this;
397
+ }
398
+
399
+ drop() {
400
+ this._refcnt -= 1;
401
+ if (this._refcnt !== 0)
402
+ return;
403
+ this._obj._registry0.unregister(this);
404
+ const dtor = this._obj._exports['canonical_abi_drop_rb-abi-value'];
405
+ const wasm_val = this._wasm_val;
406
+ delete this._obj;
407
+ delete this._refcnt;
408
+ delete this._wasm_val;
409
+ dtor(wasm_val);
410
+ }
411
+ }
412
+
413
+ function addRbJsAbiHostToImports(imports, obj, get_export) {
414
+ if (!("rb-js-abi-host" in imports)) imports["rb-js-abi-host"] = {};
415
+ imports["rb-js-abi-host"]["eval-js: func(code: string) -> variant { success(handle<js-abi-value>), failure(handle<js-abi-value>) }"] = function(arg0, arg1, arg2) {
416
+ const memory = get_export("memory");
417
+ const ptr0 = arg0;
418
+ const len0 = arg1;
419
+ const result0 = UTF8_DECODER.decode(new Uint8Array(memory.buffer, ptr0, len0));
420
+ const ret0 = obj.evalJs(result0);
421
+ const variant1 = ret0;
422
+ switch (variant1.tag) {
423
+ case "success": {
424
+ const e = variant1.val;
425
+ data_view(memory).setInt8(arg2 + 0, 0, true);
426
+ data_view(memory).setInt32(arg2 + 4, resources0.insert(e), true);
427
+ break;
428
+ }
429
+ case "failure": {
430
+ const e = variant1.val;
431
+ data_view(memory).setInt8(arg2 + 0, 1, true);
432
+ data_view(memory).setInt32(arg2 + 4, resources0.insert(e), true);
433
+ break;
434
+ }
435
+ default:
436
+ throw new RangeError("invalid variant specified for JsAbiResult");
437
+ }
438
+ };
439
+ imports["rb-js-abi-host"]["is-js: func(value: handle<js-abi-value>) -> bool"] = function(arg0) {
440
+ const ret0 = obj.isJs(resources0.get(arg0));
441
+ return ret0 ? 1 : 0;
442
+ };
443
+ imports["rb-js-abi-host"]["instance-of: func(value: handle<js-abi-value>, klass: handle<js-abi-value>) -> bool"] = function(arg0, arg1) {
444
+ const ret0 = obj.instanceOf(resources0.get(arg0), resources0.get(arg1));
445
+ return ret0 ? 1 : 0;
446
+ };
447
+ imports["rb-js-abi-host"]["global-this: func() -> handle<js-abi-value>"] = function() {
448
+ const ret0 = obj.globalThis();
449
+ return resources0.insert(ret0);
450
+ };
451
+ imports["rb-js-abi-host"]["int-to-js-number: func(value: s32) -> handle<js-abi-value>"] = function(arg0) {
452
+ const ret0 = obj.intToJsNumber(arg0);
453
+ return resources0.insert(ret0);
454
+ };
455
+ imports["rb-js-abi-host"]["float-to-js-number: func(value: float64) -> handle<js-abi-value>"] = function(arg0) {
456
+ const ret0 = obj.floatToJsNumber(arg0);
457
+ return resources0.insert(ret0);
458
+ };
459
+ imports["rb-js-abi-host"]["string-to-js-string: func(value: string) -> handle<js-abi-value>"] = function(arg0, arg1) {
460
+ const memory = get_export("memory");
461
+ const ptr0 = arg0;
462
+ const len0 = arg1;
463
+ const result0 = UTF8_DECODER.decode(new Uint8Array(memory.buffer, ptr0, len0));
464
+ const ret0 = obj.stringToJsString(result0);
465
+ return resources0.insert(ret0);
466
+ };
467
+ imports["rb-js-abi-host"]["bool-to-js-bool: func(value: bool) -> handle<js-abi-value>"] = function(arg0) {
468
+ const bool0 = arg0;
469
+ const ret0 = obj.boolToJsBool(bool0 == 0 ? false : (bool0 == 1 ? true : throw_invalid_bool()));
470
+ return resources0.insert(ret0);
471
+ };
472
+ imports["rb-js-abi-host"]["proc-to-js-function: func(value: u32) -> handle<js-abi-value>"] = function(arg0) {
473
+ const ret0 = obj.procToJsFunction(arg0 >>> 0);
474
+ return resources0.insert(ret0);
475
+ };
476
+ imports["rb-js-abi-host"]["rb-object-to-js-rb-value: func(raw-rb-abi-value: u32) -> handle<js-abi-value>"] = function(arg0) {
477
+ const ret0 = obj.rbObjectToJsRbValue(arg0 >>> 0);
478
+ return resources0.insert(ret0);
479
+ };
480
+ imports["rb-js-abi-host"]["js-value-to-string: func(value: handle<js-abi-value>) -> string"] = function(arg0, arg1) {
481
+ const memory = get_export("memory");
482
+ const realloc = get_export("cabi_realloc");
483
+ const ret0 = obj.jsValueToString(resources0.get(arg0));
484
+ const ptr0 = utf8_encode(ret0, realloc, memory);
485
+ const len0 = UTF8_ENCODED_LEN;
486
+ data_view(memory).setInt32(arg1 + 4, len0, true);
487
+ data_view(memory).setInt32(arg1 + 0, ptr0, true);
488
+ };
489
+ imports["rb-js-abi-host"]["js-value-to-integer: func(value: handle<js-abi-value>) -> variant { as-float(float64), bignum(string) }"] = function(arg0, arg1) {
490
+ const memory = get_export("memory");
491
+ const realloc = get_export("cabi_realloc");
492
+ const ret0 = obj.jsValueToInteger(resources0.get(arg0));
493
+ const variant1 = ret0;
494
+ switch (variant1.tag) {
495
+ case "as-float": {
496
+ const e = variant1.val;
497
+ data_view(memory).setInt8(arg1 + 0, 0, true);
498
+ data_view(memory).setFloat64(arg1 + 8, +e, true);
499
+ break;
500
+ }
501
+ case "bignum": {
502
+ const e = variant1.val;
503
+ data_view(memory).setInt8(arg1 + 0, 1, true);
504
+ const ptr0 = utf8_encode(e, realloc, memory);
505
+ const len0 = UTF8_ENCODED_LEN;
506
+ data_view(memory).setInt32(arg1 + 12, len0, true);
507
+ data_view(memory).setInt32(arg1 + 8, ptr0, true);
508
+ break;
509
+ }
510
+ default:
511
+ throw new RangeError("invalid variant specified for RawInteger");
512
+ }
513
+ };
514
+ imports["rb-js-abi-host"]["export-js-value-to-host: func(value: handle<js-abi-value>) -> ()"] = function(arg0) {
515
+ obj.exportJsValueToHost(resources0.get(arg0));
516
+ };
517
+ imports["rb-js-abi-host"]["import-js-value-from-host: func() -> handle<js-abi-value>"] = function() {
518
+ const ret0 = obj.importJsValueFromHost();
519
+ return resources0.insert(ret0);
520
+ };
521
+ imports["rb-js-abi-host"]["js-value-typeof: func(value: handle<js-abi-value>) -> string"] = function(arg0, arg1) {
522
+ const memory = get_export("memory");
523
+ const realloc = get_export("cabi_realloc");
524
+ const ret0 = obj.jsValueTypeof(resources0.get(arg0));
525
+ const ptr0 = utf8_encode(ret0, realloc, memory);
526
+ const len0 = UTF8_ENCODED_LEN;
527
+ data_view(memory).setInt32(arg1 + 4, len0, true);
528
+ data_view(memory).setInt32(arg1 + 0, ptr0, true);
529
+ };
530
+ imports["rb-js-abi-host"]["js-value-equal: func(lhs: handle<js-abi-value>, rhs: handle<js-abi-value>) -> bool"] = function(arg0, arg1) {
531
+ const ret0 = obj.jsValueEqual(resources0.get(arg0), resources0.get(arg1));
532
+ return ret0 ? 1 : 0;
533
+ };
534
+ imports["rb-js-abi-host"]["js-value-strictly-equal: func(lhs: handle<js-abi-value>, rhs: handle<js-abi-value>) -> bool"] = function(arg0, arg1) {
535
+ const ret0 = obj.jsValueStrictlyEqual(resources0.get(arg0), resources0.get(arg1));
536
+ return ret0 ? 1 : 0;
537
+ };
538
+ imports["rb-js-abi-host"]["reflect-apply: func(target: handle<js-abi-value>, this-argument: handle<js-abi-value>, arguments: list<handle<js-abi-value>>) -> variant { success(handle<js-abi-value>), failure(handle<js-abi-value>) }"] = function(arg0, arg1, arg2, arg3, arg4) {
539
+ const memory = get_export("memory");
540
+ const len0 = arg3;
541
+ const base0 = arg2;
542
+ const result0 = [];
543
+ for (let i = 0; i < len0; i++) {
544
+ const base = base0 + i * 4;
545
+ result0.push(resources0.get(data_view(memory).getInt32(base + 0, true)));
546
+ }
547
+ const ret0 = obj.reflectApply(resources0.get(arg0), resources0.get(arg1), result0);
548
+ const variant1 = ret0;
549
+ switch (variant1.tag) {
550
+ case "success": {
551
+ const e = variant1.val;
552
+ data_view(memory).setInt8(arg4 + 0, 0, true);
553
+ data_view(memory).setInt32(arg4 + 4, resources0.insert(e), true);
554
+ break;
555
+ }
556
+ case "failure": {
557
+ const e = variant1.val;
558
+ data_view(memory).setInt8(arg4 + 0, 1, true);
559
+ data_view(memory).setInt32(arg4 + 4, resources0.insert(e), true);
560
+ break;
561
+ }
562
+ default:
563
+ throw new RangeError("invalid variant specified for JsAbiResult");
564
+ }
565
+ };
566
+ imports["rb-js-abi-host"]["reflect-construct: func(target: handle<js-abi-value>, arguments: list<handle<js-abi-value>>) -> handle<js-abi-value>"] = function(arg0, arg1, arg2) {
567
+ const memory = get_export("memory");
568
+ const len0 = arg2;
569
+ const base0 = arg1;
570
+ const result0 = [];
571
+ for (let i = 0; i < len0; i++) {
572
+ const base = base0 + i * 4;
573
+ result0.push(resources0.get(data_view(memory).getInt32(base + 0, true)));
574
+ }
575
+ const ret0 = obj.reflectConstruct(resources0.get(arg0), result0);
576
+ return resources0.insert(ret0);
577
+ };
578
+ imports["rb-js-abi-host"]["reflect-delete-property: func(target: handle<js-abi-value>, property-key: string) -> bool"] = function(arg0, arg1, arg2) {
579
+ const memory = get_export("memory");
580
+ const ptr0 = arg1;
581
+ const len0 = arg2;
582
+ const result0 = UTF8_DECODER.decode(new Uint8Array(memory.buffer, ptr0, len0));
583
+ const ret0 = obj.reflectDeleteProperty(resources0.get(arg0), result0);
584
+ return ret0 ? 1 : 0;
585
+ };
586
+ imports["rb-js-abi-host"]["reflect-get: func(target: handle<js-abi-value>, property-key: string) -> variant { success(handle<js-abi-value>), failure(handle<js-abi-value>) }"] = function(arg0, arg1, arg2, arg3) {
587
+ const memory = get_export("memory");
588
+ const ptr0 = arg1;
589
+ const len0 = arg2;
590
+ const result0 = UTF8_DECODER.decode(new Uint8Array(memory.buffer, ptr0, len0));
591
+ const ret0 = obj.reflectGet(resources0.get(arg0), result0);
592
+ const variant1 = ret0;
593
+ switch (variant1.tag) {
594
+ case "success": {
595
+ const e = variant1.val;
596
+ data_view(memory).setInt8(arg3 + 0, 0, true);
597
+ data_view(memory).setInt32(arg3 + 4, resources0.insert(e), true);
598
+ break;
599
+ }
600
+ case "failure": {
601
+ const e = variant1.val;
602
+ data_view(memory).setInt8(arg3 + 0, 1, true);
603
+ data_view(memory).setInt32(arg3 + 4, resources0.insert(e), true);
604
+ break;
605
+ }
606
+ default:
607
+ throw new RangeError("invalid variant specified for JsAbiResult");
608
+ }
609
+ };
610
+ imports["rb-js-abi-host"]["reflect-get-own-property-descriptor: func(target: handle<js-abi-value>, property-key: string) -> handle<js-abi-value>"] = function(arg0, arg1, arg2) {
611
+ const memory = get_export("memory");
612
+ const ptr0 = arg1;
613
+ const len0 = arg2;
614
+ const result0 = UTF8_DECODER.decode(new Uint8Array(memory.buffer, ptr0, len0));
615
+ const ret0 = obj.reflectGetOwnPropertyDescriptor(resources0.get(arg0), result0);
616
+ return resources0.insert(ret0);
617
+ };
618
+ imports["rb-js-abi-host"]["reflect-get-prototype-of: func(target: handle<js-abi-value>) -> handle<js-abi-value>"] = function(arg0) {
619
+ const ret0 = obj.reflectGetPrototypeOf(resources0.get(arg0));
620
+ return resources0.insert(ret0);
621
+ };
622
+ imports["rb-js-abi-host"]["reflect-has: func(target: handle<js-abi-value>, property-key: string) -> bool"] = function(arg0, arg1, arg2) {
623
+ const memory = get_export("memory");
624
+ const ptr0 = arg1;
625
+ const len0 = arg2;
626
+ const result0 = UTF8_DECODER.decode(new Uint8Array(memory.buffer, ptr0, len0));
627
+ const ret0 = obj.reflectHas(resources0.get(arg0), result0);
628
+ return ret0 ? 1 : 0;
629
+ };
630
+ imports["rb-js-abi-host"]["reflect-is-extensible: func(target: handle<js-abi-value>) -> bool"] = function(arg0) {
631
+ const ret0 = obj.reflectIsExtensible(resources0.get(arg0));
632
+ return ret0 ? 1 : 0;
633
+ };
634
+ imports["rb-js-abi-host"]["reflect-own-keys: func(target: handle<js-abi-value>) -> list<handle<js-abi-value>>"] = function(arg0, arg1) {
635
+ const memory = get_export("memory");
636
+ const realloc = get_export("cabi_realloc");
637
+ const ret0 = obj.reflectOwnKeys(resources0.get(arg0));
638
+ const vec0 = ret0;
639
+ const len0 = vec0.length;
640
+ const result0 = realloc(0, 0, 4, len0 * 4);
641
+ for (let i = 0; i < vec0.length; i++) {
642
+ const e = vec0[i];
643
+ const base = result0 + i * 4;
644
+ data_view(memory).setInt32(base + 0, resources0.insert(e), true);
645
+ }
646
+ data_view(memory).setInt32(arg1 + 4, len0, true);
647
+ data_view(memory).setInt32(arg1 + 0, result0, true);
648
+ };
649
+ imports["rb-js-abi-host"]["reflect-prevent-extensions: func(target: handle<js-abi-value>) -> bool"] = function(arg0) {
650
+ const ret0 = obj.reflectPreventExtensions(resources0.get(arg0));
651
+ return ret0 ? 1 : 0;
652
+ };
653
+ imports["rb-js-abi-host"]["reflect-set: func(target: handle<js-abi-value>, property-key: string, value: handle<js-abi-value>) -> variant { success(handle<js-abi-value>), failure(handle<js-abi-value>) }"] = function(arg0, arg1, arg2, arg3, arg4) {
654
+ const memory = get_export("memory");
655
+ const ptr0 = arg1;
656
+ const len0 = arg2;
657
+ const result0 = UTF8_DECODER.decode(new Uint8Array(memory.buffer, ptr0, len0));
658
+ const ret0 = obj.reflectSet(resources0.get(arg0), result0, resources0.get(arg3));
659
+ const variant1 = ret0;
660
+ switch (variant1.tag) {
661
+ case "success": {
662
+ const e = variant1.val;
663
+ data_view(memory).setInt8(arg4 + 0, 0, true);
664
+ data_view(memory).setInt32(arg4 + 4, resources0.insert(e), true);
665
+ break;
666
+ }
667
+ case "failure": {
668
+ const e = variant1.val;
669
+ data_view(memory).setInt8(arg4 + 0, 1, true);
670
+ data_view(memory).setInt32(arg4 + 4, resources0.insert(e), true);
671
+ break;
672
+ }
673
+ default:
674
+ throw new RangeError("invalid variant specified for JsAbiResult");
675
+ }
676
+ };
677
+ imports["rb-js-abi-host"]["reflect-set-prototype-of: func(target: handle<js-abi-value>, prototype: handle<js-abi-value>) -> bool"] = function(arg0, arg1) {
678
+ const ret0 = obj.reflectSetPrototypeOf(resources0.get(arg0), resources0.get(arg1));
679
+ return ret0 ? 1 : 0;
680
+ };
681
+ if (!("canonical_abi" in imports)) imports["canonical_abi"] = {};
682
+
683
+ const resources0 = new Slab();
684
+ imports.canonical_abi["resource_drop_js-abi-value"] = (i) => {
685
+ const val = resources0.remove(i);
686
+ if (obj.dropJsAbiValue)
687
+ obj.dropJsAbiValue(val);
688
+ };
689
+ }
690
+
691
+ class LegacyBinding extends RbAbiGuest {
692
+ async setInstance(instance) {
693
+ await this.instantiate(instance);
694
+ }
695
+ }
696
+ class ComponentBinding {
697
+ constructor() { }
698
+ setUnderlying(underlying) {
699
+ this.underlying = underlying;
700
+ }
701
+ rubyShowVersion() {
702
+ this.underlying.rubyShowVersion();
703
+ }
704
+ rubyInit(args) {
705
+ this.underlying.rubyInit(args);
706
+ }
707
+ rubyInitLoadpath() {
708
+ this.underlying.rubyInitLoadpath();
709
+ }
710
+ rbEvalStringProtect(str) {
711
+ return this.underlying.rbEvalStringProtect(str);
712
+ }
713
+ rbFuncallvProtect(recv, mid, args) {
714
+ return this.underlying.rbFuncallvProtect(recv, mid, args);
715
+ }
716
+ rbIntern(name) {
717
+ return this.underlying.rbIntern(name);
718
+ }
719
+ rbErrinfo() {
720
+ return this.underlying.rbErrinfo();
721
+ }
722
+ rbClearErrinfo() {
723
+ return this.underlying.rbClearErrinfo();
724
+ }
725
+ rstringPtr(value) {
726
+ return this.underlying.rstringPtr(value);
727
+ }
728
+ rbVmBugreport() {
729
+ this.underlying.rbVmBugreport();
730
+ }
731
+ rbGcEnable() {
732
+ return this.underlying.rbGcEnable();
733
+ }
734
+ rbGcDisable() {
735
+ return this.underlying.rbGcDisable();
736
+ }
737
+ rbSetShouldProhibitRewind(newValue) {
738
+ return this.underlying.rbSetShouldProhibitRewind(newValue);
739
+ }
740
+ async setInstance(instance) {
741
+ // No-op
742
+ }
743
+ addToImports(imports) {
744
+ // No-op
745
+ }
746
+ }
747
+
748
+ /**
749
+ * A Ruby VM instance
750
+ * @see {@link RubyVM.instantiateComponent} and {@link RubyVM.instantiateModule} to create a new instance
751
+ * @category Essentials
752
+ */
753
+ class RubyVM {
754
+ /**
755
+ * Instantiate a Ruby VM with the given WebAssembly Core module with WASI Preview 1 implementation.
756
+ *
757
+ * @param options The options to instantiate the Ruby VM
758
+ * @returns A promise that resolves to the Ruby VM instance and the WebAssembly instance
759
+ * @category Essentials
760
+ *
761
+ * @example
762
+ *
763
+ * import { WASI } from "@bjorn3/browser_wasi_shim";
764
+ * const wasip1 = new WASI([], [], []);
765
+ * const module = await WebAssembly.compile("./path/to/ruby.wasm");
766
+ * const { vm } = await RubyVM.instantiateModule({ module, wasip1 });
767
+ *
768
+ */
769
+ static async instantiateModule(options) {
770
+ var _a, _b;
771
+ const { module, wasip1 } = options;
772
+ const vm = new RubyVM();
773
+ const imports = {
774
+ wasi_snapshot_preview1: wasip1.wasiImport,
775
+ };
776
+ vm.addToImports(imports);
777
+ (_a = options.addToImports) === null || _a === void 0 ? void 0 : _a.call(options, imports);
778
+ const instance = await WebAssembly.instantiate(module, imports);
779
+ try {
780
+ await vm.setInstance(instance);
781
+ }
782
+ catch (e) {
783
+ console.error("Failed to instantiate Ruby VM. Please make sure that you have added `gem \"js\"` to your Gemfile.");
784
+ throw e;
785
+ }
786
+ (_b = options.setMemory) === null || _b === void 0 ? void 0 : _b.call(options, instance.exports.memory);
787
+ wasip1.initialize(instance);
788
+ vm.initialize(options.args);
789
+ return { vm, instance };
790
+ }
791
+ /**
792
+ * Instantiate a Ruby VM with the given WebAssembly component with WASI Preview 2 implementation.
793
+ *
794
+ * @param options The options to instantiate the Ruby VM
795
+ * @returns A promise that resolves to the Ruby VM instance
796
+ * @category Essentials
797
+ *
798
+ * @example
799
+ *
800
+ * // First, you need to transpile the Ruby component to a JavaScript module using jco.
801
+ * // $ jco transpile --no-wasi-shim --instantiation --valid-lifting-optimization ./ruby.component.wasm -o ./component
802
+ * // Then, you can instantiate the Ruby VM with the component:
803
+ *
804
+ * import * as wasip2 from "@bytecodealliance/preview2-shim"
805
+ * import fs from "fs/promises";
806
+ * import path from "path";
807
+ *
808
+ * const { instantiate } = await import("./component/ruby.component.js");
809
+ * const getCoreModule = async (relativePath) => {
810
+ * const buffer = await fs.readFile(path.join("./component", relativePath));
811
+ * return WebAssembly.compile(buffer);
812
+ * }
813
+ *
814
+ * const { vm } = await RubyVM.instantiateComponent({
815
+ * instantiate, getCoreModule, wasip2,
816
+ * });
817
+ *
818
+ */
819
+ static async instantiateComponent(options) {
820
+ let initComponent;
821
+ if ("getCoreModule" in options) {
822
+ // A convenience overload to instantiate with "instantiate" function generated by jco
823
+ initComponent = async (jsRuntime) => {
824
+ const { instantiate, getCoreModule, wasip2 } = options;
825
+ const { cli, clocks, filesystem, io, random, sockets, http } = wasip2;
826
+ const importObject = {
827
+ "ruby:js/js-runtime": jsRuntime,
828
+ "wasi:cli/environment": cli.environment,
829
+ "wasi:cli/exit": cli.exit,
830
+ "wasi:cli/stderr": cli.stderr,
831
+ "wasi:cli/stdin": cli.stdin,
832
+ "wasi:cli/stdout": cli.stdout,
833
+ "wasi:cli/terminal-input": cli.terminalInput,
834
+ "wasi:cli/terminal-output": cli.terminalOutput,
835
+ "wasi:cli/terminal-stderr": cli.terminalStderr,
836
+ "wasi:cli/terminal-stdin": cli.terminalStdin,
837
+ "wasi:cli/terminal-stdout": cli.terminalStdout,
838
+ "wasi:clocks/monotonic-clock": clocks.monotonicClock,
839
+ "wasi:clocks/wall-clock": clocks.wallClock,
840
+ "wasi:filesystem/preopens": filesystem.preopens,
841
+ "wasi:filesystem/types": filesystem.types,
842
+ "wasi:io/error": io.error,
843
+ "wasi:io/poll": io.poll,
844
+ "wasi:io/streams": io.streams,
845
+ "wasi:random/random": random.random,
846
+ "wasi:sockets/tcp": sockets.tcp,
847
+ "wasi:http/types": http.types,
848
+ "wasi:http/incoming-handler": http.incomingHandler,
849
+ "wasi:http/outgoing-handler": http.outgoingHandler,
850
+ };
851
+ const component = await instantiate(getCoreModule, importObject, options.instantiateCore);
852
+ return component.rubyRuntime;
853
+ };
854
+ }
855
+ else {
856
+ initComponent = options.instantiate;
857
+ }
858
+ const vm = await this._instantiate({}, initComponent);
859
+ return { vm };
860
+ }
861
+ constructor(binding) {
862
+ this.instance = null;
863
+ this.interfaceState = {
864
+ hasJSFrameAfterRbFrame: false,
865
+ };
866
+ // Wrap exported functions from Ruby VM to prohibit nested VM operation
867
+ // if the call stack has sandwitched JS frames like JS -> Ruby -> JS -> Ruby.
868
+ const proxyExports = (exports) => {
869
+ const excludedMethods = [
870
+ "setInstance",
871
+ "addToImports",
872
+ "instantiate",
873
+ "rbSetShouldProhibitRewind",
874
+ "rbGcDisable",
875
+ "rbGcEnable",
876
+ ];
877
+ const excluded = ["constructor"].concat(excludedMethods);
878
+ // wrap all methods in RbAbi.RbAbiGuest class
879
+ for (const key of Object.getOwnPropertyNames(RbAbiGuest.prototype)) {
880
+ if (excluded.includes(key)) {
881
+ continue;
882
+ }
883
+ const value = exports[key];
884
+ if (typeof value === "function") {
885
+ exports[key] = (...args) => {
886
+ const isNestedVMCall = this.interfaceState.hasJSFrameAfterRbFrame;
887
+ if (isNestedVMCall) {
888
+ const oldShouldProhibitRewind = this.guest.rbSetShouldProhibitRewind(true);
889
+ const oldIsDisabledGc = this.guest.rbGcDisable();
890
+ const result = Reflect.apply(value, exports, args);
891
+ this.guest.rbSetShouldProhibitRewind(oldShouldProhibitRewind);
892
+ if (!oldIsDisabledGc) {
893
+ this.guest.rbGcEnable();
894
+ }
895
+ return result;
896
+ }
897
+ else {
898
+ return Reflect.apply(value, exports, args);
899
+ }
900
+ };
901
+ }
902
+ }
903
+ return exports;
904
+ };
905
+ this.guest = proxyExports(binding !== null && binding !== void 0 ? binding : new LegacyBinding());
906
+ this.transport = new JsValueTransport();
907
+ this.exceptionFormatter = new RbExceptionFormatter();
908
+ }
909
+ static async _instantiate(options, initComponent) {
910
+ const binding = new ComponentBinding();
911
+ const vm = new RubyVM(binding);
912
+ class JsAbiValue {
913
+ constructor(underlying) {
914
+ this.underlying = underlying;
915
+ }
916
+ }
917
+ const imports = vm.getImports((from) => new JsAbiValue(from), (to) => to.underlying);
918
+ const component = await initComponent(Object.assign(Object.assign({}, imports), { throwProhibitRewindException: (message) => {
919
+ vm.throwProhibitRewindException(message);
920
+ }, procToJsFunction: () => {
921
+ const rbValue = new RbValue(component.exportRbValueToJs(), vm, vm.privateObject());
922
+ return new JsAbiValue((...args) => {
923
+ return rbValue.call("call", ...args.map((arg) => vm.wrap(arg))).toJS();
924
+ });
925
+ }, rbObjectToJsRbValue: () => {
926
+ const rbValue = new RbValue(component.exportRbValueToJs(), vm, vm.privateObject());
927
+ return new JsAbiValue(rbValue);
928
+ }, JsAbiValue: JsAbiValue }));
929
+ binding.setUnderlying(component);
930
+ vm.initialize(options.args);
931
+ return vm;
932
+ }
933
+ /**
934
+ * Initialize the Ruby VM with the given command line arguments
935
+ * @param args The command line arguments to pass to Ruby. Must be
936
+ * an array of strings starting with the Ruby program name.
937
+ * @category Low-level initialization
938
+ */
939
+ initialize(args = ["ruby.wasm", "-EUTF-8", "-e_=0"]) {
940
+ const c_args = args.map((arg) => arg + "\0");
941
+ this.guest.rubyInit(c_args);
942
+ try {
943
+ this.eval(`
944
+ # Require Bundler standalone setup
945
+ if File.exist?("/bundle/bundler/setup.rb")
946
+ require "/bundle/bundler/setup.rb"
947
+ elsif File.exist?("/bundle/setup.rb")
948
+ # For non-CM builds, which doesn't use Bundler's standalone mode
949
+ require "/bundle/setup.rb"
950
+ end
951
+ `);
952
+ }
953
+ catch (e) {
954
+ console.warn("Failed to load /bundle/setup", e);
955
+ }
956
+ }
957
+ /**
958
+ * Set a given instance to interact JavaScript and Ruby's
959
+ * WebAssembly instance. This method must be called before calling
960
+ * Ruby API.
961
+ *
962
+ * @param instance The WebAssembly instance to interact with. Must
963
+ * be instantiated from a Ruby built with JS extension, and built
964
+ * with Reactor ABI instead of command line.
965
+ * @category Low-level initialization
966
+ */
967
+ async setInstance(instance) {
968
+ this.instance = instance;
969
+ await this.guest.setInstance(instance);
970
+ }
971
+ /**
972
+ * Add intrinsic import entries, which is necessary to interact JavaScript
973
+ * and Ruby's WebAssembly instance.
974
+ * @param imports The import object to add to the WebAssembly instance
975
+ * @category Low-level initialization
976
+ */
977
+ addToImports(imports) {
978
+ this.guest.addToImports(imports);
979
+ imports["rb-js-abi-host"] = {
980
+ rb_wasm_throw_prohibit_rewind_exception: (messagePtr, messageLen) => {
981
+ const memory = this.instance.exports.memory;
982
+ const str = new TextDecoder().decode(new Uint8Array(memory.buffer, messagePtr, messageLen));
983
+ this.throwProhibitRewindException(str);
984
+ },
985
+ };
986
+ addRbJsAbiHostToImports(imports, this.getImports((value) => value, (value) => value), (name) => {
987
+ return this.instance.exports[name];
988
+ });
989
+ }
990
+ throwProhibitRewindException(str) {
991
+ let message = "Ruby APIs that may rewind the VM stack are prohibited under nested VM operation " +
992
+ `(${str})\n` +
993
+ "Nested VM operation means that the call stack has sandwitched JS frames like JS -> Ruby -> JS -> Ruby " +
994
+ "caused by something like `window.rubyVM.eval(\"JS.global[:rubyVM].eval('Fiber.yield')\")`\n" +
995
+ "\n" +
996
+ "Please check your call stack and make sure that you are **not** doing any of the following inside the nested Ruby frame:\n" +
997
+ " 1. Switching fibers (e.g. Fiber#resume, Fiber.yield, and Fiber#transfer)\n" +
998
+ " Note that `evalAsync` JS API switches fibers internally\n" +
999
+ " 2. Raising uncaught exceptions\n" +
1000
+ " Please catch all exceptions inside the nested operation\n" +
1001
+ " 3. Calling Continuation APIs\n";
1002
+ const error = new RbValue(this.guest.rbErrinfo(), this, this.privateObject());
1003
+ if (error.call("nil?").toString() === "false") {
1004
+ message += "\n" + this.exceptionFormatter.format(error, this, this.privateObject());
1005
+ }
1006
+ throw new RbFatalError(message);
1007
+ }
1008
+ getImports(toJSAbiValue, fromJSAbiValue) {
1009
+ // NOTE: The GC may collect objects that are still referenced by Wasm
1010
+ // locals because Asyncify cannot scan the Wasm stack above the JS frame.
1011
+ // So we need to keep track whether the JS frame is sandwitched by Ruby
1012
+ // frames or not, and prohibit nested VM operation if it is.
1013
+ const proxyImports = (imports) => {
1014
+ for (const [key, value] of Object.entries(imports)) {
1015
+ if (typeof value === "function") {
1016
+ imports[key] = (...args) => {
1017
+ const oldValue = this.interfaceState.hasJSFrameAfterRbFrame;
1018
+ this.interfaceState.hasJSFrameAfterRbFrame = true;
1019
+ const result = Reflect.apply(value, imports, args);
1020
+ this.interfaceState.hasJSFrameAfterRbFrame = oldValue;
1021
+ return result;
1022
+ };
1023
+ }
1024
+ }
1025
+ return imports;
1026
+ };
1027
+ function wrapTry(f) {
1028
+ return (...args) => {
1029
+ try {
1030
+ return { tag: "success", val: f(...args) };
1031
+ }
1032
+ catch (e) {
1033
+ if (e instanceof RbFatalError) {
1034
+ // RbFatalError should not be caught by Ruby because it Ruby VM
1035
+ // can be already in an inconsistent state.
1036
+ throw e;
1037
+ }
1038
+ return { tag: "failure", val: toJSAbiValue(e) };
1039
+ }
1040
+ };
1041
+ }
1042
+ return proxyImports({
1043
+ evalJs: wrapTry((code) => {
1044
+ return toJSAbiValue(Function(code)());
1045
+ }),
1046
+ isJs: (value) => {
1047
+ // Just for compatibility with the old JS API
1048
+ return true;
1049
+ },
1050
+ globalThis: () => {
1051
+ if (typeof globalThis !== "undefined") {
1052
+ return toJSAbiValue(globalThis);
1053
+ }
1054
+ else if (typeof global !== "undefined") {
1055
+ return toJSAbiValue(global);
1056
+ }
1057
+ else if (typeof window !== "undefined") {
1058
+ return toJSAbiValue(window);
1059
+ }
1060
+ throw new Error("unable to locate global object");
1061
+ },
1062
+ intToJsNumber: (value) => {
1063
+ return toJSAbiValue(value);
1064
+ },
1065
+ floatToJsNumber: (value) => {
1066
+ return toJSAbiValue(value);
1067
+ },
1068
+ stringToJsString: (value) => {
1069
+ return toJSAbiValue(value);
1070
+ },
1071
+ boolToJsBool: (value) => {
1072
+ return toJSAbiValue(value);
1073
+ },
1074
+ procToJsFunction: (rawRbAbiValue) => {
1075
+ const rbValue = this.rbValueOfPointer(rawRbAbiValue);
1076
+ return toJSAbiValue((...args) => {
1077
+ return rbValue.call("call", ...args.map((arg) => this.wrap(arg))).toJS();
1078
+ });
1079
+ },
1080
+ rbObjectToJsRbValue: (rawRbAbiValue) => {
1081
+ return toJSAbiValue(this.rbValueOfPointer(rawRbAbiValue));
1082
+ },
1083
+ jsValueToString: (value) => {
1084
+ value = fromJSAbiValue(value);
1085
+ // According to the [spec](https://tc39.es/ecma262/multipage/text-processing.html#sec-string-constructor-string-value)
1086
+ // `String(value)` always returns a string.
1087
+ return String(value);
1088
+ },
1089
+ jsValueToInteger(value) {
1090
+ value = fromJSAbiValue(value);
1091
+ if (typeof value === "number") {
1092
+ return { tag: "as-float", val: value };
1093
+ }
1094
+ else if (typeof value === "bigint") {
1095
+ return { tag: "bignum", val: BigInt(value).toString(10) + "\0" };
1096
+ }
1097
+ else if (typeof value === "string") {
1098
+ return { tag: "bignum", val: value + "\0" };
1099
+ }
1100
+ else if (typeof value === "undefined") {
1101
+ return { tag: "as-float", val: 0 };
1102
+ }
1103
+ else {
1104
+ return { tag: "as-float", val: Number(value) };
1105
+ }
1106
+ },
1107
+ exportJsValueToHost: (value) => {
1108
+ // See `JsValueExporter` for the reason why we need to do this
1109
+ this.transport.takeJsValue(fromJSAbiValue(value));
1110
+ },
1111
+ importJsValueFromHost: () => {
1112
+ return toJSAbiValue(this.transport.consumeJsValue());
1113
+ },
1114
+ instanceOf: (value, klass) => {
1115
+ klass = fromJSAbiValue(klass);
1116
+ if (typeof klass === "function") {
1117
+ return fromJSAbiValue(value) instanceof klass;
1118
+ }
1119
+ else {
1120
+ return false;
1121
+ }
1122
+ },
1123
+ jsValueTypeof(value) {
1124
+ return typeof fromJSAbiValue(value);
1125
+ },
1126
+ jsValueEqual(lhs, rhs) {
1127
+ return fromJSAbiValue(lhs) == fromJSAbiValue(rhs);
1128
+ },
1129
+ jsValueStrictlyEqual(lhs, rhs) {
1130
+ return fromJSAbiValue(lhs) === fromJSAbiValue(rhs);
1131
+ },
1132
+ reflectApply: wrapTry((target, thisArgument, args) => {
1133
+ const jsArgs = args.map((arg) => fromJSAbiValue(arg));
1134
+ return toJSAbiValue(Reflect.apply(fromJSAbiValue(target), fromJSAbiValue(thisArgument), jsArgs));
1135
+ }),
1136
+ reflectConstruct: function (target, args) {
1137
+ throw new Error("Function not implemented.");
1138
+ },
1139
+ reflectDeleteProperty: function (target, propertyKey) {
1140
+ throw new Error("Function not implemented.");
1141
+ },
1142
+ reflectGet: wrapTry((target, propertyKey) => {
1143
+ return toJSAbiValue(fromJSAbiValue(target)[propertyKey]);
1144
+ }),
1145
+ reflectGetOwnPropertyDescriptor: function (target, propertyKey) {
1146
+ throw new Error("Function not implemented.");
1147
+ },
1148
+ reflectGetPrototypeOf: function (target) {
1149
+ throw new Error("Function not implemented.");
1150
+ },
1151
+ reflectHas: function (target, propertyKey) {
1152
+ throw new Error("Function not implemented.");
1153
+ },
1154
+ reflectIsExtensible: function (target) {
1155
+ throw new Error("Function not implemented.");
1156
+ },
1157
+ reflectOwnKeys: function (target) {
1158
+ throw new Error("Function not implemented.");
1159
+ },
1160
+ reflectPreventExtensions: function (target) {
1161
+ throw new Error("Function not implemented.");
1162
+ },
1163
+ reflectSet: wrapTry((target, propertyKey, value) => {
1164
+ return toJSAbiValue(Reflect.set(fromJSAbiValue(target), propertyKey, fromJSAbiValue(value)));
1165
+ }),
1166
+ reflectSetPrototypeOf: function (target, prototype) {
1167
+ throw new Error("Function not implemented.");
1168
+ },
1169
+ });
1170
+ }
1171
+ /**
1172
+ * Print the Ruby version to stdout
1173
+ */
1174
+ printVersion() {
1175
+ this.guest.rubyShowVersion();
1176
+ }
1177
+ /**
1178
+ * Runs a string of Ruby code from JavaScript
1179
+ * @param code The Ruby code to run
1180
+ * @returns the result of the last expression
1181
+ * @category Essentials
1182
+ *
1183
+ * @example
1184
+ * vm.eval("puts 'hello world'");
1185
+ * const result = vm.eval("1 + 2");
1186
+ * console.log(result.toString()); // 3
1187
+ *
1188
+ */
1189
+ eval(code) {
1190
+ return evalRbCode(this, this.privateObject(), code);
1191
+ }
1192
+ /**
1193
+ * Runs a string of Ruby code with top-level `JS::Object#await`
1194
+ * Returns a promise that resolves when execution completes.
1195
+ * @param code The Ruby code to run
1196
+ * @returns a promise that resolves to the result of the last expression
1197
+ * @category Essentials
1198
+ *
1199
+ * @example
1200
+ * const text = await vm.evalAsync(`
1201
+ * require 'js'
1202
+ * response = JS.global.fetch('https://example.com').await
1203
+ * response.text.await
1204
+ * `);
1205
+ * console.log(text.toString()); // <html>...</html>
1206
+ */
1207
+ evalAsync(code) {
1208
+ const JS = this.eval("require 'js'; JS");
1209
+ return newRbPromise(this, this.privateObject(), (future) => {
1210
+ JS.call("__eval_async_rb", this.wrap(code), future);
1211
+ });
1212
+ }
1213
+ /**
1214
+ * Wrap a JavaScript value into a Ruby JS::Object
1215
+ * @param value The value to convert to RbValue
1216
+ * @returns the RbValue object representing the given JS value
1217
+ *
1218
+ * @example
1219
+ * const hash = vm.eval(`Hash.new`)
1220
+ * hash.call("store", vm.eval(`"key1"`), vm.wrap(new Object()));
1221
+ */
1222
+ wrap(value) {
1223
+ return this.transport.importJsValue(value, this);
1224
+ }
1225
+ /** @private */
1226
+ privateObject() {
1227
+ return {
1228
+ transport: this.transport,
1229
+ exceptionFormatter: this.exceptionFormatter,
1230
+ };
1231
+ }
1232
+ /** @private */
1233
+ rbValueOfPointer(pointer) {
1234
+ const abiValue = new RbAbiValue(pointer, this.guest);
1235
+ return new RbValue(abiValue, this, this.privateObject());
1236
+ }
1237
+ }
1238
+ /**
1239
+ * Export a JS value held by the Ruby VM to the JS environment.
1240
+ * This is implemented in a dirty way since wit cannot reference resources
1241
+ * defined in other interfaces.
1242
+ * In our case, we can't express `function(v: rb-abi-value) -> js-abi-value`
1243
+ * because `rb-js-abi-host.wit`, that defines `js-abi-value`, is implemented
1244
+ * by embedder side (JS) but `rb-abi-guest.wit`, that defines `rb-abi-value`
1245
+ * is implemented by guest side (Wasm).
1246
+ *
1247
+ * This class is a helper to export by:
1248
+ * 1. Call `function __export_to_js(v: rb-abi-value)` defined in guest from embedder side.
1249
+ * 2. Call `function takeJsValue(v: js-abi-value)` defined in embedder from guest side with
1250
+ * underlying JS value of given `rb-abi-value`.
1251
+ * 3. Then `takeJsValue` implementation escapes the given JS value to the `_takenJsValues`
1252
+ * stored in embedder side.
1253
+ * 4. Finally, embedder side can take `_takenJsValues`.
1254
+ *
1255
+ * Note that `exportJsValue` is not reentrant.
1256
+ *
1257
+ * @private
1258
+ */
1259
+ class JsValueTransport {
1260
+ constructor() {
1261
+ this._takenJsValue = null;
1262
+ }
1263
+ takeJsValue(value) {
1264
+ this._takenJsValue = value;
1265
+ }
1266
+ consumeJsValue() {
1267
+ return this._takenJsValue;
1268
+ }
1269
+ exportJsValue(value) {
1270
+ value.call("__export_to_js");
1271
+ return this._takenJsValue;
1272
+ }
1273
+ importJsValue(value, vm) {
1274
+ this._takenJsValue = value;
1275
+ return vm.eval('require "js"; JS::Object').call("__import_from_js");
1276
+ }
1277
+ }
1278
+ /**
1279
+ * A RbValue is an object that represents a value in Ruby
1280
+ * @category Essentials
1281
+ */
1282
+ class RbValue {
1283
+ /**
1284
+ * @hideconstructor
1285
+ */
1286
+ constructor(inner, vm, privateObject) {
1287
+ this.inner = inner;
1288
+ this.vm = vm;
1289
+ this.privateObject = privateObject;
1290
+ }
1291
+ /**
1292
+ * Call a given method with given arguments
1293
+ *
1294
+ * @param callee name of the Ruby method to call
1295
+ * @param args arguments to pass to the method. Must be an array of RbValue
1296
+ * @returns The result of the method call as a new RbValue.
1297
+ *
1298
+ * @example
1299
+ * const ary = vm.eval("[1, 2, 3]");
1300
+ * ary.call("push", 4);
1301
+ * console.log(ary.call("sample").toString());
1302
+ */
1303
+ call(callee, ...args) {
1304
+ const innerArgs = args.map((arg) => arg.inner);
1305
+ return new RbValue(callRbMethod(this.vm, this.privateObject, this.inner, callee, innerArgs), this.vm, this.privateObject);
1306
+ }
1307
+ /**
1308
+ * Call a given method that may call `JS::Object#await` with given arguments
1309
+ *
1310
+ * @param callee name of the Ruby method to call
1311
+ * @param args arguments to pass to the method. Must be an array of RbValue
1312
+ * @returns A Promise that resolves to the result of the method call as a new RbValue.
1313
+ *
1314
+ * @example
1315
+ * const client = vm.eval(`
1316
+ * require 'js'
1317
+ * class HttpClient
1318
+ * def get(url)
1319
+ * JS.global.fetch(url).await
1320
+ * end
1321
+ * end
1322
+ * HttpClient.new
1323
+ * `);
1324
+ * const response = await client.callAsync("get", vm.eval(`"https://example.com"`));
1325
+ */
1326
+ callAsync(callee, ...args) {
1327
+ const JS = this.vm.eval("require 'js'; JS");
1328
+ return newRbPromise(this.vm, this.privateObject, (future) => {
1329
+ JS.call("__call_async_method", this, this.vm.wrap(callee), future, ...args);
1330
+ });
1331
+ }
1332
+ /**
1333
+ * @see {@link https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toPrimitive}
1334
+ * @param hint Preferred type of the result primitive value. `"number"`, `"string"`, or `"default"`.
1335
+ */
1336
+ [Symbol.toPrimitive](hint) {
1337
+ if (hint === "string" || hint === "default") {
1338
+ return this.toString();
1339
+ }
1340
+ else if (hint === "number") {
1341
+ return null;
1342
+ }
1343
+ return null;
1344
+ }
1345
+ /**
1346
+ * Returns a string representation of the value by calling `to_s`
1347
+ */
1348
+ toString() {
1349
+ const rbString = callRbMethod(this.vm, this.privateObject, this.inner, "to_s", []);
1350
+ return this.vm.guest.rstringPtr(rbString);
1351
+ }
1352
+ /**
1353
+ * Returns a JavaScript object representation of the value
1354
+ * by calling `to_js`.
1355
+ *
1356
+ * Returns null if the value is not convertible to a JavaScript object.
1357
+ */
1358
+ toJS() {
1359
+ const JS = this.vm.eval("JS");
1360
+ const jsValue = JS.call("try_convert", this);
1361
+ if (jsValue.call("nil?").toString() === "true") {
1362
+ return null;
1363
+ }
1364
+ return this.privateObject.transport.exportJsValue(jsValue);
1365
+ }
1366
+ }
1367
+ var ruby_tag_type;
1368
+ (function (ruby_tag_type) {
1369
+ ruby_tag_type[ruby_tag_type["None"] = 0] = "None";
1370
+ ruby_tag_type[ruby_tag_type["Return"] = 1] = "Return";
1371
+ ruby_tag_type[ruby_tag_type["Break"] = 2] = "Break";
1372
+ ruby_tag_type[ruby_tag_type["Next"] = 3] = "Next";
1373
+ ruby_tag_type[ruby_tag_type["Retry"] = 4] = "Retry";
1374
+ ruby_tag_type[ruby_tag_type["Redo"] = 5] = "Redo";
1375
+ ruby_tag_type[ruby_tag_type["Raise"] = 6] = "Raise";
1376
+ ruby_tag_type[ruby_tag_type["Throw"] = 7] = "Throw";
1377
+ ruby_tag_type[ruby_tag_type["Fatal"] = 8] = "Fatal";
1378
+ ruby_tag_type[ruby_tag_type["Mask"] = 15] = "Mask";
1379
+ })(ruby_tag_type || (ruby_tag_type = {}));
1380
+ class RbExceptionFormatter {
1381
+ constructor() {
1382
+ this.literalsCache = null;
1383
+ this.isFormmatting = false;
1384
+ }
1385
+ format(error, vm, privateObject) {
1386
+ // All Ruby exceptions raised during formatting exception message should
1387
+ // be caught and return a fallback message.
1388
+ // Therefore, we don't need to worry about infinite recursion here ideally
1389
+ // but checking re-entrancy just in case.
1390
+ class RbExceptionFormatterError extends Error {
1391
+ }
1392
+ if (this.isFormmatting) {
1393
+ throw new RbExceptionFormatterError("Unexpected exception occurred during formatting exception message");
1394
+ }
1395
+ this.isFormmatting = true;
1396
+ try {
1397
+ return this._format(error, vm, privateObject);
1398
+ }
1399
+ finally {
1400
+ this.isFormmatting = false;
1401
+ }
1402
+ }
1403
+ _format(error, vm, privateObject) {
1404
+ const [zeroLiteral, oneLiteral, newLineLiteral] = (() => {
1405
+ if (this.literalsCache == null) {
1406
+ const zeroOneNewLine = [
1407
+ evalRbCode(vm, privateObject, "0"),
1408
+ evalRbCode(vm, privateObject, "1"),
1409
+ evalRbCode(vm, privateObject, `"\n"`),
1410
+ ];
1411
+ this.literalsCache = zeroOneNewLine;
1412
+ return zeroOneNewLine;
1413
+ }
1414
+ else {
1415
+ return this.literalsCache;
1416
+ }
1417
+ })();
1418
+ let className;
1419
+ let backtrace;
1420
+ let message;
1421
+ try {
1422
+ className = error.call("class").toString();
1423
+ }
1424
+ catch (e) {
1425
+ className = "unknown";
1426
+ }
1427
+ try {
1428
+ message = error.call("message").toString();
1429
+ }
1430
+ catch (e) {
1431
+ message = "unknown";
1432
+ }
1433
+ try {
1434
+ backtrace = error.call("backtrace");
1435
+ }
1436
+ catch (e) {
1437
+ return this.formatString(className, message);
1438
+ }
1439
+ if (backtrace.call("nil?").toString() === "true") {
1440
+ return this.formatString(className, message);
1441
+ }
1442
+ try {
1443
+ const firstLine = backtrace.call("at", zeroLiteral);
1444
+ const restLines = backtrace
1445
+ .call("drop", oneLiteral)
1446
+ .call("join", newLineLiteral);
1447
+ return this.formatString(className, message, [
1448
+ firstLine.toString(),
1449
+ restLines.toString(),
1450
+ ]);
1451
+ }
1452
+ catch (e) {
1453
+ return this.formatString(className, message);
1454
+ }
1455
+ }
1456
+ formatString(klass, message, backtrace) {
1457
+ if (backtrace) {
1458
+ return `${backtrace[0]}: ${message} (${klass})\n${backtrace[1]}`;
1459
+ }
1460
+ else {
1461
+ return `${klass}: ${message}`;
1462
+ }
1463
+ }
1464
+ }
1465
+ const checkStatusTag = (rawTag, vm, privateObject) => {
1466
+ switch (rawTag & ruby_tag_type.Mask) {
1467
+ case ruby_tag_type.None:
1468
+ break;
1469
+ case ruby_tag_type.Return:
1470
+ throw new RbError("unexpected return");
1471
+ case ruby_tag_type.Next:
1472
+ throw new RbError("unexpected next");
1473
+ case ruby_tag_type.Break:
1474
+ throw new RbError("unexpected break");
1475
+ case ruby_tag_type.Redo:
1476
+ throw new RbError("unexpected redo");
1477
+ case ruby_tag_type.Retry:
1478
+ throw new RbError("retry outside of rescue clause");
1479
+ case ruby_tag_type.Throw:
1480
+ throw new RbError("unexpected throw");
1481
+ case ruby_tag_type.Raise:
1482
+ case ruby_tag_type.Fatal:
1483
+ const error = new RbValue(vm.guest.rbErrinfo(), vm, privateObject);
1484
+ if (error.call("nil?").toString() === "true") {
1485
+ throw new RbError("no exception object");
1486
+ }
1487
+ // clear errinfo if got exception due to no rb_jump_tag
1488
+ vm.guest.rbClearErrinfo();
1489
+ throw new RbError(privateObject.exceptionFormatter.format(error, vm, privateObject));
1490
+ default:
1491
+ throw new RbError(`unknown error tag: ${rawTag}`);
1492
+ }
1493
+ };
1494
+ function wrapRbOperation(vm, body) {
1495
+ try {
1496
+ return body();
1497
+ }
1498
+ catch (e) {
1499
+ if (e instanceof RbError) {
1500
+ throw e;
1501
+ }
1502
+ // All JS exceptions triggered by Ruby code are translated to Ruby exceptions,
1503
+ // so non-RbError exceptions are unexpected.
1504
+ try {
1505
+ vm.guest.rbVmBugreport();
1506
+ }
1507
+ catch (e) {
1508
+ console.error("Tried to report internal Ruby VM state but failed: ", e);
1509
+ }
1510
+ if (e instanceof WebAssembly.RuntimeError && e.message === "unreachable") {
1511
+ const error = new RbError(`Something went wrong in Ruby VM: ${e}`);
1512
+ error.stack = e.stack;
1513
+ throw error;
1514
+ }
1515
+ else {
1516
+ throw e;
1517
+ }
1518
+ }
1519
+ }
1520
+ const callRbMethod = (vm, privateObject, recv, callee, args) => {
1521
+ const mid = vm.guest.rbIntern(callee + "\0");
1522
+ return wrapRbOperation(vm, () => {
1523
+ const [value, status] = vm.guest.rbFuncallvProtect(recv, mid, args);
1524
+ checkStatusTag(status, vm, privateObject);
1525
+ return value;
1526
+ });
1527
+ };
1528
+ const evalRbCode = (vm, privateObject, code) => {
1529
+ return wrapRbOperation(vm, () => {
1530
+ const [value, status] = vm.guest.rbEvalStringProtect(code + "\0");
1531
+ checkStatusTag(status, vm, privateObject);
1532
+ return new RbValue(value, vm, privateObject);
1533
+ });
1534
+ };
1535
+ function newRbPromise(vm, privateObject, body) {
1536
+ return new Promise((resolve, reject) => {
1537
+ const future = vm.wrap({
1538
+ resolve,
1539
+ reject: (error) => {
1540
+ const rbError = new RbError(privateObject.exceptionFormatter.format(error, vm, privateObject));
1541
+ reject(rbError);
1542
+ },
1543
+ });
1544
+ body(future);
1545
+ });
1546
+ }
1547
+ /**
1548
+ * Error class thrown by Ruby execution
1549
+ */
1550
+ class RbError extends Error {
1551
+ /**
1552
+ * @hideconstructor
1553
+ */
1554
+ constructor(message) {
1555
+ super(message);
1556
+ }
1557
+ }
1558
+ /**
1559
+ * Error class thrown by Ruby execution when it is not possible to recover.
1560
+ * This is usually caused when Ruby VM is in an inconsistent state.
1561
+ */
1562
+ class RbFatalError extends RbError {
1563
+ /**
1564
+ * @hideconstructor
1565
+ */
1566
+ constructor(message) {
1567
+ super("Ruby Fatal Error: " + message);
1568
+ }
1569
+ }
1570
+
1571
+ const DefaultRubyVM = async (rubyModule, options = {}) => {
1572
+ var _a, _b;
1573
+ const args = [];
1574
+ const env = Object.entries((_a = options.env) !== null && _a !== void 0 ? _a : {}).map(([k, v]) => `${k}=${v}`);
1575
+ const fds = [
1576
+ new OpenFile(new File([])),
1577
+ new OpenFile(new File([])),
1578
+ new OpenFile(new File([])),
1579
+ new PreopenDirectory("/", new Map()),
1580
+ ];
1581
+ const wasi = new WASI(args, env, fds, { debug: false });
1582
+ const printer = ((_b = options.consolePrint) !== null && _b !== void 0 ? _b : true) ? consolePrinter() : undefined;
1583
+ const { vm, instance } = await RubyVM.instantiateModule({
1584
+ module: rubyModule, wasip1: wasi,
1585
+ addToImports: (imports) => {
1586
+ printer === null || printer === void 0 ? void 0 : printer.addToImports(imports);
1587
+ },
1588
+ setMemory: (memory) => {
1589
+ printer === null || printer === void 0 ? void 0 : printer.setMemory(memory);
1590
+ }
1591
+ });
1592
+ return {
1593
+ vm,
1594
+ wasi,
1595
+ instance,
1596
+ };
1597
+ };
1598
+
1599
+ /**
1600
+ * The main entry point of `<script type="text/ruby">`-based scripting with WebAssembly Core Module.
1601
+ */
1602
+ const main = async (pkg, options) => {
1603
+ const response = fetch(`https://cdn.jsdelivr.net/npm/${pkg.name}@${pkg.version}/dist/ruby+stdlib.wasm`);
1604
+ const module = await compileWebAssemblyModule(response);
1605
+ const { vm } = await DefaultRubyVM(module, options);
1606
+ await mainWithRubyVM(vm);
1607
+ };
1608
+ /**
1609
+ * The main entry point of `<script type="text/ruby">`-based scripting with WebAssembly Component.
1610
+ */
1611
+ const componentMain = async (pkg, options) => {
1612
+ const componentUrl = `https://cdn.jsdelivr.net/npm/${pkg.name}@${pkg.version}/dist/component`;
1613
+ const fetchComponentFile = (relativePath) => fetch(`${componentUrl}/${relativePath}`);
1614
+ const { vm } = await RubyVM.instantiateComponent(Object.assign(Object.assign({}, options), { getCoreModule: (relativePath) => {
1615
+ const response = fetchComponentFile(relativePath);
1616
+ return compileWebAssemblyModule(response);
1617
+ } }));
1618
+ await mainWithRubyVM(vm);
1619
+ };
1620
+ const mainWithRubyVM = async (vm) => {
1621
+ vm.printVersion();
1622
+ globalThis.rubyVM = vm;
1623
+ // Wait for the text/ruby script tag to be read.
1624
+ // It may take some time to read ruby+stdlib.wasm
1625
+ // and DOMContentLoaded has already been fired.
1626
+ if (document.readyState === "loading") {
1627
+ document.addEventListener("DOMContentLoaded", () => runRubyScriptsInHtml(vm));
1628
+ }
1629
+ else {
1630
+ runRubyScriptsInHtml(vm);
1631
+ }
1632
+ };
1633
+ const runRubyScriptsInHtml = async (vm) => {
1634
+ var _a, e_1, _b, _c;
1635
+ const tags = document.querySelectorAll('script[type="text/ruby"]');
1636
+ // Get Ruby scripts in parallel.
1637
+ const promisingRubyScripts = Array.from(tags).map((tag) => loadScriptAsync(tag));
1638
+ try {
1639
+ // Run Ruby scripts sequentially.
1640
+ for (var _d = true, promisingRubyScripts_1 = __asyncValues(promisingRubyScripts), promisingRubyScripts_1_1; promisingRubyScripts_1_1 = await promisingRubyScripts_1.next(), _a = promisingRubyScripts_1_1.done, !_a; _d = true) {
1641
+ _c = promisingRubyScripts_1_1.value;
1642
+ _d = false;
1643
+ const script = _c;
1644
+ if (script) {
1645
+ const { scriptContent, evalStyle } = script;
1646
+ switch (evalStyle) {
1647
+ case "async":
1648
+ vm.evalAsync(scriptContent);
1649
+ break;
1650
+ case "sync":
1651
+ vm.eval(scriptContent);
1652
+ break;
1653
+ }
1654
+ }
1655
+ }
1656
+ }
1657
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
1658
+ finally {
1659
+ try {
1660
+ if (!_d && !_a && (_b = promisingRubyScripts_1.return)) await _b.call(promisingRubyScripts_1);
1661
+ }
1662
+ finally { if (e_1) throw e_1.error; }
1663
+ }
1664
+ };
1665
+ const deriveEvalStyle = (tag) => {
1666
+ const rawEvalStyle = tag.getAttribute("data-eval") || "sync";
1667
+ if (rawEvalStyle !== "async" && rawEvalStyle !== "sync") {
1668
+ console.warn(`data-eval attribute of script tag must be "async" or "sync". ${rawEvalStyle} is ignored and "sync" is used instead.`);
1669
+ return "sync";
1670
+ }
1671
+ return rawEvalStyle;
1672
+ };
1673
+ const loadScriptAsync = async (tag) => {
1674
+ const evalStyle = deriveEvalStyle(tag);
1675
+ // Inline comments can be written with the src attribute of the script tag.
1676
+ // The presence of the src attribute is checked before the presence of the inline.
1677
+ // see: https://html.spec.whatwg.org/multipage/scripting.html#inline-documentation-for-external-scripts
1678
+ if (tag.hasAttribute("src")) {
1679
+ const url = tag.getAttribute("src");
1680
+ const response = await fetch(url);
1681
+ if (response.ok) {
1682
+ return { scriptContent: await response.text(), evalStyle };
1683
+ }
1684
+ return Promise.resolve(null);
1685
+ }
1686
+ return Promise.resolve({ scriptContent: tag.innerHTML, evalStyle });
1687
+ };
1688
+ // WebAssembly.compileStreaming is a relatively new API.
1689
+ // For example, it is not available in iOS Safari 14,
1690
+ // so check whether WebAssembly.compileStreaming is available and
1691
+ // fall back to the existing implementation using WebAssembly.compile if not.
1692
+ const compileWebAssemblyModule = async function (response) {
1693
+ if (!WebAssembly.compileStreaming) {
1694
+ const buffer = await (await response).arrayBuffer();
1695
+ return WebAssembly.compile(buffer);
1696
+ }
1697
+ else {
1698
+ return WebAssembly.compileStreaming(response);
1699
+ }
1700
+ };
1701
+
1702
+ exports.componentMain = componentMain;
1703
+ exports.main = main;
1704
+
1705
+ }));