【问题标题】:WASI-libc wait for user input when writing to stdinWASI-libc 在写入标准输入时等待用户输入
【发布时间】:2021-05-15 12:55:22
【问题描述】:

我想通过等待用户在 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,则该实现有效。例如,设置const input = "1\n" 将该字符串传递给我的C 程序中的scanf 调用,它读取的值是1

但是,在等待提供输入时,我正在努力“停止”JavaScript 执行。我知道 JavaScript 是事件驱动的,不能在传统意义上“暂停”,但是尝试将输入作为回调/承诺提供函数仍然执行的问题,导致没有任何东西传递给 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 解决方案。

【问题讨论】:

    标签: javascript c webassembly


    【解决方案1】:

    您希望将异步 JavaScript API 连接到同步 WebAssembly API。这是 WebAssembly 本身还没有内置解决方案的常见问题,但在工具级别有一些解决方案。特别是,您可能想看看 Asyncify - 我已经写了一篇关于它如何帮助解决这些用例以及如何在此处使用它的详细文章: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 或输入事件将相同的方法、Asyncify 工具甚至可能甚至相同的代码应用到您的示例中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-14
      • 2017-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-15
      • 1970-01-01
      相关资源
      最近更新 更多