summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorcjihrig <cjihrig@gmail.com>2019-09-04 17:56:51 -0400
committerAnna Henningsen <anna@addaleax.net>2019-11-30 18:06:39 +0100
commit09b1228c3a2723c6ecb768b40a507688015a478f (patch)
tree88acbfc979bc6f73572c86e8ee804bf0fa4ad326 /src
parent73c837b1ae91cb8852e75a921fa24c714471d690 (diff)
downloadandroid-node-v8-09b1228c3a2723c6ecb768b40a507688015a478f.tar.gz
android-node-v8-09b1228c3a2723c6ecb768b40a507688015a478f.tar.bz2
android-node-v8-09b1228c3a2723c6ecb768b40a507688015a478f.zip
wasi: introduce initial WASI support
Co-authored-by: Gus Caplan <me@gus.host> Co-authored-by: Daniel Bevenius <daniel.bevenius@gmail.com> Co-authored-by: Jiawen Geng <technicalcute@gmail.com> Co-authored-by: Tobias Nießen <tniessen@tnie.de> Co-authored-by: Chengzhong Wu <legendecas@gmail.com> PR-URL: https://github.com/nodejs/node/pull/30258 Refs: https://github.com/nodejs/node/pull/27850 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com> Reviewed-By: Guy Bedford <guybedford@gmail.com> Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: Wyatt Preul <wpreul@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/env-inl.h15
-rw-r--r--src/env.h8
-rw-r--r--src/node_binding.cc1
-rw-r--r--src/node_config.cc3
-rw-r--r--src/node_options.cc4
-rw-r--r--src/node_options.h1
-rw-r--r--src/node_wasi.cc1802
-rw-r--r--src/node_wasi.h103
8 files changed, 1936 insertions, 1 deletions
diff --git a/src/env-inl.h b/src/env-inl.h
index d34bd03c7c..d75b4ea743 100644
--- a/src/env-inl.h
+++ b/src/env-inl.h
@@ -1102,6 +1102,21 @@ inline void Environment::SetProtoMethodNoSideEffect(
t->SetClassName(name_string); // NODE_SET_PROTOTYPE_METHOD() compatibility.
}
+inline void Environment::SetInstanceMethod(v8::Local<v8::FunctionTemplate> that,
+ const char* name,
+ v8::FunctionCallback callback) {
+ v8::Local<v8::Signature> signature = v8::Signature::New(isolate(), that);
+ v8::Local<v8::FunctionTemplate> t =
+ NewFunctionTemplate(callback, signature, v8::ConstructorBehavior::kThrow,
+ v8::SideEffectType::kHasSideEffect);
+ // kInternalized strings are created in the old space.
+ const v8::NewStringType type = v8::NewStringType::kInternalized;
+ v8::Local<v8::String> name_string =
+ v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked();
+ that->InstanceTemplate()->Set(name_string, t);
+ t->SetClassName(name_string);
+}
+
void Environment::AddCleanupHook(void (*fn)(void*), void* arg) {
auto insertion_info = cleanup_hooks_.emplace(CleanupHookCallback {
fn, arg, cleanup_hook_counter_++
diff --git a/src/env.h b/src/env.h
index c0c8ac0db4..c25a03ea1e 100644
--- a/src/env.h
+++ b/src/env.h
@@ -541,7 +541,8 @@ struct ContextInfo {
#define DEBUG_CATEGORY_NAMES(V) \
NODE_ASYNC_PROVIDER_TYPES(V) \
V(INSPECTOR_SERVER) \
- V(INSPECTOR_PROFILER)
+ V(INSPECTOR_PROFILER) \
+ V(WASI)
enum class DebugCategory {
#define V(name) name,
@@ -1114,6 +1115,11 @@ class Environment : public MemoryRetainer {
const char* name,
v8::FunctionCallback callback);
+ inline void SetInstanceMethod(v8::Local<v8::FunctionTemplate> that,
+ const char* name,
+ v8::FunctionCallback callback);
+
+
// Safe variants denote the function has no side effects.
inline void SetMethodNoSideEffect(v8::Local<v8::Object> that,
const char* name,
diff --git a/src/node_binding.cc b/src/node_binding.cc
index f57ddb54b6..82836585c5 100644
--- a/src/node_binding.cc
+++ b/src/node_binding.cc
@@ -85,6 +85,7 @@
V(util) \
V(uv) \
V(v8) \
+ V(wasi) \
V(worker) \
V(zlib)
diff --git a/src/node_config.cc b/src/node_config.cc
index 92985dff2f..16050bdd5b 100644
--- a/src/node_config.cc
+++ b/src/node_config.cc
@@ -84,6 +84,9 @@ static void Initialize(Local<Object> target,
READONLY_PROPERTY(target, "hasCachedBuiltins",
v8::Boolean::New(isolate, native_module::has_code_cache));
+
+ if (env->options()->experimental_wasi)
+ READONLY_TRUE_PROPERTY(target, "experimentalWasi");
} // InitConfig
} // namespace node
diff --git a/src/node_options.cc b/src/node_options.cc
index 0bc6730156..44b125775f 100644
--- a/src/node_options.cc
+++ b/src/node_options.cc
@@ -347,6 +347,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
&EnvironmentOptions::experimental_report,
kAllowedInEnvironment);
#endif // NODE_REPORT
+ AddOption("--experimental-wasi-unstable-preview0",
+ "experimental WASI support",
+ &EnvironmentOptions::experimental_wasi,
+ kAllowedInEnvironment);
AddOption("--expose-internals", "", &EnvironmentOptions::expose_internals);
AddOption("--frozen-intrinsics",
"experimental frozen intrinsics support",
diff --git a/src/node_options.h b/src/node_options.h
index ce0cee5fe5..adc0ef783f 100644
--- a/src/node_options.h
+++ b/src/node_options.h
@@ -151,6 +151,7 @@ class EnvironmentOptions : public Options {
#ifdef NODE_REPORT
bool experimental_report = false;
#endif // NODE_REPORT
+ bool experimental_wasi = false;
std::string eval_string;
bool print_eval = false;
bool force_repl = false;
diff --git a/src/node_wasi.cc b/src/node_wasi.cc
new file mode 100644
index 0000000000..8de7f1fc1c
--- /dev/null
+++ b/src/node_wasi.cc
@@ -0,0 +1,1802 @@
+#include "env-inl.h"
+#include "base_object-inl.h"
+#include "debug_utils.h"
+#include "util-inl.h"
+#include "node.h"
+#include "uv.h"
+#include "uvwasi.h"
+#include "node_wasi.h"
+
+namespace node {
+namespace wasi {
+
+static inline bool is_access_oob(size_t mem_size,
+ uint32_t offset,
+ uint32_t buf_size) {
+ return offset + buf_size > mem_size;
+}
+
+template <typename... Args>
+inline void Debug(WASI* wasi, Args&&... args) {
+ Debug(wasi->env(), DebugCategory::WASI, std::forward<Args>(args)...);
+}
+
+#define RETURN_IF_BAD_ARG_COUNT(args, expected) \
+ do { \
+ if ((args).Length() != (expected)) { \
+ (args).GetReturnValue().Set(UVWASI_EINVAL); \
+ return; \
+ } \
+ } while (0)
+
+#define CHECK_TO_TYPE_OR_RETURN(args, input, type, result) \
+ do { \
+ if (!(input)->Is##type()) { \
+ (args).GetReturnValue().Set(UVWASI_EINVAL); \
+ return; \
+ } \
+ (result) = (input).As<type>()->Value(); \
+ } while (0)
+
+#define UNWRAP_BIGINT_OR_RETURN(args, input, type, result) \
+ do { \
+ if (!(input)->IsBigInt()) { \
+ (args).GetReturnValue().Set(UVWASI_EINVAL); \
+ return; \
+ } \
+ Local<BigInt> js_value = (input).As<BigInt>(); \
+ bool lossless; \
+ (result) = js_value->type ## Value(&lossless); \
+ } while (0)
+
+#define GET_BACKING_STORE_OR_RETURN(wasi, args, mem_ptr, mem_size) \
+ do { \
+ uvwasi_errno_t err = (wasi)->backingStore((mem_ptr), (mem_size)); \
+ if (err != UVWASI_ESUCCESS) { \
+ (args).GetReturnValue().Set(err); \
+ return; \
+ } \
+ } while (0)
+
+#define CHECK_BOUNDS_OR_RETURN(args, mem_size, offset, buf_size) \
+ do { \
+ if (is_access_oob((mem_size), (offset), (buf_size))) { \
+ (args).GetReturnValue().Set(UVWASI_EOVERFLOW); \
+ return; \
+ } \
+ } while (0)
+
+
+using v8::Array;
+using v8::ArrayBuffer;
+using v8::BackingStore;
+using v8::BigInt;
+using v8::Context;
+using v8::FunctionCallbackInfo;
+using v8::FunctionTemplate;
+using v8::Local;
+using v8::Object;
+using v8::String;
+using v8::Uint32;
+using v8::Value;
+
+
+WASI::WASI(Environment* env,
+ Local<Object> object,
+ uvwasi_options_t* options) : BaseObject(env, object) {
+ MakeWeak();
+ CHECK_EQ(uvwasi_init(&uvw_, options), UVWASI_ESUCCESS);
+}
+
+
+WASI::~WASI() {
+ uvwasi_destroy(&uvw_);
+}
+
+
+void WASI::New(const FunctionCallbackInfo<Value>& args) {
+ CHECK(args.IsConstructCall());
+ CHECK_EQ(args.Length(), 3);
+ CHECK(args[0]->IsArray());
+ CHECK(args[1]->IsArray());
+ CHECK(args[2]->IsArray());
+
+ Environment* env = Environment::GetCurrent(args);
+ Local<Context> context = env->context();
+ Local<Array> argv = args[0].As<Array>();
+ const uint32_t argc = argv->Length();
+ uvwasi_options_t options;
+
+ options.fd_table_size = 3;
+ options.argc = argc;
+ options.argv = argc == 0 ? nullptr : new char*[argc];
+
+ for (uint32_t i = 0; i < argc; i++) {
+ auto arg = argv->Get(context, i).ToLocalChecked();
+ CHECK(arg->IsString());
+ node::Utf8Value str(env->isolate(), arg);
+ options.argv[i] = strdup(*str);
+ CHECK_NOT_NULL(options.argv[i]);
+ }
+
+ Local<Array> env_pairs = args[1].As<Array>();
+ const uint32_t envc = env_pairs->Length();
+ options.envp = new char*[envc + 1];
+ for (uint32_t i = 0; i < envc; i++) {
+ auto pair = env_pairs->Get(context, i).ToLocalChecked();
+ CHECK(pair->IsString());
+ node::Utf8Value str(env->isolate(), pair);
+ options.envp[i] = strdup(*str);
+ CHECK_NOT_NULL(options.envp[i]);
+ }
+ options.envp[envc] = nullptr;
+
+ Local<Array> preopens = args[2].As<Array>();
+ CHECK_EQ(preopens->Length() % 2, 0);
+ options.preopenc = preopens->Length() / 2;
+ options.preopens = UncheckedCalloc<uvwasi_preopen_t>(options.preopenc);
+ int index = 0;
+ for (uint32_t i = 0; i < preopens->Length(); i += 2) {
+ auto mapped = preopens->Get(context, i).ToLocalChecked();
+ auto real = preopens->Get(context, i + 1).ToLocalChecked();
+ CHECK(mapped->IsString());
+ CHECK(real->IsString());
+ node::Utf8Value mapped_path(env->isolate(), mapped);
+ node::Utf8Value real_path(env->isolate(), real);
+ options.preopens[index].mapped_path = strdup(*mapped_path);
+ options.preopens[index].real_path = strdup(*real_path);
+ index++;
+ }
+
+ new WASI(env, args.This(), &options);
+
+ if (options.argv != nullptr) {
+ for (uint32_t i = 0; i < argc; i++)
+ free(options.argv[i]);
+ delete[] options.argv;
+ }
+
+ if (options.envp != nullptr) {
+ for (uint32_t i = 0; options.envp[i]; i++)
+ free(options.envp[i]);
+ delete[] options.envp;
+ }
+}
+
+
+void WASI::ArgsGet(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t argv_offset;
+ uint32_t argv_buf_offset;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 2);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, argv_offset);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, argv_buf_offset);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "args_get(%d, %d)\n", argv_offset, argv_buf_offset);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args,
+ mem_size,
+ argv_buf_offset,
+ wasi->uvw_.argv_buf_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, argv_offset, wasi->uvw_.argc * 4);
+ std::vector<char*> argv(wasi->uvw_.argc);
+ char* argv_buf = &memory[argv_buf_offset];
+ uvwasi_errno_t err = uvwasi_args_get(&wasi->uvw_, argv.data(), argv_buf);
+
+ if (err == UVWASI_ESUCCESS) {
+ for (size_t i = 0; i < wasi->uvw_.argc; i++) {
+ uint32_t offset = argv_buf_offset + (argv[i] - argv[0]);
+ wasi->writeUInt32(memory, offset, argv_offset + (i * 4));
+ }
+ }
+
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::ArgsSizesGet(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t argc_offset;
+ uint32_t argv_buf_offset;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 2);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, argc_offset);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, argv_buf_offset);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "args_sizes_get(%d, %d)\n", argc_offset, argv_buf_offset);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, argc_offset, 4);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, argv_buf_offset, 4);
+ size_t argc;
+ size_t argv_buf_size;
+ uvwasi_errno_t err = uvwasi_args_sizes_get(&wasi->uvw_,
+ &argc,
+ &argv_buf_size);
+ if (err == UVWASI_ESUCCESS) {
+ wasi->writeUInt32(memory, argc, argc_offset);
+ wasi->writeUInt32(memory, argv_buf_size, argv_buf_offset);
+ }
+
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::ClockResGet(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t clock_id;
+ uint32_t resolution_ptr;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 2);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, clock_id);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, resolution_ptr);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "clock_res_get(%d, %d)\n", clock_id, resolution_ptr);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, resolution_ptr, 8);
+ uvwasi_timestamp_t resolution;
+ uvwasi_errno_t err = uvwasi_clock_res_get(&wasi->uvw_,
+ clock_id,
+ &resolution);
+ if (err == UVWASI_ESUCCESS)
+ wasi->writeUInt64(memory, resolution, resolution_ptr);
+
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::ClockTimeGet(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t clock_id;
+ uint64_t precision;
+ uint32_t time_ptr;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 3);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, clock_id);
+ UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, precision);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, time_ptr);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "clock_time_get(%d, %d, %d)\n", clock_id, precision, time_ptr);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, time_ptr, 8);
+ uvwasi_timestamp_t time;
+ uvwasi_errno_t err = uvwasi_clock_time_get(&wasi->uvw_,
+ clock_id,
+ precision,
+ &time);
+ if (err == UVWASI_ESUCCESS)
+ wasi->writeUInt64(memory, time, time_ptr);
+
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::EnvironGet(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t environ_offset;
+ uint32_t environ_buf_offset;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 2);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, environ_offset);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, environ_buf_offset);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "environ_get(%d, %d)\n", environ_offset, environ_buf_offset);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args,
+ mem_size,
+ environ_buf_offset,
+ wasi->uvw_.env_buf_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, environ_offset, wasi->uvw_.envc * 4);
+ std::vector<char*> environment(wasi->uvw_.envc);
+ char* environ_buf = &memory[environ_buf_offset];
+ uvwasi_errno_t err = uvwasi_environ_get(&wasi->uvw_,
+ environment.data(),
+ environ_buf);
+
+ if (err == UVWASI_ESUCCESS) {
+ for (size_t i = 0; i < wasi->uvw_.envc; i++) {
+ uint32_t offset = environ_buf_offset + (environment[i] - environment[0]);
+ wasi->writeUInt32(memory, offset, environ_offset + (i * 4));
+ }
+ }
+
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::EnvironSizesGet(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t envc_offset;
+ uint32_t env_buf_offset;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 2);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, envc_offset);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, env_buf_offset);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "environ_sizes_get(%d, %d)\n", envc_offset, env_buf_offset);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, envc_offset, 4);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, env_buf_offset, 4);
+ size_t envc;
+ size_t env_buf_size;
+ uvwasi_errno_t err = uvwasi_environ_sizes_get(&wasi->uvw_,
+ &envc,
+ &env_buf_size);
+ if (err == UVWASI_ESUCCESS) {
+ wasi->writeUInt32(memory, envc, envc_offset);
+ wasi->writeUInt32(memory, env_buf_size, env_buf_offset);
+ }
+
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdAdvise(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint64_t offset;
+ uint64_t len;
+ uint8_t advice;
+ RETURN_IF_BAD_ARG_COUNT(args, 4);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, offset);
+ UNWRAP_BIGINT_OR_RETURN(args, args[2], Uint64, len);
+ CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, advice);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "fd_advise(%d, %d, %d, %d)\n", fd, offset, len, advice);
+ uvwasi_errno_t err = uvwasi_fd_advise(&wasi->uvw_, fd, offset, len, advice);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdAllocate(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint64_t offset;
+ uint64_t len;
+ RETURN_IF_BAD_ARG_COUNT(args, 3);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, offset);
+ UNWRAP_BIGINT_OR_RETURN(args, args[2], Uint64, len);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "fd_allocate(%d, %d, %d)\n", fd, offset, len);
+ uvwasi_errno_t err = uvwasi_fd_allocate(&wasi->uvw_, fd, offset, len);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdClose(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ RETURN_IF_BAD_ARG_COUNT(args, 1);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "fd_close(%d)\n", fd);
+ uvwasi_errno_t err = uvwasi_fd_close(&wasi->uvw_, fd);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdDatasync(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ RETURN_IF_BAD_ARG_COUNT(args, 1);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "fd_datasync(%d)\n", fd);
+ uvwasi_errno_t err = uvwasi_fd_datasync(&wasi->uvw_, fd);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdFdstatGet(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint32_t buf;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 2);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, buf);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "fd_fdstat_get(%d, %d)\n", fd, buf);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, buf, 24);
+ uvwasi_fdstat_t stats;
+ uvwasi_errno_t err = uvwasi_fd_fdstat_get(&wasi->uvw_, fd, &stats);
+
+ if (err == UVWASI_ESUCCESS) {
+ wasi->writeUInt8(memory, stats.fs_filetype, buf);
+ wasi->writeUInt16(memory, stats.fs_flags, buf + 2);
+ wasi->writeUInt64(memory, stats.fs_rights_base, buf + 8);
+ wasi->writeUInt64(memory, stats.fs_rights_inheriting, buf + 16);
+ }
+
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdFdstatSetFlags(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint16_t flags;
+ RETURN_IF_BAD_ARG_COUNT(args, 2);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, flags);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "fd_fdstat_set_flags(%d, %d)\n", fd, flags);
+ uvwasi_errno_t err = uvwasi_fd_fdstat_set_flags(&wasi->uvw_, fd, flags);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdFdstatSetRights(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint64_t fs_rights_base;
+ uint64_t fs_rights_inheriting;
+ RETURN_IF_BAD_ARG_COUNT(args, 3);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, fs_rights_base);
+ UNWRAP_BIGINT_OR_RETURN(args, args[2], Uint64, fs_rights_inheriting);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi,
+ "fd_fdstat_set_rights(%d, %d, %d)\n",
+ fd,
+ fs_rights_base,
+ fs_rights_inheriting);
+ uvwasi_errno_t err = uvwasi_fd_fdstat_set_rights(&wasi->uvw_,
+ fd,
+ fs_rights_base,
+ fs_rights_inheriting);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdFilestatGet(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint32_t buf;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 2);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, buf);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "fd_filestat_get(%d, %d)\n", fd, buf);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, buf, 56);
+ uvwasi_filestat_t stats;
+ uvwasi_errno_t err = uvwasi_fd_filestat_get(&wasi->uvw_, fd, &stats);
+
+ if (err == UVWASI_ESUCCESS) {
+ wasi->writeUInt64(memory, stats.st_dev, buf);
+ wasi->writeUInt64(memory, stats.st_ino, buf + 8);
+ wasi->writeUInt8(memory, stats.st_filetype, buf + 16);
+ wasi->writeUInt32(memory, stats.st_nlink, buf + 20);
+ wasi->writeUInt64(memory, stats.st_size, buf + 24);
+ wasi->writeUInt64(memory, stats.st_atim, buf + 32);
+ wasi->writeUInt64(memory, stats.st_mtim, buf + 40);
+ wasi->writeUInt64(memory, stats.st_ctim, buf + 48);
+ }
+
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdFilestatSetSize(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint64_t st_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 2);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, st_size);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "fd_filestat_set_size(%d, %d)\n", fd, st_size);
+ uvwasi_errno_t err = uvwasi_fd_filestat_set_size(&wasi->uvw_, fd, st_size);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdFilestatSetTimes(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint64_t st_atim;
+ uint64_t st_mtim;
+ uint16_t fst_flags;
+ RETURN_IF_BAD_ARG_COUNT(args, 4);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, st_atim);
+ UNWRAP_BIGINT_OR_RETURN(args, args[2], Uint64, st_mtim);
+ CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, fst_flags);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi,
+ "fd_filestat_set_times(%d, %d, %d, %d)\n",
+ fd,
+ st_atim,
+ st_mtim,
+ fst_flags);
+ uvwasi_errno_t err = uvwasi_fd_filestat_set_times(&wasi->uvw_,
+ fd,
+ st_atim,
+ st_mtim,
+ fst_flags);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdPread(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint32_t iovs_ptr;
+ uint32_t iovs_len;
+ uint64_t offset;
+ uint32_t nread_ptr;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 5);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, iovs_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, iovs_len);
+ UNWRAP_BIGINT_OR_RETURN(args, args[3], Uint64, offset);
+ CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, nread_ptr);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi,
+ "uvwasi_fd_pread(%d, %d, %d, %d, %d)\n",
+ fd,
+ iovs_ptr,
+ iovs_len,
+ offset,
+ nread_ptr);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, iovs_ptr, iovs_len * 8);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, nread_ptr, 4);
+ uvwasi_iovec_t* iovs = UncheckedCalloc<uvwasi_iovec_t>(iovs_len);
+
+ 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(memory, &buf_ptr, iovs_ptr);
+ wasi->readUInt32(memory, &buf_len, iovs_ptr + 4);
+
+ if (is_access_oob(mem_size, buf_ptr, buf_len)) {
+ free(iovs);
+ args.GetReturnValue().Set(UVWASI_EOVERFLOW);
+ return;
+ }
+
+ iovs_ptr += 8;
+ iovs[i].buf = static_cast<void*>(&memory[buf_ptr]);
+ iovs[i].buf_len = buf_len;
+ }
+
+ size_t nread;
+ uvwasi_errno_t err = uvwasi_fd_pread(&wasi->uvw_,
+ fd,
+ iovs,
+ iovs_len,
+ offset,
+ &nread);
+ if (err == UVWASI_ESUCCESS)
+ wasi->writeUInt32(memory, nread, nread_ptr);
+
+ free(iovs);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdPrestatGet(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint32_t buf;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 2);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, buf);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "fd_prestat_get(%d, %d)\n", fd, buf);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, buf, 8);
+ uvwasi_prestat_t prestat;
+ uvwasi_errno_t err = uvwasi_fd_prestat_get(&wasi->uvw_, fd, &prestat);
+
+ if (err == UVWASI_ESUCCESS) {
+ wasi->writeUInt32(memory, prestat.pr_type, buf);
+ wasi->writeUInt32(memory, prestat.u.dir.pr_name_len, buf + 4);
+ }
+
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdPrestatDirName(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint32_t path_ptr;
+ uint32_t path_len;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 3);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, path_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_len);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "fd_prestat_dir_name(%d, %d, %d)\n", fd, path_ptr, path_len);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len);
+ uvwasi_errno_t err = uvwasi_fd_prestat_dir_name(&wasi->uvw_,
+ fd,
+ &memory[path_ptr],
+ path_len);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdPwrite(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint32_t iovs_ptr;
+ uint32_t iovs_len;
+ uint64_t offset;
+ uint32_t nwritten_ptr;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 5);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, iovs_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, iovs_len);
+ UNWRAP_BIGINT_OR_RETURN(args, args[3], Uint64, offset);
+ CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, nwritten_ptr);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi,
+ "uvwasi_fd_pwrite(%d, %d, %d, %d, %d)\n",
+ fd,
+ iovs_ptr,
+ iovs_len,
+ offset,
+ nwritten_ptr);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, iovs_ptr, iovs_len * 8);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, nwritten_ptr, 4);
+ uvwasi_ciovec_t* iovs = UncheckedCalloc<uvwasi_ciovec_t>(iovs_len);
+
+ 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(memory, &buf_ptr, iovs_ptr);
+ wasi->readUInt32(memory, &buf_len, iovs_ptr + 4);
+
+ if (is_access_oob(mem_size, buf_ptr, buf_len)) {
+ free(iovs);
+ args.GetReturnValue().Set(UVWASI_EOVERFLOW);
+ return;
+ }
+
+ iovs_ptr += 8;
+ iovs[i].buf = static_cast<void*>(&memory[buf_ptr]);
+ iovs[i].buf_len = buf_len;
+ }
+
+ size_t nwritten;
+ uvwasi_errno_t err = uvwasi_fd_pwrite(&wasi->uvw_,
+ fd,
+ iovs,
+ iovs_len,
+ offset,
+ &nwritten);
+ if (err == UVWASI_ESUCCESS)
+ wasi->writeUInt32(memory, nwritten, nwritten_ptr);
+
+ free(iovs);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdRead(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint32_t iovs_ptr;
+ uint32_t iovs_len;
+ uint32_t nread_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);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, iovs_len);
+ CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, nread_ptr);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "fd_read(%d, %d, %d, %d)\n", fd, iovs_ptr, iovs_len, nread_ptr);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, iovs_ptr, iovs_len * 8);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, nread_ptr, 4);
+ uvwasi_iovec_t* iovs = UncheckedCalloc<uvwasi_iovec_t>(iovs_len);
+
+ 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(memory, &buf_ptr, iovs_ptr);
+ wasi->readUInt32(memory, &buf_len, iovs_ptr + 4);
+
+ if (is_access_oob(mem_size, buf_ptr, buf_len)) {
+ free(iovs);
+ args.GetReturnValue().Set(UVWASI_EOVERFLOW);
+ return;
+ }
+
+ iovs_ptr += 8;
+ iovs[i].buf = static_cast<void*>(&memory[buf_ptr]);
+ iovs[i].buf_len = buf_len;
+ }
+
+ size_t nread;
+ uvwasi_errno_t err = uvwasi_fd_read(&wasi->uvw_,
+ fd,
+ iovs,
+ iovs_len,
+ &nread);
+ if (err == UVWASI_ESUCCESS)
+ wasi->writeUInt32(memory, nread, nread_ptr);
+
+ free(iovs);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdReaddir(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint32_t buf_ptr;
+ uint32_t buf_len;
+ uint64_t cookie;
+ uint32_t bufused_ptr;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 5);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, buf_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, buf_len);
+ UNWRAP_BIGINT_OR_RETURN(args, args[3], Uint64, cookie);
+ CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, bufused_ptr);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi,
+ "uvwasi_fd_readdir(%d, %d, %d, %d, %d)\n",
+ fd,
+ buf_ptr,
+ buf_len,
+ cookie,
+ bufused_ptr);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, buf_ptr, buf_len);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, bufused_ptr, 4);
+ size_t bufused;
+ uvwasi_errno_t err = uvwasi_fd_readdir(&wasi->uvw_,
+ fd,
+ &memory[buf_ptr],
+ buf_len,
+ cookie,
+ &bufused);
+ if (err == UVWASI_ESUCCESS)
+ wasi->writeUInt32(memory, bufused, bufused_ptr);
+
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdRenumber(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t from;
+ uint32_t to;
+ RETURN_IF_BAD_ARG_COUNT(args, 2);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, from);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, to);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "fd_renumber(%d, %d)\n", from, to);
+ uvwasi_errno_t err = uvwasi_fd_renumber(&wasi->uvw_, from, to);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdSeek(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ int64_t offset;
+ uint8_t whence;
+ uint32_t newoffset_ptr;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 4);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ UNWRAP_BIGINT_OR_RETURN(args, args[1], Int64, offset);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, whence);
+ CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, newoffset_ptr);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "fd_seek(%d, %d, %d, %d)\n", fd, offset, whence, newoffset_ptr);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, newoffset_ptr, 8);
+ uvwasi_filesize_t newoffset;
+ uvwasi_errno_t err = uvwasi_fd_seek(&wasi->uvw_,
+ fd,
+ offset,
+ whence,
+ &newoffset);
+ if (err == UVWASI_ESUCCESS)
+ wasi->writeUInt64(memory, newoffset, newoffset_ptr);
+
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdSync(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ RETURN_IF_BAD_ARG_COUNT(args, 1);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "fd_sync(%d)\n", fd);
+ uvwasi_errno_t err = uvwasi_fd_sync(&wasi->uvw_, fd);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdTell(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint32_t offset_ptr;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 2);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, offset_ptr);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "fd_tell(%d, %d)\n", fd, offset_ptr);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, offset_ptr, 8);
+ uvwasi_filesize_t offset;
+ uvwasi_errno_t err = uvwasi_fd_tell(&wasi->uvw_, fd, &offset);
+
+ if (err == UVWASI_ESUCCESS)
+ wasi->writeUInt64(memory, offset, offset_ptr);
+
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::FdWrite(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ 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);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, iovs_len);
+ CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, nwritten_ptr);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi,
+ "fd_write(%d, %d, %d, %d)\n",
+ fd,
+ iovs_ptr,
+ iovs_len,
+ nwritten_ptr);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, iovs_ptr, iovs_len * 8);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, nwritten_ptr, 4);
+ uvwasi_ciovec_t* iovs = UncheckedCalloc<uvwasi_ciovec_t>(iovs_len);
+
+ 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(memory, &buf_ptr, iovs_ptr);
+ wasi->readUInt32(memory, &buf_len, iovs_ptr + 4);
+
+ if (is_access_oob(mem_size, buf_ptr, buf_len)) {
+ free(iovs);
+ args.GetReturnValue().Set(UVWASI_EOVERFLOW);
+ return;
+ }
+
+ iovs_ptr += 8;
+ iovs[i].buf = static_cast<void*>(&memory[buf_ptr]);
+ iovs[i].buf_len = buf_len;
+ }
+
+ size_t nwritten;
+ uvwasi_errno_t err = uvwasi_fd_write(&wasi->uvw_,
+ fd,
+ iovs,
+ iovs_len,
+ &nwritten);
+ if (err == UVWASI_ESUCCESS)
+ wasi->writeUInt32(memory, nwritten, nwritten_ptr);
+
+ free(iovs);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::PathCreateDirectory(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint32_t path_ptr;
+ uint32_t path_len;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 3);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, path_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_len);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "path_create_directory(%d, %d, %d)\n", fd, path_ptr, path_len);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len);
+ uvwasi_errno_t err = uvwasi_path_create_directory(&wasi->uvw_,
+ fd,
+ &memory[path_ptr],
+ path_len);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::PathFilestatGet(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint32_t flags;
+ uint32_t path_ptr;
+ uint32_t path_len;
+ uint32_t buf_ptr;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 5);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, flags);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, path_len);
+ CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, buf_ptr);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi,
+ "path_filestat_get(%d, %d, %d, %d, %d)\n",
+ fd,
+ path_ptr,
+ path_len);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, buf_ptr, 56);
+ uvwasi_filestat_t stats;
+ uvwasi_errno_t err = uvwasi_path_filestat_get(&wasi->uvw_,
+ fd,
+ flags,
+ &memory[path_ptr],
+ path_len,
+ &stats);
+ if (err == UVWASI_ESUCCESS) {
+ wasi->writeUInt64(memory, stats.st_dev, buf_ptr);
+ wasi->writeUInt64(memory, stats.st_ino, buf_ptr + 8);
+ wasi->writeUInt8(memory, stats.st_filetype, buf_ptr + 16);
+ wasi->writeUInt32(memory, stats.st_nlink, buf_ptr + 20);
+ wasi->writeUInt64(memory, stats.st_size, buf_ptr + 24);
+ wasi->writeUInt64(memory, stats.st_atim, buf_ptr + 32);
+ wasi->writeUInt64(memory, stats.st_mtim, buf_ptr + 40);
+ wasi->writeUInt64(memory, stats.st_ctim, buf_ptr + 48);
+ }
+
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::PathFilestatSetTimes(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint32_t flags;
+ uint32_t path_ptr;
+ uint32_t path_len;
+ uint64_t st_atim;
+ uint64_t st_mtim;
+ uint16_t fst_flags;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 7);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, flags);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, path_len);
+ UNWRAP_BIGINT_OR_RETURN(args, args[4], Uint64, st_atim);
+ UNWRAP_BIGINT_OR_RETURN(args, args[5], Uint64, st_mtim);
+ CHECK_TO_TYPE_OR_RETURN(args, args[6], Uint32, fst_flags);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi,
+ "path_filestat_set_times(%d, %d, %d, %d, %d, %d, %d)\n",
+ fd,
+ flags,
+ path_ptr,
+ path_len,
+ st_atim,
+ st_mtim,
+ fst_flags);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len);
+ uvwasi_errno_t err = uvwasi_path_filestat_set_times(&wasi->uvw_,
+ fd,
+ flags,
+ &memory[path_ptr],
+ path_len,
+ st_atim,
+ st_mtim,
+ fst_flags);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::PathLink(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t old_fd;
+ uint32_t old_flags;
+ uint32_t old_path_ptr;
+ uint32_t old_path_len;
+ uint32_t new_fd;
+ uint32_t new_path_ptr;
+ uint32_t new_path_len;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 7);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, old_fd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, old_flags);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, old_path_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, old_path_len);
+ CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, new_fd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[5], Uint32, new_path_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[6], Uint32, new_path_len);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi,
+ "path_link(%d, %d, %d, %d, %d, %d, %d)\n",
+ old_fd,
+ old_flags,
+ old_path_ptr,
+ old_path_len,
+ new_fd,
+ new_path_ptr,
+ new_path_len);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, old_path_ptr, old_path_len);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, new_path_ptr, new_path_len);
+ uvwasi_errno_t err = uvwasi_path_link(&wasi->uvw_,
+ old_fd,
+ old_flags,
+ &memory[old_path_ptr],
+ old_path_len,
+ new_fd,
+ &memory[new_path_ptr],
+ new_path_len);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::PathOpen(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t dirfd;
+ uint32_t dirflags;
+ uint32_t path_ptr;
+ uint32_t path_len;
+ uint32_t o_flags;
+ uint64_t fs_rights_base;
+ uint64_t fs_rights_inheriting;
+ uint32_t fs_flags;
+ uint32_t fd_ptr;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 9);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, dirfd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, dirflags);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, path_len);
+ CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, o_flags);
+ UNWRAP_BIGINT_OR_RETURN(args, args[5], Uint64, fs_rights_base);
+ UNWRAP_BIGINT_OR_RETURN(args, args[6], Uint64, fs_rights_inheriting);
+ CHECK_TO_TYPE_OR_RETURN(args, args[7], Uint32, fs_flags);
+ CHECK_TO_TYPE_OR_RETURN(args, args[8], Uint32, fd_ptr);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi,
+ "path_open(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n",
+ dirfd,
+ dirflags,
+ path_ptr,
+ path_len,
+ o_flags,
+ fs_rights_base,
+ fs_rights_inheriting,
+ fs_flags,
+ fd_ptr);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, fd_ptr, 4);
+ uvwasi_fd_t fd;
+ uvwasi_errno_t err = uvwasi_path_open(&wasi->uvw_,
+ dirfd,
+ dirflags,
+ &memory[path_ptr],
+ path_len,
+ static_cast<uvwasi_oflags_t>(o_flags),
+ fs_rights_base,
+ fs_rights_inheriting,
+ static_cast<uvwasi_fdflags_t>(fs_flags),
+ &fd);
+ if (err == UVWASI_ESUCCESS)
+ wasi->writeUInt32(memory, fd, fd_ptr);
+
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::PathReadlink(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint32_t path_ptr;
+ uint32_t path_len;
+ uint32_t buf_ptr;
+ uint32_t buf_len;
+ uint32_t bufused_ptr;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 6);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, path_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_len);
+ CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, buf_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, buf_len);
+ CHECK_TO_TYPE_OR_RETURN(args, args[5], Uint32, bufused_ptr);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi,
+ "path_readlink(%d, %d, %d, %d, %d, %d)\n",
+ fd,
+ path_ptr,
+ path_len,
+ buf_ptr,
+ buf_len,
+ bufused_ptr);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, buf_ptr, buf_len);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, bufused_ptr, 4);
+ size_t bufused;
+ uvwasi_errno_t err = uvwasi_path_readlink(&wasi->uvw_,
+ fd,
+ &memory[path_ptr],
+ path_len,
+ &memory[buf_ptr],
+ buf_len,
+ &bufused);
+ if (err == UVWASI_ESUCCESS)
+ wasi->writeUInt32(memory, bufused, bufused_ptr);
+
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::PathRemoveDirectory(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint32_t path_ptr;
+ uint32_t path_len;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 3);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, path_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_len);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "path_remove_directory(%d, %d, %d)\n", fd, path_ptr, path_len);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len);
+ uvwasi_errno_t err = uvwasi_path_remove_directory(&wasi->uvw_,
+ fd,
+ &memory[path_ptr],
+ path_len);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::PathRename(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t old_fd;
+ uint32_t old_path_ptr;
+ uint32_t old_path_len;
+ uint32_t new_fd;
+ uint32_t new_path_ptr;
+ uint32_t new_path_len;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 6);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, old_fd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, old_path_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, old_path_len);
+ CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, new_fd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, new_path_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[5], Uint32, new_path_len);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi,
+ "path_rename(%d, %d, %d, %d, %d, %d)\n",
+ old_fd,
+ old_path_ptr,
+ old_path_len,
+ new_fd,
+ new_path_ptr,
+ new_path_len);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, old_path_ptr, old_path_len);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, new_path_ptr, new_path_len);
+ uvwasi_errno_t err = uvwasi_path_rename(&wasi->uvw_,
+ old_fd,
+ &memory[old_path_ptr],
+ old_path_len,
+ new_fd,
+ &memory[new_path_ptr],
+ new_path_len);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::PathSymlink(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t old_path_ptr;
+ uint32_t old_path_len;
+ uint32_t fd;
+ uint32_t new_path_ptr;
+ uint32_t new_path_len;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 5);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, old_path_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, old_path_len);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, fd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, new_path_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, new_path_len);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi,
+ "path_symlink(%d, %d, %d, %d, %d)\n",
+ old_path_ptr,
+ old_path_len,
+ fd,
+ new_path_ptr,
+ new_path_len);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, old_path_ptr, old_path_len);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, new_path_ptr, new_path_len);
+ uvwasi_errno_t err = uvwasi_path_symlink(&wasi->uvw_,
+ &memory[old_path_ptr],
+ old_path_len,
+ fd,
+ &memory[new_path_ptr],
+ new_path_len);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::PathUnlinkFile(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t fd;
+ uint32_t path_ptr;
+ uint32_t path_len;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 3);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, path_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_len);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "path_unlink_file(%d, %d, %d)\n", fd, path_ptr, path_len);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len);
+ uvwasi_errno_t err = uvwasi_path_unlink_file(&wasi->uvw_,
+ fd,
+ &memory[path_ptr],
+ path_len);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::PollOneoff(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t in_ptr;
+ uint32_t out_ptr;
+ uint32_t nsubscriptions;
+ uint32_t nevents_ptr;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 4);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, in_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, out_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, nsubscriptions);
+ CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, nevents_ptr);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi,
+ "poll_oneoff(%d, %d, %d, %d)\n",
+ in_ptr,
+ out_ptr,
+ nsubscriptions,
+ nevents_ptr);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, in_ptr, nsubscriptions * 56);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, out_ptr, nsubscriptions * 32);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, nevents_ptr, 4);
+ uvwasi_subscription_t* in =
+ UncheckedCalloc<uvwasi_subscription_t>(nsubscriptions);
+
+ if (in == nullptr) {
+ args.GetReturnValue().Set(UVWASI_ENOMEM);
+ return;
+ }
+
+ uvwasi_event_t* out = UncheckedCalloc<uvwasi_event_t>(nsubscriptions);
+
+ if (out == nullptr) {
+ free(in);
+ args.GetReturnValue().Set(UVWASI_ENOMEM);
+ return;
+ }
+
+ for (uint32_t i = 0; i < nsubscriptions; ++i) {
+ uvwasi_subscription_t sub = in[i];
+ wasi->readUInt64(memory, &sub.userdata, in_ptr);
+ wasi->readUInt8(memory, &sub.type, in_ptr + 8);
+
+ if (sub.type == UVWASI_EVENTTYPE_CLOCK) {
+ wasi->readUInt64(memory, &sub.u.clock.identifier, in_ptr + 16);
+ wasi->readUInt32(memory, &sub.u.clock.clock_id, in_ptr + 24);
+ wasi->readUInt64(memory, &sub.u.clock.timeout, in_ptr + 32);
+ wasi->readUInt64(memory, &sub.u.clock.precision, in_ptr + 40);
+ wasi->readUInt16(memory, &sub.u.clock.flags, in_ptr + 48);
+ } else if (sub.type == UVWASI_EVENTTYPE_FD_READ ||
+ sub.type == UVWASI_EVENTTYPE_FD_WRITE) {
+ wasi->readUInt32(memory, &sub.u.fd_readwrite.fd, in_ptr + 16);
+ }
+
+ in_ptr += 56;
+ }
+
+ size_t nevents;
+ uvwasi_errno_t err = uvwasi_poll_oneoff(&wasi->uvw_,
+ in,
+ out,
+ nsubscriptions,
+ &nevents);
+ if (err == UVWASI_ESUCCESS) {
+ wasi->writeUInt32(memory, nevents, nevents_ptr);
+
+ for (uint32_t i = 0; i < nsubscriptions; ++i) {
+ uvwasi_event_t event = out[i];
+
+ wasi->writeUInt64(memory, event.userdata, out_ptr);
+ wasi->writeUInt16(memory, event.error, out_ptr + 8);
+ wasi->writeUInt8(memory, event.type, out_ptr + 10);
+
+ if (event.type == UVWASI_EVENTTYPE_FD_READ ||
+ event.type == UVWASI_EVENTTYPE_FD_WRITE) {
+ wasi->writeUInt64(memory, event.u.fd_readwrite.nbytes, out_ptr + 16);
+ wasi->writeUInt16(memory, event.u.fd_readwrite.flags, out_ptr + 24);
+ }
+
+ out_ptr += 32;
+ }
+ }
+
+ free(in);
+ free(out);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::ProcExit(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t code;
+ RETURN_IF_BAD_ARG_COUNT(args, 1);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, code);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "proc_exit(%d)\n", code);
+ args.GetReturnValue().Set(uvwasi_proc_exit(&wasi->uvw_, code));
+}
+
+
+void WASI::ProcRaise(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t sig;
+ RETURN_IF_BAD_ARG_COUNT(args, 1);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, sig);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "proc_raise(%d)\n", sig);
+ uvwasi_errno_t err = uvwasi_proc_raise(&wasi->uvw_, sig);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::RandomGet(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t buf_ptr;
+ uint32_t buf_len;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 2);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, buf_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, buf_len);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "random_get(%d, %d)\n", buf_ptr, buf_len);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, buf_ptr, buf_len);
+ uvwasi_errno_t err = uvwasi_random_get(&wasi->uvw_,
+ &memory[buf_ptr],
+ buf_len);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::SchedYield(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ RETURN_IF_BAD_ARG_COUNT(args, 0);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "sched_yield()\n");
+ uvwasi_errno_t err = uvwasi_sched_yield(&wasi->uvw_);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::SockRecv(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t sock;
+ uint32_t ri_data_ptr;
+ uint32_t ri_data_len;
+ uint16_t ri_flags;
+ uint32_t ro_datalen_ptr;
+ uint16_t ro_flags_ptr;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 6);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, sock);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, ri_data_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, ri_data_len);
+ CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, ri_flags);
+ CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, ro_datalen_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[5], Uint32, ro_flags_ptr);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi,
+ "sock_recv(%d, %d, %d, %d, %d, %d)\n",
+ sock,
+ ri_data_ptr,
+ ri_data_len,
+ ri_flags,
+ ro_datalen_ptr,
+ ro_flags_ptr);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, ri_data_ptr, ri_data_len * 8);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, ro_datalen_ptr, 4);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, ro_flags_ptr, 4);
+ uvwasi_iovec_t* ri_data = UncheckedCalloc<uvwasi_iovec_t>(ri_data_len);
+
+ if (ri_data == nullptr) {
+ args.GetReturnValue().Set(UVWASI_ENOMEM);
+ return;
+ }
+
+ for (uint32_t i = 0; i < ri_data_len; ++i) {
+ uint32_t buf_ptr;
+ uint32_t buf_len;
+
+ wasi->readUInt32(memory, &buf_ptr, ri_data_ptr);
+ wasi->readUInt32(memory, &buf_len, ri_data_ptr + 4);
+
+ if (is_access_oob(mem_size, buf_ptr, buf_len)) {
+ free(ri_data);
+ args.GetReturnValue().Set(UVWASI_EOVERFLOW);
+ return;
+ }
+
+ ri_data_ptr += 8;
+ ri_data[i].buf = static_cast<void*>(&memory[buf_ptr]);
+ ri_data[i].buf_len = buf_len;
+ }
+
+ size_t ro_datalen;
+ uvwasi_roflags_t ro_flags;
+ uvwasi_errno_t err = uvwasi_sock_recv(&wasi->uvw_,
+ sock,
+ ri_data,
+ ri_data_len,
+ ri_flags,
+ &ro_datalen,
+ &ro_flags);
+ if (err == UVWASI_ESUCCESS) {
+ wasi->writeUInt32(memory, ro_datalen, ro_datalen_ptr);
+ wasi->writeUInt32(memory, ro_flags, ro_flags_ptr);
+ }
+
+ free(ri_data);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::SockSend(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t sock;
+ uint32_t si_data_ptr;
+ uint32_t si_data_len;
+ uint16_t si_flags;
+ uint32_t so_datalen_ptr;
+ char* memory;
+ size_t mem_size;
+ RETURN_IF_BAD_ARG_COUNT(args, 5);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, sock);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, si_data_ptr);
+ CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, si_data_len);
+ CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, si_flags);
+ CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, so_datalen_ptr);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi,
+ "sock_send(%d, %d, %d, %d, %d)\n",
+ sock,
+ si_data_ptr,
+ si_data_len,
+ si_flags,
+ so_datalen_ptr);
+ GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, si_data_ptr, si_data_len * 8);
+ CHECK_BOUNDS_OR_RETURN(args, mem_size, so_datalen_ptr, 4);
+ uvwasi_ciovec_t* si_data = UncheckedCalloc<uvwasi_ciovec_t>(si_data_len);
+
+ if (si_data == nullptr) {
+ args.GetReturnValue().Set(UVWASI_ENOMEM);
+ return;
+ }
+
+ for (uint32_t i = 0; i < si_data_len; ++i) {
+ uint32_t buf_ptr;
+ uint32_t buf_len;
+
+ wasi->readUInt32(memory, &buf_ptr, si_data_ptr);
+ wasi->readUInt32(memory, &buf_len, si_data_ptr + 4);
+
+ if (is_access_oob(mem_size, buf_ptr, buf_len)) {
+ free(si_data);
+ args.GetReturnValue().Set(UVWASI_EOVERFLOW);
+ return;
+ }
+
+ si_data_ptr += 8;
+ si_data[i].buf = static_cast<void*>(&memory[buf_ptr]);
+ si_data[i].buf_len = buf_len;
+ }
+
+ size_t so_datalen;
+ uvwasi_errno_t err = uvwasi_sock_send(&wasi->uvw_,
+ sock,
+ si_data,
+ si_data_len,
+ si_flags,
+ &so_datalen);
+ if (err == UVWASI_ESUCCESS)
+ wasi->writeUInt32(memory, so_datalen, so_datalen_ptr);
+
+ free(si_data);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::SockShutdown(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ uint32_t sock;
+ uint8_t how;
+ RETURN_IF_BAD_ARG_COUNT(args, 2);
+ CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, sock);
+ CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, how);
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ Debug(wasi, "sock_shutdown(%d, %d)\n", sock, how);
+ uvwasi_errno_t err = uvwasi_sock_shutdown(&wasi->uvw_, sock, how);
+ args.GetReturnValue().Set(err);
+}
+
+
+void WASI::_SetMemory(const FunctionCallbackInfo<Value>& args) {
+ WASI* wasi;
+ CHECK_EQ(args.Length(), 1);
+ CHECK(args[0]->IsObject());
+ ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
+ wasi->memory_.Reset(wasi->env()->isolate(), args[0].As<Object>());
+}
+
+
+void WASI::readUInt8(char* memory, uint8_t* value, uint32_t offset) {
+ CHECK_NOT_NULL(memory);
+ CHECK_NOT_NULL(value);
+ *value = memory[offset] & 0xFF;
+}
+
+
+void WASI::readUInt16(char* memory, uint16_t* value, uint32_t offset) {
+ CHECK_NOT_NULL(memory);
+ CHECK_NOT_NULL(value);
+ *value = (memory[offset] & 0xFF) |
+ ((memory[offset + 1] & 0xFF) << 8);
+}
+
+
+void WASI::readUInt32(char* memory, uint32_t* value, uint32_t offset) {
+ CHECK_NOT_NULL(memory);
+ CHECK_NOT_NULL(value);
+ *value = (memory[offset] & 0xFF) |
+ ((memory[offset + 1] & 0xFF) << 8) |
+ ((memory[offset + 2] & 0xFF) << 16) |
+ ((memory[offset + 3] & 0xFF) << 24);
+}
+
+
+void WASI::readUInt64(char* memory, uint64_t* value, uint32_t offset) {
+ CHECK_NOT_NULL(memory);
+ CHECK_NOT_NULL(value);
+ uint64_t low = (memory[offset] & 0xFF) |
+ ((memory[offset + 1] & 0xFF) << 8) |
+ ((memory[offset + 2] & 0xFF) << 16) |
+ ((memory[offset + 3] & 0xFF) << 24);
+ uint64_t high = (memory[offset + 4] & 0xFF) |
+ ((memory[offset + 5] & 0xFF) << 8) |
+ ((memory[offset + 6] & 0xFF) << 16) |
+ ((memory[offset + 7] & 0xFF) << 24);
+ *value = (high << 32) + low;
+}
+
+
+void WASI::writeUInt8(char* memory, uint8_t value, uint32_t offset) {
+ CHECK_NOT_NULL(memory);
+ memory[offset] = value & 0xFF;
+}
+
+
+void WASI::writeUInt16(char* memory, uint16_t value, uint32_t offset) {
+ CHECK_NOT_NULL(memory);
+ memory[offset++] = value & 0xFF;
+ memory[offset] = (value >> 8) & 0xFF;
+}
+
+
+void WASI::writeUInt32(char* memory, uint32_t value, uint32_t offset) {
+ CHECK_NOT_NULL(memory);
+ memory[offset++] = value & 0xFF;
+ memory[offset++] = (value >> 8) & 0xFF;
+ memory[offset++] = (value >> 16) & 0xFF;
+ memory[offset] = (value >> 24) & 0xFF;
+}
+
+
+void WASI::writeUInt64(char* memory, uint64_t value, uint32_t offset) {
+ CHECK_NOT_NULL(memory);
+ memory[offset++] = value & 0xFF;
+ memory[offset++] = (value >> 8) & 0xFF;
+ memory[offset++] = (value >> 16) & 0xFF;
+ memory[offset++] = (value >> 24) & 0xFF;
+ memory[offset++] = (value >> 32) & 0xFF;
+ memory[offset++] = (value >> 40) & 0xFF;
+ memory[offset++] = (value >> 48) & 0xFF;
+ memory[offset] = (value >> 56) & 0xFF;
+}
+
+
+uvwasi_errno_t WASI::backingStore(char** store, size_t* byte_length) {
+ Environment* env = this->env();
+ Local<Object> memory = PersistentToLocal::Strong(this->memory_);
+ Local<Value> prop;
+
+ if (!memory->Get(env->context(), env->buffer_string()).ToLocal(&prop))
+ return UVWASI_EINVAL;
+
+ if (!prop->IsArrayBuffer())
+ return UVWASI_EINVAL;
+
+ Local<ArrayBuffer> ab = prop.As<ArrayBuffer>();
+ std::shared_ptr<BackingStore> backing_store = ab->GetBackingStore();
+ *byte_length = backing_store->ByteLength();
+ *store = static_cast<char*>(backing_store->Data());
+ return UVWASI_ESUCCESS;
+}
+
+
+static void Initialize(Local<Object> target,
+ Local<Value> unused,
+ Local<Context> context,
+ void* priv) {
+ Environment* env = Environment::GetCurrent(context);
+
+ Local<FunctionTemplate> tmpl = env->NewFunctionTemplate(WASI::New);
+ auto wasi_wrap_string = FIXED_ONE_BYTE_STRING(env->isolate(), "WASI");
+ tmpl->InstanceTemplate()->SetInternalFieldCount(1);
+ tmpl->SetClassName(wasi_wrap_string);
+
+ env->SetProtoMethod(tmpl, "args_get", WASI::ArgsGet);
+ env->SetProtoMethod(tmpl, "args_sizes_get", WASI::ArgsSizesGet);
+ env->SetProtoMethod(tmpl, "clock_res_get", WASI::ClockResGet);
+ env->SetProtoMethod(tmpl, "clock_time_get", WASI::ClockTimeGet);
+ env->SetProtoMethod(tmpl, "environ_get", WASI::EnvironGet);
+ env->SetProtoMethod(tmpl, "environ_sizes_get", WASI::EnvironSizesGet);
+ env->SetProtoMethod(tmpl, "fd_advise", WASI::FdAdvise);
+ env->SetProtoMethod(tmpl, "fd_allocate", WASI::FdAllocate);
+ env->SetProtoMethod(tmpl, "fd_close", WASI::FdClose);
+ env->SetProtoMethod(tmpl, "fd_datasync", WASI::FdDatasync);
+ env->SetProtoMethod(tmpl, "fd_fdstat_get", WASI::FdFdstatGet);
+ env->SetProtoMethod(tmpl, "fd_fdstat_set_flags", WASI::FdFdstatSetFlags);
+ env->SetProtoMethod(tmpl, "fd_fdstat_set_rights", WASI::FdFdstatSetRights);
+ env->SetProtoMethod(tmpl, "fd_filestat_get", WASI::FdFilestatGet);
+ env->SetProtoMethod(tmpl, "fd_filestat_set_size", WASI::FdFilestatSetSize);
+ env->SetProtoMethod(tmpl, "fd_filestat_set_times", WASI::FdFilestatSetTimes);
+ env->SetProtoMethod(tmpl, "fd_pread", WASI::FdPread);
+ env->SetProtoMethod(tmpl, "fd_prestat_get", WASI::FdPrestatGet);
+ env->SetProtoMethod(tmpl, "fd_prestat_dir_name", WASI::FdPrestatDirName);
+ env->SetProtoMethod(tmpl, "fd_pwrite", WASI::FdPwrite);
+ env->SetProtoMethod(tmpl, "fd_read", WASI::FdRead);
+ env->SetProtoMethod(tmpl, "fd_readdir", WASI::FdReaddir);
+ env->SetProtoMethod(tmpl, "fd_renumber", WASI::FdRenumber);
+ env->SetProtoMethod(tmpl, "fd_seek", WASI::FdSeek);
+ env->SetProtoMethod(tmpl, "fd_sync", WASI::FdSync);
+ env->SetProtoMethod(tmpl, "fd_tell", WASI::FdTell);
+ env->SetProtoMethod(tmpl, "fd_write", WASI::FdWrite);
+ env->SetProtoMethod(tmpl, "path_create_directory", WASI::PathCreateDirectory);
+ env->SetProtoMethod(tmpl, "path_filestat_get", WASI::PathFilestatGet);
+ env->SetProtoMethod(tmpl,
+ "path_filestat_set_times",
+ WASI::PathFilestatSetTimes);
+ env->SetProtoMethod(tmpl, "path_link", WASI::PathLink);
+ env->SetProtoMethod(tmpl, "path_open", WASI::PathOpen);
+ env->SetProtoMethod(tmpl, "path_readlink", WASI::PathReadlink);
+ env->SetProtoMethod(tmpl, "path_remove_directory", WASI::PathRemoveDirectory);
+ env->SetProtoMethod(tmpl, "path_rename", WASI::PathRename);
+ env->SetProtoMethod(tmpl, "path_symlink", WASI::PathSymlink);
+ env->SetProtoMethod(tmpl, "path_unlink_file", WASI::PathUnlinkFile);
+ env->SetProtoMethod(tmpl, "poll_oneoff", WASI::PollOneoff);
+ env->SetProtoMethod(tmpl, "proc_exit", WASI::ProcExit);
+ env->SetProtoMethod(tmpl, "proc_raise", WASI::ProcRaise);
+ env->SetProtoMethod(tmpl, "random_get", WASI::RandomGet);
+ env->SetProtoMethod(tmpl, "sched_yield", WASI::SchedYield);
+ env->SetProtoMethod(tmpl, "sock_recv", WASI::SockRecv);
+ env->SetProtoMethod(tmpl, "sock_send", WASI::SockSend);
+ env->SetProtoMethod(tmpl, "sock_shutdown", WASI::SockShutdown);
+
+ env->SetInstanceMethod(tmpl, "_setMemory", WASI::_SetMemory);
+
+ target->Set(env->context(),
+ wasi_wrap_string,
+ tmpl->GetFunction(context).ToLocalChecked()).ToChecked();
+}
+
+
+} // namespace wasi
+} // namespace node
+
+NODE_MODULE_CONTEXT_AWARE_INTERNAL(wasi, node::wasi::Initialize)
diff --git a/src/node_wasi.h b/src/node_wasi.h
new file mode 100644
index 0000000000..ca726e48a4
--- /dev/null
+++ b/src/node_wasi.h
@@ -0,0 +1,103 @@
+#ifndef SRC_NODE_WASI_H_
+#define SRC_NODE_WASI_H_
+
+#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
+
+#include "base_object.h"
+#include "memory_tracker-inl.h"
+#include "uvwasi.h"
+
+namespace node {
+namespace wasi {
+
+
+class WASI : public BaseObject {
+ public:
+ WASI(Environment* env,
+ v8::Local<v8::Object> object,
+ uvwasi_options_t* options);
+ static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
+ void MemoryInfo(MemoryTracker* tracker) const override {
+ /* TODO(cjihrig): Get memory consumption from uvwasi. */
+ tracker->TrackField("memory", memory_);
+ }
+
+ SET_MEMORY_INFO_NAME(WASI)
+ SET_SELF_SIZE(WASI)
+
+ static void ArgsGet(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void ArgsSizesGet(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void ClockResGet(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void ClockTimeGet(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void EnvironGet(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void EnvironSizesGet(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdAdvise(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdAllocate(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdClose(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdDatasync(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdFdstatGet(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdFdstatSetFlags(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdFdstatSetRights(
+ const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdFilestatGet(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdFilestatSetSize(
+ const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdFilestatSetTimes(
+ const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdPread(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdPrestatGet(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdPrestatDirName(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdPwrite(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdRead(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdReaddir(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdRenumber(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdSeek(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdSync(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdTell(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void FdWrite(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void PathCreateDirectory(
+ const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void PathFilestatGet(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void PathFilestatSetTimes(
+ const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void PathLink(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void PathOpen(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void PathReadlink(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void PathRemoveDirectory(
+ const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void PathRename(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void PathSymlink(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void PathUnlinkFile(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void PollOneoff(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void ProcExit(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void ProcRaise(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void RandomGet(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void SchedYield(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void SockRecv(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void SockSend(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void SockShutdown(const v8::FunctionCallbackInfo<v8::Value>& args);
+
+ static void _SetMemory(const v8::FunctionCallbackInfo<v8::Value>& args);
+
+ private:
+ ~WASI() override;
+ inline void readUInt8(char* memory, uint8_t* value, uint32_t offset);
+ inline void readUInt16(char* memory, uint16_t* value, uint32_t offset);
+ inline void readUInt32(char* memory, uint32_t* value, uint32_t offset);
+ inline void readUInt64(char* memory, uint64_t* value, uint32_t offset);
+ inline void writeUInt8(char* memory, uint8_t value, uint32_t offset);
+ inline void writeUInt16(char* memory, uint16_t value, uint32_t offset);
+ inline void writeUInt32(char* memory, uint32_t value, uint32_t offset);
+ inline void writeUInt64(char* memory, uint64_t value, uint32_t offset);
+ uvwasi_errno_t backingStore(char** store, size_t* byte_length);
+ uvwasi_t uvw_;
+ v8::Global<v8::Object> memory_;
+};
+
+
+} // namespace wasi
+} // namespace node
+
+#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
+
+#endif // SRC_NODE_WASI_H_