@ruby/wasm-wasi 2.3.0 → 2.4.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.
Files changed (46) hide show
  1. package/README.md +180 -4
  2. package/dist/browser.script.umd.js +170 -2048
  3. package/dist/browser.umd.js +170 -2048
  4. package/dist/cjs/bindgen/intrinsics.d.ts +13 -0
  5. package/dist/cjs/bindgen/intrinsics.js +81 -0
  6. package/dist/cjs/bindgen/rb-abi-guest.js +236 -0
  7. package/dist/cjs/bindgen/rb-js-abi-host.js +283 -0
  8. package/dist/{browser.d.ts → cjs/browser.d.ts} +2 -2
  9. package/dist/cjs/browser.js +30 -0
  10. package/dist/{browser.script.d.ts → cjs/browser.script.d.ts} +1 -1
  11. package/dist/cjs/browser.script.js +90 -0
  12. package/dist/cjs/console.d.ts +33 -0
  13. package/dist/cjs/console.js +104 -0
  14. package/dist/{index.d.ts → cjs/index.d.ts} +7 -3
  15. package/dist/cjs/index.js +646 -0
  16. package/dist/{node.d.ts → cjs/node.d.ts} +1 -1
  17. package/dist/cjs/node.js +23 -0
  18. package/dist/esm/bindgen/intrinsics.d.ts +13 -0
  19. package/dist/esm/bindgen/intrinsics.js +73 -0
  20. package/dist/esm/bindgen/rb-abi-guest.d.ts +140 -0
  21. package/dist/esm/bindgen/rb-abi-guest.js +230 -0
  22. package/dist/esm/bindgen/rb-js-abi-host.d.ts +53 -0
  23. package/dist/esm/bindgen/rb-js-abi-host.js +279 -0
  24. package/dist/esm/browser.d.ts +10 -0
  25. package/dist/esm/browser.js +26 -0
  26. package/dist/esm/browser.script.d.ts +5 -0
  27. package/dist/esm/browser.script.js +86 -0
  28. package/dist/esm/console.d.ts +33 -0
  29. package/dist/esm/console.js +100 -0
  30. package/dist/esm/index.d.ts +196 -0
  31. package/dist/esm/index.js +637 -0
  32. package/dist/esm/node.d.ts +10 -0
  33. package/dist/esm/node.js +19 -0
  34. package/dist/esm/package.json +1 -0
  35. package/dist/index.umd.js +158 -10
  36. package/package.json +22 -38
  37. package/dist/browser.cjs.js +0 -3245
  38. package/dist/browser.esm.js +0 -3243
  39. package/dist/browser.script.cjs.js +0 -3372
  40. package/dist/browser.script.esm.js +0 -3370
  41. package/dist/index.cjs.js +0 -1192
  42. package/dist/index.esm.js +0 -1187
  43. package/dist/node.cjs.js +0 -1209
  44. package/dist/node.esm.js +0 -1207
  45. /package/dist/{bindgen → cjs/bindgen}/rb-abi-guest.d.ts +0 -0
  46. /package/dist/{bindgen → cjs/bindgen}/rb-js-abi-host.d.ts +0 -0
package/dist/index.umd.js CHANGED
@@ -601,6 +601,107 @@
601
601
  };
602
602
  }
603
603
 
