diff --git a/deps/uvwasi/src/fd_table.c b/deps/uvwasi/src/fd_table.c index dd3a6c536b..038f9f2577 100644 --- a/deps/uvwasi/src/fd_table.c +++ b/deps/uvwasi/src/fd_table.c @@ -124,16 +124,12 @@ static uvwasi_errno_t uvwasi__get_type_and_rights(uv_file fd, } else if (S_ISSOCK(mode)) { handle_type = uv_guess_handle(fd); - if (handle_type == UV_TCP) { + if (handle_type == UV_TCP) *type = UVWASI_FILETYPE_SOCKET_STREAM; - } else if (handle_type == UV_UDP) { + else if (handle_type == UV_UDP) *type = UVWASI_FILETYPE_SOCKET_DGRAM; - } else { + else *type = UVWASI_FILETYPE_UNKNOWN; - *rights_base = 0; - *rights_inheriting = 0; - return UVWASI_EINVAL; - } *rights_base = UVWASI__RIGHTS_SOCKET_BASE; *rights_inheriting = UVWASI__RIGHTS_SOCKET_INHERITING; @@ -239,6 +235,9 @@ static uvwasi_errno_t uvwasi__fd_table_insert(struct uvwasi_fd_table_t* table, uvwasi_errno_t uvwasi_fd_table_init(struct uvwasi_fd_table_t* table, uint32_t init_size) { struct uvwasi_fd_wrap_t* wrap; + uvwasi_filetype_t type; + uvwasi_rights_t base; + uvwasi_rights_t inheriting; uvwasi_errno_t err; uvwasi_fd_t i; @@ -255,13 +254,21 @@ uvwasi_errno_t uvwasi_fd_table_init(struct uvwasi_fd_table_t* table, /* Create the stdio FDs. */ for (i = 0; i < 3; ++i) { + err = uvwasi__get_type_and_rights(i, + UV_FS_O_RDWR, + &type, + &base, + &inheriting); + if (err != UVWASI_ESUCCESS) + goto error_exit; + err = uvwasi__fd_table_insert(table, i, "", "", - UVWASI_FILETYPE_UNKNOWN, - 0, - 0, + type, + base, + inheriting, 0, &wrap); if (err != UVWASI_ESUCCESS) diff --git a/deps/uvwasi/src/uvwasi.c b/deps/uvwasi/src/uvwasi.c index 87a47d7ab7..51af4e5641 100644 --- a/deps/uvwasi/src/uvwasi.c +++ b/deps/uvwasi/src/uvwasi.c @@ -1003,7 +1003,7 @@ uvwasi_errno_t uvwasi_fd_write(uvwasi_t* uvwasi, if (err != UVWASI_ESUCCESS) return err; - r = uv_fs_write(NULL, &req, wrap->fd, bufs, iovs_len, 0, NULL); + r = uv_fs_write(NULL, &req, wrap->fd, bufs, iovs_len, -1, NULL); uvwritten = req.result; uv_fs_req_cleanup(&req); free(bufs); diff --git a/src/node_wasi.cc b/src/node_wasi.cc index 3cf43f39a6..9621b2d3ae 100644 --- a/src/node_wasi.cc +++ b/src/node_wasi.cc @@ -769,6 +769,8 @@ void WASI::FdWrite(const FunctionCallbackInfo& args) { uint32_t iovs_ptr; uint32_t iovs_len; uint32_t nwritten_ptr; + char* memory; + size_t mem_size; RETURN_IF_BAD_ARG_COUNT(args, 4); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, iovs_ptr); @@ -781,17 +783,37 @@ void WASI::FdWrite(const FunctionCallbackInfo& args) { iovs_ptr, iovs_len, nwritten_ptr); - // TODO(cjihrig): Handle iovs properly instead of passing nullptr. + GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); // TODO(cjihrig): Check for buffer overflows. + uvwasi_ciovec_t* iovs = + static_cast(calloc(iovs_len, sizeof(*iovs))); + + if (iovs == nullptr) { + args.GetReturnValue().Set(UVWASI_ENOMEM); + return; + } + + for (uint32_t i = 0; i < iovs_len; ++i) { + uint32_t buf_ptr; + uint32_t buf_len; + + wasi->readUInt32(&buf_ptr, iovs_ptr); + wasi->readUInt32(&buf_len, iovs_ptr + 4); + iovs_ptr += 8; + iovs[i].buf = static_cast(&memory[buf_ptr]); + iovs[i].buf_len = buf_len; + } + size_t nwritten; uvwasi_errno_t err = uvwasi_fd_write(&wasi->uvw_, fd, - nullptr, + iovs, iovs_len, &nwritten); if (err == UVWASI_ESUCCESS) err = wasi->writeUInt32(nwritten, nwritten_ptr); + free(iovs); args.GetReturnValue().Set(err); } diff --git a/test/wasi/test-wasi-binding.js b/test/wasi/test-wasi-binding.js index 91201c7ca4..d436fdba5e 100644 --- a/test/wasi/test-wasi-binding.js +++ b/test/wasi/test-wasi-binding.js @@ -6,10 +6,7 @@ const assert = require('assert'); const fixtures = require('../common/fixtures'); const buffer = fixtures.readSync(['wasi', 'simple-wasi.wasm']); const { WASI } = require('wasi'); - -const memory = new WebAssembly.Memory({ initial: 1 }); -const wasi = new WASI({ args: [], env: process.env, memory }); - +const wasi = new WASI({ args: [], env: process.env }); const importObject = { wasi_unstable: wasi.wasiImport }; @@ -17,9 +14,5 @@ const importObject = { WebAssembly.instantiate(buffer, importObject) .then(common.mustCall((results) => { assert(results.instance.exports._start); - // Currently when running this the exit status of the process will be 71 - // which if I'm reading the uvwasi error codes correctly matches __WASI_ESRCH - // which is "No such process". - // TODO(danbev) enable start when the above issue has been sorted out. - // WASI.start(results.instance); + wasi.start(results.instance); })); diff --git a/test/wasi/test-wasi.js b/test/wasi/test-wasi.js index ad087ae639..629ac937a9 100644 --- a/test/wasi/test-wasi.js +++ b/test/wasi/test-wasi.js @@ -1,13 +1,12 @@ 'use strict'; -const common = require('../common'); +require('../common'); if (process.argv[2] === 'wasi-child') { const fs = require('fs'); const path = require('path'); const { WASI } = require('wasi'); const wasmDir = path.join(__dirname, 'wasm'); - const memory = new WebAssembly.Memory({ initial: 3 }); - const wasi = new WASI({ args: [], env: process.env, memory }); + const wasi = new WASI({ args: [], env: process.env }); const importObject = { wasi_unstable: wasi.wasiImport }; const modulePath = path.join(wasmDir, `${process.argv[3]}.wasm`); const buffer = fs.readFileSync(modulePath); @@ -23,18 +22,20 @@ if (process.argv[2] === 'wasi-child') { function runWASI(options) { console.log('executing', options.test); - const child = cp.fork(__filename, ['wasi-child', options.test], { - execArgv: ['--experimental-wasm-bigint'] - }); + const child = cp.spawnSync(process.execPath, [ + '--experimental-wasm-bigint', + __filename, + 'wasi-child', + options.test + ]); - child.on('exit', common.mustCall((code, signal) => { - assert.strictEqual(code, options.exitCode || 0); - assert.strictEqual(signal, null); - })); + assert.strictEqual(child.status, options.exitCode || 0); + assert.strictEqual(child.signal, null); + assert.strictEqual(child.stdout.toString(), options.stdout || ''); } runWASI({ test: 'cant_dotdot' }); runWASI({ test: 'exitcode', exitCode: 120 }); runWASI({ test: 'fd_prestat_get_refresh' }); - runWASI({ test: 'read_file' }); + runWASI({ test: 'read_file', stdout: 'hello from input.txt\n' }); }