Skip to content

Commit 2e00a0e

Browse files
legendecasJonasBa
authored andcommitted
src: add BaseObjectPtr nullptr operations
Allow comparing a `BaseObjectPtr` or implicitly construct a `BaseObjectPtr` with `nullptr`. PR-URL: nodejs#56585 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
1 parent d6f5002 commit 2e00a0e

9 files changed

+81
-15
lines changed

src/base_object-inl.h

+21
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,17 @@ BaseObjectPtrImpl<T, kIsWeak>& BaseObjectPtrImpl<T, kIsWeak>::operator=(
250250
return *new (this) BaseObjectPtrImpl(std::move(other));
251251
}
252252

253+
template <typename T, bool kIsWeak>
254+
BaseObjectPtrImpl<T, kIsWeak>::BaseObjectPtrImpl(std::nullptr_t)
255+
: BaseObjectPtrImpl() {}
256+
257+
template <typename T, bool kIsWeak>
258+
BaseObjectPtrImpl<T, kIsWeak>& BaseObjectPtrImpl<T, kIsWeak>::operator=(
259+
std::nullptr_t) {
260+
this->~BaseObjectPtrImpl();
261+
return *new (this) BaseObjectPtrImpl();
262+
}
263+
253264
template <typename T, bool kIsWeak>
254265
void BaseObjectPtrImpl<T, kIsWeak>::reset(T* ptr) {
255266
*this = BaseObjectPtrImpl(ptr);
@@ -289,6 +300,16 @@ bool BaseObjectPtrImpl<T, kIsWeak>::operator !=(
289300
return get() != other.get();
290301
}
291302

303+
template <typename T, bool kIsWeak>
304+
bool operator==(const BaseObjectPtrImpl<T, kIsWeak> ptr, const std::nullptr_t) {
305+
return ptr.get() == nullptr;
306+
}
307+
308+
template <typename T, bool kIsWeak>
309+
bool operator==(const std::nullptr_t, const BaseObjectPtrImpl<T, kIsWeak> ptr) {
310+
return ptr.get() == nullptr;
311+
}
312+
292313
template <typename T, typename... Args>
293314
BaseObjectPtr<T> MakeBaseObject(Args&&... args) {
294315
return BaseObjectPtr<T>(new T(std::forward<Args>(args)...));

src/base_object.h

+10
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,9 @@ class BaseObjectPtrImpl final {
288288
inline BaseObjectPtrImpl(BaseObjectPtrImpl&& other);
289289
inline BaseObjectPtrImpl& operator=(BaseObjectPtrImpl&& other);
290290

291+
inline BaseObjectPtrImpl(std::nullptr_t);
292+
inline BaseObjectPtrImpl& operator=(std::nullptr_t);
293+
291294
inline void reset(T* ptr = nullptr);
292295
inline T* get() const;
293296
inline T& operator*() const;
@@ -309,6 +312,13 @@ class BaseObjectPtrImpl final {
309312
inline BaseObject::PointerData* pointer_data() const;
310313
};
311314

315+
template <typename T, bool kIsWeak>
316+
inline static bool operator==(const BaseObjectPtrImpl<T, kIsWeak>,
317+
const std::nullptr_t);
318+
template <typename T, bool kIsWeak>
319+
inline static bool operator==(const std::nullptr_t,
320+
const BaseObjectPtrImpl<T, kIsWeak>);
321+
312322
template <typename T>
313323
using BaseObjectPtr = BaseObjectPtrImpl<T, false>;
314324
template <typename T>

src/histogram.cc

+3-3
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ BaseObjectPtr<HistogramBase> HistogramBase::Create(
226226
->InstanceTemplate()
227227
->NewInstance(env->context())
228228
.ToLocal(&obj)) {
229-
return BaseObjectPtr<HistogramBase>();
229+
return nullptr;
230230
}
231231

232232
return MakeBaseObject<HistogramBase>(env, obj, options);
@@ -240,7 +240,7 @@ BaseObjectPtr<HistogramBase> HistogramBase::Create(
240240
->InstanceTemplate()
241241
->NewInstance(env->context())
242242
.ToLocal(&obj)) {
243-
return BaseObjectPtr<HistogramBase>();
243+
return nullptr;
244244
}
245245
return MakeBaseObject<HistogramBase>(env, obj, std::move(histogram));
246246
}
@@ -394,7 +394,7 @@ BaseObjectPtr<IntervalHistogram> IntervalHistogram::Create(
394394
if (!GetConstructorTemplate(env)
395395
->InstanceTemplate()
396396
->NewInstance(env->context()).ToLocal(&obj)) {
397-
return BaseObjectPtr<IntervalHistogram>();
397+
return nullptr;
398398
}
399399

400400
return MakeBaseObject<IntervalHistogram>(

src/node_blob.cc

+3-4
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,10 @@ BaseObjectPtr<Blob> Blob::Create(Environment* env,
168168

169169
Local<Function> ctor;
170170
if (!GetConstructorTemplate(env)->GetFunction(env->context()).ToLocal(&ctor))
171-
return BaseObjectPtr<Blob>();
171+
return nullptr;
172172

173173
Local<Object> obj;
174-
if (!ctor->NewInstance(env->context()).ToLocal(&obj))
175-
return BaseObjectPtr<Blob>();
174+
if (!ctor->NewInstance(env->context()).ToLocal(&obj)) return nullptr;
176175

177176
return MakeBaseObject<Blob>(env, obj, data_queue);
178177
}
@@ -326,7 +325,7 @@ BaseObjectPtr<Blob::Reader> Blob::Reader::Create(Environment* env,
326325
->InstanceTemplate()
327326
->NewInstance(env->context())
328327
.ToLocal(&obj)) {
329-
return BaseObjectPtr<Blob::Reader>();
328+
return nullptr;
330329
}
331330

332331
return MakeBaseObject<Blob::Reader>(env, obj, std::move(blob));

src/node_http2.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,7 @@ void Http2Session::Close(uint32_t code, bool socket_closed) {
846846
// but this is faster and does not fail if the stream is not found.
847847
BaseObjectPtr<Http2Stream> Http2Session::FindStream(int32_t id) {
848848
auto s = streams_.find(id);
849-
return s != streams_.end() ? s->second : BaseObjectPtr<Http2Stream>();
849+
return s != streams_.end() ? s->second : nullptr;
850850
}
851851

852852
bool Http2Session::CanAddStream() {

src/node_sockaddr.cc

+3-3
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,7 @@ BaseObjectPtr<SocketAddressBlockListWrap> SocketAddressBlockListWrap::New(
553553
if (!env->blocklist_constructor_template()
554554
->InstanceTemplate()
555555
->NewInstance(env->context()).ToLocal(&obj)) {
556-
return BaseObjectPtr<SocketAddressBlockListWrap>();
556+
return nullptr;
557557
}
558558
BaseObjectPtr<SocketAddressBlockListWrap> wrap =
559559
MakeBaseObject<SocketAddressBlockListWrap>(env, obj);
@@ -568,7 +568,7 @@ BaseObjectPtr<SocketAddressBlockListWrap> SocketAddressBlockListWrap::New(
568568
if (!env->blocklist_constructor_template()
569569
->InstanceTemplate()
570570
->NewInstance(env->context()).ToLocal(&obj)) {
571-
return BaseObjectPtr<SocketAddressBlockListWrap>();
571+
return nullptr;
572572
}
573573
BaseObjectPtr<SocketAddressBlockListWrap> wrap =
574574
MakeBaseObject<SocketAddressBlockListWrap>(
@@ -775,7 +775,7 @@ BaseObjectPtr<SocketAddressBase> SocketAddressBase::Create(
775775
if (!GetConstructorTemplate(env)
776776
->InstanceTemplate()
777777
->NewInstance(env->context()).ToLocal(&obj)) {
778-
return BaseObjectPtr<SocketAddressBase>();
778+
return nullptr;
779779
}
780780

781781
return MakeBaseObject<SocketAddressBase>(env, obj, std::move(address));

src/node_sqlite.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -2331,7 +2331,7 @@ BaseObjectPtr<StatementSync> StatementSync::Create(
23312331
->InstanceTemplate()
23322332
->NewInstance(env->context())
23332333
.ToLocal(&obj)) {
2334-
return BaseObjectPtr<StatementSync>();
2334+
return nullptr;
23352335
}
23362336

23372337
return MakeBaseObject<StatementSync>(env, obj, std::move(db), stmt);
@@ -2485,7 +2485,7 @@ BaseObjectPtr<Session> Session::Create(Environment* env,
24852485
->InstanceTemplate()
24862486
->NewInstance(env->context())
24872487
.ToLocal(&obj)) {
2488-
return BaseObjectPtr<Session>();
2488+
return nullptr;
24892489
}
24902490

24912491
return MakeBaseObject<Session>(env, obj, std::move(database), session);

src/quic/session.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,11 @@ class Session final : public AsyncWrap, private SessionTicket::AppData::Source {
135135
const CID::Factory* cid_factory = &CID::Factory::random();
136136
// If the CID::Factory is a base object, we keep a reference to it
137137
// so that it cannot be garbage collected.
138-
BaseObjectPtr<BaseObject> cid_factory_ref = {};
138+
BaseObjectPtr<BaseObject> cid_factory_ref;
139139

140140
// If the application provider is specified, it will be used to create
141141
// the underlying Application instance for the session.
142-
BaseObjectPtr<ApplicationProvider> application_provider = {};
142+
BaseObjectPtr<ApplicationProvider> application_provider;
143143

144144
// When true, QLog output will be enabled for the session.
145145
bool qlog = false;

test/cctest/test_base_object_ptr.cc

+36
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,42 @@ TEST_F(BaseObjectPtrTest, Moveable) {
155155
EXPECT_EQ(realm->base_object_created_after_bootstrap(), 0);
156156
}
157157

158+
TEST_F(BaseObjectPtrTest, Nullptr) {
159+
const HandleScope handle_scope(isolate_);
160+
const Argv argv;
161+
Env env_{handle_scope, argv};
162+
Environment* env = *env_;
163+
Realm* realm = env->principal_realm();
164+
165+
BaseObjectPtr<DummyBaseObject> ptr = nullptr;
166+
EXPECT_EQ(nullptr, ptr);
167+
EXPECT_EQ(ptr, nullptr);
168+
EXPECT_EQ(nullptr, ptr.get());
169+
170+
// Implicit constructor.
171+
BaseObjectPtr<DummyBaseObject> ptr2 = []() -> BaseObjectPtr<DummyBaseObject> {
172+
return nullptr;
173+
}();
174+
EXPECT_EQ(nullptr, ptr2);
175+
EXPECT_EQ(ptr2, nullptr);
176+
EXPECT_EQ(nullptr, ptr2.get());
177+
178+
BaseObjectWeakPtr<DummyBaseObject> weak_ptr{ptr};
179+
EXPECT_EQ(nullptr, weak_ptr);
180+
EXPECT_EQ(weak_ptr, nullptr);
181+
EXPECT_EQ(nullptr, weak_ptr.get());
182+
ptr.reset();
183+
EXPECT_EQ(weak_ptr.get(), nullptr);
184+
185+
// No object creation with nullptr.
186+
EXPECT_EQ(realm->base_object_created_after_bootstrap(), 0);
187+
188+
BaseObjectPtr<DummyBaseObject> ptr4 = DummyBaseObject::NewDetached(env);
189+
EXPECT_NE(nullptr, ptr4);
190+
EXPECT_NE(ptr4, nullptr);
191+
EXPECT_EQ(realm->base_object_created_after_bootstrap(), 1);
192+
}
193+
158194
TEST_F(BaseObjectPtrTest, NestedClasses) {
159195
class ObjectWithPtr : public BaseObject {
160196
public:

0 commit comments

Comments
 (0)