From c3f06ef037cb2eaf649d963f13d27265a68d7018 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Thu, 2 Mar 2023 01:03:52 -0800 Subject: [PATCH] fix: DCHECK in MessageSync in rare cases (#37439) --- .../browser/api/electron_api_web_contents.cc | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/shell/browser/api/electron_api_web_contents.cc b/shell/browser/api/electron_api_web_contents.cc index b3193bbb23..cf5067feb5 100644 --- a/shell/browser/api/electron_api_web_contents.cc +++ b/shell/browser/api/electron_api_web_contents.cc @@ -1857,22 +1857,23 @@ class ReplyChannel : public gin::Wrappable { } const char* GetTypeName() override { return "ReplyChannel"; } + void SendError(const std::string& msg) { + v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate(); + // If there's no current context, it means we're shutting down, so we + // don't need to send an event. + if (!isolate->GetCurrentContext().IsEmpty()) { + v8::HandleScope scope(isolate); + auto message = gin::DataObjectBuilder(isolate).Set("error", msg).Build(); + SendReply(isolate, message); + } + } + private: explicit ReplyChannel(InvokeCallback callback) : callback_(std::move(callback)) {} ~ReplyChannel() override { - if (callback_) { - v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate(); - // If there's no current context, it means we're shutting down, so we - // don't need to send an event. - if (!isolate->GetCurrentContext().IsEmpty()) { - v8::HandleScope scope(isolate); - auto message = gin::DataObjectBuilder(isolate) - .Set("error", "reply was never sent") - .Build(); - SendReply(isolate, message); - } - } + if (callback_) + SendError("reply was never sent"); } bool SendReply(v8::Isolate* isolate, v8::Local arg) { @@ -1897,8 +1898,14 @@ gin::Handle WebContents::MakeEventWithSender( content::RenderFrameHost* frame, electron::mojom::ElectronApiIPC::InvokeCallback callback) { v8::Local wrapper; - if (!GetWrapper(isolate).ToLocal(&wrapper)) + if (!GetWrapper(isolate).ToLocal(&wrapper)) { + if (callback) { + // We must always invoke the callback if present. + ReplyChannel::Create(isolate, std::move(callback)) + ->SendError("WebContents was destroyed"); + } return gin::Handle(); + } gin::Handle event = gin_helper::internal::Event::New(isolate); gin_helper::Dictionary dict(isolate, event.ToV8().As());