@@ -72,18 +72,28 @@ inline void Debug(WASI* wasi, Args&&... args) {
72
72
} \
73
73
} while (0 )
74
74
75
+ #define CHECK_BOUNDS_OR_RETURN2 (mem_size, offset, buf_size ) \
76
+ do { \
77
+ if (!uvwasi_serdes_check_bounds ((offset), (mem_size), (buf_size))) { \
78
+ return UVWASI_EOVERFLOW; \
79
+ } \
80
+ } while (0 )
81
+
75
82
using v8::Array;
76
83
using v8::BackingStore;
77
84
using v8::BigInt;
85
+ using v8::CFunction;
78
86
using v8::Context;
79
87
using v8::Exception;
88
+ using v8::FastApiCallbackOptions;
80
89
using v8::FunctionCallbackInfo;
81
90
using v8::FunctionTemplate;
82
91
using v8::Integer;
83
92
using v8::Isolate;
84
93
using v8::Local;
85
94
using v8::MaybeLocal;
86
95
using v8::Object;
96
+ using v8::Signature;
87
97
using v8::String;
88
98
using v8::Uint32;
89
99
using v8::Value;
@@ -248,46 +258,155 @@ void WASI::New(const FunctionCallbackInfo<Value>& args) {
248
258
}
249
259
}
250
260
261
+ struct WasmMemory {
262
+ char * data;
263
+ size_t size;
264
+ };
265
+
266
+ template <auto F, typename R, typename ... Args>
267
+ class WasiFunction {
268
+ public:
269
+ static void SetFunction (Environment* env,
270
+ const char * name,
271
+ Local<FunctionTemplate> tmpl) {
272
+ auto c_function = CFunction::Make (FastCallback);
273
+ Local<FunctionTemplate> t =
274
+ v8::FunctionTemplate::New (env->isolate (),
275
+ SlowCallback,
276
+ Local<Value>(),
277
+ Local<Signature>(),
278
+ sizeof ...(Args),
279
+ v8::ConstructorBehavior::kThrow ,
280
+ v8::SideEffectType::kHasSideEffect ,
281
+ &c_function);
282
+ const v8::NewStringType type = v8::NewStringType::kInternalized ;
283
+ v8::Local<v8::String> name_string =
284
+ v8::String::NewFromUtf8 (env->isolate (), name, type).ToLocalChecked ();
285
+ tmpl->PrototypeTemplate ()->Set (name_string, t);
286
+ t->SetClassName (name_string);
287
+ }
251
288
252
- void WASI::ArgsGet (const FunctionCallbackInfo<Value>& args) {
253
- WASI* wasi;
254
- uint32_t argv_offset;
255
- uint32_t argv_buf_offset;
256
- char * memory;
257
- size_t mem_size;
258
- RETURN_IF_BAD_ARG_COUNT (args, 2 );
259
- CHECK_TO_TYPE_OR_RETURN (args, args[0 ], Uint32, argv_offset);
260
- CHECK_TO_TYPE_OR_RETURN (args, args[1 ], Uint32, argv_buf_offset);
261
- ASSIGN_INITIALIZED_OR_RETURN_UNWRAP (&wasi, args.This ());
262
- Debug (wasi, " args_get(%d, %d)\n " , argv_offset, argv_buf_offset);
263
- GET_BACKING_STORE_OR_RETURN (wasi, args, &memory, &mem_size);
264
- CHECK_BOUNDS_OR_RETURN (args,
265
- mem_size,
266
- argv_buf_offset,
267
- wasi->uvw_ .argv_buf_size );
268
- CHECK_BOUNDS_OR_RETURN (args,
269
- mem_size,
270
- argv_offset,
271
- wasi->uvw_ .argc * UVWASI_SERDES_SIZE_uint32_t);
272
- std::vector<char *> argv (wasi->uvw_ .argc );
273
- char * argv_buf = &memory[argv_buf_offset];
274
- uvwasi_errno_t err = uvwasi_args_get (&wasi->uvw_ , argv.data (), argv_buf);
289
+ private:
290
+ static R FastCallback (Local<Object> receiver,
291
+ Args... args,
292
+ FastApiCallbackOptions& options) {
293
+ WASI* wasi = reinterpret_cast <WASI*>(BaseObject::FromJSObject (receiver));
294
+ if (UNLIKELY (wasi == nullptr )) return UVWASI_EINVAL;
295
+
296
+ if (UNLIKELY (options.wasm_memory == nullptr )) return UVWASI_EINVAL;
297
+ uint8_t * memory = nullptr ;
298
+ CHECK (LIKELY (options.wasm_memory ->getStorageIfAligned (&memory)));
299
+
300
+ return F (*wasi, {(char *)memory, options.wasm_memory ->length ()}, args...);
301
+ }
302
+
303
+ template <typename VT>
304
+ static uvwasi_errno_t CheckType (Local<Value> v);
305
+
306
+ template <typename VT>
307
+ static VT ConvertType (Local<Value> V);
308
+
309
+ template <>
310
+ static uvwasi_errno_t CheckType<uint32_t >(Local<Value> value) {
311
+ if (!value->IsUint32 ()) return UVWASI_EINVAL;
312
+ return UVWASI_ESUCCESS;
313
+ }
314
+
315
+ template <>
316
+ static uint32_t ConvertType (Local<Value> value) {
317
+ return value.As <Uint32>()->Value ();
318
+ }
319
+
320
+ template <>
321
+ static uvwasi_errno_t CheckType<uint64_t >(Local<Value> value) {
322
+ if (!value->IsBigInt ()) return UVWASI_EINVAL;
323
+ return UVWASI_ESUCCESS;
324
+ }
325
+
326
+ template <>
327
+ static uint64_t ConvertType (Local<Value> value) {
328
+ Local<BigInt> js_value = value.As <BigInt>();
329
+ bool lossless;
330
+ return js_value->Uint64Value (&lossless);
331
+ }
332
+
333
+ template <>
334
+ static uvwasi_errno_t CheckType<int64_t >(Local<Value> value) {
335
+ if (!value->IsBigInt ()) return UVWASI_EINVAL;
336
+ return UVWASI_ESUCCESS;
337
+ }
338
+
339
+ template <>
340
+ static int64_t ConvertType (Local<Value> value) {
341
+ Local<BigInt> js_value = value.As <BigInt>();
342
+ bool lossless;
343
+ return js_value->Int64Value (&lossless);
344
+ }
345
+
346
+ #pragma clang diagnostic push
347
+ #pragma clang diagnostic ignored "-Wunsequenced"
348
+ static void SlowCallback (const FunctionCallbackInfo<Value>& args) {
349
+ WASI* wasi;
350
+ char * memory;
351
+ size_t mem_size;
352
+ RETURN_IF_BAD_ARG_COUNT (args, sizeof ...(Args));
353
+ {
354
+ int counter = 0 ;
355
+ uvwasi_errno_t results[sizeof ...(Args)] = {
356
+ (CheckType<Args>(args[counter++]))...};
357
+ for (size_t i = 0 ; i < sizeof ...(Args); i += 1 ) {
358
+ if (results[i] != UVWASI_ESUCCESS) {
359
+ args.GetReturnValue ().Set (results[i]);
360
+ return ;
361
+ }
362
+ }
363
+ }
364
+ ASSIGN_INITIALIZED_OR_RETURN_UNWRAP (&wasi, args.This ());
365
+ GET_BACKING_STORE_OR_RETURN (wasi, args, &memory, &mem_size);
366
+
367
+ {
368
+ int counter = 0 ;
369
+ args.GetReturnValue ().Set (
370
+ F (*wasi, {memory, mem_size}, ConvertType<Args>(args[counter++])...));
371
+ }
372
+ }
373
+ #pragma clang diagnostic pop
374
+ };
375
+
376
+ template <auto F, typename R, typename ... Args>
377
+ static void SetFunction (R (*)(WASI&, WasmMemory, Args...),
378
+ Environment* env,
379
+ const char* name,
380
+ Local<FunctionTemplate> tmpl) {
381
+ WasiFunction<F, R, Args...>::SetFunction (env, name, tmpl);
382
+ }
383
+
384
+ static uint32_t ArgsGet (WASI& wasi,
385
+ WasmMemory memory,
386
+ uint32_t argv_offset,
387
+ uint32_t argv_buf_offset) {
388
+ Debug (&wasi, " args_get(%d, %d)\n " , argv_offset, argv_buf_offset);
389
+
390
+ CHECK_BOUNDS_OR_RETURN2 (
391
+ memory.size , argv_buf_offset, wasi.uvw_ .argv_buf_size );
392
+ CHECK_BOUNDS_OR_RETURN2 (
393
+ memory.size , argv_offset, wasi.uvw_ .argc * UVWASI_SERDES_SIZE_uint32_t);
394
+ std::vector<char *> argv (wasi.uvw_ .argc );
395
+ char * argv_buf = &memory.data [argv_buf_offset];
396
+ uvwasi_errno_t err = uvwasi_args_get (&wasi.uvw_ , argv.data (), argv_buf);
275
397
276
398
if (err == UVWASI_ESUCCESS) {
277
- for (size_t i = 0 ; i < wasi-> uvw_ .argc ; i++) {
399
+ for (size_t i = 0 ; i < wasi. uvw_ .argc ; i++) {
278
400
uint32_t offset =
279
401
static_cast <uint32_t >(argv_buf_offset + (argv[i] - argv[0 ]));
280
- uvwasi_serdes_write_uint32_t (memory,
281
- argv_offset +
282
- (i * UVWASI_SERDES_SIZE_uint32_t),
283
- offset);
402
+ uvwasi_serdes_write_uint32_t (
403
+ memory.data , argv_offset + (i * UVWASI_SERDES_SIZE_uint32_t), offset);
284
404
}
285
405
}
286
406
287
- args. GetReturnValue (). Set ( err) ;
407
+ return err;
288
408
}
289
409
290
-
291
410
void WASI::ArgsSizesGet (const FunctionCallbackInfo<Value>& args) {
292
411
WASI* wasi;
293
412
uint32_t argc_offset;
@@ -454,25 +573,16 @@ void WASI::EnvironSizesGet(const FunctionCallbackInfo<Value>& args) {
454
573
args.GetReturnValue ().Set (err);
455
574
}
456
575
457
-
458
- void WASI::FdAdvise (const FunctionCallbackInfo<Value>& args) {
459
- WASI* wasi;
460
- uint32_t fd;
461
- uint64_t offset;
462
- uint64_t len;
463
- uint8_t advice;
464
- RETURN_IF_BAD_ARG_COUNT (args, 4 );
465
- CHECK_TO_TYPE_OR_RETURN (args, args[0 ], Uint32, fd);
466
- UNWRAP_BIGINT_OR_RETURN (args, args[1 ], Uint64, offset);
467
- UNWRAP_BIGINT_OR_RETURN (args, args[2 ], Uint64, len);
468
- CHECK_TO_TYPE_OR_RETURN (args, args[3 ], Uint32, advice);
469
- ASSIGN_INITIALIZED_OR_RETURN_UNWRAP (&wasi, args.This ());
470
- Debug (wasi, " fd_advise(%d, %d, %d, %d)\n " , fd, offset, len, advice);
471
- uvwasi_errno_t err = uvwasi_fd_advise (&wasi->uvw_ , fd, offset, len, advice);
472
- args.GetReturnValue ().Set (err);
576
+ static uint32_t FdAdvise (WASI& wasi,
577
+ WasmMemory,
578
+ uint32_t fd,
579
+ uint64_t offset,
580
+ uint64_t len,
581
+ uint32_t advice) {
582
+ Debug (&wasi, " fd_advise(%d, %d, %d, %d)\n " , fd, offset, len, advice);
583
+ return uvwasi_fd_advise (&wasi.uvw_ , fd, offset, len, advice);
473
584
}
474
585
475
-
476
586
void WASI::FdAllocate (const FunctionCallbackInfo<Value>& args) {
477
587
WASI* wasi;
478
588
uint32_t fd;
@@ -892,40 +1002,24 @@ void WASI::FdRenumber(const FunctionCallbackInfo<Value>& args) {
892
1002
args.GetReturnValue ().Set (err);
893
1003
}
894
1004
895
-
896
- void WASI::FdSeek (const FunctionCallbackInfo<Value>& args) {
897
- WASI* wasi;
898
- uint32_t fd;
899
- int64_t offset;
900
- uint8_t whence;
901
- uint32_t newoffset_ptr;
902
- char * memory;
903
- size_t mem_size;
904
- RETURN_IF_BAD_ARG_COUNT (args, 4 );
905
- CHECK_TO_TYPE_OR_RETURN (args, args[0 ], Uint32, fd);
906
- UNWRAP_BIGINT_OR_RETURN (args, args[1 ], Int64, offset);
907
- CHECK_TO_TYPE_OR_RETURN (args, args[2 ], Uint32, whence);
908
- CHECK_TO_TYPE_OR_RETURN (args, args[3 ], Uint32, newoffset_ptr);
909
- ASSIGN_INITIALIZED_OR_RETURN_UNWRAP (&wasi, args.This ());
910
- Debug (wasi, " fd_seek(%d, %d, %d, %d)\n " , fd, offset, whence, newoffset_ptr);
911
- GET_BACKING_STORE_OR_RETURN (wasi, args, &memory, &mem_size);
912
- CHECK_BOUNDS_OR_RETURN (args,
913
- mem_size,
914
- newoffset_ptr,
915
- UVWASI_SERDES_SIZE_filesize_t);
1005
+ uint32_t FdSeek (WASI& wasi,
1006
+ WasmMemory memory,
1007
+ uint32_t fd,
1008
+ int64_t offset,
1009
+ uint32_t whence,
1010
+ uint32_t newoffset_ptr) {
1011
+ Debug (&wasi, " fd_seek(%d, %d, %d, %d)\n " , fd, offset, whence, newoffset_ptr);
1012
+ CHECK_BOUNDS_OR_RETURN2 (
1013
+ memory.size , newoffset_ptr, UVWASI_SERDES_SIZE_filesize_t);
916
1014
uvwasi_filesize_t newoffset;
917
- uvwasi_errno_t err = uvwasi_fd_seek (&wasi->uvw_ ,
918
- fd,
919
- offset,
920
- whence,
921
- &newoffset);
1015
+ uvwasi_errno_t err =
1016
+ uvwasi_fd_seek (&wasi.uvw_ , fd, offset, whence, &newoffset);
922
1017
if (err == UVWASI_ESUCCESS)
923
- uvwasi_serdes_write_filesize_t (memory, newoffset_ptr, newoffset);
1018
+ uvwasi_serdes_write_filesize_t (memory. data , newoffset_ptr, newoffset);
924
1019
925
- args. GetReturnValue (). Set ( err) ;
1020
+ return err;
926
1021
}
927
1022
928
-
929
1023
void WASI::FdSync (const FunctionCallbackInfo<Value>& args) {
930
1024
WASI* wasi;
931
1025
uint32_t fd;
@@ -1673,13 +1767,14 @@ static void Initialize(Local<Object> target,
1673
1767
tmpl->InstanceTemplate ()->SetInternalFieldCount (WASI::kInternalFieldCount );
1674
1768
tmpl->Inherit (BaseObject::GetConstructorTemplate (env));
1675
1769
1676
- env->SetProtoMethod (tmpl, " args_get" , WASI::ArgsGet);
1770
+ SetFunction<ArgsGet>(ArgsGet, env, " args_get" , tmpl);
1771
+
1677
1772
env->SetProtoMethod (tmpl, " args_sizes_get" , WASI::ArgsSizesGet);
1678
1773
env->SetProtoMethod (tmpl, " clock_res_get" , WASI::ClockResGet);
1679
1774
env->SetProtoMethod (tmpl, " clock_time_get" , WASI::ClockTimeGet);
1680
1775
env->SetProtoMethod (tmpl, " environ_get" , WASI::EnvironGet);
1681
1776
env->SetProtoMethod (tmpl, " environ_sizes_get" , WASI::EnvironSizesGet);
1682
- env-> SetProtoMethod (tmpl, " fd_advise" , WASI::FdAdvise );
1777
+ SetFunction<FdAdvise>(FdAdvise, env, " fd_advise" , tmpl );
1683
1778
env->SetProtoMethod (tmpl, " fd_allocate" , WASI::FdAllocate);
1684
1779
env->SetProtoMethod (tmpl, " fd_close" , WASI::FdClose);
1685
1780
env->SetProtoMethod (tmpl, " fd_datasync" , WASI::FdDatasync);
@@ -1696,7 +1791,7 @@ static void Initialize(Local<Object> target,
1696
1791
env->SetProtoMethod (tmpl, " fd_read" , WASI::FdRead);
1697
1792
env->SetProtoMethod (tmpl, " fd_readdir" , WASI::FdReaddir);
1698
1793
env->SetProtoMethod (tmpl, " fd_renumber" , WASI::FdRenumber);
1699
- env-> SetProtoMethod (tmpl, " fd_seek" , WASI::FdSeek );
1794
+ SetFunction<FdSeek>(FdSeek, env, " fd_seek" , tmpl );
1700
1795
env->SetProtoMethod (tmpl, " fd_sync" , WASI::FdSync);
1701
1796
env->SetProtoMethod (tmpl, " fd_tell" , WASI::FdTell);
1702
1797
env->SetProtoMethod (tmpl, " fd_write" , WASI::FdWrite);
0 commit comments