guest271314 added the bug label to Issue #9922.
guest271314 opened issue #9922:
Thanks for filing a bug report! Please fill out the TODOs below.
Note: if you want to report a security issue, please read our security policy!
Test Case
Steps to Reproduce
Follow instructions here to build Facebook's Static Hermes.
Create
fopen.wasm
fromfopen.ts
.#!/bin/bash # Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. set -e # Exit immediately if a command exits with a non-zero status set -u # Treat unset variables as an error and exit immediately # Extract the filename without path and extension file_name=$(basename "$1") # Remove path file_name_with_ext="${file_name}" file_name="${file_name%.*}" # Remove extension rm -rf out mkdir out out="$PWD/out" # rm -rf ${file_name}.c ${file_name}.o ${file_name}.wasm ${file_name}.hbc ${file_name} # ./build-host/bin/hermes ${file_name}.js --emit-binary -out "${out}/${file_name}.hbc" ./build-host/bin/shermes -v -Os -g -static-link -typed -fstatic-builtins -Xenable-tdz -emit-c "${file_name_with_ext}" -o "${out}/${file_name}.c" # ./build-host/bin/shermes -v -Os -g -Xenable-tdz \ # -fstatic-builtins -fstd-globals ${file_name}.js \ # -o "${out}/${file_name}" # cp fopen.c out/fopen.c ../wasi-sdk/bin/wasm32-wasi-clang "${out}/${file_name}.c" -c \ -O3 \ -DNDEBUG \ -fno-strict-aliasing -fno-strict-overflow \ -I./build-wasm/lib/config \ -I../hermes/include \ -mllvm -wasm-enable-sjlj \ -Wno-c23-extensions \ -o "${out}/${file_name}.o" ../wasi-sdk/bin/clang++ -O3 "${out}/${file_name}.o" ./build-wasm/tools/sh-demo/CMakeFiles/sh-demo.dir/cxa.cpp.obj -o "${out}/${file_name}.wasm" \ -L./build-wasm/lib \ -L./build-wasm/jsi \ -L./build-wasm/tools/shermes \ -lshermes_console_a -lhermesvmlean_a -ljsi -lwasi-emulated-mman -lsetjmp ../wasi-sdk/bin/strip "${out}/${file_name}.wasm" ls -lh "${out}"
./wasm-standalone-test.sh fopen.ts In file included from /media/user/1234/hermes-builds/out/fopen.c:2: ../hermes/include/hermes/VM/static_h.h:334:2: warning: "JS exceptions are currenly broken with WASI" [-W#warnings] 334 | #warning "JS exceptions are currenly broken with WASI" | ^ 1 warning generated. total 1.7M -rw-rw-r-- 1 user user 96K Jan 5 09:46 fopen.c -rw-rw-r-- 1 user user 25K Jan 5 09:46 fopen.o -rwxrwxr-x 1 user user 1.5M Jan 5 09:46 fopen.wasm
Expected Results
wasmer
version wasmer 5.0.4 produces the expected resultecho '9 5' | wasmer out/fopen.wasm 5 of 362879 (0-indexed, factorial 362880) => [0,1,2,3,4,5,8,7,6]
echo '10 4' | wasmer out/fopen.wasm 4 of 3628799 (0-indexed, factorial 3628800) => [0,1,2,3,4,5,6,9,7,8]
Actual Results
echo '4 5' | wasmtime out/fopen.wasm Error: failed to run main module `out/fopen.wasm` Caused by: 0: failed to invoke command default 1: error while executing at wasm backtrace: 0: 0x130e14 - <unknown>!<wasm function 4066> 1: 0xa5995 - <unknown>!<wasm function 2511> 2: 0xa5e29 - <unknown>!<wasm function 2520> 3: 0x5884 - <unknown>!<wasm function 33> 4: 0x2be4 - <unknown>!<wasm function 24> 5: 0x25bd - <unknown>!<wasm function 23> 6: 0xb9a8c - <unknown>!<wasm function 2934> 7: 0xb9984 - <unknown>!<wasm function 2933> 8: 0xb96a2 - <unknown>!<wasm function 2932> 9: 0xb95c6 - <unknown>!<wasm function 2931> 10: 0x35ac - <unknown>!<wasm function 25> 11: 0x130be0 - <unknown>!<wasm function 4044> 12: 0x2393 - <unknown>!<wasm function 21> 2: wasm trap: wasm `unreachable` instruction executed
Without using
wasi-sdk/bin/strip
echo '4 5' | WASM_BACKTRACE_DETAILS=1 wasmtime out/fopen.wasm Error: failed to run main module `out/fopen.wasm` Caused by: 0: failed to invoke command default 1: error while executing at wasm backtrace: 0: 0x130e14 - fopen.wasm!abort 1: 0xa5995 - fopen.wasm!_sh_throw_current 2: 0xa5e29 - fopen.wasm!_sh_throw 3: 0x5884 - fopen.wasm!_7_fopen 4: 0x2be4 - fopen.wasm!_1__1_ 5: 0x25bd - fopen.wasm!_0_global 6: 0xb9a8c - fopen.wasm!sh_unit_run(SHRuntime*, SHUnit*) 7: 0xb9984 - fopen.wasm!_sh_unit_init 8: 0xb96a2 - fopen.wasm!_sh_unit_init_guarded 9: 0xb95c6 - fopen.wasm!_sh_initialize_units 10: 0x35ac - fopen.wasm!main 11: 0x130be0 - fopen.wasm!__main_void 12: 0x2393 - fopen.wasm!_start note: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information 2: wasm trap: wasm `unreachable` instruction executed
Versions and Environment
Wasmtime version or commit: wasmtime 28.0.0 (2e584e841 2024-12-20)
Operating system: Linux
Architecture: x86_64 x86_64 x86_64 GNU/Linux
Extra Info
I initially thought this was an issue with Static Hermes source code, specifically related to reading STDIN. Then I tested the same WASM file with
wasmer
.
bjorn3 commented on issue #9922:
WASI doesn't have
/dev
nor/dev/stdin
. Looks like Wasmer adds/dev/stdin
as non-standard extension: https://github.com/wasmerio/wasmer/blob/1d03406174b204ac403f61e2deb0a41601c8e41b/lib/virtual-fs/src/builder.rs#L106-L110 Instead of usingfopen("/dev/stdin")
you can use thestdin
global variable instead. This is of typeFILE *
just like the return value offopen
. You just have to make sure not tofclose
it.
guest271314 commented on issue #9922:
stdin
is not globally defined in the source JavaScript.That's the only way I know of to read STDIN in Static Hermes. Modified from this https://github.com/facebook/hermes/blob/static_h/examples/ffi/fopen.js.
fopen.ts
/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ // https://github.com/facebook/hermes/tree/static_h/examples/ffi "use strict"; // Emulate a module scope, since global scope is unsound. (function (exports) { const c_null = $SHBuiltin.c_null(); // stdio.h const _fopen = $SHBuiltin.extern_c( { include: "stdio.h" }, function fopen(path: c_ptr, mode: c_ptr): c_ptr { throw 0; }, ); const _fclose = $SHBuiltin.extern_c( { include: "stdio.h" }, function fclose(f: c_ptr): void { }, ); const _fread = $SHBuiltin.extern_c( { include: "stdio.h" }, function fread( ptr: c_ptr, size: c_size_t, nitems: c_size_t, stream: c_ptr, ): c_size_t { throw 0; }, ); // stdlib.h const _malloc = $SHBuiltin.extern_c( { include: "stdlib.h" }, function malloc(size: c_size_t): c_ptr { throw 0; }, ); const _free = $SHBuiltin.extern_c( { include: "stdlib.h" }, function free(p: c_ptr): void { }, ); // string.h const _strerror_r = $SHBuiltin.extern_c( { include: "string.h" }, function strerror_r(errnum: c_int, errbuf: c_ptr, buflen: c_size_t): c_int { throw 0; }, ); // Builtin provided by SH to wrap errno. const _sh_errno = $SHBuiltin.extern_c( { declared: true }, function _sh_errno(): c_int { throw 0; }, ); // Pointer access builtins. const _ptr_write_char = $SHBuiltin.extern_c( { declared: true }, function _sh_ptr_write_char(ptr: c_ptr, offset: c_int, v: c_char): void { }, ); const _ptr_read_uchar = $SHBuiltin.extern_c( { declared: true }, function _sh_ptr_read_uchar(ptr: c_ptr, offset: c_int): c_uchar { throw 0; }, ); /// Allocate native memory using malloc() or throw an exception. function malloc(size: number): c_ptr { "inline"; "use unsafe"; let res = _malloc(size); if (res === 0) throw Error("OOM"); return res; } /// Convert a JS string to ASCIIZ. function stringToAsciiz(s: any): c_ptr { "use unsafe"; if (typeof s !== "string") s = String(s); let buf = malloc(s.length + 1); try { let i = 0; for (let e = s.length; i < e; ++i) { let code: number = s.charCodeAt(i); if (code > 127) throw Error("String is not ASCII"); _ptr_write_char(buf, i, code); } _ptr_write_char(buf, i, 0); return buf; } catch (e) { _free(buf); throw e; } } /// Convert an ASCII string of certain size to a JS string. function asciiToString_unsafe(buf: c_ptr, size: number): string { let res = ""; for (let i = 0; i < size; ++i) { let ch = _ptr_read_uchar(buf, i); // if (ch > 127) throw Error("String is not ASCII"); res += String.fromCharCode(ch); } return res; } /// Convert an ASCIIZ string up to a maximum size to a JS string. function asciizToString_unsafe(buf: c_ptr, maxsize: number): string { let res = ""; for (let i = 0; i < maxsize; ++i) { let ch = _ptr_read_uchar(buf, i); //if (ch > 127) throw Error("String is not ASCII"); //if (ch === 0) break; res += String.fromCharCode(ch); } return res; } function strerror(errnum: number): string { "use unsafe"; let errbuf = malloc(1024); try { _strerror_r(errnum, errbuf, 1024); return asciizToString_unsafe(errbuf, 1024); } finally { _free(errbuf); } } /// Very simple hack to ensure safety. let handles: c_ptr[] = []; // FIXME: fast array doesn't support .pop() yet. let closedHandles = Array(); function fopen(path: string, mode: string): number { "use unsafe"; let pathz: c_ptr = c_null; let modez: c_ptr = c_null; try { pathz = stringToAsciiz(path); modez = stringToAsciiz(mode); let filePtr = _fopen(pathz, modez); if (!filePtr) { let errnum = _sh_errno(); throw Error(path + ": " + strerror(errnum)); } // Allocate a handle. if (closedHandles.length > 0) { let f = closedHandles.pop(); handles[f] = filePtr; return f; } handles.push(filePtr); return handles.length - 1; } finally { _free(pathz); _free(modez); } } function fclose(f: number): void { "use unsafe"; if (f < 0 || f >= handles.length) throw Error("invalid file handle"); if (handles[f]) { _fclose(handles[f]); handles[f] = c_null; closedHandles.push(f); } } function fread(size: number, f: number): string { "use unsafe"; if (f < 0 || f >= handles.length) throw Error("invalid file handle"); if (!handles[f]) throw Error("file is closed"); if (size <= 0) throw Error("invalid size"); let buf = malloc(size); try { let nr = _fread(buf, 1, size, handles[f]); return asciiToString_unsafe(buf, nr); } finally { _free(buf); } } function freadAll(f: number): string { let res = ""; for (;;) { let s = fread(1024, f); if (!s) break; res += s; } return res; } // https://stackoverflow.com/a/34238979 function array_nth_permutation(a, n) { let lex = n; let b = Array(); // copy of the set a.slice() for (let x = 0; x < a.length; x++) { b[x] = a[x]; } let len = a.length; // length of the set const res = Array(); // return value, undefined let i = 1; let f = 1; // compute f = factorial(len) for (; i <= len; i++) { f *= i; } let fac = f; // if the permutation number is within range if (n >= 0 && n < f) { // start with the empty set, loop for len elements // let result_len = 0; for (; len > 0; len--) { // determine the next element: // there are f/len subsets for each possible element, f /= len; // a simple division gives the leading element index i = (n - n % f) / f; // Math.floor(n / f); // alternately: i = (n - n % f) / f; // res[(result_len)++] = b[i]; // for (let j = i; j < len; j++) { // b[j] = b[j + 1]; // shift elements left // } res.push(b.splice(i, 1)[0]); // reduce n for the remaining subset: // compute the remainder of the above division n %= f; // extract the i-th element from b and push it at the end of res } return `${lex} of ${fac - 1} (0-indexed, factorial ${fac}) => ${ JSON.stringify(res) }`; } else { if (n === 0) { return `${JSON.stringify(res)}\n`; } return `${n} >= 0 && ${n} < ${f}: ${n >= 0 && n < f}`; } } let f = fopen("/dev/stdin", "r"); try { let [input, lex] = String(freadAll(f)).split(" ").map(Number); if (input < 2 || lex < 0) { print(`Expected n > 2, m >= 0, got ${input}, ${lex}\n`); // eval(input) return 1; } else { print( array_nth_permutation(Array.from({ length: input }, (_, i) => i), lex), ); return 0; } } finally { fclose(f); } // Optionally force some methods to be emitted for debugging. // exports.foo = foo; })({});
Substituting
"stdin"
for"/dev/stdin"
produces the same result.Trying to maunally change the contents of the compiled C file produces other errors
fopen.ts:158:39: error: incompatible pointer to integer conversion passing 'FILE *const' (aka 'struct _IO_FILE *const') to parameter of type 'SHSymbolID' (aka 'unsigned int') [-Wint-conversion] 158 | locals.t9 = _sh_ljs_get_string(shr, stdin /*/dev/stdin*/);
/wasi-sdk/bin/../share/wasi-sysroot/include/wasm32-wasi/stdio.h:79:16: note: expanded from macro 'stdin' 79 | #define stdin (stdin) | ^~~~~~~
../hermes/include/hermes/VM/static_h.h:653:47: note: passing argument to parameter 'symID' here 653 | _sh_ljs_get_string(SHRuntime *shr, SHSymbolID symID); | ^ 1 warning and 1 error generated. clang++: error: no such file or directory: 'fopen.o'
Would using a similar mapping as
wasmer
does work in `wasmtime?
cfallin commented on issue #9922:
Would using a similar mapping as wasmer does work in
wasmtime
?In general, no, we try not to make non-standard extensions to WASI. This has negative downstream consequences on the ecosystem -- it creates expectations of other engines and a back-and-forth of bug reports (exactly as we see here!) that ends up forcing a de-facto standard, without the usual discussion and care, which we want to avoid.
If Static Hermes can only access stdin by opening a file named
/dev/stdin
, that seems like an issue with their standard library on WASI -- perhaps you could report an issue upstream?
guest271314 commented on issue #9922:
@cfallin I think I wore out my welcome there to get this far How to translate gcc CLI arguments to correponding clang arguments? #1588. A Collaborator over there has taken the time to implement compiling JavaScript to WASM using Emscripten and JavaScript to WASM with WASI support over a couple weeks. With patience until the last comment.
Technically Static Hermes doesn't provide a way at all to read STDIN, officially.
I'm basically trying to reproduce what is possible with Bytecode Alliance's Javy, with the bonus of the capability to compile to native executable, too, with the same C source code output by
-emit-c
. So far WABT'swasm2c
has not yet implemented outputting amain.c
forwasm2c nm_javy_permutations.wasm
. Withshermes
we get C first, then we can branch to WASM standalone and WASM with WASI support, and nativ executable; and if we want, back to JavaScript withwasm2js
.I had no idea
wasmer
was doing something different that is not standardized. I know from my experiments in WebAssembly world that the Wasmer folks to their own thing.
bjorn3 commented on issue #9922:
stdin is not globally defined in the source JavaScript.
I meant importing libc's stdin global variable.
guest271314 commented on issue #9922:
Havn't tried that, but thought about it. I'm not sure how to do that given the base
examples/fopen.js
. I don't think Facebook' Hermes is interested in implementing reading STDIN.
guest271314 commented on issue #9922:
@bjorn3
const _stdin = $SHBuiltin.extern_c( { include: "stdio.h" }, function (): c_ptr { return /* ? */ } );
?
bjorn3 commented on issue #9922:
I have no clue how to import C global variables from js code with static hermes. I hadn't heard of static hermes before today.
guest271314 closed issue #9922:
Thanks for filing a bug report! Please fill out the TODOs below.
Note: if you want to report a security issue, please read our security policy!
Test Case
Steps to Reproduce
Follow instructions here to build Facebook's Static Hermes.
Create
fopen.wasm
fromfopen.ts
.#!/bin/bash # Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. set -e # Exit immediately if a command exits with a non-zero status set -u # Treat unset variables as an error and exit immediately # Extract the filename without path and extension file_name=$(basename "$1") # Remove path file_name_with_ext="${file_name}" file_name="${file_name%.*}" # Remove extension rm -rf out mkdir out out="$PWD/out" # rm -rf ${file_name}.c ${file_name}.o ${file_name}.wasm ${file_name}.hbc ${file_name} # ./build-host/bin/hermes ${file_name}.js --emit-binary -out "${out}/${file_name}.hbc" ./build-host/bin/shermes -v -Os -g -static-link -typed -fstatic-builtins -Xenable-tdz -emit-c "${file_name_with_ext}" -o "${out}/${file_name}.c" # ./build-host/bin/shermes -v -Os -g -Xenable-tdz \ # -fstatic-builtins -fstd-globals ${file_name}.js \ # -o "${out}/${file_name}" # cp fopen.c out/fopen.c ../wasi-sdk/bin/wasm32-wasi-clang "${out}/${file_name}.c" -c \ -O3 \ -DNDEBUG \ -fno-strict-aliasing -fno-strict-overflow \ -I./build-wasm/lib/config \ -I../hermes/include \ -mllvm -wasm-enable-sjlj \ -Wno-c23-extensions \ -o "${out}/${file_name}.o" ../wasi-sdk/bin/clang++ -O3 "${out}/${file_name}.o" ./build-wasm/tools/sh-demo/CMakeFiles/sh-demo.dir/cxa.cpp.obj -o "${out}/${file_name}.wasm" \ -L./build-wasm/lib \ -L./build-wasm/jsi \ -L./build-wasm/tools/shermes \ -lshermes_console_a -lhermesvmlean_a -ljsi -lwasi-emulated-mman -lsetjmp ../wasi-sdk/bin/strip "${out}/${file_name}.wasm" ls -lh "${out}"
./wasm-standalone-test.sh fopen.ts In file included from /media/user/1234/hermes-builds/out/fopen.c:2: ../hermes/include/hermes/VM/static_h.h:334:2: warning: "JS exceptions are currenly broken with WASI" [-W#warnings] 334 | #warning "JS exceptions are currenly broken with WASI" | ^ 1 warning generated. total 1.7M -rw-rw-r-- 1 user user 96K Jan 5 09:46 fopen.c -rw-rw-r-- 1 user user 25K Jan 5 09:46 fopen.o -rwxrwxr-x 1 user user 1.5M Jan 5 09:46 fopen.wasm
Expected Results
wasmer
version wasmer 5.0.4 produces the expected resultecho '9 5' | wasmer out/fopen.wasm 5 of 362879 (0-indexed, factorial 362880) => [0,1,2,3,4,5,8,7,6]
echo '10 4' | wasmer out/fopen.wasm 4 of 3628799 (0-indexed, factorial 3628800) => [0,1,2,3,4,5,6,9,7,8]
Actual Results
echo '4 5' | wasmtime out/fopen.wasm Error: failed to run main module `out/fopen.wasm` Caused by: 0: failed to invoke command default 1: error while executing at wasm backtrace: 0: 0x130e14 - <unknown>!<wasm function 4066> 1: 0xa5995 - <unknown>!<wasm function 2511> 2: 0xa5e29 - <unknown>!<wasm function 2520> 3: 0x5884 - <unknown>!<wasm function 33> 4: 0x2be4 - <unknown>!<wasm function 24> 5: 0x25bd - <unknown>!<wasm function 23> 6: 0xb9a8c - <unknown>!<wasm function 2934> 7: 0xb9984 - <unknown>!<wasm function 2933> 8: 0xb96a2 - <unknown>!<wasm function 2932> 9: 0xb95c6 - <unknown>!<wasm function 2931> 10: 0x35ac - <unknown>!<wasm function 25> 11: 0x130be0 - <unknown>!<wasm function 4044> 12: 0x2393 - <unknown>!<wasm function 21> 2: wasm trap: wasm `unreachable` instruction executed
Without using
wasi-sdk/bin/strip
echo '4 5' | WASM_BACKTRACE_DETAILS=1 wasmtime out/fopen.wasm Error: failed to run main module `out/fopen.wasm` Caused by: 0: failed to invoke command default 1: error while executing at wasm backtrace: 0: 0x130e14 - fopen.wasm!abort 1: 0xa5995 - fopen.wasm!_sh_throw_current 2: 0xa5e29 - fopen.wasm!_sh_throw 3: 0x5884 - fopen.wasm!_7_fopen 4: 0x2be4 - fopen.wasm!_1__1_ 5: 0x25bd - fopen.wasm!_0_global 6: 0xb9a8c - fopen.wasm!sh_unit_run(SHRuntime*, SHUnit*) 7: 0xb9984 - fopen.wasm!_sh_unit_init 8: 0xb96a2 - fopen.wasm!_sh_unit_init_guarded 9: 0xb95c6 - fopen.wasm!_sh_initialize_units 10: 0x35ac - fopen.wasm!main 11: 0x130be0 - fopen.wasm!__main_void 12: 0x2393 - fopen.wasm!_start note: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information 2: wasm trap: wasm `unreachable` instruction executed
Versions and Environment
Wasmtime version or commit: wasmtime 28.0.0 (2e584e841 2024-12-20)
Operating system: Linux
Architecture: x86_64 x86_64 x86_64 GNU/Linux
Extra Info
I initially thought this was an issue with Static Hermes source code, specifically related to reading STDIN. Then I tested the same WASM file with
wasmer
.
guest271314 commented on issue #9922:
Fair enough. Some background Does hermes expose the capability to read standard input and write standard output? #1469.
In pertinent part https://github.com/facebook/hermes/discussions/1469#discussioncomment-10237485
Unfortunately an I/O library is currently out of scope for Hermes, and is technically orthogonal to our work.
Such a library can be implemented, but it would likely be mostly engine-agnostic.
and https://github.com/facebook/hermes/discussions/1469#discussioncomment-10452501
Static Hermes allows calling of any C API and generates native code.
I'm basically trying to use JavaScript as the source code that can be cross-compiled to various targets.
I can do this to an appreciable degree with Bytecode Alliance's Javy. Minus the compiling to native executable with C output part.
// ./javy emit-plugin -o plugin.wasm // ./javy build -C dynamic -C plugin=plugin.wasm -o nm_javy_permutations.wasm nm_javy_test.js // wasmtime run --preload javy_quickjs_provider_v3=plugin.wasm javy-permutations.wasm // ./binaryen/bin/wasm2js javy-permutations.wasm --enable-bulk-memory -o javy-permutations.js // node --no-warnings node-javy-test.js '4 5' // 5 of 23 (0-indexed, factorial 24) => [0,3,2,1] // echo '4 5' | wasmtime run --dir=. --preload javy_quickjs_provider_v3=plugin.wasm nm_javy_permutations.wasm - // 5 of 23 (0-indexed, factorial 24) => [0,3,2,1] // echo "4 5" | node --no-warnings node-javy-test.js - // 5 of 23 (0-indexed, factorial 24) => [0,3,2,1]
I guess this is not a bug in
wasmtime
.
cfallin commented on issue #9922:
@cfallin I think I wore out my welcome there to get this far https://github.com/facebook/hermes/discussions/1588#discussioncomment-11731049.
For what it's worth, I agree with tmikov (intentionally not tagging) in that thread. In particular posting long (100+ line) snippets without attempting to reduce or debug the issue at all is not a super-great use of maintainers' time.
Technically Static Hermes doesn't provide a way at all to read STDIN, officially.
Regardless, it seems that your issue is with Static Hermes: you want a piece of functionality, they do not provide it; I would recommend either working with them or working with your own fork. For what it's worth, maintainers tend to respond more positively to "I have debugged the issue and here is a PR that fixes it" sorts of contributions.
guest271314 commented on issue #9922:
@cfallin
For what it's worth, I agree with tmikov (intentionally not tagging) in that thread. In particular posting long (100+ line) snippets without attempting to reduce or debug the issue at all is not a super-great use of maintainers' time.
Um, I've generally tested and tried to break code a few thousand times before I file issues.
I'm on an island. There's not a whole bunch of developers hacking
node
,deno
,bun
,qjs
canary versionstjs
,llrt
,hermes
,shermes
, Google'sd8
, SerenityOS's LibJSjs
, Mozilla's SpiderMonkeyjs
shell,wasmtime
,wasmer
, running Chromium Dev Channel, and Firefox Nightly, at the same time, trying to write runtime agnostic code that works in each JavaScript/WebAssembly engine and runtime.I'm testing your gear in the field. At least until something breaks. I don't expect appreciation. I would at least expect a maintainer to ask what I've tried, before assuming I havn't tried anything. But alas, that rarely happens. Folkds are pigeoonholed in their own domains. I at least try to bridge gaps. Oh, well. The best I can do is test, and try to ask questions, until people ban me. I begin my experiments and tests on edges with these mottos in mind, understanding that not all maintainers, hackers, developers, engineers have the same interests. That's fine, different interests make the world go round!
So we need people to have weird new
ideas ... we need more ideas to break it
and make it better ...Use it. Break it. File bugs. Request features.
- Soledad Penadés, Real time front-end alchemy, or: capturing, playing,
altering and encoding video and audio streams, without
servers or plugins!von Braun believed in testing. I cannot
emphasize that term enough – test, test,
test. Test to the point it breaks.
- Ed Buckbee, NASA Public Affairs Officer, Chasing the Moon
Thanks for your time and effort in this matter. Have a great day. Without rancor.
guest271314 commented on issue #9922:
WASI doesn't have
/dev
nor/dev/stdin
. Looks like Wasmer adds/dev/stdin
as non-standard extension: https://github.com/wasmerio/wasmer/blob/1d03406174b204ac403f61e2deb0a41601c8e41b/lib/virtual-fs/src/builder.rs#L106-L110 Instead of usingfopen("/dev/stdin")
you can use thestdin
global variable instead. This is of typeFILE *
just like the return value offopen
. You just have to make sure not tofclose
it.@bjorn3 Helpful hint. Thanks.
Using
int getchar(void);
to avoid trying to definestdin
from WASI-SDKstdio.h
in Static Hermes context.const _getchar = $SHBuiltin.extern_c( { include: "stdio.h" }, function getchar(): c_int { throw 0; }, ); function getchars(): string { "use unsafe"; try { let n: number = 50; let c: string = String(); while (--n) { let int: number = _getchar(); if (int === -1) { break; } c += String.fromCodePoint(int); // print("int:", int); // print("string:", c); } return String(c).trim(); } catch (e) { return String(e.message); } } let stdin = getchars();
echo '15 2' | wasmer run ./out/fopen.wasm 2 of 1307674367999 (0-indexed, factorial 1307674368000) => [0,1,2,3,4,5,6,7,8,9,10,11,13,12,14]
echo '15 2' | wasmtime run ./out/fopen.wasm 2 of 1307674367999 (0-indexed, factorial 1307674368000) => [0,1,2,3,4,5,6,7,8,9,10,11,13,12,14]
Last updated: Jan 24 2025 at 00:11 UTC