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