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