common: RefBase fixes and improvements

Fix missing Release() on RefBase::operator=(const T&).

Always acquire the new reference before dropping the existing reference.
Consider:
* Object A holds the only reference to object B.
* Ref of A is assigned B.
If A were released before referencing B, then B would be a dead pointer.

Remove RefBase::kNullValue, just use Traits::kNullValue. Avoids an unnecessary constexpr copy.

Add even more tests.

Change-Id: I111079d56cbf8c09162aa6e493078bead9ae97fa
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/55882
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/tests/unittests/ObjectBaseTests.cpp b/src/tests/unittests/ObjectBaseTests.cpp
index ab141d3..51244c7 100644
--- a/src/tests/unittests/ObjectBaseTests.cpp
+++ b/src/tests/unittests/ObjectBaseTests.cpp
@@ -120,6 +120,24 @@
     ASSERT_EQ(refcount, 2);
 }
 
+// Test the repeated copy assignment of C++ objects
+TEST(ObjectBase, RepeatedCopyAssignment) {
+    int refcount = 1;
+    Object source(&refcount);
+
+    Object destination;
+    for (int i = 0; i < 10; i++) {
+        destination = source;
+    }
+
+    ASSERT_EQ(source.Get(), &refcount);
+    ASSERT_EQ(destination.Get(), &refcount);
+    ASSERT_EQ(3, refcount);
+
+    destination = Object();
+    ASSERT_EQ(refcount, 2);
+}
+
 // Test the copy assignment of C++ objects onto themselves
 TEST(ObjectBase, CopyAssignmentSelf) {
     int refcount = 1;