fix: remove catch-all HandleScope (#22531)
This commit is contained in:
parent
4bca5205bb
commit
19314d3caf
21 changed files with 131 additions and 75 deletions
|
@ -139,23 +139,20 @@ int NodeMain(int argc, char* argv[]) {
|
||||||
JavascriptEnvironment gin_env(loop);
|
JavascriptEnvironment gin_env(loop);
|
||||||
|
|
||||||
v8::Isolate* isolate = gin_env.isolate();
|
v8::Isolate* isolate = gin_env.isolate();
|
||||||
|
v8::Isolate::Scope isolate_scope(isolate);
|
||||||
|
v8::Locker locker(isolate);
|
||||||
|
node::Environment* env = nullptr;
|
||||||
|
node::IsolateData* isolate_data = nullptr;
|
||||||
|
{
|
||||||
|
v8::HandleScope scope(isolate);
|
||||||
|
|
||||||
node::IsolateData* isolate_data =
|
isolate_data = node::CreateIsolateData(isolate, loop, gin_env.platform());
|
||||||
node::CreateIsolateData(isolate, loop, gin_env.platform());
|
|
||||||
CHECK_NE(nullptr, isolate_data);
|
CHECK_NE(nullptr, isolate_data);
|
||||||
|
|
||||||
v8::Locker locker(isolate);
|
env = node::CreateEnvironment(isolate_data, gin_env.context(), argc, argv,
|
||||||
v8::Isolate::Scope isolate_scope(isolate);
|
exec_argc, exec_argv);
|
||||||
v8::HandleScope handle_scope(isolate);
|
|
||||||
|
|
||||||
node::Environment* env = node::CreateEnvironment(
|
|
||||||
isolate_data, gin_env.context(), argc, argv, exec_argc, exec_argv);
|
|
||||||
CHECK_NE(nullptr, env);
|
CHECK_NE(nullptr, env);
|
||||||
|
|
||||||
// Enable support for v8 inspector.
|
|
||||||
NodeDebugger node_debugger(env);
|
|
||||||
node_debugger.Start();
|
|
||||||
|
|
||||||
// TODO(codebytere): we shouldn't have to call this - upstream?
|
// TODO(codebytere): we shouldn't have to call this - upstream?
|
||||||
env->InitializeDiagnostics();
|
env->InitializeDiagnostics();
|
||||||
|
|
||||||
|
@ -172,7 +169,8 @@ int NodeMain(int argc, char* argv[]) {
|
||||||
|
|
||||||
// Setup process.crashReporter.start in child node processes
|
// Setup process.crashReporter.start in child node processes
|
||||||
gin_helper::Dictionary reporter = gin::Dictionary::CreateEmpty(isolate);
|
gin_helper::Dictionary reporter = gin::Dictionary::CreateEmpty(isolate);
|
||||||
reporter.SetMethod("start", &crash_reporter::CrashReporter::StartInstance);
|
reporter.SetMethod("start",
|
||||||
|
&crash_reporter::CrashReporter::StartInstance);
|
||||||
|
|
||||||
#if !defined(OS_LINUX)
|
#if !defined(OS_LINUX)
|
||||||
reporter.SetMethod("addExtraParameter", &AddExtraParameter);
|
reporter.SetMethod("addExtraParameter", &AddExtraParameter);
|
||||||
|
@ -185,9 +183,15 @@ int NodeMain(int argc, char* argv[]) {
|
||||||
if (process.Get("versions", &versions)) {
|
if (process.Get("versions", &versions)) {
|
||||||
versions.SetReadOnly(ELECTRON_PROJECT_NAME, ELECTRON_VERSION_STRING);
|
versions.SetReadOnly(ELECTRON_PROJECT_NAME, ELECTRON_VERSION_STRING);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable support for v8 inspector.
|
||||||
|
NodeDebugger node_debugger(env);
|
||||||
|
node_debugger.Start();
|
||||||
|
|
||||||
// TODO(codebytere): we should try to handle this upstream.
|
// TODO(codebytere): we should try to handle this upstream.
|
||||||
{
|
{
|
||||||
|
v8::HandleScope scope(isolate);
|
||||||
node::InternalCallbackScope callback_scope(
|
node::InternalCallbackScope callback_scope(
|
||||||
env, v8::Local<v8::Object>(), {1, 0},
|
env, v8::Local<v8::Object>(), {1, 0},
|
||||||
node::InternalCallbackScope::kAllowEmptyResource |
|
node::InternalCallbackScope::kAllowEmptyResource |
|
||||||
|
|
|
@ -788,8 +788,11 @@ void App::RenderProcessReady(content::RenderProcessHost* host) {
|
||||||
// `RenderProcessPreferences`, so this is at least more explicit...
|
// `RenderProcessPreferences`, so this is at least more explicit...
|
||||||
content::WebContents* web_contents =
|
content::WebContents* web_contents =
|
||||||
ElectronBrowserClient::Get()->GetWebContentsFromProcessID(host->GetID());
|
ElectronBrowserClient::Get()->GetWebContentsFromProcessID(host->GetID());
|
||||||
if (web_contents)
|
if (web_contents) {
|
||||||
WebContents::FromOrCreate(v8::Isolate::GetCurrent(), web_contents);
|
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||||
|
v8::HandleScope scope(isolate);
|
||||||
|
WebContents::FromOrCreate(isolate, web_contents);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::RenderProcessDisconnected(base::ProcessId host_pid) {
|
void App::RenderProcessDisconnected(base::ProcessId host_pid) {
|
||||||
|
|
|
@ -314,6 +314,7 @@ v8::Local<v8::Promise> Cookies::FlushStore() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cookies::OnCookieChanged(const net::CookieChangeInfo& change) {
|
void Cookies::OnCookieChanged(const net::CookieChangeInfo& change) {
|
||||||
|
v8::HandleScope scope(isolate());
|
||||||
Emit("changed", gin::ConvertToV8(isolate(), change.cookie),
|
Emit("changed", gin::ConvertToV8(isolate(), change.cookie),
|
||||||
gin::ConvertToV8(isolate(), change.cause),
|
gin::ConvertToV8(isolate(), change.cause),
|
||||||
gin::ConvertToV8(isolate(),
|
gin::ConvertToV8(isolate(),
|
||||||
|
|
|
@ -214,6 +214,7 @@ void Menu::OnMenuWillClose() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::OnMenuWillShow() {
|
void Menu::OnMenuWillShow() {
|
||||||
|
v8::HandleScope scope(isolate());
|
||||||
g_menus[weak_map_id()] = v8::Global<v8::Object>(isolate(), GetWrapper());
|
g_menus[weak_map_id()] = v8::Global<v8::Object>(isolate(), GetWrapper());
|
||||||
Emit("menu-will-show");
|
Emit("menu-will-show");
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,8 +85,10 @@ ServiceWorkerContext::~ServiceWorkerContext() {
|
||||||
void ServiceWorkerContext::OnReportConsoleMessage(
|
void ServiceWorkerContext::OnReportConsoleMessage(
|
||||||
int64_t version_id,
|
int64_t version_id,
|
||||||
const content::ConsoleMessage& message) {
|
const content::ConsoleMessage& message) {
|
||||||
|
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||||
|
v8::HandleScope scope(isolate);
|
||||||
Emit("console-message",
|
Emit("console-message",
|
||||||
gin::DataObjectBuilder(v8::Isolate::GetCurrent())
|
gin::DataObjectBuilder(isolate)
|
||||||
.Set("versionId", version_id)
|
.Set("versionId", version_id)
|
||||||
.Set("source", MessageSourceToString(message.source))
|
.Set("source", MessageSourceToString(message.source))
|
||||||
.Set("level", static_cast<int32_t>(message.message_level))
|
.Set("level", static_cast<int32_t>(message.message_level))
|
||||||
|
|
|
@ -433,6 +433,7 @@ void SimpleURLLoaderWrapper::OnRetry(base::OnceClosure start_retry) {}
|
||||||
void SimpleURLLoaderWrapper::OnResponseStarted(
|
void SimpleURLLoaderWrapper::OnResponseStarted(
|
||||||
const GURL& final_url,
|
const GURL& final_url,
|
||||||
const network::mojom::URLResponseHead& response_head) {
|
const network::mojom::URLResponseHead& response_head) {
|
||||||
|
v8::HandleScope scope(isolate());
|
||||||
gin::Dictionary dict = gin::Dictionary::CreateEmpty(isolate());
|
gin::Dictionary dict = gin::Dictionary::CreateEmpty(isolate());
|
||||||
dict.Set("statusCode", response_head.headers->response_code());
|
dict.Set("statusCode", response_head.headers->response_code());
|
||||||
dict.Set("statusMessage", response_head.headers->GetStatusText());
|
dict.Set("statusMessage", response_head.headers->GetStatusText());
|
||||||
|
|
|
@ -6,8 +6,10 @@
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include "gin/data_object_builder.h"
|
||||||
#include "gin/object_template_builder.h"
|
#include "gin/object_template_builder.h"
|
||||||
#include "shell/common/gin_converters/blink_converter.h"
|
#include "shell/common/gin_converters/blink_converter.h"
|
||||||
|
#include "shell/common/gin_converters/std_converter.h"
|
||||||
|
|
||||||
namespace gin_helper {
|
namespace gin_helper {
|
||||||
|
|
||||||
|
@ -15,7 +17,16 @@ gin::WrapperInfo Event::kWrapperInfo = {gin::kEmbedderNativeGin};
|
||||||
|
|
||||||
Event::Event() {}
|
Event::Event() {}
|
||||||
|
|
||||||
Event::~Event() = default;
|
Event::~Event() {
|
||||||
|
if (callback_) {
|
||||||
|
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||||
|
v8::HandleScope scope(isolate);
|
||||||
|
auto message = gin::DataObjectBuilder(isolate)
|
||||||
|
.Set("error", "reply was never sent")
|
||||||
|
.Build();
|
||||||
|
SendReply(isolate, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Event::SetCallback(InvokeCallback callback) {
|
void Event::SetCallback(InvokeCallback callback) {
|
||||||
DCHECK(!callback_);
|
DCHECK(!callback_);
|
||||||
|
|
|
@ -28,10 +28,11 @@ void AutofillDriver::ShowAutofillPopup(
|
||||||
const gfx::RectF& bounds,
|
const gfx::RectF& bounds,
|
||||||
const std::vector<base::string16>& values,
|
const std::vector<base::string16>& values,
|
||||||
const std::vector<base::string16>& labels) {
|
const std::vector<base::string16>& labels) {
|
||||||
|
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||||
|
v8::HandleScope scope(isolate);
|
||||||
auto* web_contents =
|
auto* web_contents =
|
||||||
api::WebContents::From(
|
api::WebContents::From(isolate, content::WebContents::FromRenderFrameHost(
|
||||||
v8::Isolate::GetCurrent(),
|
render_frame_host_))
|
||||||
content::WebContents::FromRenderFrameHost(render_frame_host_))
|
|
||||||
.get();
|
.get();
|
||||||
if (!web_contents || !web_contents->owner_window())
|
if (!web_contents || !web_contents->owner_window())
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1300,6 +1300,7 @@ bool ElectronBrowserClient::WillInterceptWebSocket(
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||||
|
v8::HandleScope scope(isolate);
|
||||||
auto* browser_context = frame->GetProcess()->GetBrowserContext();
|
auto* browser_context = frame->GetProcess()->GetBrowserContext();
|
||||||
auto web_request = api::WebRequest::FromOrCreate(isolate, browser_context);
|
auto web_request = api::WebRequest::FromOrCreate(isolate, browser_context);
|
||||||
|
|
||||||
|
@ -1320,6 +1321,7 @@ void ElectronBrowserClient::CreateWebSocket(
|
||||||
mojo::PendingRemote<network::mojom::WebSocketHandshakeClient>
|
mojo::PendingRemote<network::mojom::WebSocketHandshakeClient>
|
||||||
handshake_client) {
|
handshake_client) {
|
||||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||||
|
v8::HandleScope scope(isolate);
|
||||||
auto* browser_context = frame->GetProcess()->GetBrowserContext();
|
auto* browser_context = frame->GetProcess()->GetBrowserContext();
|
||||||
auto web_request = api::WebRequest::FromOrCreate(isolate, browser_context);
|
auto web_request = api::WebRequest::FromOrCreate(isolate, browser_context);
|
||||||
DCHECK(web_request.get());
|
DCHECK(web_request.get());
|
||||||
|
@ -1345,6 +1347,7 @@ bool ElectronBrowserClient::WillCreateURLLoaderFactory(
|
||||||
bool* disable_secure_dns,
|
bool* disable_secure_dns,
|
||||||
network::mojom::URLLoaderFactoryOverridePtr* factory_override) {
|
network::mojom::URLLoaderFactoryOverridePtr* factory_override) {
|
||||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||||
|
v8::HandleScope scope(isolate);
|
||||||
api::Protocol* protocol =
|
api::Protocol* protocol =
|
||||||
api::Protocol::FromWrappedClass(isolate, browser_context);
|
api::Protocol::FromWrappedClass(isolate, browser_context);
|
||||||
DCHECK(protocol);
|
DCHECK(protocol);
|
||||||
|
|
|
@ -293,6 +293,8 @@ void ElectronBrowserMainParts::PostEarlyInitialization() {
|
||||||
// avoid conflicts we only initialize our V8 environment after that.
|
// avoid conflicts we only initialize our V8 environment after that.
|
||||||
js_env_ = std::make_unique<JavascriptEnvironment>(node_bindings_->uv_loop());
|
js_env_ = std::make_unique<JavascriptEnvironment>(node_bindings_->uv_loop());
|
||||||
|
|
||||||
|
v8::HandleScope scope(js_env_->isolate());
|
||||||
|
|
||||||
node_bindings_->Initialize();
|
node_bindings_->Initialize();
|
||||||
// Create the global environment.
|
// Create the global environment.
|
||||||
node::Environment* env = node_bindings_->CreateEnvironment(
|
node::Environment* env = node_bindings_->CreateEnvironment(
|
||||||
|
|
|
@ -28,8 +28,9 @@ ElectronNavigationThrottle::WillRedirectRequest() {
|
||||||
return PROCEED;
|
return PROCEED;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto api_contents =
|
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||||
electron::api::WebContents::From(v8::Isolate::GetCurrent(), contents);
|
v8::HandleScope scope(isolate);
|
||||||
|
auto api_contents = electron::api::WebContents::From(isolate, contents);
|
||||||
if (api_contents.IsEmpty()) {
|
if (api_contents.IsEmpty()) {
|
||||||
// No need to emit any event if the WebContents is not available in JS.
|
// No need to emit any event if the WebContents is not available in JS.
|
||||||
return PROCEED;
|
return PROCEED;
|
||||||
|
|
|
@ -29,13 +29,21 @@ JavascriptEnvironment::JavascriptEnvironment(uv_loop_t* event_loop)
|
||||||
gin::IsolateHolder::IsolateType::kUtility,
|
gin::IsolateHolder::IsolateType::kUtility,
|
||||||
gin::IsolateHolder::IsolateCreationMode::kNormal,
|
gin::IsolateHolder::IsolateCreationMode::kNormal,
|
||||||
isolate_),
|
isolate_),
|
||||||
isolate_scope_(isolate_),
|
locker_(isolate_) {
|
||||||
locker_(isolate_),
|
isolate_->Enter();
|
||||||
handle_scope_(isolate_),
|
v8::HandleScope scope(isolate_);
|
||||||
context_(isolate_, node::NewContext(isolate_)),
|
auto context = node::NewContext(isolate_);
|
||||||
context_scope_(v8::Local<v8::Context>::New(isolate_, context_)) {}
|
context_ = v8::Global<v8::Context>(isolate_, context);
|
||||||
|
context->Enter();
|
||||||
|
}
|
||||||
|
|
||||||
JavascriptEnvironment::~JavascriptEnvironment() = default;
|
JavascriptEnvironment::~JavascriptEnvironment() {
|
||||||
|
{
|
||||||
|
v8::HandleScope scope(isolate_);
|
||||||
|
context_.Get(isolate_)->Exit();
|
||||||
|
}
|
||||||
|
isolate_->Exit();
|
||||||
|
}
|
||||||
|
|
||||||
v8::Isolate* JavascriptEnvironment::Initialize(uv_loop_t* event_loop) {
|
v8::Isolate* JavascriptEnvironment::Initialize(uv_loop_t* event_loop) {
|
||||||
auto* cmd = base::CommandLine::ForCurrentProcess();
|
auto* cmd = base::CommandLine::ForCurrentProcess();
|
||||||
|
|
|
@ -41,11 +41,8 @@ class JavascriptEnvironment {
|
||||||
|
|
||||||
v8::Isolate* isolate_;
|
v8::Isolate* isolate_;
|
||||||
gin::IsolateHolder isolate_holder_;
|
gin::IsolateHolder isolate_holder_;
|
||||||
v8::Isolate::Scope isolate_scope_;
|
|
||||||
v8::Locker locker_;
|
v8::Locker locker_;
|
||||||
v8::HandleScope handle_scope_;
|
|
||||||
v8::Global<v8::Context> context_;
|
v8::Global<v8::Context> context_;
|
||||||
v8::Context::Scope context_scope_;
|
|
||||||
|
|
||||||
std::unique_ptr<MicrotasksRunner> microtasks_runner_;
|
std::unique_ptr<MicrotasksRunner> microtasks_runner_;
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ void LoginHandler::EmitEvent(
|
||||||
scoped_refptr<net::HttpResponseHeaders> response_headers,
|
scoped_refptr<net::HttpResponseHeaders> response_headers,
|
||||||
bool first_auth_attempt) {
|
bool first_auth_attempt) {
|
||||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||||
|
v8::HandleScope scope(isolate);
|
||||||
|
|
||||||
auto api_web_contents = api::WebContents::From(isolate, web_contents());
|
auto api_web_contents = api::WebContents::From(isolate, web_contents());
|
||||||
if (api_web_contents.IsEmpty()) {
|
if (api_web_contents.IsEmpty()) {
|
||||||
|
@ -58,8 +59,6 @@ void LoginHandler::EmitEvent(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::HandleScope scope(isolate);
|
|
||||||
|
|
||||||
auto details = gin::Dictionary::CreateEmpty(isolate);
|
auto details = gin::Dictionary::CreateEmpty(isolate);
|
||||||
details.Set("url", url);
|
details.Set("url", url);
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,7 @@ void NodeStreamLoader::ReadMore() {
|
||||||
}
|
}
|
||||||
is_reading_ = true;
|
is_reading_ = true;
|
||||||
auto weak = weak_factory_.GetWeakPtr();
|
auto weak = weak_factory_.GetWeakPtr();
|
||||||
|
v8::HandleScope scope(isolate_);
|
||||||
// buffer = emitter.read()
|
// buffer = emitter.read()
|
||||||
v8::MaybeLocal<v8::Value> ret = node::MakeCallback(
|
v8::MaybeLocal<v8::Value> ret = node::MakeCallback(
|
||||||
isolate_, emitter_.Get(isolate_), "read", 0, nullptr, {0, 0});
|
isolate_, emitter_.Get(isolate_), "read", 0, nullptr, {0, 0});
|
||||||
|
|
|
@ -302,6 +302,7 @@ void OpenDialogCompletion(int chosen,
|
||||||
NSOpenPanel* dialog,
|
NSOpenPanel* dialog,
|
||||||
bool security_scoped_bookmarks,
|
bool security_scoped_bookmarks,
|
||||||
gin_helper::Promise<gin_helper::Dictionary> promise) {
|
gin_helper::Promise<gin_helper::Dictionary> promise) {
|
||||||
|
v8::HandleScope scope(promise.isolate());
|
||||||
gin_helper::Dictionary dict = gin::Dictionary::CreateEmpty(promise.isolate());
|
gin_helper::Dictionary dict = gin::Dictionary::CreateEmpty(promise.isolate());
|
||||||
if (chosen == NSFileHandlingPanelCancelButton) {
|
if (chosen == NSFileHandlingPanelCancelButton) {
|
||||||
dict.Set("canceled", true);
|
dict.Set("canceled", true);
|
||||||
|
@ -379,6 +380,7 @@ void SaveDialogCompletion(int chosen,
|
||||||
NSSavePanel* dialog,
|
NSSavePanel* dialog,
|
||||||
bool security_scoped_bookmarks,
|
bool security_scoped_bookmarks,
|
||||||
gin_helper::Promise<gin_helper::Dictionary> promise) {
|
gin_helper::Promise<gin_helper::Dictionary> promise) {
|
||||||
|
v8::HandleScope scope(promise.isolate());
|
||||||
gin_helper::Dictionary dict = gin::Dictionary::CreateEmpty(promise.isolate());
|
gin_helper::Dictionary dict = gin::Dictionary::CreateEmpty(promise.isolate());
|
||||||
if (chosen == NSFileHandlingPanelCancelButton) {
|
if (chosen == NSFileHandlingPanelCancelButton) {
|
||||||
dict.Set("canceled", true);
|
dict.Set("canceled", true);
|
||||||
|
|
|
@ -38,6 +38,7 @@ v8::Local<v8::Object> CreateEvent(v8::Isolate* isolate,
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
||||||
|
CHECK(!context.IsEmpty());
|
||||||
v8::Local<v8::Object> event =
|
v8::Local<v8::Object> event =
|
||||||
v8::Local<v8::ObjectTemplate>::New(isolate, event_template)
|
v8::Local<v8::ObjectTemplate>::New(isolate, event_template)
|
||||||
->NewInstance(context)
|
->NewInstance(context)
|
||||||
|
|
|
@ -55,13 +55,16 @@ class TrackableObject : public TrackableObjectBase, public EventEmitter<T> {
|
||||||
public:
|
public:
|
||||||
// Mark the JS object as destroyed.
|
// Mark the JS object as destroyed.
|
||||||
void MarkDestroyed() {
|
void MarkDestroyed() {
|
||||||
|
v8::HandleScope scope(gin_helper::Wrappable<T>::isolate());
|
||||||
v8::Local<v8::Object> wrapper = gin_helper::Wrappable<T>::GetWrapper();
|
v8::Local<v8::Object> wrapper = gin_helper::Wrappable<T>::GetWrapper();
|
||||||
if (!wrapper.IsEmpty()) {
|
if (!wrapper.IsEmpty()) {
|
||||||
wrapper->SetAlignedPointerInInternalField(0, nullptr);
|
wrapper->SetAlignedPointerInInternalField(0, nullptr);
|
||||||
|
gin_helper::WrappableBase::wrapper_.ClearWeak();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsDestroyed() {
|
bool IsDestroyed() {
|
||||||
|
v8::HandleScope scope(gin_helper::Wrappable<T>::isolate());
|
||||||
v8::Local<v8::Object> wrapper = gin_helper::Wrappable<T>::GetWrapper();
|
v8::Local<v8::Object> wrapper = gin_helper::Wrappable<T>::GetWrapper();
|
||||||
return wrapper->InternalFieldCount() == 0 ||
|
return wrapper->InternalFieldCount() == 0 ||
|
||||||
wrapper->GetAlignedPointerFromInternalField(0) == nullptr;
|
wrapper->GetAlignedPointerFromInternalField(0) == nullptr;
|
||||||
|
@ -72,6 +75,7 @@ class TrackableObject : public TrackableObjectBase, public EventEmitter<T> {
|
||||||
if (!weak_map_)
|
if (!weak_map_)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
v8::HandleScope scope(isolate);
|
||||||
v8::MaybeLocal<v8::Object> object = weak_map_->Get(isolate, id);
|
v8::MaybeLocal<v8::Object> object = weak_map_->Get(isolate, id);
|
||||||
if (object.IsEmpty())
|
if (object.IsEmpty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -16,6 +16,7 @@ WrappableBase::~WrappableBase() {
|
||||||
if (wrapper_.IsEmpty())
|
if (wrapper_.IsEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
v8::HandleScope scope(isolate());
|
||||||
GetWrapper()->SetAlignedPointerInInternalField(0, nullptr);
|
GetWrapper()->SetAlignedPointerInInternalField(0, nullptr);
|
||||||
wrapper_.ClearWeak();
|
wrapper_.ClearWeak();
|
||||||
wrapper_.Reset();
|
wrapper_.Reset();
|
||||||
|
@ -49,7 +50,8 @@ void WrappableBase::InitWith(v8::Isolate* isolate,
|
||||||
isolate_ = isolate;
|
isolate_ = isolate;
|
||||||
wrapper->SetAlignedPointerInInternalField(0, this);
|
wrapper->SetAlignedPointerInInternalField(0, this);
|
||||||
wrapper_.Reset(isolate, wrapper);
|
wrapper_.Reset(isolate, wrapper);
|
||||||
wrapper_.SetWeak(this, FirstWeakCallback, v8::WeakCallbackType::kParameter);
|
wrapper_.SetWeak(this, FirstWeakCallback,
|
||||||
|
v8::WeakCallbackType::kInternalFields);
|
||||||
|
|
||||||
// Call object._init if we have one.
|
// Call object._init if we have one.
|
||||||
v8::Local<v8::Function> init;
|
v8::Local<v8::Function> init;
|
||||||
|
@ -62,24 +64,21 @@ void WrappableBase::InitWith(v8::Isolate* isolate,
|
||||||
// static
|
// static
|
||||||
void WrappableBase::FirstWeakCallback(
|
void WrappableBase::FirstWeakCallback(
|
||||||
const v8::WeakCallbackInfo<WrappableBase>& data) {
|
const v8::WeakCallbackInfo<WrappableBase>& data) {
|
||||||
WrappableBase* wrappable = data.GetParameter();
|
WrappableBase* wrappable =
|
||||||
|
static_cast<WrappableBase*>(data.GetInternalField(0));
|
||||||
|
if (wrappable) {
|
||||||
wrappable->wrapper_.Reset();
|
wrappable->wrapper_.Reset();
|
||||||
data.SetSecondPassCallback(SecondWeakCallback);
|
data.SetSecondPassCallback(SecondWeakCallback);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void WrappableBase::SecondWeakCallback(
|
void WrappableBase::SecondWeakCallback(
|
||||||
const v8::WeakCallbackInfo<WrappableBase>& data) {
|
const v8::WeakCallbackInfo<WrappableBase>& data) {
|
||||||
// Certain classes (for example api::WebContents and api::WebContentsView)
|
WrappableBase* wrappable =
|
||||||
// are running JS code in the destructor, while V8 may crash when JS code
|
static_cast<WrappableBase*>(data.GetInternalField(0));
|
||||||
// runs inside weak callback.
|
if (wrappable)
|
||||||
//
|
delete wrappable;
|
||||||
// We work around this problem by delaying the deletion to next tick where
|
|
||||||
// garbage collection is done.
|
|
||||||
base::ThreadTaskRunnerHandle::Get()->PostNonNestableTask(
|
|
||||||
FROM_HERE,
|
|
||||||
base::BindOnce([](WrappableBase* wrappable) { delete wrappable; },
|
|
||||||
base::Unretained(data.GetParameter())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
|
@ -52,6 +52,8 @@ class WrappableBase {
|
||||||
// Helper to init with arguments.
|
// Helper to init with arguments.
|
||||||
void InitWithArgs(gin::Arguments* args);
|
void InitWithArgs(gin::Arguments* args);
|
||||||
|
|
||||||
|
v8::Global<v8::Object> wrapper_; // Weak
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void FirstWeakCallback(
|
static void FirstWeakCallback(
|
||||||
const v8::WeakCallbackInfo<WrappableBase>& data);
|
const v8::WeakCallbackInfo<WrappableBase>& data);
|
||||||
|
@ -59,7 +61,6 @@ class WrappableBase {
|
||||||
const v8::WeakCallbackInfo<WrappableBase>& data);
|
const v8::WeakCallbackInfo<WrappableBase>& data);
|
||||||
|
|
||||||
v8::Isolate* isolate_ = nullptr;
|
v8::Isolate* isolate_ = nullptr;
|
||||||
v8::Global<v8::Object> wrapper_; // Weak
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(WrappableBase);
|
DISALLOW_COPY_AND_ASSIGN(WrappableBase);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { BrowserWindow, ipcMain, IpcMainInvokeEvent } from 'electron'
|
import { BrowserWindow, ipcMain, IpcMainInvokeEvent } from 'electron'
|
||||||
|
import { emittedOnce } from './events-helpers'
|
||||||
|
|
||||||
|
const v8Util = process.electronBinding('v8_util')
|
||||||
|
|
||||||
describe('ipc module', () => {
|
describe('ipc module', () => {
|
||||||
describe('invoke', () => {
|
describe('invoke', () => {
|
||||||
|
@ -103,6 +106,17 @@ describe('ipc module', () => {
|
||||||
ipcMain.removeHandler('test')
|
ipcMain.removeHandler('test')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('throws an error in the renderer if the reply callback is dropped', async () => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
ipcMain.handleOnce('test', () => new Promise(resolve => {
|
||||||
|
setTimeout(() => v8Util.requestGarbageCollectionForTesting())
|
||||||
|
/* never resolve */
|
||||||
|
}))
|
||||||
|
w.webContents.executeJavaScript(`(${rendererInvoke})()`)
|
||||||
|
const [, { error }] = await emittedOnce(ipcMain, 'result')
|
||||||
|
expect(error).to.match(/reply was never sent/)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('ordering', () => {
|
describe('ordering', () => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue