fix: segfault when moving WebContentsView between BrowserWindows (#44599)

* fix: segfault when moving WebContentsView between BrowserWindows

* chore: actually enable fix

* fixup segfault when moving WebContentsView between BrowserWindows
This commit is contained in:
John Kleinschmidt 2024-11-11 18:44:13 -05:00 committed by GitHub
parent c6c430bff1
commit 777e547922
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 58 additions and 1 deletions

View file

@ -124,6 +124,15 @@ struct Converter<views::FlexAllocationOrder> {
}
};
template <>
struct Converter<electron::api::View> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
electron::api::View* out) {
return gin::ConvertFromV8(isolate, val, &out);
}
};
template <>
struct Converter<views::SizeBound> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
@ -257,11 +266,13 @@ void View::RemoveChildView(gin::Handle<View> child) {
#if BUILDFLAG(IS_MAC)
ScopedCAActionDisabler disable_animations;
#endif
// Remove from child_views first so that OnChildViewRemoved doesn't try to
// remove it again
child_views_.erase(it);
// It's possible for the child's view to be invalid here
// if the child's webContents was closed or destroyed.
if (child->view())
view_->RemoveChildView(child->view());
child_views_.erase(it);
}
}
@ -388,6 +399,19 @@ void View::OnViewIsDeleting(views::View* observed_view) {
view_ = nullptr;
}
void View::OnChildViewRemoved(views::View* observed_view, views::View* child) {
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
auto it = std::ranges::find_if(
child_views_, [&](const v8::Global<v8::Object>& child_view) {
View current_view;
gin::ConvertFromV8(isolate, child_view.Get(isolate), &current_view);
return current_view.view()->GetID() == child->GetID();
});
if (it != child_views_.end()) {
child_views_.erase(it);
}
}
// static
gin_helper::WrappableBase* View::New(gin::Arguments* args) {
View* view = new View();

View file

@ -47,6 +47,8 @@ class View : public gin_helper::EventEmitter<View>,
// views::ViewObserver
void OnViewBoundsChanged(views::View* observed_view) override;
void OnViewIsDeleting(views::View* observed_view) override;
void OnChildViewRemoved(views::View* observed_view,
views::View* child) override;
views::View* view() const { return view_; }
std::optional<int> border_radius() const { return border_radius_; }