diff --git a/src/node_wasi.cc b/src/node_wasi.cc index 7ee59f46331097..9c82df1916e4b9 100644 --- a/src/node_wasi.cc +++ b/src/node_wasi.cc @@ -36,6 +36,7 @@ using v8::FastApiCallbackOptions; using v8::FunctionCallbackInfo; using v8::FunctionTemplate; using v8::HandleScope; +using v8::Int32; using v8::Integer; using v8::Isolate; using v8::Local; @@ -306,6 +307,16 @@ uint32_t ConvertType(Local value) { return value.As()->Value(); } +template <> +bool CheckType(Local value) { + return value->IsInt32(); +} + +template <> +int32_t ConvertType(Local value) { + return value.As()->Value(); +} + template <> bool CheckType(Local value) { return value->IsBigInt(); @@ -486,14 +497,17 @@ uint32_t WASI::ClockTimeGet(WASI& wasi, WasmMemory memory, uint32_t clock_id, uint64_t precision, - uint32_t time_ptr) { - Debug(wasi, "clock_time_get(%d, %d, %d)\n", clock_id, precision, time_ptr); - CHECK_BOUNDS_OR_RETURN(memory.size, time_ptr, UVWASI_SERDES_SIZE_timestamp_t); + int32_t time_ptr) { + const auto time_ptr_u32 = static_cast(time_ptr); + Debug( + wasi, "clock_time_get(%d, %d, %d)\n", clock_id, precision, time_ptr_u32); + CHECK_BOUNDS_OR_RETURN( + memory.size, time_ptr_u32, UVWASI_SERDES_SIZE_timestamp_t); uvwasi_timestamp_t time; uvwasi_errno_t err = uvwasi_clock_time_get(&wasi.uvw_, clock_id, precision, &time); if (err == UVWASI_ESUCCESS) - uvwasi_serdes_write_timestamp_t(memory.data, time_ptr, time); + uvwasi_serdes_write_timestamp_t(memory.data, time_ptr_u32, time); return err; } diff --git a/src/node_wasi.h b/src/node_wasi.h index 25551936e6be36..383bd17bf7d639 100644 --- a/src/node_wasi.h +++ b/src/node_wasi.h @@ -31,7 +31,7 @@ class WASI : public BaseObject, static uint32_t ArgsGet(WASI&, WasmMemory, uint32_t, uint32_t); static uint32_t ArgsSizesGet(WASI&, WasmMemory, uint32_t, uint32_t); static uint32_t ClockResGet(WASI&, WasmMemory, uint32_t, uint32_t); - static uint32_t ClockTimeGet(WASI&, WasmMemory, uint32_t, uint64_t, uint32_t); + static uint32_t ClockTimeGet(WASI&, WasmMemory, uint32_t, uint64_t, int32_t); static uint32_t EnvironGet(WASI&, WasmMemory, uint32_t, uint32_t); static uint32_t EnvironSizesGet(WASI&, WasmMemory, uint32_t, uint32_t); static uint32_t FdAdvise( diff --git a/test/fixtures/wasi-uint32-int32.wasm b/test/fixtures/wasi-uint32-int32.wasm new file mode 100644 index 00000000000000..d82ca14a53466f Binary files /dev/null and b/test/fixtures/wasi-uint32-int32.wasm differ diff --git a/test/fixtures/wasi-uint32-int32.wat b/test/fixtures/wasi-uint32-int32.wat new file mode 100644 index 00000000000000..5ab1fba75f2d94 --- /dev/null +++ b/test/fixtures/wasi-uint32-int32.wat @@ -0,0 +1,50 @@ +(module + (import "wasi_snapshot_preview1" "clock_time_get" + (func $clock_time_get (param i32 i64 i32) (result i32))) + + (memory (export "memory") 2) + + (func (export "test_clock_time_get") (result i32) + i32.const 0 + i64.const 1 + i32.const 0x80000000 + call $clock_time_get + ) + + (func (export "test_clock_time_get_zero") (result i32) + i32.const 0 + i64.const 1 + i32.const 0 + call $clock_time_get + ) + + (func (export "test_clock_time_get_one") (result i32) + i32.const 1 + i64.const 1 + i32.const 1 + call $clock_time_get + ) + + (func (export "test_clock_time_get_int32_max") (result i32) + i32.const 0 + i64.const 1 + i32.const 0x7fffffff + call $clock_time_get + ) + + (func (export "test_clock_time_get_uint32_min") (result i32) + i32.const 0 + i64.const 1 + i32.const 0x80000000 + call $clock_time_get + ) + + (func (export "test_clock_time_get_uint32_max") (result i32) + i32.const 0 + i64.const 1 + i32.const 0xffffffff + call $clock_time_get + ) + + (func (export "_start")) +) diff --git a/test/wasi/test-wasi-uint32-int32.js b/test/wasi/test-wasi-uint32-int32.js new file mode 100644 index 00000000000000..661f0ae059d9fc --- /dev/null +++ b/test/wasi/test-wasi-uint32-int32.js @@ -0,0 +1,42 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const fs = require('fs'); +const path = require('path'); +const { WASI } = require('wasi'); + +const wasm = fs.readFileSync( + path.join(__dirname, '..', 'fixtures', 'wasi-uint32-int32.wasm'), +); + +const kWasiUint32Expectations = [ + ['test_clock_time_get', 61], + ['test_clock_time_get_zero', 0], + ['test_clock_time_get_one', 0], + ['test_clock_time_get_int32_max', 61], + ['test_clock_time_get_uint32_min', 61], + ['test_clock_time_get_uint32_max', 61], +]; + +const kWasiUint32ExportNames = kWasiUint32Expectations.map(([name]) => name); + +(async () => { + const wasi = new WASI({ version: 'preview1', returnOnExit: true }); + const importObject = { wasi_snapshot_preview1: wasi.wasiImport }; + const { instance } = await WebAssembly.instantiate(wasm, importObject); + + assert.deepStrictEqual( + Object.keys(instance.exports).sort(), + ['_start', 'memory', ...kWasiUint32ExportNames].sort(), + ); + + wasi.start(instance); + + for (const [name, expectedErrno] of kWasiUint32Expectations) { + assert.strictEqual( + instance.exports[name](), + expectedErrno, + name, + ); + } +})().then(common.mustCall());