diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index 76b8fd2..89c88af 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -790,6 +790,7 @@ public function __set($name, $value) {
    */
   public function __isset($name) {
     if ($this->hasField($name)) {
+      // @todo Now returns array() after $entity->field = NULL.
       return $this->get($name)->getValue() !== NULL;
     }
     else {
diff --git a/core/lib/Drupal/Core/Field/FieldItemList.php b/core/lib/Drupal/Core/Field/FieldItemList.php
index 56579e4..547ec75 100644
--- a/core/lib/Drupal/Core/Field/FieldItemList.php
+++ b/core/lib/Drupal/Core/Field/FieldItemList.php
@@ -126,37 +126,12 @@ public function getValue($include_computed = FALSE) {
    * {@inheritdoc}
    */
   public function setValue($values, $notify = TRUE) {
-    if (!isset($values) || $values === array()) {
-      $this->list = $values;
-    }
-    else {
-      // Support passing in only the value of the first item.
-      if (!is_array($values) || !is_numeric(current(array_keys($values)))) {
-        $values = array(0 => $values);
-      }
-
-      // Clear the values of properties for which no value has been passed.
-      if (isset($this->list)) {
-        $this->list = array_intersect_key($this->list, $values);
-      }
-
-      // Set the values.
-      foreach ($values as $delta => $value) {
-        if (!is_numeric($delta)) {
-          throw new \InvalidArgumentException('Unable to set a value with a non-numeric delta in a list.');
-        }
-        elseif (!isset($this->list[$delta])) {
-          $this->list[$delta] = $this->createItem($delta, $value);
-        }
-        else {
-          $this->list[$delta]->setValue($value, FALSE);
-        }
-      }
-    }
-    // Notify the parent of any changes.
-    if ($notify && isset($this->parent)) {
-      $this->parent->onChange($this->name);
+    // Support passing in only the value of the first item, either as a litteral
+    // (value of the first property) or as an array of properties.
+    if (isset($values) && (!is_array($values) || (!empty($values) && !is_numeric(current(array_keys($values)))))) {
+      $values = array(0 => $values);
     }
+    parent::setValue($values, $notify);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php
index cdb7246..513835c 100644
--- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php
+++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php
@@ -79,7 +79,7 @@ public function setValue($values, $notify = TRUE) {
           $this->list[$delta] = $this->createItem($delta, $value);
         }
         else {
-          $this->list[$delta]->setValue($value);
+          $this->list[$delta]->setValue($value, FALSE);
         }
       }
     }
diff --git a/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php b/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php
index 6a24454..2422a9e 100644
--- a/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php
+++ b/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php
@@ -144,15 +144,6 @@ public function denormalize($data, $class, $format = NULL, array $context = arra
 
     $entity = $this->entityManager->getStorage($typed_data_ids['entity_type'])->create($values);
 
-    // Special handling for PATCH: destroy all possible default values that
-    // might have been set on entity creation. We want an "empty" entity that
-    // will only get filled with fields from the data array.
-    if (isset($context['request_method']) && $context['request_method'] == 'patch') {
-      foreach ($entity as $field_name => $field) {
-        $entity->set($field_name, NULL);
-      }
-    }
-
     // Remove links from data array.
     unset($data['_links']);
     // Get embedded resources and remove from data array.
@@ -171,6 +162,12 @@ public function denormalize($data, $class, $format = NULL, array $context = arra
       }
     }
 
+    // Special handling for PATCH: pass the names of the fields whose values
+    // should be merged.
+    if (isset($context['request_method']) && $context['request_method'] == 'patch') {
+      $entity->_restPatchFields = array_keys($data);
+    }
+
     // Iterate through remaining items in data array. These should all
     // correspond to fields.
     foreach ($data as $field_name => $field_data) {
diff --git a/core/modules/hal/src/Tests/DenormalizeTest.php b/core/modules/hal/src/Tests/DenormalizeTest.php
index 8b5711c..6931d1c 100644
--- a/core/modules/hal/src/Tests/DenormalizeTest.php
+++ b/core/modules/hal/src/Tests/DenormalizeTest.php
@@ -176,7 +176,7 @@ public function testBasicFieldDenormalization() {
   }
 
   /**
-   * Verifies that only specified properties get populated in the PATCH context.
+   * Verifies that the denormalized entity is correct in the PATCH context.
    */
   public function testPatchDenormailzation() {
     $data = array(
@@ -195,15 +195,7 @@ public function testPatchDenormailzation() {
     $denormalized = $this->serializer->denormalize($data, $this->entityClass, $this->format, array('request_method' => 'patch'));
     // Check that the one field got populated as expected.
     $this->assertEqual($data['field_test_text'], $denormalized->get('field_test_text')->getValue());
-    // Unset that field so that now all fields are NULL.
-    $denormalized->set('field_test_text', NULL);
-    // Assert that all fields are NULL and not set to default values. Example:
-    // the UUID field is NULL and not initialized as usual.
-    foreach ($denormalized as $field_name => $field) {
-      // The 'langcode' field always has a value.
-      if ($field_name != 'langcode') {
-        $this->assertFalse(isset($denormalized->$field_name), "$field_name is not set.");
-      }
-    }
+    // Check the custom property that contains the list of fields to merge.
+    $this->assertEqual($denormalized->_restPatchFields, ['field_test_text']);
   }
 }
diff --git a/core/modules/quickedit/src/Form/QuickEditFieldForm.php b/core/modules/quickedit/src/Form/QuickEditFieldForm.php
index a1516fe..6d9d2c3 100644
--- a/core/modules/quickedit/src/Form/QuickEditFieldForm.php
+++ b/core/modules/quickedit/src/Form/QuickEditFieldForm.php
@@ -187,7 +187,7 @@ protected function buildEntity(array $form, FormStateInterface $form_state) {
 
     // @todo Refine automated log messages and abstract them to all entity
     //   types: http://drupal.org/node/1678002.
-    if ($entity->getEntityTypeId() == 'node' && $entity->isNewRevision() && !isset($entity->revision_log)) {
+    if ($entity->getEntityTypeId() == 'node' && $entity->isNewRevision() && $entity->revision_log->isEmpty()) {
       $entity->revision_log = t('Updated the %field-name field through in-place editing.', array('%field-name' => $entity->get($field_name)->getFieldDefinition()->getLabel()));
     }
 
diff --git a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
index 7b3e49e..25b75ac 100644
--- a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
+++ b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
@@ -133,22 +133,21 @@ public function patch(EntityInterface $original_entity, EntityInterface $entity
     }
 
     // Overwrite the received properties.
-    foreach ($entity as $field_name => $field) {
-      if (isset($entity->{$field_name})) {
-        // It is not possible to set the language to NULL as it is automatically
-        // re-initialized. As it must not be empty, skip it if it is.
-        // @todo: Use the langcode entity key when available. See
-        //   https://drupal.org/node/2143729.
-        if ($field_name == 'langcode' && $field->isEmpty()) {
-          continue;
-        }
-        if ($field->isEmpty() && !$original_entity->get($field_name)->access('delete')) {
-          throw new AccessDeniedHttpException(t('Access denied on deleting field @field.', array('@field' => $field_name)));
-        }
-        $original_entity->set($field_name, $field->getValue());
-        if (!$original_entity->get($field_name)->access('update')) {
-          throw new AccessDeniedHttpException(t('Access denied on updating field @field.', array('@field' => $field_name)));
-        }
+    foreach ($entity->_restPatchFields as $field_name) {
+      $field = $entity->get($field_name);
+      // It is not possible to set the language to NULL as it is automatically
+      // re-initialized. As it must not be empty, skip it if it is.
+      // @todo: Use the langcode entity key when available. See
+      //   https://drupal.org/node/2143729.
+      if ($field_name == 'langcode' && $field->isEmpty()) {
+        continue;
+      }
+      if ($field->isEmpty() && !$original_entity->get($field_name)->access('delete')) {
+        throw new AccessDeniedHttpException(t('Access denied on deleting field @field.', array('@field' => $field_name)));
+      }
+      $original_entity->set($field_name, $field->getValue());
+      if (!$original_entity->get($field_name)->access('update')) {
+        throw new AccessDeniedHttpException(t('Access denied on updating field @field.', array('@field' => $field_name)));
       }
     }
 
diff --git a/core/modules/system/src/Tests/Entity/EntityFieldTest.php b/core/modules/system/src/Tests/Entity/EntityFieldTest.php
index 369da19..2f16a59 100644
--- a/core/modules/system/src/Tests/Entity/EntityFieldTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityFieldTest.php
@@ -178,7 +178,7 @@ protected function doTestReadWrite($entity_type) {
     $this->assertFalse(isset($entity->name->value), 'Name value is not set.');
 
     $entity->name = NULL;
-    $this->assertFalse(isset($entity->name), 'Name field is not set.');
+    $this->assertTrue(isset($entity->name), 'Name field is set.');
     $this->assertFalse(isset($entity->name[0]), 'Name field item is not set.');
     $this->assertFalse(isset($entity->name[0]->value), 'First name item value is not set.');
     $this->assertFalse(isset($entity->name->value), 'Name value is not set.');
@@ -186,7 +186,7 @@ protected function doTestReadWrite($entity_type) {
     $entity->name->value = 'a value';
     $this->assertTrue(isset($entity->name->value), format_string('%entity_type: Name is set.', array('%entity_type' => $entity_type)));
     unset($entity->name);
-    $this->assertFalse(isset($entity->name), format_string('%entity_type: Name field is not set.', array('%entity_type' => $entity_type)));
+    $this->assertTrue(isset($entity->name), format_string('%entity_type: Name field is set.', array('%entity_type' => $entity_type)));
     $this->assertFalse(isset($entity->name[0]), format_string('%entity_type: Name field item is not set.', array('%entity_type' => $entity_type)));
     $this->assertFalse(isset($entity->name[0]->value), format_string('%entity_type: Name is not set.', array('%entity_type' => $entity_type)));
     $this->assertFalse(isset($entity->name->value), format_string('%entity_type: Name is not set.', array('%entity_type' => $entity_type)));
@@ -275,7 +275,7 @@ protected function doTestReadWrite($entity_type) {
     // Test removing all list items by setting it to NULL.
     $entity->name = NULL;
     $this->assertIdentical(count($entity->name), 0, format_string('%entity_type: Name field contains no items.', array('%entity_type' => $entity_type)));
-    $this->assertNull($entity->name->getValue(), format_string('%entity_type: Name field value is an empty array.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($entity->name->getValue(), array(), format_string('%entity_type: Name field value is an empty array.', array('%entity_type' => $entity_type)));
 
     // Test get and set field values.
     $entity->name = 'foo';
