WIP.
diff --git a/python/map.c b/python/map.c
index a3e922e..c7f5675 100644
--- a/python/map.c
+++ b/python/map.c
@@ -114,7 +114,8 @@
   self->version++;
 }
 
-static upb_map* PyUpb_MapContainer_AssureReified(PyUpb_MapContainer* self) {
+upb_map* PyUpb_MapContainer_EnsureReified(PyObject* _self) {
+  PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
   self->version++;
   upb_map* map = PyUpb_MapContainer_GetIfReified(self);
   if (map) return map;  // Already writable.
@@ -134,7 +135,7 @@
 int PyUpb_MapContainer_AssignSubscript(PyObject* _self, PyObject* key,
                                        PyObject* val) {
   PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
-  upb_map* map = PyUpb_MapContainer_AssureReified(self);
+  upb_map* map = PyUpb_MapContainer_EnsureReified(_self);
   const upb_fielddef* f = PyUpb_MapContainer_GetField(self);
   const upb_msgdef* entry_m = upb_fielddef_msgsubdef(f);
   const upb_fielddef* key_f = upb_msgdef_field(entry_m, 0);
@@ -166,7 +167,7 @@
   upb_msgval u_key, u_val;
   if (!PyUpb_PyToUpb(key, key_f, &u_key, arena)) return NULL;
   if (!map || !upb_map_get(map, u_key, &u_val)) {
-    map = PyUpb_MapContainer_AssureReified(self);
+    map = PyUpb_MapContainer_EnsureReified(_self);
     upb_arena* arena = PyUpb_Arena_Get(self->arena);
     if (upb_fielddef_issubmsg(val_f)) {
       u_val.msg_val = upb_msg_new(upb_fielddef_msgsubdef(val_f), arena);
@@ -196,7 +197,7 @@
 
 PyObject* PyUpb_MapContainer_Clear(PyObject* _self, PyObject* key) {
   PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
-  upb_map* map = PyUpb_MapContainer_AssureReified(self);
+  upb_map* map = PyUpb_MapContainer_EnsureReified(_self);
   upb_map_clear(map);
   Py_RETURN_NONE;
 }
diff --git a/python/map.h b/python/map.h
index 9adc3de..8430f3b 100644
--- a/python/map.h
+++ b/python/map.h
@@ -48,6 +48,9 @@
 // Reifies a map stub to point to the concrete data in `map`.
 void PyUpb_MapContainer_Reify(PyObject* self, upb_map* map);
 
+// Reifies this map object if it is not already reified.
+upb_map* PyUpb_MapContainer_EnsureReified(PyObject* self);
+
 // Assigns `self[key] = val` for the map `self`.
 int PyUpb_MapContainer_AssignSubscript(PyObject* self, PyObject* key,
                                        PyObject* val);
diff --git a/python/message.c b/python/message.c
index 736358c..a3da671 100644
--- a/python/message.c
+++ b/python/message.c
@@ -326,7 +326,7 @@
   return ret;
 }
 
-void PyUpb_CMessage_AssureReified(PyUpb_CMessage* self);
+void PyUpb_CMessage_EnsureReified(PyUpb_CMessage* self);
 
 static bool PyUpb_CMessage_InitMapAttribute(PyObject* _self, PyObject* name,
                                             const upb_fielddef* f,
@@ -396,7 +396,7 @@
   Py_ssize_t pos = 0;
   PyObject* name;
   PyObject* value;
-  PyUpb_CMessage_AssureReified(self);
+  PyUpb_CMessage_EnsureReified(self);
   upb_msg* msg = PyUpb_CMessage_GetMsg(self);
   upb_arena* arena = PyUpb_Arena_Get(self->arena);
 
@@ -493,7 +493,7 @@
 }
 
 /*
- * PyUpb_CMessage_AssureReified()
+ * PyUpb_CMessage_EnsureReified()
  *
  * This implements the "expando" behavior of Python protos:
  *   foo = FooProto()
@@ -510,7 +510,7 @@
  * Post-condition:
  *   PyUpb_CMessage_IsStub(self) is false
  */
-void PyUpb_CMessage_AssureReified(PyUpb_CMessage* self) {
+void PyUpb_CMessage_EnsureReified(PyUpb_CMessage* self) {
   if (!PyUpb_CMessage_IsStub(self)) return;
   upb_arena* arena = PyUpb_Arena_Get(self->arena);
 
@@ -562,7 +562,7 @@
  *
  * This operation must be invoked whenever the underlying upb_msg has been
  * mutated directly in C.  This will attach any newly-present field data
- * to previously returned "empty" wrapper objects.
+ * to previously returned stub wrapper objects.
  *
  * For example:
  *   foo = FooMessage()
@@ -658,7 +658,7 @@
 void PyUpb_CMessage_SetConcreteSubobj(PyObject* _self, const upb_fielddef* f,
                                       upb_msgval subobj) {
   PyUpb_CMessage* self = (void*)_self;
-  PyUpb_CMessage_AssureReified(self);
+  PyUpb_CMessage_EnsureReified(self);
   PyUpb_CMessage_CacheDelete(_self, f);
   upb_msg_set(self->ptr.msg, f, subobj, PyUpb_Arena_Get(self->arena));
 }
@@ -808,7 +808,7 @@
     return -1;
   }
 
-  PyUpb_CMessage_AssureReified(self);
+  PyUpb_CMessage_EnsureReified(self);
 
   upb_msgval val;
   upb_arena* arena = PyUpb_Arena_Get(self->arena);
@@ -958,7 +958,7 @@
 
 static PyObject* PyUpb_CMessage_SetInParent(PyObject* _self, PyObject* arg) {
   PyUpb_CMessage* self = (void*)_self;
-  PyUpb_CMessage_AssureReified(self);
+  PyUpb_CMessage_EnsureReified(self);
   Py_RETURN_NONE;
 }
 
@@ -985,7 +985,7 @@
     return NULL;
   }
 
-  PyUpb_CMessage_AssureReified(self);
+  PyUpb_CMessage_EnsureReified(self);
   const upb_msgdef* msgdef = _PyUpb_CMessage_GetMsgdef(self);
   const upb_filedef* file = upb_msgdef_file(msgdef);
   const upb_extreg* extreg = upb_symtab_extreg(upb_filedef_symtab(file));
@@ -1027,7 +1027,7 @@
 }
 
 static PyObject* PyUpb_CMessage_Clear(PyUpb_CMessage* self, PyObject* args) {
-  PyUpb_CMessage_AssureReified(self);
+  PyUpb_CMessage_EnsureReified(self);
   const upb_msgdef* msgdef = _PyUpb_CMessage_GetMsgdef(self);
   upb_msg_clear(self->ptr.msg, msgdef);
   Py_RETURN_NONE;
@@ -1035,39 +1035,39 @@
 
 void PyUpb_CMessage_DoClearField(PyObject* _self, const upb_fielddef* f) {
   PyUpb_CMessage* self = (void*)_self;
-  PyUpb_CMessage_AssureReified((PyUpb_CMessage*)self);
+  PyUpb_CMessage_EnsureReified((PyUpb_CMessage*)self);
+
+  // We must ensure that any stub object is reified so its parent no longer
+  // points to us.
+  PyObject* sub = self->unset_subobj_map
+                      ? PyUpb_WeakMap_Get(self->unset_subobj_map, f)
+                      : NULL;
 
   if (upb_fielddef_ismap(f)) {
-    // We have to invalidate any existing iterator over this map.
-    PyObject* obj = NULL;
-    if (self->unset_subobj_map) {
-      obj = PyUpb_WeakMap_Get(self->unset_subobj_map, f);
+    // For maps we additionally have to invalidate any iterators.  So we need
+    // to get an object even if it's reified.
+    if (!sub) {
+      sub = PyUpb_CMessage_GetFieldValue(_self, f);
     }
-    if (!obj) {
-      upb_msg* msg = PyUpb_CMessage_GetMsg(self);
-      upb_msgval msgval = upb_msg_get(msg, f);
-      obj = PyUpb_ObjCache_Get(msgval.map_val);
+    PyUpb_MapContainer_EnsureReified(sub);
+    PyUpb_MapContainer_Invalidate(sub);
+  } else if (upb_fielddef_isseq(f)) {
+    if (sub) {
+      //PyUpb_RepeatedContainer_EnsureReified(sub);
     }
-    if (obj) {
-      PyUpb_MapContainer_Invalidate(obj);
-      Py_DECREF(obj);
-    }
-  } else if (upb_fielddef_issubmsg(f) && !upb_fielddef_isseq(f)) {
-    if (self->unset_subobj_map) {
-      PyObject* sub = PyUpb_WeakMap_Get(self->unset_subobj_map, f);
-      if (sub) {
-        PyUpb_CMessage_AssureReified((PyUpb_CMessage*)sub);
-        Py_DECREF(sub);
-      }
+  } else if (upb_fielddef_issubmsg(f)) {
+    if (sub) {
+      PyUpb_CMessage_EnsureReified((PyUpb_CMessage*)sub);
     }
   }
 
+  Py_XDECREF(sub);
   upb_msg_clearfield(self->ptr.msg, f);
 }
 
 static PyObject* PyUpb_CMessage_ClearExtension(PyObject* _self, PyObject* arg) {
   PyUpb_CMessage* self = (void*)_self;
-  PyUpb_CMessage_AssureReified(self);
+  PyUpb_CMessage_EnsureReified(self);
   const upb_fielddef* f = PyUpb_CMessage_GetExtensionDef(_self, arg);
   if (!f) return NULL;
   PyUpb_CMessage_DoClearField(_self, f);
@@ -1077,12 +1077,12 @@
 static PyObject* PyUpb_CMessage_ClearField(PyObject* _self, PyObject* arg) {
   PyUpb_CMessage* self = (void*)_self;
 
-  // We always need AssureWritable() here (even for an unset message) to
+  // We always need EnsureReified() here (even for an unset message) to
   // preserve behavior like:
   //   msg = FooMessage()
   //   msg.foo.Clear()
   //   assert msg.HasField("foo")
-  PyUpb_CMessage_AssureReified(self);
+  PyUpb_CMessage_EnsureReified(self);
 
   const upb_fielddef* f;
   const upb_oneofdef* o;
@@ -1097,7 +1097,7 @@
 
 static PyObject* PyUpb_CMessage_DiscardUnknownFields(PyUpb_CMessage* self,
                                                      PyObject* arg) {
-  PyUpb_CMessage_AssureReified(self);
+  PyUpb_CMessage_EnsureReified(self);
   const upb_msgdef* msgdef = _PyUpb_CMessage_GetMsgdef(self);
   upb_msg_discardunknown(self->ptr.msg, msgdef, 64);
   Py_RETURN_NONE;
diff --git a/python/minimal_test.py b/python/minimal_test.py
index 01eef6e..a87f6b3 100644
--- a/python/minimal_test.py
+++ b/python/minimal_test.py
@@ -31,6 +31,7 @@
 from google.protobuf.pyext import _message
 from google.protobuf.internal import api_implementation
 from google.protobuf import unittest_pb2
+from google.protobuf import map_unittest_pb2
 from google.protobuf import descriptor_pool
 from google.protobuf import text_format
 from google.protobuf import message_factory
@@ -79,6 +80,37 @@
     def testExtensionsErrors(self):
         msg = unittest_pb2.TestAllTypes()
         self.assertRaises(AttributeError, getattr, msg, 'Extensions')
+    
+    def testClearStubMapField(self):
+        msg = map_unittest_pb2.TestMap()
+        int32_map = msg.map_int32_int32
+        msg.ClearField("map_int32_int32")
+        int32_map[123] = 456
+        self.assertEqual(0, msg.ByteSize())
+
+    def testClearReifiedMapField(self):
+        msg = map_unittest_pb2.TestMap()
+        int32_map = msg.map_int32_int32
+        int32_map[123] = 456
+        msg.ClearField("map_int32_int32")
+        int32_map[111] = 222
+        self.assertEqual(0, msg.ByteSize())
+
+    def testClearStubRepeatedField(self):
+        msg = unittest_pb2.TestAllTypes()
+        int32_array = msg.repeated_int32
+        msg.ClearField("repeated_int32")
+        int32_array.append(123)
+        self.assertEqual(0, msg.ByteSize())
+
+    def testClearReifiedRepeatdField(self):
+        msg = unittest_pb2.TestAllTypes()
+        int32_array = msg.repeated_int32
+        int32_array.append(123)
+        self.assertNotEqual(0, msg.ByteSize())
+        msg.ClearField("repeated_int32")
+        int32_array.append(123)
+        self.assertEqual(0, msg.ByteSize())
 
 #TestMessageExtension.test_descriptor_pool.__unittest_expecting_failure__ = True
 
diff --git a/python/repeated.c b/python/repeated.c
index 35e876c..09e5657 100644
--- a/python/repeated.c
+++ b/python/repeated.c
@@ -116,7 +116,7 @@
   assert(!PyUpb_RepeatedContainer_IsStub(self));
 }
 
-static upb_array* PyUpb_RepeatedContainer_AssureReified(PyObject* _self) {
+upb_array* PyUpb_RepeatedContainer_EnsureReified(PyObject* _self) {
   PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
   upb_array* arr = PyUpb_RepeatedContainer_GetIfReified(self);
   if (arr) return arr;  // Already writable.
@@ -209,7 +209,7 @@
 
 PyObject* PyUpb_RepeatedContainer_Extend(PyObject* _self, PyObject* value) {
   PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
-  upb_array* arr = PyUpb_RepeatedContainer_AssureReified(_self);
+  upb_array* arr = PyUpb_RepeatedContainer_EnsureReified(_self);
   size_t start_size = upb_array_size(arr);
   PyObject* it = PyObject_GetIter(value);
   if (!it) {
@@ -435,7 +435,7 @@
   PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
   Py_ssize_t index = -1;
   if (!PyArg_ParseTuple(args, "|n", &index)) return NULL;
-  upb_array* arr = PyUpb_RepeatedContainer_AssureReified(_self);
+  upb_array* arr = PyUpb_RepeatedContainer_EnsureReified(_self);
   size_t size = upb_array_size(arr);
   if (index < 0) index += size;
   if (index >= size) index = size - 1;
@@ -447,7 +447,7 @@
 
 static PyObject* PyUpb_RepeatedContainer_Remove(PyObject* _self,
                                                 PyObject* value) {
-  upb_array* arr = PyUpb_RepeatedContainer_AssureReified(_self);
+  upb_array* arr = PyUpb_RepeatedContainer_EnsureReified(_self);
   Py_ssize_t match_index = -1;
   Py_ssize_t n = PyUpb_RepeatedContainer_Length(_self);
   for (Py_ssize_t i = 0; i < n; ++i) {
@@ -474,7 +474,7 @@
 static bool PyUpb_RepeatedContainer_Assign(PyObject* _self, PyObject* list) {
   PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
   const upb_fielddef* f = PyUpb_RepeatedContainer_GetField(self);
-  upb_array* arr = PyUpb_RepeatedContainer_AssureReified(_self);
+  upb_array* arr = PyUpb_RepeatedContainer_EnsureReified(_self);
   Py_ssize_t size = PyList_Size(list);
   bool submsg = upb_fielddef_issubmsg(f);
   upb_arena* arena = PyUpb_Arena_Get(self->arena);
@@ -538,7 +538,7 @@
 
 static PyObject* PyUpb_RepeatedCompositeContainer_AppendNew(PyObject* _self) {
   PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
-  upb_array* arr = PyUpb_RepeatedContainer_AssureReified(_self);
+  upb_array* arr = PyUpb_RepeatedContainer_EnsureReified(_self);
   if (!arr) return NULL;
   const upb_fielddef* f = PyUpb_RepeatedContainer_GetField(self);
   upb_arena* arena = PyUpb_Arena_Get(self->arena);
@@ -582,7 +582,7 @@
   Py_ssize_t index;
   PyObject* value;
   if (!PyArg_ParseTuple(args, "nO", &index, &value)) return NULL;
-  upb_array* arr = PyUpb_RepeatedContainer_AssureReified(_self);
+  upb_array* arr = PyUpb_RepeatedContainer_EnsureReified(_self);
   if (!arr) return NULL;
 
   // Normalize index.
@@ -667,7 +667,7 @@
 static PyObject* PyUpb_RepeatedScalarContainer_Append(PyObject* _self,
                                                       PyObject* value) {
   PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
-  upb_array* arr = PyUpb_RepeatedContainer_AssureReified(_self);
+  upb_array* arr = PyUpb_RepeatedContainer_EnsureReified(_self);
   upb_arena* arena = PyUpb_Arena_Get(self->arena);
   const upb_fielddef* f = PyUpb_RepeatedContainer_GetField(self);
   upb_msgval msgval;
diff --git a/python/repeated.h b/python/repeated.h
index 06945bf..9e8530b 100644
--- a/python/repeated.h
+++ b/python/repeated.h
@@ -49,6 +49,9 @@
 // Reifies a repeated field stub to point to the concrete data in `arr`.
 void PyUpb_RepeatedContainer_Reify(PyObject* self, upb_array* arr);
 
+// Reifies this repeated object if it is not already reified.
+upb_array* PyUpb_RepeatedContainer_EnsureReified(PyObject* self);
+
 // Implements repeated_field.extend(iterable).  `_self` must be a repeated
 // field (either repeated composite or repeated scalar).
 PyObject* PyUpb_RepeatedContainer_Extend(PyObject* _self, PyObject* value);