refactor: avoid deprecated v8::Context::GetIsolate() pt 4 (#47973)

* refactor: remove GetIsolate() calls from SetPrivate()

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* refactor: remove excess GetIsolate() calls in PassValueToOtherContextInner()

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* refactor: remove GetIsolate() calls from GetPrivate()

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* refactor: add a v8::Isolate* local to ProxyFunctionWrapper()

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* refactor: remove error_context->GetIsolate() call from PassValueToOtherContextInner()

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* refactor: remove GetIsolate() call from ProxyFunctionWrapper()

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* refactor: pass source and destination isolate as arg to CreateProxyForAPI()

Co-authored-by: Charles Kerr <charles@charleskerr.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
This commit is contained in:
trop[bot] 2025-08-05 23:32:50 -05:00 committed by GitHub
commit c3f64712de
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -112,26 +112,24 @@ bool IsPlainArray(const v8::Local<v8::Value>& arr) {
return !arr->IsTypedArray();
}
void SetPrivate(v8::Local<v8::Context> context,
void SetPrivate(v8::Isolate* const isolate,
v8::Local<v8::Context> context,
v8::Local<v8::Object> target,
const std::string_view key,
v8::Local<v8::Value> value) {
target
->SetPrivate(
context,
v8::Private::ForApi(context->GetIsolate(),
gin::StringToV8(context->GetIsolate(), key)),
value)
->SetPrivate(context,
v8::Private::ForApi(isolate, gin::StringToV8(isolate, key)),
value)
.Check();
}
v8::MaybeLocal<v8::Value> GetPrivate(v8::Local<v8::Context> context,
v8::MaybeLocal<v8::Value> GetPrivate(v8::Isolate* const isolate,
v8::Local<v8::Context> context,
v8::Local<v8::Object> target,
const std::string_view key) {
return target->GetPrivate(
context,
v8::Private::ForApi(context->GetIsolate(),
gin::StringToV8(context->GetIsolate(), key)));
context, v8::Private::ForApi(isolate, gin::StringToV8(isolate, key)));
}
} // namespace
@ -140,8 +138,10 @@ v8::MaybeLocal<v8::Value> GetPrivate(v8::Local<v8::Context> context,
void ProxyFunctionWrapper(const v8::FunctionCallbackInfo<v8::Value>& info);
v8::MaybeLocal<v8::Object> CreateProxyForAPI(
const v8::Local<v8::Object>& api_object,
v8::Isolate* const source_isolate,
const v8::Local<v8::Context>& source_context,
const blink::ExecutionContext* source_execution_context,
v8::Isolate* const destination_isolate,
const v8::Local<v8::Context>& destination_context,
context_bridge::ObjectCache* object_cache,
bool support_dynamic_properties,
@ -149,8 +149,10 @@ v8::MaybeLocal<v8::Object> CreateProxyForAPI(
BridgeErrorTarget error_target);
v8::MaybeLocal<v8::Value> PassValueToOtherContextInner(
v8::Isolate* const source_isolate,
v8::Local<v8::Context> source_context,
const blink::ExecutionContext* source_execution_context,
v8::Isolate* const destination_isolate,
v8::Local<v8::Context> destination_context,
v8::Local<v8::Value> value,
v8::Local<v8::Value> parent_value,
@ -158,8 +160,6 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContextInner(
bool support_dynamic_properties,
int recursion_depth,
BridgeErrorTarget error_target) {
v8::Isolate* const source_isolate = source_context->GetIsolate();
TRACE_EVENT0("electron", "ContextBridge::PassValueToOtherContextInner");
if (recursion_depth >= kMaxRecursion) {
v8::Context::Scope error_scope(error_target == BridgeErrorTarget::kSource
@ -193,8 +193,8 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContextInner(
// the global handle at the right time.
if (value->IsFunction()) {
auto func = value.As<v8::Function>();
v8::MaybeLocal<v8::Value> maybe_original_fn =
GetPrivate(source_context, func, kOriginalFunctionPrivateKey);
v8::MaybeLocal<v8::Value> maybe_original_fn = GetPrivate(
source_isolate, source_context, func, kOriginalFunctionPrivateKey);
{
v8::Context::Scope destination_scope(destination_context);
@ -213,21 +213,22 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContextInner(
return v8::MaybeLocal<v8::Value>(proxy_func);
}
v8::Local<v8::Object> state =
v8::Object::New(destination_context->GetIsolate());
SetPrivate(destination_context, state, kProxyFunctionPrivateKey, func);
SetPrivate(destination_context, state, kProxyFunctionReceiverPrivateKey,
parent_value);
SetPrivate(destination_context, state,
kSupportsDynamicPropertiesPrivateKey,
gin::ConvertToV8(destination_context->GetIsolate(),
support_dynamic_properties));
v8::Local<v8::Object> state = v8::Object::New(destination_isolate);
SetPrivate(destination_isolate, destination_context, state,
kProxyFunctionPrivateKey, func);
SetPrivate(destination_isolate, destination_context, state,
kProxyFunctionReceiverPrivateKey, parent_value);
SetPrivate(
destination_isolate, destination_context, state,
kSupportsDynamicPropertiesPrivateKey,
gin::ConvertToV8(destination_isolate, support_dynamic_properties));
if (!v8::Function::New(destination_context, ProxyFunctionWrapper, state)
.ToLocal(&proxy_func))
return {};
SetPrivate(destination_context, proxy_func.As<v8::Object>(),
kOriginalFunctionPrivateKey, func);
SetPrivate(destination_isolate, destination_context,
proxy_func.As<v8::Object>(), kOriginalFunctionPrivateKey,
func);
object_cache->CacheProxiedObject(value, proxy_func);
return v8::MaybeLocal<v8::Value>(proxy_func);
}
@ -242,14 +243,14 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContextInner(
// left dangling
auto proxied_promise =
std::make_shared<gin_helper::Promise<v8::Local<v8::Value>>>(
destination_context->GetIsolate());
destination_isolate);
v8::Local<v8::Promise> proxied_promise_handle =
proxied_promise->GetHandle();
v8::Global<v8::Context> global_then_source_context(source_isolate,
source_context);
v8::Global<v8::Context> global_then_destination_context(
destination_context->GetIsolate(), destination_context);
destination_isolate, destination_context);
global_then_source_context.SetWeak();
global_then_destination_context.SetWeak();
auto then_cb = base::BindOnce(
@ -289,14 +290,14 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContextInner(
if (!val.IsEmpty())
proxied_promise->Resolve(val.ToLocalChecked());
},
proxied_promise, destination_context->GetIsolate(),
proxied_promise, destination_isolate,
std::move(global_then_source_context),
std::move(global_then_destination_context));
v8::Global<v8::Context> global_catch_source_context(source_isolate,
source_context);
v8::Global<v8::Context> global_catch_destination_context(
destination_context->GetIsolate(), destination_context);
destination_isolate, destination_context);
global_catch_source_context.SetWeak();
global_catch_destination_context.SetWeak();
auto catch_cb = base::BindOnce(
@ -335,15 +336,15 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContextInner(
if (!val.IsEmpty())
proxied_promise->Reject(val.ToLocalChecked());
},
proxied_promise, destination_context->GetIsolate(),
proxied_promise, destination_isolate,
std::move(global_catch_source_context),
std::move(global_catch_destination_context));
std::ignore = source_promise->Then(
source_context,
gin::ConvertToV8(destination_context->GetIsolate(), std::move(then_cb))
gin::ConvertToV8(destination_isolate, std::move(then_cb))
.As<v8::Function>(),
gin::ConvertToV8(destination_context->GetIsolate(), std::move(catch_cb))
gin::ConvertToV8(destination_isolate, std::move(catch_cb))
.As<v8::Function>());
object_cache->CacheProxiedObject(value, proxied_promise_handle);
@ -366,8 +367,7 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContextInner(
v8::Exception::Error(message.As<v8::String>()));
}
return v8::MaybeLocal<v8::Value>(v8::Exception::Error(
v8::Exception::CreateMessage(destination_context->GetIsolate(), value)
->Get()));
v8::Exception::CreateMessage(destination_isolate, value)->Get()));
}
// Manually go through the array and pass each value individually into a new
@ -378,10 +378,11 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContextInner(
v8::Local<v8::Array> arr = value.As<v8::Array>();
size_t length = arr->Length();
v8::Local<v8::Array> cloned_arr =
v8::Array::New(destination_context->GetIsolate(), length);
v8::Array::New(destination_isolate, length);
for (size_t i = 0; i < length; i++) {
auto value_for_array = PassValueToOtherContextInner(
source_context, source_execution_context, destination_context,
source_isolate, source_context, source_execution_context,
destination_isolate, destination_context,
arr->Get(source_context, i).ToLocalChecked(), value, object_cache,
support_dynamic_properties, recursion_depth + 1, error_target);
if (value_for_array.IsEmpty())
@ -399,21 +400,19 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContextInner(
// Clone certain DOM APIs only within Window contexts.
if (source_execution_context->IsWindow()) {
// Custom logic to "clone" Element references
blink::WebElement elem = blink::WebElement::FromV8Value(
destination_context->GetIsolate(), value);
blink::WebElement elem =
blink::WebElement::FromV8Value(destination_isolate, value);
if (!elem.IsNull()) {
v8::Context::Scope destination_context_scope(destination_context);
return v8::MaybeLocal<v8::Value>(
elem.ToV8Value(destination_context->GetIsolate()));
return v8::MaybeLocal<v8::Value>(elem.ToV8Value(destination_isolate));
}
// Custom logic to "clone" Blob references
blink::WebBlob blob =
blink::WebBlob::FromV8Value(destination_context->GetIsolate(), value);
blink::WebBlob::FromV8Value(destination_isolate, value);
if (!blob.IsNull()) {
v8::Context::Scope destination_context_scope(destination_context);
return v8::MaybeLocal<v8::Value>(
blob.ToV8Value(destination_context->GetIsolate()));
return v8::MaybeLocal<v8::Value>(blob.ToV8Value(destination_isolate));
}
}
@ -421,9 +420,9 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContextInner(
if (IsPlainObject(value)) {
auto object_value = value.As<v8::Object>();
auto passed_value = CreateProxyForAPI(
object_value, source_context, source_execution_context,
destination_context, object_cache, support_dynamic_properties,
recursion_depth + 1, error_target);
object_value, source_isolate, source_context, source_execution_context,
destination_isolate, destination_context, object_cache,
support_dynamic_properties, recursion_depth + 1, error_target);
if (passed_value.IsEmpty())
return {};
return v8::MaybeLocal<v8::Value>(passed_value.ToLocalChecked());
@ -435,9 +434,12 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContextInner(
v8::Local<v8::Context> error_context =
error_target == BridgeErrorTarget::kSource ? source_context
: destination_context;
v8::Context::Scope error_scope(error_context);
v8::Context::Scope error_scope{error_context};
// V8 serializer will throw an error if required
if (!gin::ConvertFromV8(error_context->GetIsolate(), value, &ret)) {
v8::Isolate* const error_isolate =
error_target == BridgeErrorTarget::kSource ? source_isolate
: destination_isolate;
if (!gin::ConvertFromV8(error_isolate, value, &ret)) {
return {};
}
}
@ -445,7 +447,7 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContextInner(
{
v8::Context::Scope destination_context_scope(destination_context);
v8::Local<v8::Value> cloned_value =
gin::ConvertToV8(destination_context->GetIsolate(), ret);
gin::ConvertToV8(destination_isolate, ret);
object_cache->CacheProxiedObject(value, cloned_value);
return v8::MaybeLocal<v8::Value>(cloned_value);
}
@ -469,7 +471,8 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContext(
blink::ExecutionContext::From(source_context);
DCHECK(source_execution_context);
return PassValueToOtherContextInner(
source_context, source_execution_context, destination_context, value,
source_context->GetIsolate(), source_context, source_execution_context,
destination_context->GetIsolate(), destination_context, value,
parent_value, object_cache, support_dynamic_properties, 0, error_target);
}
@ -478,27 +481,28 @@ void ProxyFunctionWrapper(const v8::FunctionCallbackInfo<v8::Value>& info) {
CHECK(info.Data()->IsObject());
v8::Local<v8::Object> data = info.Data().As<v8::Object>();
bool support_dynamic_properties = false;
gin::Arguments args(info);
gin::Arguments args{info};
v8::Isolate* const isolate = args.isolate();
// Context the proxy function was called from
v8::Local<v8::Context> calling_context = args.isolate()->GetCurrentContext();
v8::Local<v8::Context> calling_context = isolate->GetCurrentContext();
// Pull the original function and its context off of the data private key
v8::MaybeLocal<v8::Value> sdp_value =
GetPrivate(calling_context, data, kSupportsDynamicPropertiesPrivateKey);
v8::MaybeLocal<v8::Value> sdp_value = GetPrivate(
isolate, calling_context, data, kSupportsDynamicPropertiesPrivateKey);
v8::MaybeLocal<v8::Value> maybe_func =
GetPrivate(calling_context, data, kProxyFunctionPrivateKey);
v8::MaybeLocal<v8::Value> maybe_recv =
GetPrivate(calling_context, data, kProxyFunctionReceiverPrivateKey);
GetPrivate(isolate, calling_context, data, kProxyFunctionPrivateKey);
v8::MaybeLocal<v8::Value> maybe_recv = GetPrivate(
isolate, calling_context, data, kProxyFunctionReceiverPrivateKey);
v8::Local<v8::Value> func_value;
if (sdp_value.IsEmpty() || maybe_func.IsEmpty() || maybe_recv.IsEmpty() ||
!gin::ConvertFromV8(args.isolate(), sdp_value.ToLocalChecked(),
!gin::ConvertFromV8(isolate, sdp_value.ToLocalChecked(),
&support_dynamic_properties) ||
!maybe_func.ToLocal(&func_value))
return;
v8::Local<v8::Function> func = func_value.As<v8::Function>();
v8::Local<v8::Context> func_owning_context =
func->GetCreationContextChecked(args.isolate());
func->GetCreationContextChecked(isolate);
{
v8::Context::Scope func_owning_context_scope(func_owning_context);
@ -524,7 +528,7 @@ void ProxyFunctionWrapper(const v8::FunctionCallbackInfo<v8::Value>& info) {
bool did_error = false;
v8::Local<v8::Value> error_message;
{
v8::TryCatch try_catch(args.isolate());
v8::TryCatch try_catch(isolate);
maybe_return_value =
func->Call(func_owning_context, maybe_recv.ToLocalChecked(),
proxied_args.size(), proxied_args.data());
@ -539,22 +543,21 @@ void ProxyFunctionWrapper(const v8::FunctionCallbackInfo<v8::Value>& info) {
if (!exception->IsNull() && exception->IsObject()) {
v8::MaybeLocal<v8::Value> maybe_message =
exception.As<v8::Object>()->Get(
func_owning_context,
gin::ConvertToV8(args.isolate(), "message"));
func_owning_context, gin::ConvertToV8(isolate, "message"));
if (!maybe_message.ToLocal(&error_message) ||
!error_message->IsString()) {
error_message = gin::StringToV8(args.isolate(), err_msg);
error_message = gin::StringToV8(isolate, err_msg);
}
} else {
error_message = gin::StringToV8(args.isolate(), err_msg);
error_message = gin::StringToV8(isolate, err_msg);
}
}
}
if (did_error) {
v8::Context::Scope calling_context_scope(calling_context);
args.isolate()->ThrowException(
isolate->ThrowException(
v8::Exception::Error(error_message.As<v8::String>()));
return;
}
@ -579,7 +582,7 @@ void ProxyFunctionWrapper(const v8::FunctionCallbackInfo<v8::Value>& info) {
v8::MaybeLocal<v8::Value> ret;
v8::Local<v8::String> exception;
{
v8::TryCatch try_catch(args.isolate());
v8::TryCatch try_catch(isolate);
ret = PassValueToOtherContext(
func_owning_context, calling_context,
maybe_return_value.ToLocalChecked(), func_owning_context->Global(),
@ -598,10 +601,10 @@ void ProxyFunctionWrapper(const v8::FunctionCallbackInfo<v8::Value>& info) {
"An unknown exception occurred while sending a function return "
"value over the context bridge, an error "
"occurred but a valid exception was not thrown.";
args.isolate()->ThrowException(v8::Exception::Error(
gin::StringToV8(args.isolate(), err_msg).As<v8::String>()));
isolate->ThrowException(v8::Exception::Error(
gin::StringToV8(isolate, err_msg).As<v8::String>()));
} else {
args.isolate()->ThrowException(v8::Exception::Error(exception));
isolate->ThrowException(v8::Exception::Error(exception));
}
return;
}
@ -614,19 +617,20 @@ void ProxyFunctionWrapper(const v8::FunctionCallbackInfo<v8::Value>& info) {
v8::MaybeLocal<v8::Object> CreateProxyForAPI(
const v8::Local<v8::Object>& api_object,
v8::Isolate* const source_isolate,
const v8::Local<v8::Context>& source_context,
const blink::ExecutionContext* source_execution_context,
v8::Isolate* const destination_isolate,
const v8::Local<v8::Context>& destination_context,
context_bridge::ObjectCache* object_cache,
bool support_dynamic_properties,
int recursion_depth,
BridgeErrorTarget error_target) {
gin_helper::Dictionary api(source_context->GetIsolate(), api_object);
gin_helper::Dictionary api{source_isolate, api_object};
{
v8::Context::Scope destination_context_scope(destination_context);
auto proxy =
gin_helper::Dictionary::CreateEmpty(destination_context->GetIsolate());
auto proxy = gin_helper::Dictionary::CreateEmpty(destination_isolate);
object_cache->CacheProxiedObject(api.GetHandle(), proxy.GetHandle());
auto maybe_keys = api.GetHandle()->GetOwnPropertyNames(
source_context, static_cast<v8::PropertyFilter>(v8::ONLY_ENUMERABLE));
@ -660,19 +664,19 @@ v8::MaybeLocal<v8::Object> CreateProxyForAPI(
v8::Local<v8::Value> setter_proxy;
if (!getter.IsEmpty()) {
if (!PassValueToOtherContextInner(
source_context, source_execution_context,
destination_context, getter, api.GetHandle(),
object_cache, support_dynamic_properties, 1,
error_target)
source_isolate, source_context, source_execution_context,
destination_isolate, destination_context, getter,
api.GetHandle(), object_cache,
support_dynamic_properties, 1, error_target)
.ToLocal(&getter_proxy))
continue;
}
if (!setter.IsEmpty()) {
if (!PassValueToOtherContextInner(
source_context, source_execution_context,
destination_context, setter, api.GetHandle(),
object_cache, support_dynamic_properties, 1,
error_target)
source_isolate, source_context, source_execution_context,
destination_isolate, destination_context, setter,
api.GetHandle(), object_cache,
support_dynamic_properties, 1, error_target)
.ToLocal(&setter_proxy))
continue;
}
@ -692,9 +696,10 @@ v8::MaybeLocal<v8::Object> CreateProxyForAPI(
continue;
auto passed_value = PassValueToOtherContextInner(
source_context, source_execution_context, destination_context,
value, api.GetHandle(), object_cache, support_dynamic_properties,
recursion_depth + 1, error_target);
source_isolate, source_context, source_execution_context,
destination_isolate, destination_context, value, api.GetHandle(),
object_cache, support_dynamic_properties, recursion_depth + 1,
error_target);
if (passed_value.IsEmpty())
return {};