@ruby/head-wasm-wasi 2.4.1 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.script.iife.js +151 -113
- package/dist/browser.script.umd.js +143 -110
- package/dist/browser.umd.js +1339 -1306
- package/dist/index.umd.js +1317 -1284
- package/dist/ruby+stdlib.wasm +0 -0
- package/dist/ruby.debug+stdlib.wasm +0 -0
- package/dist/ruby.wasm +0 -0
- package/package.json +8 -3
|
@@ -1343,6 +1343,107 @@ SOFTWARE.
|
|
|
1343
1343
|
|
|
1344
1344
|
class WASIProcExit extends Error{constructor(code){super("exit with exit code "+code);this.code=code;}}let WASI=class WASI{start(instance){this.inst=instance;try{instance.exports._start();}catch(e){if(e instanceof WASIProcExit){return e.code}else {throw e}}}initialize(instance){this.inst=instance;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 self.fds[fd].fd_advise(offset,len,advice)}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_datasync()}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);const{ret,nread}=self.fds[fd].fd_pread(buffer8,iovecs,offset);buffer.setUint32(nread_ptr,nread,true);return ret}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_dir_name}=self.fds[fd].fd_prestat_dir_name();if(prestat_dir_name!=null){const buffer8=new Uint8Array(self.inst.exports.memory.buffer);buffer8.set(prestat_dir_name,path_ptr);}return ret}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);const{ret,nwritten}=self.fds[fd].fd_pwrite(buffer8,iovecs,offset);buffer.setUint32(nwritten_ptr,nwritten,true);return ret}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);const{ret,nread}=self.fds[fd].fd_read(buffer8,iovecs);buffer.setUint32(nread_ptr,nread,true);return ret}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);const{ret,nwritten}=self.fds[fd].fd_write(buffer8,iovecs);buffer.setUint32(nwritten_ptr,nwritten,true);return ret}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)}},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));return self.fds[new_fd].path_link(old_fd,old_flags,old_path,new_path)}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){if(data.length>buf_len){buffer.setUint32(nread_ptr,0,true);return ERRNO_BADF}buffer8.set(data,buf_ptr);buffer.setUint32(nread_ptr,data.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){throw "FIXME what is the best abstraction for this?"},path_symlink(old_path_ptr,old_path_len,fd,new_path_ptr,new_path_len){const buffer8=new Uint8Array(self.inst.exports.memory.buffer);if(self.fds[fd]!=undefined){const old_path=new TextDecoder("utf-8").decode(buffer8.slice(old_path_ptr,old_path_ptr+old_path_len));const new_path=new TextDecoder("utf-8").decode(buffer8.slice(new_path_ptr,new_path_ptr+new_path_len));return self.fds[fd].path_symlink(old_path,new_path)}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"}};}};
|
|
1345
1345
|
|
|
1346
|
+
/**
|
|
1347
|
+
* Create a console printer that can be used as an overlay of WASI imports.
|
|
1348
|
+
* See the example below for how to use it.
|
|
1349
|
+
*
|
|
1350
|
+
* ```javascript
|
|
1351
|
+
* const imports = {
|
|
1352
|
+
* "wasi_snapshot_preview1": wasi.wasiImport,
|
|
1353
|
+
* }
|
|
1354
|
+
* const printer = consolePrinter();
|
|
1355
|
+
* printer.addToImports(imports);
|
|
1356
|
+
*
|
|
1357
|
+
* const instance = await WebAssembly.instantiate(module, imports);
|
|
1358
|
+
* printer.setMemory(instance.exports.memory);
|
|
1359
|
+
* ```
|
|
1360
|
+
*
|
|
1361
|
+
* Note that the `stdout` and `stderr` functions are called with text, not
|
|
1362
|
+
* bytes. This means that bytes written to stdout/stderr will be decoded as
|
|
1363
|
+
* UTF-8 and then passed to the `stdout`/`stderr` functions every time a write
|
|
1364
|
+
* occurs without buffering.
|
|
1365
|
+
*
|
|
1366
|
+
* @param stdout A function that will be called when stdout is written to.
|
|
1367
|
+
* Defaults to `console.log`.
|
|
1368
|
+
* @param stderr A function that will be called when stderr is written to.
|
|
1369
|
+
* Defaults to `console.warn`.
|
|
1370
|
+
* @returns An object that can be used as an overlay of WASI imports.
|
|
1371
|
+
*/
|
|
1372
|
+
function consolePrinter({ stdout, stderr, } = {
|
|
1373
|
+
stdout: console.log,
|
|
1374
|
+
stderr: console.warn,
|
|
1375
|
+
}) {
|
|
1376
|
+
let memory = undefined;
|
|
1377
|
+
let _view = undefined;
|
|
1378
|
+
function getMemoryView() {
|
|
1379
|
+
if (typeof memory === "undefined") {
|
|
1380
|
+
throw new Error("Memory is not set");
|
|
1381
|
+
}
|
|
1382
|
+
if (_view === undefined || _view.buffer.byteLength === 0) {
|
|
1383
|
+
_view = new DataView(memory.buffer);
|
|
1384
|
+
}
|
|
1385
|
+
return _view;
|
|
1386
|
+
}
|
|
1387
|
+
const decoder = new TextDecoder();
|
|
1388
|
+
return {
|
|
1389
|
+
addToImports(imports) {
|
|
1390
|
+
const wasiImport = imports.wasi_snapshot_preview1;
|
|
1391
|
+
const original_fd_write = wasiImport.fd_write;
|
|
1392
|
+
wasiImport.fd_write = (fd, iovs, iovsLen, nwritten) => {
|
|
1393
|
+
if (fd !== 1 && fd !== 2) {
|
|
1394
|
+
return original_fd_write(fd, iovs, iovsLen, nwritten);
|
|
1395
|
+
}
|
|
1396
|
+
const view = getMemoryView();
|
|
1397
|
+
const buffers = Array.from({ length: iovsLen }, (_, i) => {
|
|
1398
|
+
const ptr = iovs + i * 8;
|
|
1399
|
+
const buf = view.getUint32(ptr, true);
|
|
1400
|
+
const bufLen = view.getUint32(ptr + 4, true);
|
|
1401
|
+
return new Uint8Array(memory.buffer, buf, bufLen);
|
|
1402
|
+
});
|
|
1403
|
+
let written = 0;
|
|
1404
|
+
let str = "";
|
|
1405
|
+
for (const buffer of buffers) {
|
|
1406
|
+
str += decoder.decode(buffer);
|
|
1407
|
+
written += buffer.byteLength;
|
|
1408
|
+
}
|
|
1409
|
+
view.setUint32(nwritten, written, true);
|
|
1410
|
+
const log = fd === 1 ? stdout : stderr;
|
|
1411
|
+
log(str);
|
|
1412
|
+
return 0;
|
|
1413
|
+
};
|
|
1414
|
+
const original_fd_filestat_get = wasiImport.fd_filestat_get;
|
|
1415
|
+
wasiImport.fd_filestat_get = (fd, filestat) => {
|
|
1416
|
+
if (fd !== 1 && fd !== 2) {
|
|
1417
|
+
return original_fd_filestat_get(fd, filestat);
|
|
1418
|
+
}
|
|
1419
|
+
const view = getMemoryView();
|
|
1420
|
+
const result = original_fd_filestat_get(fd, filestat);
|
|
1421
|
+
if (result !== 0) {
|
|
1422
|
+
return result;
|
|
1423
|
+
}
|
|
1424
|
+
const filetypePtr = filestat + 0;
|
|
1425
|
+
view.setUint8(filetypePtr, 2); // FILETYPE_CHARACTER_DEVICE
|
|
1426
|
+
return 0;
|
|
1427
|
+
};
|
|
1428
|
+
const original_fd_fdstat_get = wasiImport.fd_fdstat_get;
|
|
1429
|
+
wasiImport.fd_fdstat_get = (fd, fdstat) => {
|
|
1430
|
+
if (fd !== 1 && fd !== 2) {
|
|
1431
|
+
return original_fd_fdstat_get(fd, fdstat);
|
|
1432
|
+
}
|
|
1433
|
+
const view = getMemoryView();
|
|
1434
|
+
const fs_filetypePtr = fdstat + 0;
|
|
1435
|
+
view.setUint8(fs_filetypePtr, 2); // FILETYPE_CHARACTER_DEVICE
|
|
1436
|
+
const fs_rights_basePtr = fdstat + 8;
|
|
1437
|
+
view.setBigUint64(fs_rights_basePtr, BigInt(1)); // RIGHTS_FD_WRITE
|
|
1438
|
+
return 0;
|
|
1439
|
+
};
|
|
1440
|
+
},
|
|
1441
|
+
setMemory(m) {
|
|
1442
|
+
memory = m;
|
|
1443
|
+
},
|
|
1444
|
+
};
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1346
1447
|
let DATA_VIEW = new DataView(new ArrayBuffer());
|
|
1347
1448
|
function data_view(mem) {
|
|
1348
1449
|
if (DATA_VIEW.buffer !== mem.buffer)
|
|
@@ -1926,107 +2027,6 @@ SOFTWARE.
|
|
|
1926
2027
|
};
|
|
1927
2028
|
}
|
|
1928
2029
|
|
|
1929
|
-
/**
|
|
1930
|
-
* Create a console printer that can be used as an overlay of WASI imports.
|
|
1931
|
-
* See the example below for how to use it.
|
|
1932
|
-
*
|
|
1933
|
-
* ```javascript
|
|
1934
|
-
* const imports = {
|
|
1935
|
-
* "wasi_snapshot_preview1": wasi.wasiImport,
|
|
1936
|
-
* }
|
|
1937
|
-
* const printer = consolePrinter();
|
|
1938
|
-
* printer.addToImports(imports);
|
|
1939
|
-
*
|
|
1940
|
-
* const instance = await WebAssembly.instantiate(module, imports);
|
|
1941
|
-
* printer.setMemory(instance.exports.memory);
|
|
1942
|
-
* ```
|
|
1943
|
-
*
|
|
1944
|
-
* Note that the `stdout` and `stderr` functions are called with text, not
|
|
1945
|
-
* bytes. This means that bytes written to stdout/stderr will be decoded as
|
|
1946
|
-
* UTF-8 and then passed to the `stdout`/`stderr` functions every time a write
|
|
1947
|
-
* occurs without buffering.
|
|
1948
|
-
*
|
|
1949
|
-
* @param stdout A function that will be called when stdout is written to.
|
|
1950
|
-
* Defaults to `console.log`.
|
|
1951
|
-
* @param stderr A function that will be called when stderr is written to.
|
|
1952
|
-
* Defaults to `console.warn`.
|
|
1953
|
-
* @returns An object that can be used as an overlay of WASI imports.
|
|
1954
|
-
*/
|
|
1955
|
-
function consolePrinter({ stdout, stderr, } = {
|
|
1956
|
-
stdout: console.log,
|
|
1957
|
-
stderr: console.warn,
|
|
1958
|
-
}) {
|
|
1959
|
-
let memory = undefined;
|
|
1960
|
-
let _view = undefined;
|
|
1961
|
-
function getMemoryView() {
|
|
1962
|
-
if (typeof memory === "undefined") {
|
|
1963
|
-
throw new Error("Memory is not set");
|
|
1964
|
-
}
|
|
1965
|
-
if (_view === undefined || _view.buffer.byteLength === 0) {
|
|
1966
|
-
_view = new DataView(memory.buffer);
|
|
1967
|
-
}
|
|
1968
|
-
return _view;
|
|
1969
|
-
}
|
|
1970
|
-
const decoder = new TextDecoder();
|
|
1971
|
-
return {
|
|
1972
|
-
addToImports(imports) {
|
|
1973
|
-
const wasiImport = imports.wasi_snapshot_preview1;
|
|
1974
|
-
const original_fd_write = wasiImport.fd_write;
|
|
1975
|
-
wasiImport.fd_write = (fd, iovs, iovsLen, nwritten) => {
|
|
1976
|
-
if (fd !== 1 && fd !== 2) {
|
|
1977
|
-
return original_fd_write(fd, iovs, iovsLen, nwritten);
|
|
1978
|
-
}
|
|
1979
|
-
const view = getMemoryView();
|
|
1980
|
-
const buffers = Array.from({ length: iovsLen }, (_, i) => {
|
|
1981
|
-
const ptr = iovs + i * 8;
|
|
1982
|
-
const buf = view.getUint32(ptr, true);
|
|
1983
|
-
const bufLen = view.getUint32(ptr + 4, true);
|
|
1984
|
-
return new Uint8Array(memory.buffer, buf, bufLen);
|
|
1985
|
-
});
|
|
1986
|
-
let written = 0;
|
|
1987
|
-
let str = "";
|
|
1988
|
-
for (const buffer of buffers) {
|
|
1989
|
-
str += decoder.decode(buffer);
|
|
1990
|
-
written += buffer.byteLength;
|
|
1991
|
-
}
|
|
1992
|
-
view.setUint32(nwritten, written, true);
|
|
1993
|
-
const log = fd === 1 ? stdout : stderr;
|
|
1994
|
-
log(str);
|
|
1995
|
-
return 0;
|
|
1996
|
-
};
|
|
1997
|
-
const original_fd_filestat_get = wasiImport.fd_filestat_get;
|
|
1998
|
-
wasiImport.fd_filestat_get = (fd, filestat) => {
|
|
1999
|
-
if (fd !== 1 && fd !== 2) {
|
|
2000
|
-
return original_fd_filestat_get(fd, filestat);
|
|
2001
|
-
}
|
|
2002
|
-
const view = getMemoryView();
|
|
2003
|
-
const result = original_fd_filestat_get(fd, filestat);
|
|
2004
|
-
if (result !== 0) {
|
|
2005
|
-
return result;
|
|
2006
|
-
}
|
|
2007
|
-
const filetypePtr = filestat + 0;
|
|
2008
|
-
view.setUint8(filetypePtr, 2); // FILETYPE_CHARACTER_DEVICE
|
|
2009
|
-
return 0;
|
|
2010
|
-
};
|
|
2011
|
-
const original_fd_fdstat_get = wasiImport.fd_fdstat_get;
|
|
2012
|
-
wasiImport.fd_fdstat_get = (fd, fdstat) => {
|
|
2013
|
-
if (fd !== 1 && fd !== 2) {
|
|
2014
|
-
return original_fd_fdstat_get(fd, fdstat);
|
|
2015
|
-
}
|
|
2016
|
-
const view = getMemoryView();
|
|
2017
|
-
const fs_filetypePtr = fdstat + 0;
|
|
2018
|
-
view.setUint8(fs_filetypePtr, 2); // FILETYPE_CHARACTER_DEVICE
|
|
2019
|
-
const fs_rights_basePtr = fdstat + 8;
|
|
2020
|
-
view.setBigUint64(fs_rights_basePtr, BigInt(1)); // RIGHTS_FD_WRITE
|
|
2021
|
-
return 0;
|
|
2022
|
-
};
|
|
2023
|
-
},
|
|
2024
|
-
setMemory(m) {
|
|
2025
|
-
memory = m;
|
|
2026
|
-
},
|
|
2027
|
-
};
|
|
2028
|
-
}
|
|
2029
|
-
|
|
2030
2030
|
/**
|
|
2031
2031
|
* A Ruby VM instance
|
|
2032
2032
|
*
|
|
@@ -2099,11 +2099,12 @@ SOFTWARE.
|
|
|
2099
2099
|
* @param args The command line arguments to pass to Ruby. Must be
|
|
2100
2100
|
* an array of strings starting with the Ruby program name.
|
|
2101
2101
|
*/
|
|
2102
|
-
initialize(args = ["ruby.wasm", "
|
|
2102
|
+
initialize(args = ["ruby.wasm", "-EUTF-8", "-e_=0"]) {
|
|
2103
2103
|
const c_args = args.map((arg) => arg + "\0");
|
|
2104
2104
|
this.guest.rubyInit();
|
|
2105
2105
|
this.guest.rubySysinit(c_args);
|
|
2106
2106
|
this.guest.rubyOptions(c_args);
|
|
2107
|
+
this.eval(`require "/bundle/setup"`);
|
|
2107
2108
|
}
|
|
2108
2109
|
/**
|
|
2109
2110
|
* Set a given instance to interact JavaScript and Ruby's
|
|
@@ -2338,13 +2339,8 @@ SOFTWARE.
|
|
|
2338
2339
|
*/
|
|
2339
2340
|
evalAsync(code) {
|
|
2340
2341
|
const JS = this.eval("require 'js'; JS");
|
|
2341
|
-
return
|
|
2342
|
-
JS.call("__eval_async_rb", this.wrap(code),
|
|
2343
|
-
resolve,
|
|
2344
|
-
reject: (error) => {
|
|
2345
|
-
reject(new RbError(this.exceptionFormatter.format(error, this, this.privateObject())));
|
|
2346
|
-
},
|
|
2347
|
-
}));
|
|
2342
|
+
return newRbPromise(this, this.privateObject(), (future) => {
|
|
2343
|
+
JS.call("__eval_async_rb", this.wrap(code), future);
|
|
2348
2344
|
});
|
|
2349
2345
|
}
|
|
2350
2346
|
/**
|
|
@@ -2429,17 +2425,42 @@ SOFTWARE.
|
|
|
2429
2425
|
*
|
|
2430
2426
|
* @param callee name of the Ruby method to call
|
|
2431
2427
|
* @param args arguments to pass to the method. Must be an array of RbValue
|
|
2428
|
+
* @returns The result of the method call as a new RbValue.
|
|
2432
2429
|
*
|
|
2433
2430
|
* @example
|
|
2434
2431
|
* const ary = vm.eval("[1, 2, 3]");
|
|
2435
2432
|
* ary.call("push", 4);
|
|
2436
2433
|
* console.log(ary.call("sample").toString());
|
|
2437
|
-
*
|
|
2438
2434
|
*/
|
|
2439
2435
|
call(callee, ...args) {
|
|
2440
2436
|
const innerArgs = args.map((arg) => arg.inner);
|
|
2441
2437
|
return new RbValue(callRbMethod(this.vm, this.privateObject, this.inner, callee, innerArgs), this.vm, this.privateObject);
|
|
2442
2438
|
}
|
|
2439
|
+
/**
|
|
2440
|
+
* Call a given method that may call `JS::Object#await` with given arguments
|
|
2441
|
+
*
|
|
2442
|
+
* @param callee name of the Ruby method to call
|
|
2443
|
+
* @param args arguments to pass to the method. Must be an array of RbValue
|
|
2444
|
+
* @returns A Promise that resolves to the result of the method call as a new RbValue.
|
|
2445
|
+
*
|
|
2446
|
+
* @example
|
|
2447
|
+
* const client = vm.eval(`
|
|
2448
|
+
* require 'js'
|
|
2449
|
+
* class HttpClient
|
|
2450
|
+
* def get(url)
|
|
2451
|
+
* JS.global.fetch(url).await
|
|
2452
|
+
* end
|
|
2453
|
+
* end
|
|
2454
|
+
* HttpClient.new
|
|
2455
|
+
* `);
|
|
2456
|
+
* const response = await client.callAsync("get", vm.eval(`"https://example.com"`));
|
|
2457
|
+
*/
|
|
2458
|
+
callAsync(callee, ...args) {
|
|
2459
|
+
const JS = this.vm.eval("require 'js'; JS");
|
|
2460
|
+
return newRbPromise(this.vm, this.privateObject, (future) => {
|
|
2461
|
+
JS.call("__call_async_method", this, this.vm.wrap(callee), future, ...args);
|
|
2462
|
+
});
|
|
2463
|
+
}
|
|
2443
2464
|
/**
|
|
2444
2465
|
* @see {@link https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toPrimitive}
|
|
2445
2466
|
* @param hint Preferred type of the result primitive value. `"number"`, `"string"`, or `"default"`.
|
|
@@ -2638,6 +2659,18 @@ SOFTWARE.
|
|
|
2638
2659
|
return new RbValue(value, vm, privateObject);
|
|
2639
2660
|
});
|
|
2640
2661
|
};
|
|
2662
|
+
function newRbPromise(vm, privateObject, body) {
|
|
2663
|
+
return new Promise((resolve, reject) => {
|
|
2664
|
+
const future = vm.wrap({
|
|
2665
|
+
resolve,
|
|
2666
|
+
reject: (error) => {
|
|
2667
|
+
const rbError = new RbError(privateObject.exceptionFormatter.format(error, vm, privateObject));
|
|
2668
|
+
reject(rbError);
|
|
2669
|
+
},
|
|
2670
|
+
});
|
|
2671
|
+
body(future);
|
|
2672
|
+
});
|
|
2673
|
+
}
|
|
2641
2674
|
/**
|
|
2642
2675
|
* Error class thrown by Ruby execution
|
|
2643
2676
|
*/
|
|
@@ -2773,7 +2806,7 @@ SOFTWARE.
|
|
|
2773
2806
|
};
|
|
2774
2807
|
|
|
2775
2808
|
var name = "@ruby/head-wasm-wasi";
|
|
2776
|
-
var version = "2.
|
|
2809
|
+
var version = "2.5.0";
|
|
2777
2810
|
var description = "Ruby head built on WASI";
|
|
2778
2811
|
var main = "./dist/cjs/index.js";
|
|
2779
2812
|
var module = "./dist/esm/index.js";
|
|
@@ -2789,6 +2822,12 @@ SOFTWARE.
|
|
|
2789
2822
|
umd: "./dist/umd/*.js",
|
|
2790
2823
|
"import": "./dist/esm/*.js",
|
|
2791
2824
|
require: "./dist/cjs/*.js"
|
|
2825
|
+
},
|
|
2826
|
+
"./*.wasm": {
|
|
2827
|
+
browser: "./*.wasm",
|
|
2828
|
+
umd: "./*.wasm",
|
|
2829
|
+
"import": "./*.wasm",
|
|
2830
|
+
require: "./*.wasm"
|
|
2792
2831
|
}
|
|
2793
2832
|
};
|
|
2794
2833
|
var files = [
|
|
@@ -2801,9 +2840,8 @@ SOFTWARE.
|
|
|
2801
2840
|
"build:static:files": "../ruby-wasm-wasi/tools/pack-static-files.sh ./dist",
|
|
2802
2841
|
"build:static:compat": "../ruby-wasm-wasi/tools/pack-compat-shim.mjs --dist=./dist --pkg=ruby-head-wasm-wasi",
|
|
2803
2842
|
"build:static": "npm run build:static:files && npm run build:static:compat",
|
|
2804
|
-
"build:wasm": "../ruby-wasm-wasi/tools/pack-ruby-wasm.sh ../../../rubies/head-wasm32-unknown-wasi-full-js-debug ./dist",
|
|
2805
2843
|
"build:rollup": "rollup -c rollup.config.mjs",
|
|
2806
|
-
build: "npm run build:deps && npm run build:static && npm run build:
|
|
2844
|
+
build: "npm run build:deps && npm run build:static && npm run build:rollup && ../ruby-wasm-wasi/tools/post-build.sh ./dist"
|
|
2807
2845
|
};
|
|
2808
2846
|
var repository = "https://github.com/ruby/ruby.wasm";
|
|
2809
2847
|
var homepage = "https://github.com/ruby/ruby.wasm/tree/main/packages/npm-packages/ruby-head-wasm-wasi";
|