Skip to content

Commit 87f15c0

Browse files
cjihrigBridgeAR
authored andcommitted
wasi: throw on failed uvwasi_init()
Prior to this commit, if uvwasi_init() failed in any way, Node would abort due to a failed CHECK_EQ(). This commit changes that behavior to a thrown exception. PR-URL: #31076 Fixes: #30878 Reviewed-By: Jiawen Geng <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Chengzhong Wu <[email protected]> Reviewed-By: Rich Trott <[email protected]>
1 parent 2ec817e commit 87f15c0

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

src/node_wasi.cc

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,22 +74,64 @@ using v8::ArrayBuffer;
7474
using v8::BackingStore;
7575
using v8::BigInt;
7676
using v8::Context;
77+
using v8::Exception;
7778
using v8::FunctionCallbackInfo;
7879
using v8::FunctionTemplate;
80+
using v8::Integer;
81+
using v8::Isolate;
7982
using v8::Local;
83+
using v8::MaybeLocal;
8084
using v8::Object;
8185
using v8::String;
8286
using v8::Uint32;
8387
using v8::Value;
8488

8589

90+
static MaybeLocal<Value> WASIException(Local<Context> context,
91+
int errorno,
92+
const char* syscall) {
93+
Isolate* isolate = context->GetIsolate();
94+
Environment* env = Environment::GetCurrent(context);
95+
CHECK_NOT_NULL(env);
96+
const char* err_name = uvwasi_embedder_err_code_to_string(errorno);
97+
Local<String> js_code = OneByteString(isolate, err_name);
98+
Local<String> js_syscall = OneByteString(isolate, syscall);
99+
Local<String> js_msg = js_code;
100+
js_msg =
101+
String::Concat(isolate, js_msg, FIXED_ONE_BYTE_STRING(isolate, ", "));
102+
js_msg = String::Concat(isolate, js_msg, js_syscall);
103+
Local<Object> e =
104+
Exception::Error(js_msg)->ToObject(context)
105+
.ToLocalChecked();
106+
107+
if (e->Set(context,
108+
env->errno_string(),
109+
Integer::New(isolate, errorno)).IsNothing() ||
110+
e->Set(context, env->code_string(), js_code).IsNothing() ||
111+
e->Set(context, env->syscall_string(), js_syscall).IsNothing()) {
112+
return MaybeLocal<Value>();
113+
}
114+
115+
return e;
116+
}
117+
118+
86119
WASI::WASI(Environment* env,
87120
Local<Object> object,
88121
uvwasi_options_t* options) : BaseObject(env, object) {
89122
MakeWeak();
90123
alloc_info_ = MakeAllocator();
91124
options->allocator = &alloc_info_;
92-
CHECK_EQ(uvwasi_init(&uvw_, options), UVWASI_ESUCCESS);
125+
int err = uvwasi_init(&uvw_, options);
126+
if (err != UVWASI_ESUCCESS) {
127+
Local<Context> context = env->context();
128+
MaybeLocal<Value> exception = WASIException(context, err, "uvwasi_init");
129+
130+
if (exception.IsEmpty())
131+
return;
132+
133+
context->GetIsolate()->ThrowException(exception.ToLocalChecked());
134+
}
93135
}
94136

95137

test/wasi/test-wasi-options-validation.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,8 @@ assert.throws(() => { new WASI({ preopens: 'fhqwhgads' }); },
2626
assert.throws(() => { new WASI(value); },
2727
{ code: 'ERR_INVALID_ARG_TYPE' });
2828
});
29+
30+
// Verify that exceptions thrown from the binding layer are handled.
31+
assert.throws(() => {
32+
new WASI({ preopens: { '/sandbox': '__/not/real/path' } });
33+
}, { code: 'UVWASI_ENOENT', message: /uvwasi_init/ });

0 commit comments

Comments
 (0)