fix: WebContentsView
removal should compare directly (#44673)
fix: `WebContentsView` removal should compare directly (#44656) * fix: WebContentsView removal should compare directly * fixup view comparision * chore: use erase_if * Apply review suggestions --------- Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
This commit is contained in:
parent
9c5c5d0fea
commit
2bd3a9fe65
3 changed files with 43 additions and 26 deletions
|
@ -122,15 +122,6 @@ 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 <>
|
template <>
|
||||||
struct Converter<views::SizeBound> {
|
struct Converter<views::SizeBound> {
|
||||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||||
|
@ -193,7 +184,10 @@ View::~View() {
|
||||||
void View::ReorderChildView(gin::Handle<View> child, size_t index) {
|
void View::ReorderChildView(gin::Handle<View> child, size_t index) {
|
||||||
view_->ReorderChildView(child->view(), index);
|
view_->ReorderChildView(child->view(), index);
|
||||||
|
|
||||||
const auto i = base::ranges::find(child_views_, child.ToV8());
|
const auto i =
|
||||||
|
std::ranges::find_if(child_views_, [&](const ChildPair& child_view) {
|
||||||
|
return child_view.first == child->view();
|
||||||
|
});
|
||||||
DCHECK(i != child_views_.end());
|
DCHECK(i != child_views_.end());
|
||||||
|
|
||||||
// If |view| is already at the desired position, there's nothing to do.
|
// If |view| is already at the desired position, there's nothing to do.
|
||||||
|
@ -237,8 +231,9 @@ void View::AddChildViewAt(gin::Handle<View> child,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
child_views_.emplace(child_views_.begin() + index, // index
|
child_views_.emplace(child_views_.begin() + index, // index
|
||||||
isolate(), child->GetWrapper()); // v8::Global(args...)
|
child->view(),
|
||||||
|
v8::Global<v8::Object>(isolate(), child->GetWrapper()));
|
||||||
#if BUILDFLAG(IS_MAC)
|
#if BUILDFLAG(IS_MAC)
|
||||||
// Disable the implicit CALayer animations that happen by default when adding
|
// Disable the implicit CALayer animations that happen by default when adding
|
||||||
// or removing sublayers.
|
// or removing sublayers.
|
||||||
|
@ -258,7 +253,10 @@ void View::RemoveChildView(gin::Handle<View> child) {
|
||||||
if (!view_)
|
if (!view_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto it = base::ranges::find(child_views_, child.ToV8());
|
const auto it =
|
||||||
|
std::ranges::find_if(child_views_, [&](const ChildPair& child_view) {
|
||||||
|
return child_view.first == child->view();
|
||||||
|
});
|
||||||
if (it != child_views_.end()) {
|
if (it != child_views_.end()) {
|
||||||
#if BUILDFLAG(IS_MAC)
|
#if BUILDFLAG(IS_MAC)
|
||||||
ScopedCAActionDisabler disable_animations;
|
ScopedCAActionDisabler disable_animations;
|
||||||
|
@ -336,8 +334,8 @@ std::vector<v8::Local<v8::Value>> View::GetChildren() {
|
||||||
|
|
||||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||||
|
|
||||||
for (auto& child_view : child_views_)
|
for (auto& [view, global] : child_views_)
|
||||||
ret.push_back(child_view.Get(isolate));
|
ret.push_back(global.Get(isolate));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -364,16 +362,9 @@ void View::OnViewIsDeleting(views::View* observed_view) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void View::OnChildViewRemoved(views::View* observed_view, views::View* child) {
|
void View::OnChildViewRemoved(views::View* observed_view, views::View* child) {
|
||||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
std::erase_if(child_views_, [child](const ChildPair& child_view) {
|
||||||
auto it = std::ranges::find_if(
|
return child_view.first == child;
|
||||||
child_views_, [&](const v8::Global<v8::Object>& child_view) {
|
});
|
||||||
View current_view;
|
|
||||||
gin::ConvertFromV8(isolate, child_view.Get(isolate), ¤t_view);
|
|
||||||
return current_view.view()->GetID() == child->GetID();
|
|
||||||
});
|
|
||||||
if (it != child_views_.end()) {
|
|
||||||
child_views_.erase(it);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
namespace electron::api {
|
namespace electron::api {
|
||||||
|
|
||||||
|
using ChildPair = std::pair<raw_ptr<views::View>, v8::Global<v8::Object>>;
|
||||||
|
|
||||||
class View : public gin_helper::EventEmitter<View>, public views::ViewObserver {
|
class View : public gin_helper::EventEmitter<View>, public views::ViewObserver {
|
||||||
public:
|
public:
|
||||||
static gin_helper::WrappableBase* New(gin::Arguments* args);
|
static gin_helper::WrappableBase* New(gin::Arguments* args);
|
||||||
|
@ -61,7 +63,7 @@ class View : public gin_helper::EventEmitter<View>, public views::ViewObserver {
|
||||||
private:
|
private:
|
||||||
void ReorderChildView(gin::Handle<View> child, size_t index);
|
void ReorderChildView(gin::Handle<View> child, size_t index);
|
||||||
|
|
||||||
std::vector<v8::Global<v8::Object>> child_views_;
|
std::vector<ChildPair> child_views_;
|
||||||
|
|
||||||
bool delete_view_ = true;
|
bool delete_view_ = true;
|
||||||
raw_ptr<views::View> view_ = nullptr;
|
raw_ptr<views::View> view_ = nullptr;
|
||||||
|
|
|
@ -100,6 +100,30 @@ describe('WebContentsView', () => {
|
||||||
expect(w.contentView.children).to.deep.equal([wcv3, wcv1, wcv2]);
|
expect(w.contentView.children).to.deep.equal([wcv3, wcv1, wcv2]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('handle removal and re-addition of children', () => {
|
||||||
|
const w = new BaseWindow({ show: false });
|
||||||
|
const cv = new View();
|
||||||
|
w.setContentView(cv);
|
||||||
|
|
||||||
|
const wcv1 = new WebContentsView();
|
||||||
|
const wcv2 = new WebContentsView();
|
||||||
|
|
||||||
|
expect(w.contentView.children).to.deep.equal([]);
|
||||||
|
|
||||||
|
w.contentView.addChildView(wcv1);
|
||||||
|
w.contentView.addChildView(wcv2);
|
||||||
|
|
||||||
|
expect(w.contentView.children).to.deep.equal([wcv1, wcv2]);
|
||||||
|
|
||||||
|
w.contentView.removeChildView(wcv1);
|
||||||
|
|
||||||
|
expect(w.contentView.children).to.deep.equal([wcv2]);
|
||||||
|
|
||||||
|
w.contentView.addChildView(wcv1);
|
||||||
|
|
||||||
|
expect(w.contentView.children).to.deep.equal([wcv2, wcv1]);
|
||||||
|
});
|
||||||
|
|
||||||
function triggerGCByAllocation () {
|
function triggerGCByAllocation () {
|
||||||
const arr = [];
|
const arr = [];
|
||||||
for (let i = 0; i < 1000000; i++) {
|
for (let i = 0; i < 1000000; i++) {
|
||||||
|
|
Loading…
Reference in a new issue