• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "env-inl.h"
2 #include "base_object-inl.h"
3 #include "debug_utils-inl.h"
4 #include "memory_tracker-inl.h"
5 #include "node_mem-inl.h"
6 #include "util-inl.h"
7 #include "node.h"
8 #include "node_errors.h"
9 #include "uv.h"
10 #include "uvwasi.h"
11 #include "node_wasi.h"
12 
13 namespace node {
14 namespace wasi {
15 
16 template <typename... Args>
Debug(WASI * wasi,Args &&...args)17 inline void Debug(WASI* wasi, Args&&... args) {
18   Debug(wasi->env(), DebugCategory::WASI, std::forward<Args>(args)...);
19 }
20 
21 #define ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(ptr, obj)                          \
22   do {                                                                         \
23     ASSIGN_OR_RETURN_UNWRAP(ptr, obj);                                         \
24     if ((*(ptr))->memory_.IsEmpty()) {                                         \
25       THROW_ERR_WASI_NOT_STARTED(Environment::GetCurrent(args));               \
26       return;                                                                  \
27     }                                                                          \
28   } while (0)
29 
30 #define RETURN_IF_BAD_ARG_COUNT(args, expected)                               \
31   do {                                                                        \
32     if ((args).Length() != (expected)) {                                      \
33       (args).GetReturnValue().Set(UVWASI_EINVAL);                             \
34       return;                                                                 \
35     }                                                                         \
36   } while (0)
37 
38 #define CHECK_TO_TYPE_OR_RETURN(args, input, type, result)                    \
39   do {                                                                        \
40     if (!(input)->Is##type()) {                                               \
41       (args).GetReturnValue().Set(UVWASI_EINVAL);                             \
42       return;                                                                 \
43     }                                                                         \
44     (result) = (input).As<type>()->Value();                                   \
45   } while (0)
46 
47 #define UNWRAP_BIGINT_OR_RETURN(args, input, type, result)                    \
48   do {                                                                        \
49     if (!(input)->IsBigInt()) {                                               \
50       (args).GetReturnValue().Set(UVWASI_EINVAL);                             \
51       return;                                                                 \
52     }                                                                         \
53     Local<BigInt> js_value = (input).As<BigInt>();                            \
54     bool lossless;                                                            \
55     (result) = js_value->type ## Value(&lossless);                            \
56   } while (0)
57 
58 #define GET_BACKING_STORE_OR_RETURN(wasi, args, mem_ptr, mem_size)            \
59   do {                                                                        \
60     uvwasi_errno_t err = (wasi)->backingStore((mem_ptr), (mem_size));         \
61     if (err != UVWASI_ESUCCESS) {                                             \
62       (args).GetReturnValue().Set(err);                                       \
63       return;                                                                 \
64     }                                                                         \
65   } while (0)
66 
67 #define CHECK_BOUNDS_OR_RETURN(args, mem_size, offset, buf_size)              \
68   do {                                                                        \
69     if (!uvwasi_serdes_check_bounds((offset), (mem_size), (buf_size))) {      \
70       (args).GetReturnValue().Set(UVWASI_EOVERFLOW);                          \
71       return;                                                                 \
72     }                                                                         \
73   } while (0)
74 
75 
76 using v8::Array;
77 using v8::ArrayBuffer;
78 using v8::BackingStore;
79 using v8::BigInt;
80 using v8::Context;
81 using v8::Exception;
82 using v8::FunctionCallbackInfo;
83 using v8::FunctionTemplate;
84 using v8::Integer;
85 using v8::Isolate;
86 using v8::Local;
87 using v8::MaybeLocal;
88 using v8::Object;
89 using v8::String;
90 using v8::Uint32;
91 using v8::Value;
92 
93 
WASIException(Local<Context> context,int errorno,const char * syscall)94 static MaybeLocal<Value> WASIException(Local<Context> context,
95                                        int errorno,
96                                        const char* syscall) {
97   Isolate* isolate = context->GetIsolate();
98   Environment* env = Environment::GetCurrent(context);
99   CHECK_NOT_NULL(env);
100   const char* err_name = uvwasi_embedder_err_code_to_string(errorno);
101   Local<String> js_code = OneByteString(isolate, err_name);
102   Local<String> js_syscall = OneByteString(isolate, syscall);
103   Local<String> js_msg = js_code;
104   js_msg =
105       String::Concat(isolate, js_msg, FIXED_ONE_BYTE_STRING(isolate, ", "));
106   js_msg = String::Concat(isolate, js_msg, js_syscall);
107   Local<Object> e;
108   if (!Exception::Error(js_msg)->ToObject(context).ToLocal(&e))
109     return MaybeLocal<Value>();
110 
111   if (e->Set(context,
112              env->errno_string(),
113              Integer::New(isolate, errorno)).IsNothing() ||
114       e->Set(context, env->code_string(), js_code).IsNothing() ||
115       e->Set(context, env->syscall_string(), js_syscall).IsNothing()) {
116     return MaybeLocal<Value>();
117   }
118 
119   return e;
120 }
121 
122 
WASI(Environment * env,Local<Object> object,uvwasi_options_t * options)123 WASI::WASI(Environment* env,
124            Local<Object> object,
125            uvwasi_options_t* options) : BaseObject(env, object) {
126   MakeWeak();
127   alloc_info_ = MakeAllocator();
128   options->allocator = &alloc_info_;
129   int err = uvwasi_init(&uvw_, options);
130   if (err != UVWASI_ESUCCESS) {
131     Local<Value> exception;
132     if (!WASIException(env->context(), err, "uvwasi_init").ToLocal(&exception))
133       return;
134 
135     env->isolate()->ThrowException(exception);
136   }
137 }
138 
139 
~WASI()140 WASI::~WASI() {
141   uvwasi_destroy(&uvw_);
142   CHECK_EQ(current_uvwasi_memory_, 0);
143 }
144 
MemoryInfo(MemoryTracker * tracker) const145 void WASI::MemoryInfo(MemoryTracker* tracker) const {
146   tracker->TrackField("memory", memory_);
147   tracker->TrackFieldWithSize("uvwasi_memory", current_uvwasi_memory_);
148 }
149 
CheckAllocatedSize(size_t previous_size) const150 void WASI::CheckAllocatedSize(size_t previous_size) const {
151   CHECK_GE(current_uvwasi_memory_, previous_size);
152 }
153 
IncreaseAllocatedSize(size_t size)154 void WASI::IncreaseAllocatedSize(size_t size) {
155   current_uvwasi_memory_ += size;
156 }
157 
DecreaseAllocatedSize(size_t size)158 void WASI::DecreaseAllocatedSize(size_t size) {
159   current_uvwasi_memory_ -= size;
160 }
161 
New(const FunctionCallbackInfo<Value> & args)162 void WASI::New(const FunctionCallbackInfo<Value>& args) {
163   CHECK(args.IsConstructCall());
164   CHECK_EQ(args.Length(), 4);
165   CHECK(args[0]->IsArray());
166   CHECK(args[1]->IsArray());
167   CHECK(args[2]->IsArray());
168   CHECK(args[3]->IsArray());
169 
170   Environment* env = Environment::GetCurrent(args);
171   Local<Context> context = env->context();
172   Local<Array> argv = args[0].As<Array>();
173   const uint32_t argc = argv->Length();
174   uvwasi_options_t options;
175 
176   uvwasi_options_init(&options);
177 
178   Local<Array> stdio = args[3].As<Array>();
179   CHECK_EQ(stdio->Length(), 3);
180   options.in = stdio->Get(context, 0).ToLocalChecked()->
181     Int32Value(context).FromJust();
182   options.out = stdio->Get(context, 1).ToLocalChecked()->
183     Int32Value(context).FromJust();
184   options.err = stdio->Get(context, 2).ToLocalChecked()->
185     Int32Value(context).FromJust();
186 
187   options.fd_table_size = 3;
188   options.argc = argc;
189   options.argv =
190     const_cast<const char**>(argc == 0 ? nullptr : new char*[argc]);
191 
192   for (uint32_t i = 0; i < argc; i++) {
193     auto arg = argv->Get(context, i).ToLocalChecked();
194     CHECK(arg->IsString());
195     node::Utf8Value str(env->isolate(), arg);
196     options.argv[i] = strdup(*str);
197     CHECK_NOT_NULL(options.argv[i]);
198   }
199 
200   Local<Array> env_pairs = args[1].As<Array>();
201   const uint32_t envc = env_pairs->Length();
202   options.envp = const_cast<const char**>(new char*[envc + 1]);
203   for (uint32_t i = 0; i < envc; i++) {
204     auto pair = env_pairs->Get(context, i).ToLocalChecked();
205     CHECK(pair->IsString());
206     node::Utf8Value str(env->isolate(), pair);
207     options.envp[i] = strdup(*str);
208     CHECK_NOT_NULL(options.envp[i]);
209   }
210   options.envp[envc] = nullptr;
211 
212   Local<Array> preopens = args[2].As<Array>();
213   CHECK_EQ(preopens->Length() % 2, 0);
214   options.preopenc = preopens->Length() / 2;
215   options.preopens = Calloc<uvwasi_preopen_t>(options.preopenc);
216   int index = 0;
217   for (uint32_t i = 0; i < preopens->Length(); i += 2) {
218     auto mapped = preopens->Get(context, i).ToLocalChecked();
219     auto real = preopens->Get(context, i + 1).ToLocalChecked();
220     CHECK(mapped->IsString());
221     CHECK(real->IsString());
222     node::Utf8Value mapped_path(env->isolate(), mapped);
223     node::Utf8Value real_path(env->isolate(), real);
224     options.preopens[index].mapped_path = strdup(*mapped_path);
225     CHECK_NOT_NULL(options.preopens[index].mapped_path);
226     options.preopens[index].real_path = strdup(*real_path);
227     CHECK_NOT_NULL(options.preopens[index].real_path);
228     index++;
229   }
230 
231   new WASI(env, args.This(), &options);
232 
233   if (options.argv != nullptr) {
234     for (uint32_t i = 0; i < argc; i++)
235       free(const_cast<char*>(options.argv[i]));
236     delete[] options.argv;
237   }
238 
239   if (options.envp != nullptr) {
240     for (uint32_t i = 0; options.envp[i]; i++)
241       free(const_cast<char*>(options.envp[i]));
242     delete[] options.envp;
243   }
244 
245   if (options.preopens != nullptr) {
246     for (uint32_t i = 0; i < options.preopenc; i++) {
247       free(const_cast<char*>(options.preopens[i].mapped_path));
248       free(const_cast<char*>(options.preopens[i].real_path));
249     }
250 
251     free(options.preopens);
252   }
253 }
254 
255 
ArgsGet(const FunctionCallbackInfo<Value> & args)256 void WASI::ArgsGet(const FunctionCallbackInfo<Value>& args) {
257   WASI* wasi;
258   uint32_t argv_offset;
259   uint32_t argv_buf_offset;
260   char* memory;
261   size_t mem_size;
262   RETURN_IF_BAD_ARG_COUNT(args, 2);
263   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, argv_offset);
264   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, argv_buf_offset);
265   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
266   Debug(wasi, "args_get(%d, %d)\n", argv_offset, argv_buf_offset);
267   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
268   CHECK_BOUNDS_OR_RETURN(args,
269                          mem_size,
270                          argv_buf_offset,
271                          wasi->uvw_.argv_buf_size);
272   CHECK_BOUNDS_OR_RETURN(args,
273                          mem_size,
274                          argv_offset,
275                          wasi->uvw_.argc * UVWASI_SERDES_SIZE_uint32_t);
276   std::vector<char*> argv(wasi->uvw_.argc);
277   char* argv_buf = &memory[argv_buf_offset];
278   uvwasi_errno_t err = uvwasi_args_get(&wasi->uvw_, argv.data(), argv_buf);
279 
280   if (err == UVWASI_ESUCCESS) {
281     for (size_t i = 0; i < wasi->uvw_.argc; i++) {
282       uint32_t offset =
283           static_cast<uint32_t>(argv_buf_offset + (argv[i] - argv[0]));
284       uvwasi_serdes_write_uint32_t(memory,
285                                    argv_offset +
286                                    (i * UVWASI_SERDES_SIZE_uint32_t),
287                                    offset);
288     }
289   }
290 
291   args.GetReturnValue().Set(err);
292 }
293 
294 
ArgsSizesGet(const FunctionCallbackInfo<Value> & args)295 void WASI::ArgsSizesGet(const FunctionCallbackInfo<Value>& args) {
296   WASI* wasi;
297   uint32_t argc_offset;
298   uint32_t argv_buf_offset;
299   char* memory;
300   size_t mem_size;
301   RETURN_IF_BAD_ARG_COUNT(args, 2);
302   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, argc_offset);
303   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, argv_buf_offset);
304   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
305   Debug(wasi, "args_sizes_get(%d, %d)\n", argc_offset, argv_buf_offset);
306   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
307   CHECK_BOUNDS_OR_RETURN(args,
308                          mem_size,
309                          argc_offset,
310                          UVWASI_SERDES_SIZE_size_t);
311   CHECK_BOUNDS_OR_RETURN(args,
312                          mem_size,
313                          argv_buf_offset,
314                          UVWASI_SERDES_SIZE_size_t);
315   uvwasi_size_t argc;
316   uvwasi_size_t argv_buf_size;
317   uvwasi_errno_t err = uvwasi_args_sizes_get(&wasi->uvw_,
318                                              &argc,
319                                              &argv_buf_size);
320   if (err == UVWASI_ESUCCESS) {
321     uvwasi_serdes_write_size_t(memory, argc_offset, argc);
322     uvwasi_serdes_write_size_t(memory, argv_buf_offset, argv_buf_size);
323   }
324 
325   args.GetReturnValue().Set(err);
326 }
327 
328 
ClockResGet(const FunctionCallbackInfo<Value> & args)329 void WASI::ClockResGet(const FunctionCallbackInfo<Value>& args) {
330   WASI* wasi;
331   uint32_t clock_id;
332   uint32_t resolution_ptr;
333   char* memory;
334   size_t mem_size;
335   RETURN_IF_BAD_ARG_COUNT(args, 2);
336   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, clock_id);
337   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, resolution_ptr);
338   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
339   Debug(wasi, "clock_res_get(%d, %d)\n", clock_id, resolution_ptr);
340   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
341   CHECK_BOUNDS_OR_RETURN(args,
342                          mem_size,
343                          resolution_ptr,
344                          UVWASI_SERDES_SIZE_timestamp_t);
345   uvwasi_timestamp_t resolution;
346   uvwasi_errno_t err = uvwasi_clock_res_get(&wasi->uvw_,
347                                             clock_id,
348                                             &resolution);
349   if (err == UVWASI_ESUCCESS)
350     uvwasi_serdes_write_timestamp_t(memory, resolution_ptr, resolution);
351 
352   args.GetReturnValue().Set(err);
353 }
354 
355 
ClockTimeGet(const FunctionCallbackInfo<Value> & args)356 void WASI::ClockTimeGet(const FunctionCallbackInfo<Value>& args) {
357   WASI* wasi;
358   uint32_t clock_id;
359   uint64_t precision;
360   uint32_t time_ptr;
361   char* memory;
362   size_t mem_size;
363   RETURN_IF_BAD_ARG_COUNT(args, 3);
364   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, clock_id);
365   UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, precision);
366   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, time_ptr);
367   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
368   Debug(wasi, "clock_time_get(%d, %d, %d)\n", clock_id, precision, time_ptr);
369   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
370   CHECK_BOUNDS_OR_RETURN(args,
371                          mem_size,
372                          time_ptr,
373                          UVWASI_SERDES_SIZE_timestamp_t);
374   uvwasi_timestamp_t time;
375   uvwasi_errno_t err = uvwasi_clock_time_get(&wasi->uvw_,
376                                              clock_id,
377                                              precision,
378                                              &time);
379   if (err == UVWASI_ESUCCESS)
380     uvwasi_serdes_write_timestamp_t(memory, time_ptr, time);
381 
382   args.GetReturnValue().Set(err);
383 }
384 
385 
EnvironGet(const FunctionCallbackInfo<Value> & args)386 void WASI::EnvironGet(const FunctionCallbackInfo<Value>& args) {
387   WASI* wasi;
388   uint32_t environ_offset;
389   uint32_t environ_buf_offset;
390   char* memory;
391   size_t mem_size;
392   RETURN_IF_BAD_ARG_COUNT(args, 2);
393   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, environ_offset);
394   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, environ_buf_offset);
395   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
396   Debug(wasi, "environ_get(%d, %d)\n", environ_offset, environ_buf_offset);
397   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
398   CHECK_BOUNDS_OR_RETURN(args,
399                          mem_size,
400                          environ_buf_offset,
401                          wasi->uvw_.env_buf_size);
402   CHECK_BOUNDS_OR_RETURN(args,
403                          mem_size,
404                          environ_offset,
405                          wasi->uvw_.envc * UVWASI_SERDES_SIZE_uint32_t);
406   std::vector<char*> environment(wasi->uvw_.envc);
407   char* environ_buf = &memory[environ_buf_offset];
408   uvwasi_errno_t err = uvwasi_environ_get(&wasi->uvw_,
409                                           environment.data(),
410                                           environ_buf);
411 
412   if (err == UVWASI_ESUCCESS) {
413     for (size_t i = 0; i < wasi->uvw_.envc; i++) {
414       uint32_t offset = static_cast<uint32_t>(
415           environ_buf_offset + (environment[i] - environment[0]));
416 
417       uvwasi_serdes_write_uint32_t(memory,
418                                    environ_offset +
419                                    (i * UVWASI_SERDES_SIZE_uint32_t),
420                                    offset);
421     }
422   }
423 
424   args.GetReturnValue().Set(err);
425 }
426 
427 
EnvironSizesGet(const FunctionCallbackInfo<Value> & args)428 void WASI::EnvironSizesGet(const FunctionCallbackInfo<Value>& args) {
429   WASI* wasi;
430   uint32_t envc_offset;
431   uint32_t env_buf_offset;
432   char* memory;
433   size_t mem_size;
434   RETURN_IF_BAD_ARG_COUNT(args, 2);
435   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, envc_offset);
436   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, env_buf_offset);
437   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
438   Debug(wasi, "environ_sizes_get(%d, %d)\n", envc_offset, env_buf_offset);
439   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
440   CHECK_BOUNDS_OR_RETURN(args,
441                          mem_size,
442                          envc_offset,
443                          UVWASI_SERDES_SIZE_size_t);
444   CHECK_BOUNDS_OR_RETURN(args,
445                          mem_size,
446                          env_buf_offset,
447                          UVWASI_SERDES_SIZE_size_t);
448   uvwasi_size_t envc;
449   uvwasi_size_t env_buf_size;
450   uvwasi_errno_t err = uvwasi_environ_sizes_get(&wasi->uvw_,
451                                                 &envc,
452                                                 &env_buf_size);
453   if (err == UVWASI_ESUCCESS) {
454     uvwasi_serdes_write_size_t(memory, envc_offset, envc);
455     uvwasi_serdes_write_size_t(memory, env_buf_offset, env_buf_size);
456   }
457 
458   args.GetReturnValue().Set(err);
459 }
460 
461 
FdAdvise(const FunctionCallbackInfo<Value> & args)462 void WASI::FdAdvise(const FunctionCallbackInfo<Value>& args) {
463   WASI* wasi;
464   uint32_t fd;
465   uint64_t offset;
466   uint64_t len;
467   uint8_t advice;
468   RETURN_IF_BAD_ARG_COUNT(args, 4);
469   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
470   UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, offset);
471   UNWRAP_BIGINT_OR_RETURN(args, args[2], Uint64, len);
472   CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, advice);
473   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
474   Debug(wasi, "fd_advise(%d, %d, %d, %d)\n", fd, offset, len, advice);
475   uvwasi_errno_t err = uvwasi_fd_advise(&wasi->uvw_, fd, offset, len, advice);
476   args.GetReturnValue().Set(err);
477 }
478 
479 
FdAllocate(const FunctionCallbackInfo<Value> & args)480 void WASI::FdAllocate(const FunctionCallbackInfo<Value>& args) {
481   WASI* wasi;
482   uint32_t fd;
483   uint64_t offset;
484   uint64_t len;
485   RETURN_IF_BAD_ARG_COUNT(args, 3);
486   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
487   UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, offset);
488   UNWRAP_BIGINT_OR_RETURN(args, args[2], Uint64, len);
489   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
490   Debug(wasi, "fd_allocate(%d, %d, %d)\n", fd, offset, len);
491   uvwasi_errno_t err = uvwasi_fd_allocate(&wasi->uvw_, fd, offset, len);
492   args.GetReturnValue().Set(err);
493 }
494 
495 
FdClose(const FunctionCallbackInfo<Value> & args)496 void WASI::FdClose(const FunctionCallbackInfo<Value>& args) {
497   WASI* wasi;
498   uint32_t fd;
499   RETURN_IF_BAD_ARG_COUNT(args, 1);
500   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
501   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
502   Debug(wasi, "fd_close(%d)\n", fd);
503   uvwasi_errno_t err = uvwasi_fd_close(&wasi->uvw_, fd);
504   args.GetReturnValue().Set(err);
505 }
506 
507 
FdDatasync(const FunctionCallbackInfo<Value> & args)508 void WASI::FdDatasync(const FunctionCallbackInfo<Value>& args) {
509   WASI* wasi;
510   uint32_t fd;
511   RETURN_IF_BAD_ARG_COUNT(args, 1);
512   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
513   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
514   Debug(wasi, "fd_datasync(%d)\n", fd);
515   uvwasi_errno_t err = uvwasi_fd_datasync(&wasi->uvw_, fd);
516   args.GetReturnValue().Set(err);
517 }
518 
519 
FdFdstatGet(const FunctionCallbackInfo<Value> & args)520 void WASI::FdFdstatGet(const FunctionCallbackInfo<Value>& args) {
521   WASI* wasi;
522   uint32_t fd;
523   uint32_t buf;
524   char* memory;
525   size_t mem_size;
526   RETURN_IF_BAD_ARG_COUNT(args, 2);
527   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
528   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, buf);
529   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
530   Debug(wasi, "fd_fdstat_get(%d, %d)\n", fd, buf);
531   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
532   CHECK_BOUNDS_OR_RETURN(args, mem_size, buf, UVWASI_SERDES_SIZE_fdstat_t);
533   uvwasi_fdstat_t stats;
534   uvwasi_errno_t err = uvwasi_fd_fdstat_get(&wasi->uvw_, fd, &stats);
535 
536   if (err == UVWASI_ESUCCESS)
537     uvwasi_serdes_write_fdstat_t(memory, buf, &stats);
538 
539   args.GetReturnValue().Set(err);
540 }
541 
542 
FdFdstatSetFlags(const FunctionCallbackInfo<Value> & args)543 void WASI::FdFdstatSetFlags(const FunctionCallbackInfo<Value>& args) {
544   WASI* wasi;
545   uint32_t fd;
546   uint16_t flags;
547   RETURN_IF_BAD_ARG_COUNT(args, 2);
548   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
549   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, flags);
550   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
551   Debug(wasi, "fd_fdstat_set_flags(%d, %d)\n", fd, flags);
552   uvwasi_errno_t err = uvwasi_fd_fdstat_set_flags(&wasi->uvw_, fd, flags);
553   args.GetReturnValue().Set(err);
554 }
555 
556 
FdFdstatSetRights(const FunctionCallbackInfo<Value> & args)557 void WASI::FdFdstatSetRights(const FunctionCallbackInfo<Value>& args) {
558   WASI* wasi;
559   uint32_t fd;
560   uint64_t fs_rights_base;
561   uint64_t fs_rights_inheriting;
562   RETURN_IF_BAD_ARG_COUNT(args, 3);
563   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
564   UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, fs_rights_base);
565   UNWRAP_BIGINT_OR_RETURN(args, args[2], Uint64, fs_rights_inheriting);
566   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
567   Debug(wasi,
568         "fd_fdstat_set_rights(%d, %d, %d)\n",
569         fd,
570         fs_rights_base,
571         fs_rights_inheriting);
572   uvwasi_errno_t err = uvwasi_fd_fdstat_set_rights(&wasi->uvw_,
573                                                    fd,
574                                                    fs_rights_base,
575                                                    fs_rights_inheriting);
576   args.GetReturnValue().Set(err);
577 }
578 
579 
FdFilestatGet(const FunctionCallbackInfo<Value> & args)580 void WASI::FdFilestatGet(const FunctionCallbackInfo<Value>& args) {
581   WASI* wasi;
582   uint32_t fd;
583   uint32_t buf;
584   char* memory;
585   size_t mem_size;
586   RETURN_IF_BAD_ARG_COUNT(args, 2);
587   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
588   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, buf);
589   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
590   Debug(wasi, "fd_filestat_get(%d, %d)\n", fd, buf);
591   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
592   CHECK_BOUNDS_OR_RETURN(args, mem_size, buf, UVWASI_SERDES_SIZE_filestat_t);
593   uvwasi_filestat_t stats;
594   uvwasi_errno_t err = uvwasi_fd_filestat_get(&wasi->uvw_, fd, &stats);
595 
596   if (err == UVWASI_ESUCCESS)
597     uvwasi_serdes_write_filestat_t(memory, buf, &stats);
598 
599   args.GetReturnValue().Set(err);
600 }
601 
602 
FdFilestatSetSize(const FunctionCallbackInfo<Value> & args)603 void WASI::FdFilestatSetSize(const FunctionCallbackInfo<Value>& args) {
604   WASI* wasi;
605   uint32_t fd;
606   uint64_t st_size;
607   RETURN_IF_BAD_ARG_COUNT(args, 2);
608   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
609   UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, st_size);
610   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
611   Debug(wasi, "fd_filestat_set_size(%d, %d)\n", fd, st_size);
612   uvwasi_errno_t err = uvwasi_fd_filestat_set_size(&wasi->uvw_, fd, st_size);
613   args.GetReturnValue().Set(err);
614 }
615 
616 
FdFilestatSetTimes(const FunctionCallbackInfo<Value> & args)617 void WASI::FdFilestatSetTimes(const FunctionCallbackInfo<Value>& args) {
618   WASI* wasi;
619   uint32_t fd;
620   uint64_t st_atim;
621   uint64_t st_mtim;
622   uint16_t fst_flags;
623   RETURN_IF_BAD_ARG_COUNT(args, 4);
624   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
625   UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, st_atim);
626   UNWRAP_BIGINT_OR_RETURN(args, args[2], Uint64, st_mtim);
627   CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, fst_flags);
628   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
629   Debug(wasi,
630         "fd_filestat_set_times(%d, %d, %d, %d)\n",
631         fd,
632         st_atim,
633         st_mtim,
634         fst_flags);
635   uvwasi_errno_t err = uvwasi_fd_filestat_set_times(&wasi->uvw_,
636                                                     fd,
637                                                     st_atim,
638                                                     st_mtim,
639                                                     fst_flags);
640   args.GetReturnValue().Set(err);
641 }
642 
643 
FdPread(const FunctionCallbackInfo<Value> & args)644 void WASI::FdPread(const FunctionCallbackInfo<Value>& args) {
645   WASI* wasi;
646   uint32_t fd;
647   uint32_t iovs_ptr;
648   uint32_t iovs_len;
649   uint64_t offset;
650   uint32_t nread_ptr;
651   char* memory;
652   size_t mem_size;
653   RETURN_IF_BAD_ARG_COUNT(args, 5);
654   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
655   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, iovs_ptr);
656   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, iovs_len);
657   UNWRAP_BIGINT_OR_RETURN(args, args[3], Uint64, offset);
658   CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, nread_ptr);
659   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
660   Debug(wasi,
661         "uvwasi_fd_pread(%d, %d, %d, %d, %d)\n",
662         fd,
663         iovs_ptr,
664         iovs_len,
665         offset,
666         nread_ptr);
667   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
668   CHECK_BOUNDS_OR_RETURN(args,
669                          mem_size,
670                          iovs_ptr,
671                          iovs_len * UVWASI_SERDES_SIZE_iovec_t);
672   CHECK_BOUNDS_OR_RETURN(args, mem_size, nread_ptr, UVWASI_SERDES_SIZE_size_t);
673   std::vector<uvwasi_iovec_t> iovs(iovs_len);
674   uvwasi_errno_t err;
675 
676   err = uvwasi_serdes_readv_iovec_t(memory,
677                                     mem_size,
678                                     iovs_ptr,
679                                     iovs.data(),
680                                     iovs_len);
681   if (err != UVWASI_ESUCCESS) {
682     args.GetReturnValue().Set(err);
683     return;
684   }
685 
686   uvwasi_size_t nread;
687   err = uvwasi_fd_pread(&wasi->uvw_, fd, iovs.data(), iovs_len, offset, &nread);
688   if (err == UVWASI_ESUCCESS)
689     uvwasi_serdes_write_size_t(memory, nread_ptr, nread);
690 
691   args.GetReturnValue().Set(err);
692 }
693 
694 
FdPrestatGet(const FunctionCallbackInfo<Value> & args)695 void WASI::FdPrestatGet(const FunctionCallbackInfo<Value>& args) {
696   WASI* wasi;
697   uint32_t fd;
698   uint32_t buf;
699   char* memory;
700   size_t mem_size;
701   RETURN_IF_BAD_ARG_COUNT(args, 2);
702   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
703   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, buf);
704   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
705   Debug(wasi, "fd_prestat_get(%d, %d)\n", fd, buf);
706   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
707   CHECK_BOUNDS_OR_RETURN(args, mem_size, buf, UVWASI_SERDES_SIZE_prestat_t);
708   uvwasi_prestat_t prestat;
709   uvwasi_errno_t err = uvwasi_fd_prestat_get(&wasi->uvw_, fd, &prestat);
710 
711   if (err == UVWASI_ESUCCESS)
712     uvwasi_serdes_write_prestat_t(memory, buf, &prestat);
713 
714   args.GetReturnValue().Set(err);
715 }
716 
717 
FdPrestatDirName(const FunctionCallbackInfo<Value> & args)718 void WASI::FdPrestatDirName(const FunctionCallbackInfo<Value>& args) {
719   WASI* wasi;
720   uint32_t fd;
721   uint32_t path_ptr;
722   uint32_t path_len;
723   char* memory;
724   size_t mem_size;
725   RETURN_IF_BAD_ARG_COUNT(args, 3);
726   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
727   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, path_ptr);
728   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_len);
729   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
730   Debug(wasi, "fd_prestat_dir_name(%d, %d, %d)\n", fd, path_ptr, path_len);
731   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
732   CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len);
733   uvwasi_errno_t err = uvwasi_fd_prestat_dir_name(&wasi->uvw_,
734                                                   fd,
735                                                   &memory[path_ptr],
736                                                   path_len);
737   args.GetReturnValue().Set(err);
738 }
739 
740 
FdPwrite(const FunctionCallbackInfo<Value> & args)741 void WASI::FdPwrite(const FunctionCallbackInfo<Value>& args) {
742   WASI* wasi;
743   uint32_t fd;
744   uint32_t iovs_ptr;
745   uint32_t iovs_len;
746   uint64_t offset;
747   uint32_t nwritten_ptr;
748   char* memory;
749   size_t mem_size;
750   RETURN_IF_BAD_ARG_COUNT(args, 5);
751   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
752   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, iovs_ptr);
753   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, iovs_len);
754   UNWRAP_BIGINT_OR_RETURN(args, args[3], Uint64, offset);
755   CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, nwritten_ptr);
756   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
757   Debug(wasi,
758         "uvwasi_fd_pwrite(%d, %d, %d, %d, %d)\n",
759         fd,
760         iovs_ptr,
761         iovs_len,
762         offset,
763         nwritten_ptr);
764   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
765   CHECK_BOUNDS_OR_RETURN(args,
766                          mem_size,
767                          iovs_ptr,
768                          iovs_len * UVWASI_SERDES_SIZE_ciovec_t);
769   CHECK_BOUNDS_OR_RETURN(args,
770                          mem_size,
771                          nwritten_ptr,
772                          UVWASI_SERDES_SIZE_size_t);
773   std::vector<uvwasi_ciovec_t> iovs(iovs_len);
774   uvwasi_errno_t err;
775 
776   err = uvwasi_serdes_readv_ciovec_t(memory,
777                                      mem_size,
778                                      iovs_ptr,
779                                      iovs.data(),
780                                      iovs_len);
781   if (err != UVWASI_ESUCCESS) {
782     args.GetReturnValue().Set(err);
783     return;
784   }
785 
786   uvwasi_size_t nwritten;
787   err = uvwasi_fd_pwrite(&wasi->uvw_,
788                          fd,
789                          iovs.data(),
790                          iovs_len,
791                          offset,
792                          &nwritten);
793   if (err == UVWASI_ESUCCESS)
794     uvwasi_serdes_write_size_t(memory, nwritten_ptr, nwritten);
795 
796   args.GetReturnValue().Set(err);
797 }
798 
799 
FdRead(const FunctionCallbackInfo<Value> & args)800 void WASI::FdRead(const FunctionCallbackInfo<Value>& args) {
801   WASI* wasi;
802   uint32_t fd;
803   uint32_t iovs_ptr;
804   uint32_t iovs_len;
805   uint32_t nread_ptr;
806   char* memory;
807   size_t mem_size;
808   RETURN_IF_BAD_ARG_COUNT(args, 4);
809   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
810   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, iovs_ptr);
811   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, iovs_len);
812   CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, nread_ptr);
813   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
814   Debug(wasi, "fd_read(%d, %d, %d, %d)\n", fd, iovs_ptr, iovs_len, nread_ptr);
815   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
816   CHECK_BOUNDS_OR_RETURN(args,
817                          mem_size,
818                          iovs_ptr,
819                          iovs_len * UVWASI_SERDES_SIZE_iovec_t);
820   CHECK_BOUNDS_OR_RETURN(args, mem_size, nread_ptr, UVWASI_SERDES_SIZE_size_t);
821   std::vector<uvwasi_iovec_t> iovs(iovs_len);
822   uvwasi_errno_t err;
823 
824   err = uvwasi_serdes_readv_iovec_t(memory,
825                                     mem_size,
826                                     iovs_ptr,
827                                     iovs.data(),
828                                     iovs_len);
829   if (err != UVWASI_ESUCCESS) {
830     args.GetReturnValue().Set(err);
831     return;
832   }
833 
834   uvwasi_size_t nread;
835   err = uvwasi_fd_read(&wasi->uvw_, fd, iovs.data(), iovs_len, &nread);
836   if (err == UVWASI_ESUCCESS)
837     uvwasi_serdes_write_size_t(memory, nread_ptr, nread);
838 
839   args.GetReturnValue().Set(err);
840 }
841 
842 
FdReaddir(const FunctionCallbackInfo<Value> & args)843 void WASI::FdReaddir(const FunctionCallbackInfo<Value>& args) {
844   WASI* wasi;
845   uint32_t fd;
846   uint32_t buf_ptr;
847   uint32_t buf_len;
848   uint64_t cookie;
849   uint32_t bufused_ptr;
850   char* memory;
851   size_t mem_size;
852   RETURN_IF_BAD_ARG_COUNT(args, 5);
853   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
854   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, buf_ptr);
855   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, buf_len);
856   UNWRAP_BIGINT_OR_RETURN(args, args[3], Uint64, cookie);
857   CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, bufused_ptr);
858   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
859   Debug(wasi,
860         "uvwasi_fd_readdir(%d, %d, %d, %d, %d)\n",
861         fd,
862         buf_ptr,
863         buf_len,
864         cookie,
865         bufused_ptr);
866   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
867   CHECK_BOUNDS_OR_RETURN(args, mem_size, buf_ptr, buf_len);
868   CHECK_BOUNDS_OR_RETURN(args,
869                          mem_size,
870                          bufused_ptr,
871                          UVWASI_SERDES_SIZE_size_t);
872   uvwasi_size_t bufused;
873   uvwasi_errno_t err = uvwasi_fd_readdir(&wasi->uvw_,
874                                          fd,
875                                          &memory[buf_ptr],
876                                          buf_len,
877                                          cookie,
878                                          &bufused);
879   if (err == UVWASI_ESUCCESS)
880     uvwasi_serdes_write_size_t(memory, bufused_ptr, bufused);
881 
882   args.GetReturnValue().Set(err);
883 }
884 
885 
FdRenumber(const FunctionCallbackInfo<Value> & args)886 void WASI::FdRenumber(const FunctionCallbackInfo<Value>& args) {
887   WASI* wasi;
888   uint32_t from;
889   uint32_t to;
890   RETURN_IF_BAD_ARG_COUNT(args, 2);
891   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, from);
892   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, to);
893   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
894   Debug(wasi, "fd_renumber(%d, %d)\n", from, to);
895   uvwasi_errno_t err = uvwasi_fd_renumber(&wasi->uvw_, from, to);
896   args.GetReturnValue().Set(err);
897 }
898 
899 
FdSeek(const FunctionCallbackInfo<Value> & args)900 void WASI::FdSeek(const FunctionCallbackInfo<Value>& args) {
901   WASI* wasi;
902   uint32_t fd;
903   int64_t offset;
904   uint8_t whence;
905   uint32_t newoffset_ptr;
906   char* memory;
907   size_t mem_size;
908   RETURN_IF_BAD_ARG_COUNT(args, 4);
909   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
910   UNWRAP_BIGINT_OR_RETURN(args, args[1], Int64, offset);
911   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, whence);
912   CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, newoffset_ptr);
913   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
914   Debug(wasi, "fd_seek(%d, %d, %d, %d)\n", fd, offset, whence, newoffset_ptr);
915   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
916   CHECK_BOUNDS_OR_RETURN(args,
917                          mem_size,
918                          newoffset_ptr,
919                          UVWASI_SERDES_SIZE_filesize_t);
920   uvwasi_filesize_t newoffset;
921   uvwasi_errno_t err = uvwasi_fd_seek(&wasi->uvw_,
922                                       fd,
923                                       offset,
924                                       whence,
925                                       &newoffset);
926   if (err == UVWASI_ESUCCESS)
927     uvwasi_serdes_write_filesize_t(memory, newoffset_ptr, newoffset);
928 
929   args.GetReturnValue().Set(err);
930 }
931 
932 
FdSync(const FunctionCallbackInfo<Value> & args)933 void WASI::FdSync(const FunctionCallbackInfo<Value>& args) {
934   WASI* wasi;
935   uint32_t fd;
936   RETURN_IF_BAD_ARG_COUNT(args, 1);
937   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
938   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
939   Debug(wasi, "fd_sync(%d)\n", fd);
940   uvwasi_errno_t err = uvwasi_fd_sync(&wasi->uvw_, fd);
941   args.GetReturnValue().Set(err);
942 }
943 
944 
FdTell(const FunctionCallbackInfo<Value> & args)945 void WASI::FdTell(const FunctionCallbackInfo<Value>& args) {
946   WASI* wasi;
947   uint32_t fd;
948   uint32_t offset_ptr;
949   char* memory;
950   size_t mem_size;
951   RETURN_IF_BAD_ARG_COUNT(args, 2);
952   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
953   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, offset_ptr);
954   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
955   Debug(wasi, "fd_tell(%d, %d)\n", fd, offset_ptr);
956   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
957   CHECK_BOUNDS_OR_RETURN(args,
958                          mem_size,
959                          offset_ptr,
960                          UVWASI_SERDES_SIZE_filesize_t);
961   uvwasi_filesize_t offset;
962   uvwasi_errno_t err = uvwasi_fd_tell(&wasi->uvw_, fd, &offset);
963 
964   if (err == UVWASI_ESUCCESS)
965     uvwasi_serdes_write_filesize_t(memory, offset_ptr, offset);
966 
967   args.GetReturnValue().Set(err);
968 }
969 
970 
FdWrite(const FunctionCallbackInfo<Value> & args)971 void WASI::FdWrite(const FunctionCallbackInfo<Value>& args) {
972   WASI* wasi;
973   uint32_t fd;
974   uint32_t iovs_ptr;
975   uint32_t iovs_len;
976   uint32_t nwritten_ptr;
977   char* memory;
978   size_t mem_size;
979   RETURN_IF_BAD_ARG_COUNT(args, 4);
980   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
981   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, iovs_ptr);
982   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, iovs_len);
983   CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, nwritten_ptr);
984   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
985   Debug(wasi,
986         "fd_write(%d, %d, %d, %d)\n",
987         fd,
988         iovs_ptr,
989         iovs_len,
990         nwritten_ptr);
991   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
992   CHECK_BOUNDS_OR_RETURN(args,
993                          mem_size,
994                          iovs_ptr,
995                          iovs_len * UVWASI_SERDES_SIZE_ciovec_t);
996   CHECK_BOUNDS_OR_RETURN(args,
997                          mem_size,
998                          nwritten_ptr,
999                          UVWASI_SERDES_SIZE_size_t);
1000   std::vector<uvwasi_ciovec_t> iovs(iovs_len);
1001   uvwasi_errno_t err;
1002 
1003   err = uvwasi_serdes_readv_ciovec_t(memory,
1004                                      mem_size,
1005                                      iovs_ptr,
1006                                      iovs.data(),
1007                                      iovs_len);
1008   if (err != UVWASI_ESUCCESS) {
1009     args.GetReturnValue().Set(err);
1010     return;
1011   }
1012 
1013   uvwasi_size_t nwritten;
1014   err = uvwasi_fd_write(&wasi->uvw_, fd, iovs.data(), iovs_len, &nwritten);
1015   if (err == UVWASI_ESUCCESS)
1016     uvwasi_serdes_write_size_t(memory, nwritten_ptr, nwritten);
1017 
1018   args.GetReturnValue().Set(err);
1019 }
1020 
1021 
PathCreateDirectory(const FunctionCallbackInfo<Value> & args)1022 void WASI::PathCreateDirectory(const FunctionCallbackInfo<Value>& args) {
1023   WASI* wasi;
1024   uint32_t fd;
1025   uint32_t path_ptr;
1026   uint32_t path_len;
1027   char* memory;
1028   size_t mem_size;
1029   RETURN_IF_BAD_ARG_COUNT(args, 3);
1030   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
1031   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, path_ptr);
1032   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_len);
1033   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
1034   Debug(wasi, "path_create_directory(%d, %d, %d)\n", fd, path_ptr, path_len);
1035   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
1036   CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len);
1037   uvwasi_errno_t err = uvwasi_path_create_directory(&wasi->uvw_,
1038                                                     fd,
1039                                                     &memory[path_ptr],
1040                                                     path_len);
1041   args.GetReturnValue().Set(err);
1042 }
1043 
1044 
PathFilestatGet(const FunctionCallbackInfo<Value> & args)1045 void WASI::PathFilestatGet(const FunctionCallbackInfo<Value>& args) {
1046   WASI* wasi;
1047   uint32_t fd;
1048   uint32_t flags;
1049   uint32_t path_ptr;
1050   uint32_t path_len;
1051   uint32_t buf_ptr;
1052   char* memory;
1053   size_t mem_size;
1054   RETURN_IF_BAD_ARG_COUNT(args, 5);
1055   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
1056   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, flags);
1057   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_ptr);
1058   CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, path_len);
1059   CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, buf_ptr);
1060   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
1061   Debug(wasi,
1062         "path_filestat_get(%d, %d, %d)\n",
1063         fd,
1064         path_ptr,
1065         path_len);
1066   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
1067   CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len);
1068   CHECK_BOUNDS_OR_RETURN(args,
1069                          mem_size,
1070                          buf_ptr,
1071                          UVWASI_SERDES_SIZE_filestat_t);
1072   uvwasi_filestat_t stats;
1073   uvwasi_errno_t err = uvwasi_path_filestat_get(&wasi->uvw_,
1074                                                 fd,
1075                                                 flags,
1076                                                 &memory[path_ptr],
1077                                                 path_len,
1078                                                 &stats);
1079   if (err == UVWASI_ESUCCESS)
1080     uvwasi_serdes_write_filestat_t(memory, buf_ptr, &stats);
1081 
1082   args.GetReturnValue().Set(err);
1083 }
1084 
1085 
PathFilestatSetTimes(const FunctionCallbackInfo<Value> & args)1086 void WASI::PathFilestatSetTimes(const FunctionCallbackInfo<Value>& args) {
1087   WASI* wasi;
1088   uint32_t fd;
1089   uint32_t flags;
1090   uint32_t path_ptr;
1091   uint32_t path_len;
1092   uint64_t st_atim;
1093   uint64_t st_mtim;
1094   uint16_t fst_flags;
1095   char* memory;
1096   size_t mem_size;
1097   RETURN_IF_BAD_ARG_COUNT(args, 7);
1098   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
1099   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, flags);
1100   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_ptr);
1101   CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, path_len);
1102   UNWRAP_BIGINT_OR_RETURN(args, args[4], Uint64, st_atim);
1103   UNWRAP_BIGINT_OR_RETURN(args, args[5], Uint64, st_mtim);
1104   CHECK_TO_TYPE_OR_RETURN(args, args[6], Uint32, fst_flags);
1105   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
1106   Debug(wasi,
1107         "path_filestat_set_times(%d, %d, %d, %d, %d, %d, %d)\n",
1108         fd,
1109         flags,
1110         path_ptr,
1111         path_len,
1112         st_atim,
1113         st_mtim,
1114         fst_flags);
1115   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
1116   CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len);
1117   uvwasi_errno_t err = uvwasi_path_filestat_set_times(&wasi->uvw_,
1118                                                       fd,
1119                                                       flags,
1120                                                       &memory[path_ptr],
1121                                                       path_len,
1122                                                       st_atim,
1123                                                       st_mtim,
1124                                                       fst_flags);
1125   args.GetReturnValue().Set(err);
1126 }
1127 
1128 
PathLink(const FunctionCallbackInfo<Value> & args)1129 void WASI::PathLink(const FunctionCallbackInfo<Value>& args) {
1130   WASI* wasi;
1131   uint32_t old_fd;
1132   uint32_t old_flags;
1133   uint32_t old_path_ptr;
1134   uint32_t old_path_len;
1135   uint32_t new_fd;
1136   uint32_t new_path_ptr;
1137   uint32_t new_path_len;
1138   char* memory;
1139   size_t mem_size;
1140   RETURN_IF_BAD_ARG_COUNT(args, 7);
1141   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, old_fd);
1142   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, old_flags);
1143   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, old_path_ptr);
1144   CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, old_path_len);
1145   CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, new_fd);
1146   CHECK_TO_TYPE_OR_RETURN(args, args[5], Uint32, new_path_ptr);
1147   CHECK_TO_TYPE_OR_RETURN(args, args[6], Uint32, new_path_len);
1148   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
1149   Debug(wasi,
1150         "path_link(%d, %d, %d, %d, %d, %d, %d)\n",
1151         old_fd,
1152         old_flags,
1153         old_path_ptr,
1154         old_path_len,
1155         new_fd,
1156         new_path_ptr,
1157         new_path_len);
1158   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
1159   CHECK_BOUNDS_OR_RETURN(args, mem_size, old_path_ptr, old_path_len);
1160   CHECK_BOUNDS_OR_RETURN(args, mem_size, new_path_ptr, new_path_len);
1161   uvwasi_errno_t err = uvwasi_path_link(&wasi->uvw_,
1162                                         old_fd,
1163                                         old_flags,
1164                                         &memory[old_path_ptr],
1165                                         old_path_len,
1166                                         new_fd,
1167                                         &memory[new_path_ptr],
1168                                         new_path_len);
1169   args.GetReturnValue().Set(err);
1170 }
1171 
1172 
PathOpen(const FunctionCallbackInfo<Value> & args)1173 void WASI::PathOpen(const FunctionCallbackInfo<Value>& args) {
1174   WASI* wasi;
1175   uint32_t dirfd;
1176   uint32_t dirflags;
1177   uint32_t path_ptr;
1178   uint32_t path_len;
1179   uint32_t o_flags;
1180   uint64_t fs_rights_base;
1181   uint64_t fs_rights_inheriting;
1182   uint32_t fs_flags;
1183   uint32_t fd_ptr;
1184   char* memory;
1185   size_t mem_size;
1186   RETURN_IF_BAD_ARG_COUNT(args, 9);
1187   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, dirfd);
1188   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, dirflags);
1189   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_ptr);
1190   CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, path_len);
1191   CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, o_flags);
1192   UNWRAP_BIGINT_OR_RETURN(args, args[5], Uint64, fs_rights_base);
1193   UNWRAP_BIGINT_OR_RETURN(args, args[6], Uint64, fs_rights_inheriting);
1194   CHECK_TO_TYPE_OR_RETURN(args, args[7], Uint32, fs_flags);
1195   CHECK_TO_TYPE_OR_RETURN(args, args[8], Uint32, fd_ptr);
1196   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
1197   Debug(wasi,
1198         "path_open(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n",
1199         dirfd,
1200         dirflags,
1201         path_ptr,
1202         path_len,
1203         o_flags,
1204         fs_rights_base,
1205         fs_rights_inheriting,
1206         fs_flags,
1207         fd_ptr);
1208   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
1209   CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len);
1210   CHECK_BOUNDS_OR_RETURN(args, mem_size, fd_ptr, UVWASI_SERDES_SIZE_fd_t);
1211   uvwasi_fd_t fd;
1212   uvwasi_errno_t err = uvwasi_path_open(&wasi->uvw_,
1213                                         dirfd,
1214                                         dirflags,
1215                                         &memory[path_ptr],
1216                                         path_len,
1217                                         static_cast<uvwasi_oflags_t>(o_flags),
1218                                         fs_rights_base,
1219                                         fs_rights_inheriting,
1220                                         static_cast<uvwasi_fdflags_t>(fs_flags),
1221                                         &fd);
1222   if (err == UVWASI_ESUCCESS)
1223     uvwasi_serdes_write_size_t(memory, fd_ptr, fd);
1224 
1225   args.GetReturnValue().Set(err);
1226 }
1227 
1228 
PathReadlink(const FunctionCallbackInfo<Value> & args)1229 void WASI::PathReadlink(const FunctionCallbackInfo<Value>& args) {
1230   WASI* wasi;
1231   uint32_t fd;
1232   uint32_t path_ptr;
1233   uint32_t path_len;
1234   uint32_t buf_ptr;
1235   uint32_t buf_len;
1236   uint32_t bufused_ptr;
1237   char* memory;
1238   size_t mem_size;
1239   RETURN_IF_BAD_ARG_COUNT(args, 6);
1240   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
1241   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, path_ptr);
1242   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_len);
1243   CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, buf_ptr);
1244   CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, buf_len);
1245   CHECK_TO_TYPE_OR_RETURN(args, args[5], Uint32, bufused_ptr);
1246   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
1247   Debug(wasi,
1248         "path_readlink(%d, %d, %d, %d, %d, %d)\n",
1249         fd,
1250         path_ptr,
1251         path_len,
1252         buf_ptr,
1253         buf_len,
1254         bufused_ptr);
1255   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
1256   CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len);
1257   CHECK_BOUNDS_OR_RETURN(args, mem_size, buf_ptr, buf_len);
1258   CHECK_BOUNDS_OR_RETURN(args,
1259                          mem_size,
1260                          bufused_ptr,
1261                          UVWASI_SERDES_SIZE_size_t);
1262   uvwasi_size_t bufused;
1263   uvwasi_errno_t err = uvwasi_path_readlink(&wasi->uvw_,
1264                                             fd,
1265                                             &memory[path_ptr],
1266                                             path_len,
1267                                             &memory[buf_ptr],
1268                                             buf_len,
1269                                             &bufused);
1270   if (err == UVWASI_ESUCCESS)
1271     uvwasi_serdes_write_size_t(memory, bufused_ptr, bufused);
1272 
1273   args.GetReturnValue().Set(err);
1274 }
1275 
1276 
PathRemoveDirectory(const FunctionCallbackInfo<Value> & args)1277 void WASI::PathRemoveDirectory(const FunctionCallbackInfo<Value>& args) {
1278   WASI* wasi;
1279   uint32_t fd;
1280   uint32_t path_ptr;
1281   uint32_t path_len;
1282   char* memory;
1283   size_t mem_size;
1284   RETURN_IF_BAD_ARG_COUNT(args, 3);
1285   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
1286   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, path_ptr);
1287   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_len);
1288   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
1289   Debug(wasi, "path_remove_directory(%d, %d, %d)\n", fd, path_ptr, path_len);
1290   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
1291   CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len);
1292   uvwasi_errno_t err = uvwasi_path_remove_directory(&wasi->uvw_,
1293                                                     fd,
1294                                                     &memory[path_ptr],
1295                                                     path_len);
1296   args.GetReturnValue().Set(err);
1297 }
1298 
1299 
PathRename(const FunctionCallbackInfo<Value> & args)1300 void WASI::PathRename(const FunctionCallbackInfo<Value>& args) {
1301   WASI* wasi;
1302   uint32_t old_fd;
1303   uint32_t old_path_ptr;
1304   uint32_t old_path_len;
1305   uint32_t new_fd;
1306   uint32_t new_path_ptr;
1307   uint32_t new_path_len;
1308   char* memory;
1309   size_t mem_size;
1310   RETURN_IF_BAD_ARG_COUNT(args, 6);
1311   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, old_fd);
1312   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, old_path_ptr);
1313   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, old_path_len);
1314   CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, new_fd);
1315   CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, new_path_ptr);
1316   CHECK_TO_TYPE_OR_RETURN(args, args[5], Uint32, new_path_len);
1317   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
1318   Debug(wasi,
1319         "path_rename(%d, %d, %d, %d, %d, %d)\n",
1320         old_fd,
1321         old_path_ptr,
1322         old_path_len,
1323         new_fd,
1324         new_path_ptr,
1325         new_path_len);
1326   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
1327   CHECK_BOUNDS_OR_RETURN(args, mem_size, old_path_ptr, old_path_len);
1328   CHECK_BOUNDS_OR_RETURN(args, mem_size, new_path_ptr, new_path_len);
1329   uvwasi_errno_t err = uvwasi_path_rename(&wasi->uvw_,
1330                                           old_fd,
1331                                           &memory[old_path_ptr],
1332                                           old_path_len,
1333                                           new_fd,
1334                                           &memory[new_path_ptr],
1335                                           new_path_len);
1336   args.GetReturnValue().Set(err);
1337 }
1338 
1339 
PathSymlink(const FunctionCallbackInfo<Value> & args)1340 void WASI::PathSymlink(const FunctionCallbackInfo<Value>& args) {
1341   WASI* wasi;
1342   uint32_t old_path_ptr;
1343   uint32_t old_path_len;
1344   uint32_t fd;
1345   uint32_t new_path_ptr;
1346   uint32_t new_path_len;
1347   char* memory;
1348   size_t mem_size;
1349   RETURN_IF_BAD_ARG_COUNT(args, 5);
1350   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, old_path_ptr);
1351   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, old_path_len);
1352   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, fd);
1353   CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, new_path_ptr);
1354   CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, new_path_len);
1355   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
1356   Debug(wasi,
1357         "path_symlink(%d, %d, %d, %d, %d)\n",
1358         old_path_ptr,
1359         old_path_len,
1360         fd,
1361         new_path_ptr,
1362         new_path_len);
1363   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
1364   CHECK_BOUNDS_OR_RETURN(args, mem_size, old_path_ptr, old_path_len);
1365   CHECK_BOUNDS_OR_RETURN(args, mem_size, new_path_ptr, new_path_len);
1366   uvwasi_errno_t err = uvwasi_path_symlink(&wasi->uvw_,
1367                                            &memory[old_path_ptr],
1368                                            old_path_len,
1369                                            fd,
1370                                            &memory[new_path_ptr],
1371                                            new_path_len);
1372   args.GetReturnValue().Set(err);
1373 }
1374 
1375 
PathUnlinkFile(const FunctionCallbackInfo<Value> & args)1376 void WASI::PathUnlinkFile(const FunctionCallbackInfo<Value>& args) {
1377   WASI* wasi;
1378   uint32_t fd;
1379   uint32_t path_ptr;
1380   uint32_t path_len;
1381   char* memory;
1382   size_t mem_size;
1383   RETURN_IF_BAD_ARG_COUNT(args, 3);
1384   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd);
1385   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, path_ptr);
1386   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_len);
1387   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
1388   Debug(wasi, "path_unlink_file(%d, %d, %d)\n", fd, path_ptr, path_len);
1389   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
1390   CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len);
1391   uvwasi_errno_t err = uvwasi_path_unlink_file(&wasi->uvw_,
1392                                                fd,
1393                                                &memory[path_ptr],
1394                                                path_len);
1395   args.GetReturnValue().Set(err);
1396 }
1397 
1398 
PollOneoff(const FunctionCallbackInfo<Value> & args)1399 void WASI::PollOneoff(const FunctionCallbackInfo<Value>& args) {
1400   WASI* wasi;
1401   uint32_t in_ptr;
1402   uint32_t out_ptr;
1403   uint32_t nsubscriptions;
1404   uint32_t nevents_ptr;
1405   char* memory;
1406   size_t mem_size;
1407   RETURN_IF_BAD_ARG_COUNT(args, 4);
1408   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, in_ptr);
1409   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, out_ptr);
1410   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, nsubscriptions);
1411   CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, nevents_ptr);
1412   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
1413   Debug(wasi,
1414         "poll_oneoff(%d, %d, %d, %d)\n",
1415         in_ptr,
1416         out_ptr,
1417         nsubscriptions,
1418         nevents_ptr);
1419   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
1420   CHECK_BOUNDS_OR_RETURN(args,
1421                          mem_size,
1422                          in_ptr,
1423                          nsubscriptions * UVWASI_SERDES_SIZE_subscription_t);
1424   CHECK_BOUNDS_OR_RETURN(args,
1425                          mem_size,
1426                          out_ptr,
1427                          nsubscriptions * UVWASI_SERDES_SIZE_event_t);
1428   CHECK_BOUNDS_OR_RETURN(args,
1429                          mem_size,
1430                          nevents_ptr,
1431                          UVWASI_SERDES_SIZE_size_t);
1432   std::vector<uvwasi_subscription_t> in(nsubscriptions);
1433   std::vector<uvwasi_event_t> out(nsubscriptions);
1434 
1435   for (uint32_t i = 0; i < nsubscriptions; ++i) {
1436     uvwasi_serdes_read_subscription_t(memory, in_ptr, &in[i]);
1437     in_ptr += UVWASI_SERDES_SIZE_subscription_t;
1438   }
1439 
1440   uvwasi_size_t nevents;
1441   uvwasi_errno_t err = uvwasi_poll_oneoff(&wasi->uvw_,
1442                                           in.data(),
1443                                           out.data(),
1444                                           nsubscriptions,
1445                                           &nevents);
1446   if (err == UVWASI_ESUCCESS) {
1447     uvwasi_serdes_write_size_t(memory, nevents_ptr, nevents);
1448 
1449     for (uint32_t i = 0; i < nsubscriptions; ++i) {
1450       uvwasi_serdes_write_event_t(memory, out_ptr, &out[i]);
1451       out_ptr += UVWASI_SERDES_SIZE_event_t;
1452     }
1453   }
1454 
1455   args.GetReturnValue().Set(err);
1456 }
1457 
1458 
ProcExit(const FunctionCallbackInfo<Value> & args)1459 void WASI::ProcExit(const FunctionCallbackInfo<Value>& args) {
1460   WASI* wasi;
1461   uint32_t code;
1462   RETURN_IF_BAD_ARG_COUNT(args, 1);
1463   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, code);
1464   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
1465   Debug(wasi, "proc_exit(%d)\n", code);
1466   args.GetReturnValue().Set(uvwasi_proc_exit(&wasi->uvw_, code));
1467 }
1468 
1469 
ProcRaise(const FunctionCallbackInfo<Value> & args)1470 void WASI::ProcRaise(const FunctionCallbackInfo<Value>& args) {
1471   WASI* wasi;
1472   uint32_t sig;
1473   RETURN_IF_BAD_ARG_COUNT(args, 1);
1474   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, sig);
1475   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
1476   Debug(wasi, "proc_raise(%d)\n", sig);
1477   uvwasi_errno_t err = uvwasi_proc_raise(&wasi->uvw_, sig);
1478   args.GetReturnValue().Set(err);
1479 }
1480 
1481 
RandomGet(const FunctionCallbackInfo<Value> & args)1482 void WASI::RandomGet(const FunctionCallbackInfo<Value>& args) {
1483   WASI* wasi;
1484   uint32_t buf_ptr;
1485   uint32_t buf_len;
1486   char* memory;
1487   size_t mem_size;
1488   RETURN_IF_BAD_ARG_COUNT(args, 2);
1489   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, buf_ptr);
1490   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, buf_len);
1491   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
1492   Debug(wasi, "random_get(%d, %d)\n", buf_ptr, buf_len);
1493   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
1494   CHECK_BOUNDS_OR_RETURN(args, mem_size, buf_ptr, buf_len);
1495   uvwasi_errno_t err = uvwasi_random_get(&wasi->uvw_,
1496                                          &memory[buf_ptr],
1497                                          buf_len);
1498   args.GetReturnValue().Set(err);
1499 }
1500 
1501 
SchedYield(const FunctionCallbackInfo<Value> & args)1502 void WASI::SchedYield(const FunctionCallbackInfo<Value>& args) {
1503   WASI* wasi;
1504   RETURN_IF_BAD_ARG_COUNT(args, 0);
1505   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
1506   Debug(wasi, "sched_yield()\n");
1507   uvwasi_errno_t err = uvwasi_sched_yield(&wasi->uvw_);
1508   args.GetReturnValue().Set(err);
1509 }
1510 
1511 
SockRecv(const FunctionCallbackInfo<Value> & args)1512 void WASI::SockRecv(const FunctionCallbackInfo<Value>& args) {
1513   WASI* wasi;
1514   uint32_t sock;
1515   uint32_t ri_data_ptr;
1516   uint32_t ri_data_len;
1517   uint16_t ri_flags;
1518   uint32_t ro_datalen_ptr;
1519   uint16_t ro_flags_ptr;
1520   char* memory;
1521   size_t mem_size;
1522   RETURN_IF_BAD_ARG_COUNT(args, 6);
1523   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, sock);
1524   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, ri_data_ptr);
1525   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, ri_data_len);
1526   CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, ri_flags);
1527   CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, ro_datalen_ptr);
1528   CHECK_TO_TYPE_OR_RETURN(args, args[5], Uint32, ro_flags_ptr);
1529   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
1530   Debug(wasi,
1531         "sock_recv(%d, %d, %d, %d, %d, %d)\n",
1532         sock,
1533         ri_data_ptr,
1534         ri_data_len,
1535         ri_flags,
1536         ro_datalen_ptr,
1537         ro_flags_ptr);
1538   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
1539   CHECK_BOUNDS_OR_RETURN(args,
1540                          mem_size,
1541                          ri_data_ptr,
1542                          ri_data_len * UVWASI_SERDES_SIZE_iovec_t);
1543   CHECK_BOUNDS_OR_RETURN(args, mem_size, ro_datalen_ptr, 4);
1544   CHECK_BOUNDS_OR_RETURN(args, mem_size, ro_flags_ptr, 4);
1545   std::vector<uvwasi_iovec_t> ri_data(ri_data_len);
1546   uvwasi_errno_t err = uvwasi_serdes_readv_iovec_t(memory,
1547                                                    mem_size,
1548                                                    ri_data_ptr,
1549                                                    ri_data.data(),
1550                                                    ri_data_len);
1551   if (err != UVWASI_ESUCCESS) {
1552     args.GetReturnValue().Set(err);
1553     return;
1554   }
1555 
1556   uvwasi_size_t ro_datalen;
1557   uvwasi_roflags_t ro_flags;
1558   err = uvwasi_sock_recv(&wasi->uvw_,
1559                          sock,
1560                          ri_data.data(),
1561                          ri_data_len,
1562                          ri_flags,
1563                          &ro_datalen,
1564                          &ro_flags);
1565   if (err == UVWASI_ESUCCESS) {
1566     uvwasi_serdes_write_size_t(memory, ro_datalen_ptr, ro_datalen);
1567     uvwasi_serdes_write_roflags_t(memory, ro_flags_ptr, ro_flags);
1568   }
1569 
1570   args.GetReturnValue().Set(err);
1571 }
1572 
1573 
SockSend(const FunctionCallbackInfo<Value> & args)1574 void WASI::SockSend(const FunctionCallbackInfo<Value>& args) {
1575   WASI* wasi;
1576   uint32_t sock;
1577   uint32_t si_data_ptr;
1578   uint32_t si_data_len;
1579   uint16_t si_flags;
1580   uint32_t so_datalen_ptr;
1581   char* memory;
1582   size_t mem_size;
1583   RETURN_IF_BAD_ARG_COUNT(args, 5);
1584   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, sock);
1585   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, si_data_ptr);
1586   CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, si_data_len);
1587   CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, si_flags);
1588   CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, so_datalen_ptr);
1589   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
1590   Debug(wasi,
1591         "sock_send(%d, %d, %d, %d, %d)\n",
1592         sock,
1593         si_data_ptr,
1594         si_data_len,
1595         si_flags,
1596         so_datalen_ptr);
1597   GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size);
1598   CHECK_BOUNDS_OR_RETURN(args,
1599                          mem_size,
1600                          si_data_ptr,
1601                          si_data_len * UVWASI_SERDES_SIZE_ciovec_t);
1602   CHECK_BOUNDS_OR_RETURN(args,
1603                          mem_size,
1604                          so_datalen_ptr,
1605                          UVWASI_SERDES_SIZE_size_t);
1606   std::vector<uvwasi_ciovec_t> si_data(si_data_len);
1607   uvwasi_errno_t err = uvwasi_serdes_readv_ciovec_t(memory,
1608                                                     mem_size,
1609                                                     si_data_ptr,
1610                                                     si_data.data(),
1611                                                     si_data_len);
1612   if (err != UVWASI_ESUCCESS) {
1613     args.GetReturnValue().Set(err);
1614     return;
1615   }
1616 
1617   uvwasi_size_t so_datalen;
1618   err = uvwasi_sock_send(&wasi->uvw_,
1619                          sock,
1620                          si_data.data(),
1621                          si_data_len,
1622                          si_flags,
1623                          &so_datalen);
1624   if (err == UVWASI_ESUCCESS)
1625     uvwasi_serdes_write_size_t(memory, so_datalen_ptr, so_datalen);
1626 
1627   args.GetReturnValue().Set(err);
1628 }
1629 
1630 
SockShutdown(const FunctionCallbackInfo<Value> & args)1631 void WASI::SockShutdown(const FunctionCallbackInfo<Value>& args) {
1632   WASI* wasi;
1633   uint32_t sock;
1634   uint8_t how;
1635   RETURN_IF_BAD_ARG_COUNT(args, 2);
1636   CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, sock);
1637   CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, how);
1638   ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This());
1639   Debug(wasi, "sock_shutdown(%d, %d)\n", sock, how);
1640   uvwasi_errno_t err = uvwasi_sock_shutdown(&wasi->uvw_, sock, how);
1641   args.GetReturnValue().Set(err);
1642 }
1643 
1644 
_SetMemory(const FunctionCallbackInfo<Value> & args)1645 void WASI::_SetMemory(const FunctionCallbackInfo<Value>& args) {
1646   WASI* wasi;
1647   CHECK_EQ(args.Length(), 1);
1648   CHECK(args[0]->IsObject());
1649   ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
1650   wasi->memory_.Reset(wasi->env()->isolate(), args[0].As<Object>());
1651 }
1652 
1653 
backingStore(char ** store,size_t * byte_length)1654 uvwasi_errno_t WASI::backingStore(char** store, size_t* byte_length) {
1655   Environment* env = this->env();
1656   Local<Object> memory = PersistentToLocal::Strong(this->memory_);
1657   Local<Value> prop;
1658 
1659   if (!memory->Get(env->context(), env->buffer_string()).ToLocal(&prop))
1660     return UVWASI_EINVAL;
1661 
1662   if (!prop->IsArrayBuffer())
1663     return UVWASI_EINVAL;
1664 
1665   Local<ArrayBuffer> ab = prop.As<ArrayBuffer>();
1666   std::shared_ptr<BackingStore> backing_store = ab->GetBackingStore();
1667   *byte_length = backing_store->ByteLength();
1668   *store = static_cast<char*>(backing_store->Data());
1669   CHECK_NOT_NULL(*store);
1670   return UVWASI_ESUCCESS;
1671 }
1672 
1673 
Initialize(Local<Object> target,Local<Value> unused,Local<Context> context,void * priv)1674 static void Initialize(Local<Object> target,
1675                        Local<Value> unused,
1676                        Local<Context> context,
1677                        void* priv) {
1678   Environment* env = Environment::GetCurrent(context);
1679 
1680   Local<FunctionTemplate> tmpl = env->NewFunctionTemplate(WASI::New);
1681   tmpl->InstanceTemplate()->SetInternalFieldCount(WASI::kInternalFieldCount);
1682   tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
1683 
1684   env->SetProtoMethod(tmpl, "args_get", WASI::ArgsGet);
1685   env->SetProtoMethod(tmpl, "args_sizes_get", WASI::ArgsSizesGet);
1686   env->SetProtoMethod(tmpl, "clock_res_get", WASI::ClockResGet);
1687   env->SetProtoMethod(tmpl, "clock_time_get", WASI::ClockTimeGet);
1688   env->SetProtoMethod(tmpl, "environ_get", WASI::EnvironGet);
1689   env->SetProtoMethod(tmpl, "environ_sizes_get", WASI::EnvironSizesGet);
1690   env->SetProtoMethod(tmpl, "fd_advise", WASI::FdAdvise);
1691   env->SetProtoMethod(tmpl, "fd_allocate", WASI::FdAllocate);
1692   env->SetProtoMethod(tmpl, "fd_close", WASI::FdClose);
1693   env->SetProtoMethod(tmpl, "fd_datasync", WASI::FdDatasync);
1694   env->SetProtoMethod(tmpl, "fd_fdstat_get", WASI::FdFdstatGet);
1695   env->SetProtoMethod(tmpl, "fd_fdstat_set_flags", WASI::FdFdstatSetFlags);
1696   env->SetProtoMethod(tmpl, "fd_fdstat_set_rights", WASI::FdFdstatSetRights);
1697   env->SetProtoMethod(tmpl, "fd_filestat_get", WASI::FdFilestatGet);
1698   env->SetProtoMethod(tmpl, "fd_filestat_set_size", WASI::FdFilestatSetSize);
1699   env->SetProtoMethod(tmpl, "fd_filestat_set_times", WASI::FdFilestatSetTimes);
1700   env->SetProtoMethod(tmpl, "fd_pread", WASI::FdPread);
1701   env->SetProtoMethod(tmpl, "fd_prestat_get", WASI::FdPrestatGet);
1702   env->SetProtoMethod(tmpl, "fd_prestat_dir_name", WASI::FdPrestatDirName);
1703   env->SetProtoMethod(tmpl, "fd_pwrite", WASI::FdPwrite);
1704   env->SetProtoMethod(tmpl, "fd_read", WASI::FdRead);
1705   env->SetProtoMethod(tmpl, "fd_readdir", WASI::FdReaddir);
1706   env->SetProtoMethod(tmpl, "fd_renumber", WASI::FdRenumber);
1707   env->SetProtoMethod(tmpl, "fd_seek", WASI::FdSeek);
1708   env->SetProtoMethod(tmpl, "fd_sync", WASI::FdSync);
1709   env->SetProtoMethod(tmpl, "fd_tell", WASI::FdTell);
1710   env->SetProtoMethod(tmpl, "fd_write", WASI::FdWrite);
1711   env->SetProtoMethod(tmpl, "path_create_directory", WASI::PathCreateDirectory);
1712   env->SetProtoMethod(tmpl, "path_filestat_get", WASI::PathFilestatGet);
1713   env->SetProtoMethod(tmpl,
1714                       "path_filestat_set_times",
1715                       WASI::PathFilestatSetTimes);
1716   env->SetProtoMethod(tmpl, "path_link", WASI::PathLink);
1717   env->SetProtoMethod(tmpl, "path_open", WASI::PathOpen);
1718   env->SetProtoMethod(tmpl, "path_readlink", WASI::PathReadlink);
1719   env->SetProtoMethod(tmpl, "path_remove_directory", WASI::PathRemoveDirectory);
1720   env->SetProtoMethod(tmpl, "path_rename", WASI::PathRename);
1721   env->SetProtoMethod(tmpl, "path_symlink", WASI::PathSymlink);
1722   env->SetProtoMethod(tmpl, "path_unlink_file", WASI::PathUnlinkFile);
1723   env->SetProtoMethod(tmpl, "poll_oneoff", WASI::PollOneoff);
1724   env->SetProtoMethod(tmpl, "proc_exit", WASI::ProcExit);
1725   env->SetProtoMethod(tmpl, "proc_raise", WASI::ProcRaise);
1726   env->SetProtoMethod(tmpl, "random_get", WASI::RandomGet);
1727   env->SetProtoMethod(tmpl, "sched_yield", WASI::SchedYield);
1728   env->SetProtoMethod(tmpl, "sock_recv", WASI::SockRecv);
1729   env->SetProtoMethod(tmpl, "sock_send", WASI::SockSend);
1730   env->SetProtoMethod(tmpl, "sock_shutdown", WASI::SockShutdown);
1731 
1732   env->SetInstanceMethod(tmpl, "_setMemory", WASI::_SetMemory);
1733 
1734   env->SetConstructorFunction(target, "WASI", tmpl);
1735 }
1736 
1737 
1738 }  // namespace wasi
1739 }  // namespace node
1740 
1741 NODE_MODULE_CONTEXT_AWARE_INTERNAL(wasi, node::wasi::Initialize)
1742