604
+ /**
605
+ * Create a console printer that can be used as an overlay of WASI imports.
606
+ * See the example below for how to use it.
607
+ *
608
+ * ```javascript
609
+ * const imports = {
610
+ * "wasi_snapshot_preview1": wasi.wasiImport,
611
+ * }
612
+ * const printer = consolePrinter();
613
+ * printer.addToImports(imports);
614
+ *
615
+ * const instance = await WebAssembly.instantiate(module, imports);
616
+ * printer.setMemory(instance.exports.memory);
617
+ * ```
618
+ *
619
+ * Note that the `stdout` and `stderr` functions are called with text, not
620
+ * bytes. This means that bytes written to stdout/stderr will be decoded as
621
+ * UTF-8 and then passed to the `stdout`/`stderr` functions every time a write
622
+ * occurs without buffering.
623
+ *
624
+ * @param stdout A function that will be called when stdout is written to.
625
+ * Defaults to `console.log`.
626
+ * @param stderr A function that will be called when stderr is written to.
627
+ * Defaults to `console.warn`.
628
+ * @returns An object that can be used as an overlay of WASI imports.
629
+ */
630
+ function consolePrinter({ stdout, stderr, } = {
631
+ stdout: console.log,
632
+ stderr: console.warn,
633
+ }) {
634
+ let memory = undefined;
635
+ let _view = undefined;
636
+ function getMemoryView() {
637
+ if (typeof memory === "undefined") {
638
+ throw new Error("Memory is not set");
639
+ }
640
+ if (_view === undefined || _view.buffer.byteLength === 0) {
641
+ _view = new DataView(memory.buffer);
642
+ }
643
+ return _view;
644
+ }
645
+ const decoder = new TextDecoder();
646
+ return {
647
+ addToImports(imports) {
648
+ const wasiImport = imports.wasi_snapshot_preview1;
649
+ const original_fd_write = wasiImport.fd_write;
650
+ wasiImport.fd_write = (fd, iovs, iovsLen, nwritten) => {
651
+ if (fd !== 1 && fd !== 2) {
652
+ return original_fd_write(fd, iovs, iovsLen, nwritten);
653
+ }
654
+ const view = getMemoryView();
655
+ const buffers = Array.from({ length: iovsLen }, (_, i) => {
656
+ const ptr = iovs + i * 8;
657
+ const buf = view.getUint32(ptr, true);
658
+ const bufLen = view.getUint32(ptr + 4, true);
659
+ return new Uint8Array(memory.buffer, buf, bufLen);
660
+ });
661
+ let written = 0;
662
+ let str = "";
663
+ for (const buffer of buffers) {
664
+ str += decoder.decode(buffer);
665
+ written += buffer.byteLength;
666
+ }
667
+ view.setUint32(nwritten, written, true);
668
+ const log = fd === 1 ? stdout : stderr;
669
+ log(str);
670
+ return 0;
671
+ };
672
+ const original_fd_filestat_get = wasiImport.fd_filestat_get;
673
+ wasiImport.fd_filestat_get = (fd, filestat) => {
674
+ if (fd !== 1 && fd !== 2) {
675
+ return original_fd_filestat_get(fd, filestat);
676
+ }
677
+ const view = getMemoryView();
678
+ const result = original_fd_filestat_get(fd, filestat);
679
+ if (result !== 0) {
680
+ return result;
681
+ }
682
+ const filetypePtr = filestat + 0;
683
+ view.setUint8(filetypePtr, 2); // FILETYPE_CHARACTER_DEVICE
684
+ return 0;
685
+ };
686
+ const original_fd_fdstat_get = wasiImport.fd_fdstat_get;
687
+ wasiImport.fd_fdstat_get = (fd, fdstat) => {
688
+ if (fd !== 1 && fd !== 2) {
689
+ return original_fd_fdstat_get(fd, fdstat);
690
+ }
691
+ const view = getMemoryView();
692
+ const fs_filetypePtr = fdstat + 0;
693
+ view.setUint8(fs_filetypePtr, 2); // FILETYPE_CHARACTER_DEVICE
694
+ const fs_rights_basePtr = fdstat + 8;
695
+ view.setBigUint64(fs_rights_basePtr, BigInt(1)); // RIGHTS_FD_WRITE
696
+ return 0;
697
+ };
698
+ },
699
+ setMemory(m) {
700
+ memory = m;
701
+ },
702
+ };
703
+ }
704
+
604
705
  /**
605
706
  * A Ruby VM instance
606
707
  *
@@ -933,12 +1034,14 @@
933
1034
  wrap(value) {
934
1035
  return this.transport.importJsValue(value, this);
935
1036
  }
1037
+ /** @private */
936
1038
  privateObject() {
937
1039
  return {
938
1040
  transport: this.transport,
939
1041
  exceptionFormatter: this.exceptionFormatter,
940
1042
  };
941
1043
  }
