refactor: prefer GetCreationContextChecked(v8::Isolate*) over GetCreationContextChecked() (#47890)

* refactor: pass an isolate when calling GetCreationContextChecked() in V8FunctionInvoker

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

* refactor: pass an isolate when calling GetCreationContextChecked() in RendererClientBase

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

* refactor: pass an isolate when calling GetCreationContextChecked() in ScriptExecutionCallback::Completed()

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

* refactor: pass an isolate when calling GetCreationContextChecked() in ScriptExecutionCallback::CopyResultToCallingContextAndFinalize()

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

* refactor: pass an isolate when calling GetCreationContextChecked() in electron::GetRenderFrame()

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

* refactor: pass an isolate when calling GetCreationContextChecked() in gin_helper::internal::CallMethodWithArgs()

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

* refactor: pass an isolate when calling GetCreationContextChecked() in OverrideGlobalPropertyFromIsolatedWorld()

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

* refactor: pass an isolate when calling GetCreationContextChecked() in OverrideGlobalValueFromIsolatedWorld()

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

* refactor: pass an isolate when calling GetCreationContextChecked() in ProxyFunctionWrapper()

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

* refactor: pass an isolate when calling GetCreationContextChecked() in PassValueToOtherContextInner()

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

* fixup! refactor: pass an isolate when calling GetCreationContextChecked() in electron::GetRenderFrame()

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-07-29 10:37:29 -04:00 committed by GitHub
commit 3fefa06d34
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 44 additions and 35 deletions

View file

@ -49,7 +49,7 @@ struct V8FunctionInvoker<v8::Local<v8::Value>(ArgTypes...)> {
if (!function.IsAlive())
return v8::Null(isolate);
v8::Local<v8::Function> holder = function.NewHandle(isolate);
v8::Local<v8::Context> context = holder->GetCreationContextChecked();
v8::Local<v8::Context> context = holder->GetCreationContextChecked(isolate);
v8::MicrotasksScope microtasks_scope(context,
v8::MicrotasksScope::kRunMicrotasks);
v8::Context::Scope context_scope(context);
@ -74,7 +74,7 @@ struct V8FunctionInvoker<void(ArgTypes...)> {
if (!function.IsAlive())
return;
v8::Local<v8::Function> holder = function.NewHandle(isolate);
v8::Local<v8::Context> context = holder->GetCreationContextChecked();
v8::Local<v8::Context> context = holder->GetCreationContextChecked(isolate);
v8::MicrotasksScope microtasks_scope(context,
v8::MicrotasksScope::kRunMicrotasks);
v8::Context::Scope context_scope(context);
@ -98,7 +98,7 @@ struct V8FunctionInvoker<ReturnType(ArgTypes...)> {
if (!function.IsAlive())
return ret;
v8::Local<v8::Function> holder = function.NewHandle(isolate);
v8::Local<v8::Context> context = holder->GetCreationContextChecked();
v8::Local<v8::Context> context = holder->GetCreationContextChecked(isolate);
v8::MicrotasksScope microtasks_scope(context,
v8::MicrotasksScope::kRunMicrotasks);
v8::Context::Scope context_scope(context);

View file

@ -23,7 +23,7 @@ v8::Local<v8::Value> CallMethodWithArgs(
node::async_context{0, 0}};
// Perform microtask checkpoint after running JavaScript.
v8::MicrotasksScope microtasks_scope(obj->GetCreationContextChecked(),
v8::MicrotasksScope microtasks_scope(obj->GetCreationContextChecked(isolate),
v8::MicrotasksScope::kRunMicrotasks);
// node::MakeCallback will also run pending tasks in Node.js.

View file

@ -38,7 +38,8 @@ BASE_FEATURE(kContextBridgeMutability,
namespace electron {
content::RenderFrame* GetRenderFrame(v8::Local<v8::Object> value);
content::RenderFrame* GetRenderFrame(v8::Isolate* const isolate,
v8::Local<v8::Object> value);
namespace api {
@ -157,13 +158,15 @@ 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
? source_context
: destination_context);
source_context->GetIsolate()->ThrowException(v8::Exception::TypeError(
gin::StringToV8(source_context->GetIsolate(),
source_isolate->ThrowException(v8::Exception::TypeError(
gin::StringToV8(source_isolate,
"Electron contextBridge recursion depth exceeded. "
"Nested objects "
"deeper than 1000 are not supported.")));
@ -205,8 +208,8 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContextInner(
// creation context of the original method. If it's not we proceed
// with the proxy logic
if (maybe_original_fn.ToLocal(&proxy_func) && proxy_func->IsFunction() &&
proxy_func.As<v8::Object>()->GetCreationContextChecked() ==
destination_context) {
proxy_func.As<v8::Object>()->GetCreationContextChecked(
source_isolate) == destination_context) {
return v8::MaybeLocal<v8::Value>(proxy_func);
}
@ -243,8 +246,8 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContextInner(
v8::Local<v8::Promise> proxied_promise_handle =
proxied_promise->GetHandle();
v8::Global<v8::Context> global_then_source_context(
source_context->GetIsolate(), source_context);
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);
global_then_source_context.SetWeak();
@ -290,8 +293,8 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContextInner(
std::move(global_then_source_context),
std::move(global_then_destination_context));
v8::Global<v8::Context> global_catch_source_context(
source_context->GetIsolate(), source_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);
global_catch_source_context.SetWeak();
@ -356,8 +359,7 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContextInner(
// crosses the bridge we fallback to the v8::Message approach if we can't
// pull "message" for some reason
v8::MaybeLocal<v8::Value> maybe_message = value.As<v8::Object>()->Get(
source_context,
gin::ConvertToV8(source_context->GetIsolate(), "message"));
source_context, gin::ConvertToV8(source_isolate, "message"));
v8::Local<v8::Value> message;
if (maybe_message.ToLocal(&message) && message->IsString()) {
return v8::MaybeLocal<v8::Value>(
@ -496,7 +498,7 @@ void ProxyFunctionWrapper(const v8::FunctionCallbackInfo<v8::Value>& info) {
v8::Local<v8::Function> func = func_value.As<v8::Function>();
v8::Local<v8::Context> func_owning_context =
func->GetCreationContextChecked();
func->GetCreationContextChecked(args.isolate());
{
v8::Context::Scope func_owning_context_scope(func_owning_context);
@ -760,7 +762,7 @@ v8::MaybeLocal<v8::Context> GetTargetContext(v8::Isolate* isolate,
blink::ExecutionContext* execution_context =
blink::ExecutionContext::From(source_context);
if (execution_context->IsWindow()) {
auto* render_frame = GetRenderFrame(source_context->Global());
auto* render_frame = GetRenderFrame(isolate, source_context->Global());
CHECK(render_frame);
auto* frame = render_frame->GetWebFrame();
CHECK(frame);
@ -812,13 +814,14 @@ gin_helper::Dictionary TraceKeyPath(const gin_helper::Dictionary& start,
}
void OverrideGlobalValueFromIsolatedWorld(
v8::Isolate* isolate,
const std::vector<std::string>& key_path,
v8::Local<v8::Object> value,
bool support_dynamic_properties) {
if (key_path.empty())
return;
auto* render_frame = GetRenderFrame(value);
auto* render_frame = GetRenderFrame(isolate, value);
CHECK(render_frame);
auto* frame = render_frame->GetWebFrame();
CHECK(frame);
@ -831,7 +834,8 @@ void OverrideGlobalValueFromIsolatedWorld(
{
v8::Context::Scope main_context_scope(main_context);
v8::Local<v8::Context> source_context = value->GetCreationContextChecked();
v8::Local<v8::Context> source_context =
value->GetCreationContextChecked(isolate);
v8::MaybeLocal<v8::Value> maybe_proxy = PassValueToOtherContext(
source_context, main_context, value, source_context->Global(),
support_dynamic_properties, BridgeErrorTarget::kSource);
@ -843,6 +847,7 @@ void OverrideGlobalValueFromIsolatedWorld(
}
bool OverrideGlobalPropertyFromIsolatedWorld(
v8::Isolate* const isolate,
const std::vector<std::string>& key_path,
v8::Local<v8::Object> getter,
v8::Local<v8::Value> setter,
@ -850,7 +855,7 @@ bool OverrideGlobalPropertyFromIsolatedWorld(
if (key_path.empty())
return false;
auto* render_frame = GetRenderFrame(getter);
auto* render_frame = GetRenderFrame(isolate, getter);
CHECK(render_frame);
auto* frame = render_frame->GetWebFrame();
CHECK(frame);
@ -869,7 +874,7 @@ bool OverrideGlobalPropertyFromIsolatedWorld(
v8::Local<v8::Value> setter_proxy;
if (!getter->IsNullOrUndefined()) {
v8::Local<v8::Context> source_context =
getter->GetCreationContextChecked();
getter->GetCreationContextChecked(isolate);
v8::MaybeLocal<v8::Value> maybe_getter_proxy = PassValueToOtherContext(
source_context, main_context, getter, source_context->Global(), false,
BridgeErrorTarget::kSource);
@ -878,7 +883,7 @@ bool OverrideGlobalPropertyFromIsolatedWorld(
}
if (!setter->IsNullOrUndefined() && setter->IsObject()) {
v8::Local<v8::Context> source_context =
getter->GetCreationContextChecked();
getter->GetCreationContextChecked(isolate);
v8::MaybeLocal<v8::Value> maybe_setter_proxy = PassValueToOtherContext(
source_context, main_context, setter, source_context->Global(), false,
BridgeErrorTarget::kSource);

View file

@ -90,8 +90,9 @@ struct Converter<blink::WebCssOrigin> {
namespace electron {
content::RenderFrame* GetRenderFrame(v8::Local<v8::Object> value) {
v8::Local<v8::Context> context = value->GetCreationContextChecked();
content::RenderFrame* GetRenderFrame(v8::Isolate* const isolate,
v8::Local<v8::Object> value) {
v8::Local<v8::Context> context = value->GetCreationContextChecked(isolate);
if (context.IsEmpty())
return nullptr;
blink::WebLocalFrame* frame = blink::WebLocalFrame::FrameForContext(context);
@ -146,7 +147,7 @@ class ScriptExecutionCallback {
ScriptExecutionCallback& operator=(const ScriptExecutionCallback&) = delete;
void CopyResultToCallingContextAndFinalize(
v8::Isolate* isolate,
v8::Isolate* const isolate,
const v8::Local<v8::Object>& result) {
v8::MaybeLocal<v8::Value> maybe_result;
bool success = true;
@ -155,7 +156,7 @@ class ScriptExecutionCallback {
{
v8::TryCatch try_catch(isolate);
v8::Local<v8::Context> source_context =
result->GetCreationContextChecked();
result->GetCreationContextChecked(isolate);
maybe_result = PassValueToOtherContext(
source_context, promise_.GetContext(), result,
source_context->Global(), false, BridgeErrorTarget::kSource);
@ -201,7 +202,7 @@ class ScriptExecutionCallback {
bool should_clone_value =
!(value->IsObject() &&
promise_.GetContext() ==
value.As<v8::Object>()->GetCreationContextChecked()) &&
value.As<v8::Object>()->GetCreationContextChecked(isolate)) &&
value->IsObject();
if (should_clone_value) {
CopyResultToCallingContextAndFinalize(isolate,
@ -839,7 +840,8 @@ class WebFrameRenderer final
// Get the WebLocalFrame before (possibly) executing any user-space JS while
// getting the |params|. We track the status of the RenderFrame via an
// observer in case it is deleted during user code execution.
content::RenderFrame* render_frame = GetRenderFrame(content_window);
content::RenderFrame* render_frame =
GetRenderFrame(isolate, content_window);
if (!render_frame)
return v8::Null(isolate);
@ -965,8 +967,9 @@ void Initialize(v8::Local<v8::Object> exports,
v8::Isolate* const isolate = v8::Isolate::GetCurrent();
gin_helper::Dictionary dict{isolate, exports};
dict.Set("mainFrame", WebFrameRenderer::Create(
isolate, electron::GetRenderFrame(exports)));
dict.Set("mainFrame",
WebFrameRenderer::Create(
isolate, electron::GetRenderFrame(isolate, exports)));
}
} // namespace

View file

@ -102,7 +102,8 @@
namespace electron {
content::RenderFrame* GetRenderFrame(v8::Local<v8::Object> value);
content::RenderFrame* GetRenderFrame(v8::Isolate* const isolate,
v8::Local<v8::Object> value);
namespace {
@ -613,16 +614,16 @@ void RendererClientBase::AllowGuestViewElementDefinition(
v8::Local<v8::Object> context,
v8::Local<v8::Function> register_cb) {
v8::HandleScope handle_scope(isolate);
v8::Context::Scope context_scope(context->GetCreationContextChecked());
v8::Context::Scope context_scope(context->GetCreationContextChecked(isolate));
blink::WebCustomElement::EmbedderNamesAllowedScope embedder_names_scope;
content::RenderFrame* render_frame = GetRenderFrame(context);
content::RenderFrame* render_frame = GetRenderFrame(isolate, context);
if (!render_frame)
return;
render_frame->GetWebFrame()->RequestExecuteV8Function(
context->GetCreationContextChecked(), register_cb, v8::Null(isolate), 0,
nullptr, base::NullCallback());
context->GetCreationContextChecked(isolate), register_cb,
v8::Null(isolate), 0, nullptr, base::NullCallback());
}
} // namespace electron