@@ -283,6 +283,8 @@ class PinnedValue : private PinnedHermesValue {
283283// / This is the base object factoring out common code from the type-specific
284284// / versions.
285285class HandleBase {
286+ template <typename U>
287+ friend class MutableHandle ;
286288#ifndef NDEBUG
287289 // / In debug mode we store the GCScope that created us so we can update its
288290 // / active handle count in our destructor.
@@ -544,9 +546,6 @@ static_assert(
544546// / explicit as possible by using this class.
545547template <typename T>
546548class MutableHandle : public Handle <T> {
547- MutableHandle (const MutableHandle &) = delete ;
548- void operator =(const MutableHandle &) = delete ;
549-
550549 // / Alias a MutableHandle with a non-movable HermesValue without any checks.
551550 explicit MutableHandle (PinnedHermesValue *valueAddr, bool dummy)
552551 : Handle<T>(valueAddr, dummy) {}
@@ -564,6 +563,16 @@ class MutableHandle : public Handle<T> {
564563 // / type.
565564 /* implicit */ MutableHandle(const PinnedValue<T> &pv) : Handle<T>(pv) {}
566565
566+ // / Copy constructor.
567+ MutableHandle (const MutableHandle &sc) : Handle<T>(sc) {}
568+
569+ // / Copy constructor from MutableHandle<U> where U is compatible with T.
570+ template <
571+ typename U,
572+ typename =
573+ typename std::enable_if<IsHermesValueConvertible<T, U>::value>::type>
574+ MutableHandle (const MutableHandle<U> &sc) : Handle<T>(sc) {}
575+
567576 // / A move constructor.
568577 MutableHandle (MutableHandle &&sc) : Handle<T>(std::move(sc)) {}
569578
@@ -591,6 +600,19 @@ class MutableHandle : public Handle<T> {
591600 *HandleBase::handleRef () = HermesValueTraits<T>::encode (value);
592601 }
593602
603+ // / Assign the HermesValue \p val to this MutableHandle, asserting that it
604+ // / has type U which is compatible with T. This allows assigning a HermesValue
605+ // / with a known type to the PinnedValue without having to extract a
606+ // / pointer/symbol from it only to then re-encode it.
607+ template <
608+ typename U,
609+ typename =
610+ typename std::enable_if<IsHermesValueConvertible<U, T>::value>::type>
611+ void castAndSetHermesValue (HermesValue val) {
612+ HermesValueCast<U>::assertValid (val);
613+ *HandleBase::handleRef () = val;
614+ }
615+
594616 // / Create a MutableHandle from a pinned HermesValue and assert that the value
595617 // / has the correct type.
596618 static MutableHandle<T> vmcast (PinnedHermesValue *valueAddr) {
@@ -613,6 +635,19 @@ class MutableHandle : public Handle<T> {
613635 // register before we've read it if we used this method on it.
614636 return MutableHandle<T>(valueAddr, true );
615637 }
638+
639+ // / A version of \c aliasForOutput() that takes a \c MutableHandle<U>.
640+ template <
641+ typename U,
642+ typename =
643+ typename std::enable_if<IsHermesValueConvertible<T, U>::value>::type>
644+ static MutableHandle aliasForOutput (MutableHandle<U> &other) {
645+ return MutableHandle (other.handleRef (), true );
646+ }
647+
648+ PinnedHermesValue *unsafeGetPinnedHermesValue () {
649+ return HandleBase::handleRef ();
650+ }
616651} HERMES_ATTRIBUTE_WARN_UNUSED_VARIABLES;
617652
618653static_assert (
0 commit comments