From 3c9bbc96653fe8480e30bd6ab947a31a650721d5 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Fri, 6 Mar 2026 13:13:21 -0600 Subject: [PATCH] Issue #2304 - Part 1 - Prerequisite: Make Handle> more convenient. This is required to implement JS::NothingHandleValue. https://bugzilla.mozilla.org/show_bug.cgi?id=1631114 --- js/public/RootingAPI.h | 28 ++++++++++++++++++++++++++++ js/public/Value.h | 1 + js/src/vm/Value.cpp | 2 ++ 3 files changed, 31 insertions(+) diff --git a/js/public/RootingAPI.h b/js/public/RootingAPI.h index e03bc56fb7..137a86e48f 100644 --- a/js/public/RootingAPI.h +++ b/js/public/RootingAPI.h @@ -10,6 +10,7 @@ #include "mozilla/DebugOnly.h" #include "mozilla/GuardObjects.h" #include "mozilla/LinkedList.h" +#include "mozilla/Maybe.h" #include "mozilla/Move.h" #include "mozilla/TypeTraits.h" @@ -1278,6 +1279,33 @@ class MutableWrappedPtrOperations, Container> void reset(T* ptr = T()) { uniquePtr().reset(ptr); } }; +template +class WrappedPtrOperations, Container> { + const mozilla::Maybe& maybe() const { + return static_cast(this)->get(); + } + + public: + // This only supports a subset of Maybe's interface. + bool isSome() const { return maybe().isSome(); } + bool isNothing() const { return maybe().isNothing(); } + const T value() const { return maybe().value(); } + const T* operator->() const { return maybe().ptr(); } + const T& operator*() const { return maybe().ref(); } +}; + +template +class MutableWrappedPtrOperations, Container> + : public WrappedPtrOperations, Container> { + mozilla::Maybe& maybe() { return static_cast(this)->get(); } + + public: + // This only supports a subset of Maybe's interface. + T* operator->() { return maybe().ptr(); } + T& operator*() { return maybe().ref(); } + void reset() { return maybe().reset(); } +}; + namespace gc { template diff --git a/js/public/Value.h b/js/public/Value.h index a6ceaad669..46c3995f24 100644 --- a/js/public/Value.h +++ b/js/public/Value.h @@ -1535,6 +1535,7 @@ extern JS_PUBLIC_DATA(const HandleValue) NullHandleValue; extern JS_PUBLIC_DATA(const HandleValue) UndefinedHandleValue; extern JS_PUBLIC_DATA(const HandleValue) TrueHandleValue; extern JS_PUBLIC_DATA(const HandleValue) FalseHandleValue; +extern JS_PUBLIC_DATA(const Handle>) NothingHandleValue; } // namespace JS diff --git a/js/src/vm/Value.cpp b/js/src/vm/Value.cpp index 674b5ec774..6df86aa0f2 100644 --- a/js/src/vm/Value.cpp +++ b/js/src/vm/Value.cpp @@ -9,6 +9,7 @@ static const JS::Value JSVAL_NULL = JS::Value::fromTagAndPayload(JSVAL_TAG_NULL static const JS::Value JSVAL_FALSE = JS::Value::fromTagAndPayload(JSVAL_TAG_BOOLEAN, false); static const JS::Value JSVAL_TRUE = JS::Value::fromTagAndPayload(JSVAL_TAG_BOOLEAN, true); static const JS::Value JSVAL_VOID = JS::Value::fromTagAndPayload(JSVAL_TAG_UNDEFINED, 0); +static const mozilla::Maybe JSVAL_NOTHING; namespace JS { @@ -16,5 +17,6 @@ const HandleValue NullHandleValue = HandleValue::fromMarkedLocation(&JSVAL_NULL) const HandleValue UndefinedHandleValue = HandleValue::fromMarkedLocation(&JSVAL_VOID); const HandleValue TrueHandleValue = HandleValue::fromMarkedLocation(&JSVAL_TRUE); const HandleValue FalseHandleValue = HandleValue::fromMarkedLocation(&JSVAL_FALSE); +const Handle> NothingHandleValue = Handle>::fromMarkedLocation(&JSVAL_NOTHING); } // namespace JS