fix: errors thrown in functions over the contextBridge
(#28346)
* fix: errors thrown in functions over the contextBridge * spec: add a test * fix: ensure exception is a v8::Object
This commit is contained in:
parent
9a7cfc42aa
commit
9fecf8369f
2 changed files with 33 additions and 9 deletions
|
@ -429,21 +429,31 @@ void ProxyFunctionWrapper(const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||||
|
|
||||||
v8::MaybeLocal<v8::Value> maybe_return_value;
|
v8::MaybeLocal<v8::Value> maybe_return_value;
|
||||||
bool did_error = false;
|
bool did_error = false;
|
||||||
std::string error_message;
|
v8::Local<v8::Value> error_message;
|
||||||
{
|
{
|
||||||
v8::TryCatch try_catch(args.isolate());
|
v8::TryCatch try_catch(args.isolate());
|
||||||
maybe_return_value = func->Call(func_owning_context, func,
|
maybe_return_value = func->Call(func_owning_context, func,
|
||||||
proxied_args.size(), proxied_args.data());
|
proxied_args.size(), proxied_args.data());
|
||||||
if (try_catch.HasCaught()) {
|
if (try_catch.HasCaught()) {
|
||||||
did_error = true;
|
did_error = true;
|
||||||
auto message = try_catch.Message();
|
v8::Local<v8::Value> exception = try_catch.Exception();
|
||||||
|
|
||||||
if (message.IsEmpty() ||
|
const char* err_msg =
|
||||||
!gin::ConvertFromV8(args.isolate(), message->Get(),
|
"An unknown exception occurred in the isolated context, an error "
|
||||||
&error_message)) {
|
"occurred but a valid exception was not thrown.";
|
||||||
error_message =
|
|
||||||
"An unknown exception occurred in the isolated context, an error "
|
if (!exception->IsNull() && exception->IsObject()) {
|
||||||
"occurred but a valid exception was not thrown.";
|
v8::MaybeLocal<v8::Value> maybe_message =
|
||||||
|
exception.As<v8::Object>()->Get(
|
||||||
|
func_owning_context,
|
||||||
|
gin::ConvertToV8(args.isolate(), "message"));
|
||||||
|
|
||||||
|
if (!maybe_message.ToLocal(&error_message) ||
|
||||||
|
!error_message->IsString()) {
|
||||||
|
error_message = gin::StringToV8(args.isolate(), err_msg);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error_message = gin::StringToV8(args.isolate(), err_msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -451,7 +461,7 @@ void ProxyFunctionWrapper(const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||||
if (did_error) {
|
if (did_error) {
|
||||||
v8::Context::Scope calling_context_scope(calling_context);
|
v8::Context::Scope calling_context_scope(calling_context);
|
||||||
args.isolate()->ThrowException(
|
args.isolate()->ThrowException(
|
||||||
v8::Exception::Error(gin::StringToV8(args.isolate(), error_message)));
|
v8::Exception::Error(error_message.As<v8::String>()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -364,6 +364,20 @@ describe('contextBridge', () => {
|
||||||
expect(result).equal(true);
|
expect(result).equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should properly handle errors thrown in proxied functions', async () => {
|
||||||
|
await makeBindingWindow(() => {
|
||||||
|
contextBridge.exposeInMainWorld('example', () => { throw new Error('oh no'); });
|
||||||
|
});
|
||||||
|
const result = await callWithBindings(async (root: any) => {
|
||||||
|
try {
|
||||||
|
root.example();
|
||||||
|
} catch (e) {
|
||||||
|
return e.message;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(result).equal('oh no');
|
||||||
|
});
|
||||||
|
|
||||||
it('should proxy methods that are callable multiple times', async () => {
|
it('should proxy methods that are callable multiple times', async () => {
|
||||||
await makeBindingWindow(() => {
|
await makeBindingWindow(() => {
|
||||||
contextBridge.exposeInMainWorld('example', {
|
contextBridge.exposeInMainWorld('example', {
|
||||||
|
|
Loading…
Reference in a new issue