Skip to content

Commit 9a8939f

Browse files
committed
fix insane weakref behavior when assigned to nullptr
1 parent e3df146 commit 9a8939f

File tree

2 files changed

+28
-11
lines changed

2 files changed

+28
-11
lines changed

loader/include/Geode/utils/cocos.hpp

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ namespace geode {
413413
* to it is freed or locked
414414
* @param obj Object to construct the WeakRef from
415415
*/
416-
WeakRef(T* obj) : m_controller(WeakRefPool::get()->manage(obj)) {}
416+
WeakRef(T* obj) : m_controller(obj ? WeakRefPool::get()->manage(obj) : nullptr) {}
417417

418418
WeakRef(WeakRef<T> const& other) : WeakRef(other.m_controller) {}
419419

@@ -437,7 +437,7 @@ namespace geode {
437437
* a null Ref if the object has been freed
438438
*/
439439
Ref<T> lock() const {
440-
if (m_controller->isManaged()) {
440+
if (m_controller && m_controller->isManaged()) {
441441
return Ref(static_cast<T*>(m_controller->get()));
442442
}
443443
return Ref<T>(nullptr);
@@ -447,7 +447,7 @@ namespace geode {
447447
* Check if the WeakRef points to a valid object
448448
*/
449449
bool valid() const {
450-
return m_controller->isManaged();
450+
return m_controller && m_controller->isManaged();
451451
}
452452

453453
/**
@@ -456,7 +456,13 @@ namespace geode {
456456
* @param other The new object to swap to
457457
*/
458458
void swap(T* other) {
459-
m_controller->swap(other);
459+
if (m_controller) {
460+
m_controller->swap(other);
461+
} else if (other) {
462+
m_controller = WeakRefPool::get()->manage(other);
463+
} else {
464+
m_controller = nullptr;
465+
}
460466
}
461467

462468
Ref<T> operator=(T* obj) {
@@ -465,7 +471,7 @@ namespace geode {
465471
}
466472

467473
WeakRef<T>& operator=(WeakRef<T> const& other) {
468-
this->swap(static_cast<T*>(other.m_controller->get()));
474+
this->swap(static_cast<T*>(other.m_controller ? other.m_controller->get() : nullptr));
469475
return *this;
470476
}
471477

@@ -479,33 +485,40 @@ namespace geode {
479485
}
480486

481487
bool operator==(T* other) const {
482-
return m_controller->get() == other;
488+
return (m_controller && m_controller->get() == other) || (!m_controller && !other);
483489
}
484490

485491
bool operator==(WeakRef<T> const& other) const {
492+
if (!m_controller && !other.m_controller) return true;
493+
if (!m_controller || !other.m_controller) return false;
494+
486495
return m_controller->get() == other.m_controller->get();
487496
}
488497

489498
bool operator!=(T* other) const {
490-
return m_controller->get() != other;
499+
return !(*this == other);
491500
}
492501

493502
bool operator!=(WeakRef<T> const& other) const {
494-
return m_controller->get() != other.m_controller->get();
503+
return !(*this == other);
495504
}
496505

497506
// for containers
498507
bool operator<(WeakRef<T> const& other) const {
508+
if (!m_controller && !other.m_controller) return false;
509+
if (!m_controller) return true;
510+
if (!other.m_controller) return false;
511+
499512
return m_controller->get() < other.m_controller->get();
500513
}
501514
bool operator<=(WeakRef<T> const& other) const {
502-
return m_controller->get() <= other.m_controller->get();
515+
return !(*this > other);
503516
}
504517
bool operator>(WeakRef<T> const& other) const {
505-
return m_controller->get() > other.m_controller->get();
518+
return other < *this;
506519
}
507520
bool operator>=(WeakRef<T> const& other) const {
508-
return m_controller->get() >= other.m_controller->get();
521+
return !(*this < other);
509522
}
510523
};
511524

loader/src/utils/cocos.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,10 @@ void WeakRefPool::check(CCObject* obj) {
290290
}
291291

292292
std::shared_ptr<WeakRefController> WeakRefPool::manage(CCObject* obj) {
293+
if (!obj) {
294+
return std::shared_ptr<WeakRefController>();
295+
}
296+
293297
if (!m_pool.contains(obj)) {
294298
CC_SAFE_RETAIN(obj);
295299
auto controller = std::make_shared<WeakRefController>();

0 commit comments

Comments
 (0)