我想通过等待用户在HTML input字段中键入一些文本,然后继续执行其余的WASI调用来实现WASI API中的fd_read。也就是说,使用类似以下内容:
fd_read = (fd, iovs, iovsLen, nread) => {
// only care about 'stdin'
if(fd !== STDIN)
return WASI_ERRNO_BADF;
const encoder = new TextEncoder();
const view = new DataView(memory.buffer);
view.setUint32(nread, 0, true);
// create a UInt8Array for each buffer
const buffers = Array.from({ length: iovsLen }, (_, i) => {
const ptr = iovs + i * 8;
const buf = view.getUint32(ptr, true);
const bufLen = view.getUint32(ptr + 4, true);
return new Uint8Array(memory.buffer, buf, bufLen);
});
// get input for each buffer
buffers.forEach(buf => {
const input = waitForUserInput();
buf.set(encoder.encode(input));
view.setUint32(nread, view.getUint32(nread, true) + input.length, true);
});
return WASI_ESUCCESS;
}如果提供了变量input,则实现可以正常工作。例如,在我的C程序中,设置const input = "1\n"将该字符串传递给scanf调用,然后它读入一个值1。
但是,在等待输入提供的同时,我很难“停止”JavaScript的执行。我知道JavaScript是事件驱动的,在传统意义上不能“暂停”,但是尝试将输入作为回调/Promise提供会导致函数仍在执行,导致不会向stdin传递任何内容
buffers.forEach(buf => {
let input;
waitForUserInput().then(value => {
input = value;
});
buf.set(encoder.encode(input));
view.setUint32(nread, view.getUint32(nread, true) + input.length, true);
});由于输入仍在等待设置,因此缓冲区中没有任何内容被编码,而stdin只读取0。
有没有办法使用async/await等待输入,或者使用setTimeout的"hack-y“解决方案?我知道window.Prompt()会停止执行,但我希望输入成为页面的一部分。寻找普通的JavaScript解决方案。
发布于 2021-05-27 04:16:25
您希望将异步JavaScript API连接到同步WebAssembly API。这是一个常见的问题,WebAssembly本身还没有内置的解决方案,但是在工具级别上有一些。特别是,你可能想看看异步-我已经写了一篇详细的文章,关于它如何帮助解决这些用例以及如何在这里使用它:https://web.dev/asyncify/
特别是对于WASI,这篇文章还展示了一个演示,该演示将fd_read和其他同步操作从文件系统访问连接到异步API。你可以在https://wasi.rreverser.com/上找到现场演示,在https://github.com/GoogleChromeLabs/wasi-fs-access上找到它的代码。
例如,下面是您感兴趣的fd_read函数的一个实现,它使用async-await来等待异步API:https://github.com/GoogleChromeLabs/wasi-fs-access/blob/4c2d29fdfe79abb9b48bd44e296c2019f55d0eec/src/bindings.ts#L449-L461
您应该能够使用setTimeout或输入事件使相同的方法、异步工具甚至潜在的相同代码适应您的示例。
https://stackoverflow.com/questions/67546934
复制相似问题