1044
+ /** @private */
942
1045
  rbValueOfPointer(pointer) {
943
1046
  const abiValue = new RbAbiValue(pointer, this.guest);
944
1047
  return new RbValue(abiValue, this, this.privateObject());
@@ -1063,8 +1166,27 @@
1063
1166
  class RbExceptionFormatter {
1064
1167
  constructor() {
1065
1168
  this.literalsCache = null;
1169
+ this.isFormmatting = false;
1066
1170
  }
1067
1171
  format(error, vm, privateObject) {
1172
+ // All Ruby exceptions raised during formatting exception message should
1173
+ // be caught and return a fallback message.
1174
+ // Therefore, we don't need to worry about infinite recursion here ideally
1175
+ // but checking re-entrancy just in case.
1176
+ class RbExceptionFormatterError extends Error {
1177
+ }
1178
+ if (this.isFormmatting) {
1179
+ throw new RbExceptionFormatterError("Unexpected exception occurred during formatting exception message");
1180
+ }
1181
+ this.isFormmatting = true;
1182
+ try {
1183
+ return this._format(error, vm, privateObject);
1184
+ }
1185
+ finally {
1186
+ this.isFormmatting = false;
1187
+ }
1188
+ }
1189
+ _format(error, vm, privateObject) {
1068
1190
  const [zeroLiteral, oneLiteral, newLineLiteral] = (() => {
1069
1191
  if (this.literalsCache == null) {
1070
1192
  const zeroOneNewLine = [
@@ -1079,18 +1201,43 @@
1079
1201
  return this.literalsCache;
1080
1202
  }
1081
1203
  })();
1082
- const backtrace = error.call("backtrace");
1204
+ let className;
1205
+ let backtrace;
1206
+ let message;
1207
+ try {
1208
+ className = error.call("class").toString();
1209
+ }
1210
+ catch (e) {
1211
+ className = "unknown";
1212
+ }
1213
+ try {
1214
+ message = error.toString();
1215
+ }
1216
+ catch (e) {
1217
+ message = "unknown";
1218
+ }
1219
+ try {
1220
+ backtrace = error.call("backtrace");
1221
+ }
1222
+ catch (e) {
1223
+ return this.formatString(className, message);
1224
+ }
1083
1225
  if (backtrace.call("nil?").toString() === "true") {
1084
- return this.formatString(error.call("class").toString(), error.toString());
1226
+ return this.formatString(className, message);
1227
+ }
1228
+ try {
1229
+ const firstLine = backtrace.call("at", zeroLiteral);
1230
+ const restLines = backtrace
1231
+ .call("drop", oneLiteral)
1232
+ .call("join", newLineLiteral);
1233
+ return this.formatString(className, message, [
1234
+ firstLine.toString(),
1235
+ restLines.toString(),
1236
+ ]);
1237
+ }
1238
+ catch (e) {
1239
+ return this.formatString(className, message);
1085
1240
  }
1086
- const firstLine = backtrace.call("at", zeroLiteral);
1087
- const restLines = backtrace
1088
- .call("drop", oneLiteral)
1089
- .call("join", newLineLiteral);
1090
- return this.formatString(error.call("class").toString(), error.toString(), [
1091
- firstLine.toString(),
1092
- restLines.toString(),
1093
- ]);
1094
1241
  }
1095
1242
  formatString(klass, message, backtrace) {
1096
1243
  if (backtrace) {
@@ -1194,5 +1341,6 @@
1194
1341
  exports.RbFatalError = RbFatalError;
1195
1342
  exports.RbValue = RbValue;
1196
1343
  exports.RubyVM = RubyVM;
1344
+ exports.consolePrinter = consolePrinter;
1197
1345
 
1198
1346
  }));
package/package.json CHANGED
@@ -1,36 +1,25 @@
1
1
  {
2
2
  "name": "@ruby/wasm-wasi",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "description": "WebAssembly port of CRuby with WASI",
5
- "main": "./dist/index.cjs.js",
6
- "umd:main": "./dist/index.umd.js",
7
- "module": "./dist/index.esm.js",
8
- "typings": "./dist/index.d.ts",
5
+ "main": "./dist/cjs/index.js",
6
+ "module": "./dist/esm/index.js",
7
+ "browser": "./dist/index.umd.js",
8
+ "typings": "./dist/esm/index.d.ts",
9
9
  "exports": {
10
10
  ".": {
11
- "browser": "./dist/index.esm.js",
12
- "umd": "./dist/index.umd.js",
13
- "import": "./dist/index.esm.js",
14
- "require": "./dist/index.cjs.js",
15
- "types": "./dist/browser.d.ts"
11
+ "browser": "./dist/esm/index.js",
12
+ "umd": "./dist/umd/index.js",
13
+ "import": "./dist/esm/index.js",
14
+ "require": "./dist/cjs/index.js",
15
+ "types": "./dist/esm/browser.d.ts"
16
16
  },
17
- "./dist/browser": {
18
- "browser": "./dist/browser.esm.js",
19
- "umd": "./dist/browser.umd.js",
20
- "import": "./dist/browser.esm.js",
21
- "require": "./dist/browser.cjs.js",
22
- "types": "./dist/browser.d.ts"
23
- },
24
- "./dist/browser.script": {
25
- "browser": "./dist/browser.script.esm.js",
26
- "umd": "./dist/browser.script.umd.js",
27
- "import": "./dist/browser.script.esm.js",
28
- "types": "./dist/browser.script.d.ts"
29
- },
30
- "./dist/node": {
31
- "import": "./dist/node.esm.js",
32
- "require": "./dist/node.cjs.js",
33
- "types": "./dist/node.d.ts"
17
+ "./dist/*": {
18
+ "browser": "./dist/esm/*.js",
19
+ "umd": "./dist/umd/*.js",
20
+ "import": "./dist/esm/*.js",
21
+ "require": "./dist/cjs/*.js",
22
+ "types": "./dist/esm/*.d.ts"
34
23
  }
35
24
  },
36
25
  "files": [
@@ -61,25 +50,20 @@
61
50
  "serve:example": "bundle exec ruby -run -e httpd ./example -p 8085",
62
51
  "format": "prettier --write .",
63
52
  "build:static": "./tools/pack-bindgen-src.sh ./dist",
64
- "build:rollup": "rollup -c rollup.config.mjs && tsc --build",
65
- "build": "npm run build:static && npm run build:rollup"
53
+ "build:rollup": "rollup -c rollup.config.mjs",
54
+ "build:tsc": "tsc -p tsconfig.json && tsc -p tsconfig.cjs.json",
55
+ "build": "npm run build:rollup && npm run build:tsc && npm run build:static && ./tools/post-build.sh ./dist"
66
56
  },
67
57
  "devDependencies": {
68
- "@babel/core": "^7.19.3",
69
- "@babel/preset-env": "^7.19.3",
70
- "@babel/preset-typescript": "^7.18.6",
71
- "@rollup/plugin-inject": "^5.0.5",
72
58
  "@rollup/plugin-node-resolve": "^15.1.0",
73
59
  "@rollup/plugin-typescript": "^11.1.2",
74
60
  "@types/jest": "^29.5.3",
75
61
  "@types/node": "20.8.10",
76
- "@wasmer/wasi": "^1.2.2",
77
- "babel-jest": "^29.7.0",
78
62
  "jest": "^29.6.2",
79
63
  "prettier": "^3.0.0",
80
- "rollup": "^3.2.2",
81
- "rollup-plugin-polyfill-node": "^0.12.0",
82
- "typescript": "^5.2.2"
64
+ "rollup": "^4.6.1",
65
+ "@bjorn3/browser_wasi_shim": "^0.2.17",
66
+ "typescript": "^5.3.2"
83
67
  },
84
68
  "dependencies": {
85
69
  "tslib": "^2.6.1"