Bug 1025173 - Nullable copy, move, and assignment should not transfer |mValue| if |mIsNull|. r=bz
authorNathan Yee <ny.nathan.yee@gmail.com>
Thu, 28 Aug 2014 22:37:00 +0200
changeset 203037 764e8c5fe5981ba54b7b9f7efa609373d87349be
parent 203036 fd07f405c3a0bfa12b7a0fbe64dc1bd313c372d0
child 203038 dc77ebda2445634ef5a45de79f27f4c978efaee1
push id27418
push userryanvm@gmail.com
push dateTue, 02 Sep 2014 18:33:17 +0000
treeherdermozilla-central@7753c52d5976 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1025173
milestone34.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1025173 - Nullable copy, move, and assignment should not transfer |mValue| if |mIsNull|. r=bz
dom/bindings/Nullable.h
--- a/dom/bindings/Nullable.h
+++ b/dom/bindings/Nullable.h
@@ -5,122 +5,99 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_Nullable_h
 #define mozilla_dom_Nullable_h
 
 #include "mozilla/Assertions.h"
 #include "nsTArrayForwardDeclare.h"
 #include "mozilla/Move.h"
+#include "mozilla/Maybe.h"
 
 class nsCycleCollectionTraversalCallback;
 
 namespace mozilla {
 namespace dom {
 
 // Support for nullable types
 template <typename T>
 struct Nullable
 {
 private:
-  // mIsNull MUST COME FIRST because otherwise the casting in our array
-  // conversion operators would shift where it is found in the struct.
-  bool mIsNull;
-  T mValue;
+  Maybe<T> mValue;
 
 public:
   Nullable()
-    : mIsNull(true)
+    : mValue()
   {}
 
   explicit Nullable(T aValue)
-    : mIsNull(false)
-    , mValue(aValue)
-  {}
+    : mValue()
+  {
+    mValue.emplace(aValue);
+  }
 
   explicit Nullable(Nullable<T>&& aOther)
-    : mIsNull(aOther.mIsNull)
-    , mValue(mozilla::Move(aOther.mValue))
+    : mValue(mozilla::Move(aOther.mValue))
   {}
 
   Nullable(const Nullable<T>& aOther)
-    : mIsNull(aOther.mIsNull)
-    , mValue(aOther.mValue)
+    : mValue(aOther.mValue)
   {}
 
   void operator=(const Nullable<T>& aOther)
   {
-    mIsNull = aOther.mIsNull;
     mValue = aOther.mValue;
   }
 
   void SetValue(T aValue) {
-    mValue = aValue;
-    mIsNull = false;
+    mValue.reset();
+    mValue.emplace(aValue);
   }
 
   // For cases when |T| is some type with nontrivial copy behavior, we may want
   // to get a reference to our internal copy of T and work with it directly
   // instead of relying on the copying version of SetValue().
   T& SetValue() {
-    mIsNull = false;
-    return mValue;
+    if (mValue.isNothing()) {
+      mValue.emplace();
+    }
+    return mValue.ref();
   }
 
   void SetNull() {
-    mIsNull = true;
+    mValue.reset();
   }
 
   const T& Value() const {
-    MOZ_ASSERT(!mIsNull);
-    return mValue;
+    return mValue.ref();
   }
 
   T& Value() {
-    MOZ_ASSERT(!mIsNull);
-    return mValue;
+    return mValue.ref();
   }
 
   bool IsNull() const {
-    return mIsNull;
+    return mValue.isNothing();
   }
 
   bool Equals(const Nullable<T>& aOtherNullable) const
   {
-    return (mIsNull && aOtherNullable.mIsNull) ||
-           (!mIsNull && !aOtherNullable.mIsNull &&
-            mValue == aOtherNullable.mValue);
+    return mValue == aOtherNullable.mValue;
   }
 
   bool operator==(const Nullable<T>& aOtherNullable) const
   {
     return Equals(aOtherNullable);
   }
 
   bool operator!=(const Nullable<T>& aOtherNullable) const
   {
     return !Equals(aOtherNullable);
   }
-
-  // Make it possible to use a const Nullable of an array type with other
-  // array types.
-  template<typename U>
-  operator const Nullable< nsTArray<U> >&() const {
-    // Make sure that T is ok to reinterpret to nsTArray<U>
-    const nsTArray<U>& arr = mValue;
-    (void)arr;
-    return *reinterpret_cast<const Nullable< nsTArray<U> >*>(this);
-  }
-  template<typename U>
-  operator const Nullable< FallibleTArray<U> >&() const {
-    // Make sure that T is ok to reinterpret to FallibleTArray<U>
-    const FallibleTArray<U>& arr = mValue;
-    (void)arr;
-    return *reinterpret_cast<const Nullable< FallibleTArray<U> >*>(this);
-  }
 };
 
 
 template<typename T>
 void
 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
                             Nullable<T>& aNullable,
                             const char* aName,