diff --git a/core/includes/entity.inc b/core/includes/entity.inc
index fe30114..a6cf164 100644
--- a/core/includes/entity.inc
+++ b/core/includes/entity.inc
@@ -555,7 +555,7 @@ function entity_get_form(EntityInterface $entity, $operation = 'default', array
  * so the builder function for such forms needs to implement the required
  * functionality instead of calling this function.
  */
-function entity_form_submit_build_entity($entity_type, $entity, $form, &$form_state) {
+function entity_form_submit_build_entity($entity_type, $entity, $form, &$form_state, array $options = array()) {
   $info = entity_get_info($entity_type);
 
   // Copy top-level form values that are not for fields to entity properties,
@@ -576,7 +576,7 @@ function entity_form_submit_build_entity($entity_type, $entity, $form, &$form_st
 
   // Copy field values to the entity.
   if ($info['fieldable']) {
-    field_attach_extract_form_values($entity, $form, $form_state);
+    field_attach_extract_form_values($entity, $form, $form_state, $options);
   }
 }
 
diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php
index 36fb318..d2c42d3 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormController.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormController.php
@@ -484,7 +484,7 @@ public function buildEntity(array $form, array &$form_state) {
     $form_state['controller'] = $this;
     // @todo Move entity_form_submit_build_entity() here.
     // @todo Exploit the Field API to process the submitted entity field.
-    entity_form_submit_build_entity($entity->entityType(), $entity, $form, $form_state);
+    entity_form_submit_build_entity($entity->entityType(), $entity, $form, $form_state, array('langcode' => $this->getFormLangcode($form_state)));
     return $entity;
   }
 
diff --git a/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php b/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php
index 3b064f6..f760057 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php
@@ -77,7 +77,7 @@ public function buildEntity(array $form, array &$form_state) {
 
     // Invoke field API for copying field values.
     if ($info['fieldable']) {
-      field_attach_extract_form_values($entity, $form, $form_state);
+      field_attach_extract_form_values($entity, $form, $form_state, array('langcode' => $this->getFormLangcode($form_state)));
     }
     return $entity;
   }
diff --git a/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php b/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php
index 84eb341..1f74752 100644
--- a/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php
+++ b/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php
@@ -123,6 +123,7 @@ public function __isset($name) {
    */
   public function __unset($name) {
     $this->set($name, NULL);
+    unset($this->values[$name]);
   }
 
   /**
diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimeDefaultFormatter.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimeDefaultFormatter.php
index 729c44e..3c45ec3 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimeDefaultFormatter.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimeDefaultFormatter.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Annotation\Translation;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\Core\Datetime\DrupalDateTime;
 use Drupal\Core\Template\Attribute;
 
@@ -34,7 +35,7 @@ class DateTimeDefaultFormatter extends FormatterBase {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
 
     $elements = array();
 
@@ -43,10 +44,10 @@ public function viewElements(EntityInterface $entity, $langcode, array $items) {
       $formatted_date = '';
       $iso_date = '';
 
-      if (!empty($item['date'])) {
+      if (!empty($item->date)) {
         // The date was created and verified during field_load(), so it is safe
         // to use without further inspection.
-        $date = $item['date'];
+        $date = $item->date;
 
         // Create the ISO date in Universal Time.
         $iso_date = $date->format("Y-m-d\TH:i:s") . 'Z';
diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimePlainFormatter.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimePlainFormatter.php
index 7c59dda..dde14bb 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimePlainFormatter.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimePlainFormatter.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Annotation\Translation;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\Core\Datetime\DrupalDateTime;
 
 /**
@@ -30,17 +31,17 @@ class DateTimePlainFormatter extends FormatterBase {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
 
     $elements = array();
 
     foreach ($items as $delta => $item) {
 
       $output = '';
-      if (!empty($item['date'])) {
+      if (!empty($item->date)) {
         // The date was created and verified during field_load(), so it is safe
         // to use without further inspection.
-        $date = $item['date'];
+        $date = $item->date;
         $date->setTimeZone(timezone_open(drupal_get_user_timezone()));
         $format = DATETIME_DATETIME_STORAGE_FORMAT;
         if ($this->getFieldSetting('datetime_type') == 'date') {
diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php
index 267f691..2dd1e38 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php
@@ -12,6 +12,7 @@
 use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\Field\FieldDefinitionInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\PluginSettingsBase;
 use Drupal\field\FieldInstanceInterface;
 use Drupal\Core\Datetime\DrupalDateTime;
@@ -62,7 +63,7 @@ public function defaultValueFunction() {
   /**
    * {@inheritdoc}
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $date_order = $this->getSetting('date_order');
     $time_type = $this->getSetting('time_type');
     $increment = $this->getSetting('increment');
@@ -130,8 +131,8 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
     // validator will not have access to the field definition.
     $element['value']['#date_storage_format'] = $storage_format;
 
-    if (!empty($items[$delta]['date'])) {
-      $date = $items[$delta]['date'];
+    if (!empty($items[$delta]->date)) {
+      $date = $items[$delta]->date;
       // The date was created and verified during field_load(), so it is safe to
       // use without further inspection.
       $date->setTimezone( new \DateTimeZone($element['value']['#date_timezone']));
diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php
index 79f12bc..364945b 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php
@@ -12,6 +12,7 @@
 use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\Field\FieldDefinitionInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\PluginSettingsBase;
 use Drupal\field\FieldInstanceInterface;
 use Drupal\Core\Datetime\DrupalDateTime;
@@ -56,7 +57,7 @@ public function defaultValueFunction() {
   /**
    * {@inheritdoc}
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $format_type = datetime_default_format_type();
 
     // We are nesting some sub-elements inside the parent, so we need a wrapper.
@@ -109,8 +110,8 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
     $element['value']['#date_element_format'] = $element_format;
     $element['value']['#date_storage_format'] = $storage_format;
 
-    if (!empty($items[$delta]['date'])) {
-      $date = $items[$delta]['date'];
+    if (!empty($items[$delta]->date)) {
+      $date = $items[$delta]->date;
       // The date was created and verified during field_load(), so it is safe to
       // use without further inspection.
       $date->setTimezone(new \DateTimeZone($element['value']['#date_timezone']));
diff --git a/core/modules/email/lib/Drupal/email/Plugin/field/formatter/MailToFormatter.php b/core/modules/email/lib/Drupal/email/Plugin/field/formatter/MailToFormatter.php
index 33e5920..d706601 100644
--- a/core/modules/email/lib/Drupal/email/Plugin/field/formatter/MailToFormatter.php
+++ b/core/modules/email/lib/Drupal/email/Plugin/field/formatter/MailToFormatter.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Annotation\Translation;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'email_mailto' formatter.
@@ -29,14 +30,14 @@ class MailToFormatter extends FormatterBase {
   /**
    * Implements Drupal\field\Plugin\Type\Formatter\FormatterInterface::viewElements().
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
 
     foreach ($items as $delta => $item) {
       $elements[$delta] = array(
         '#type' => 'link',
-        '#title' => $item['value'],
-        '#href' => 'mailto:' . $item['value'],
+        '#title' => $item->value,
+        '#href' => 'mailto:' . $item->value,
       );
     }
 
diff --git a/core/modules/email/lib/Drupal/email/Plugin/field/widget/EmailDefaultWidget.php b/core/modules/email/lib/Drupal/email/Plugin/field/widget/EmailDefaultWidget.php
index 0e51452..3cb7f6d 100644
--- a/core/modules/email/lib/Drupal/email/Plugin/field/widget/EmailDefaultWidget.php
+++ b/core/modules/email/lib/Drupal/email/Plugin/field/widget/EmailDefaultWidget.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\Type\Widget\WidgetBase;
 
 /**
@@ -61,10 +62,10 @@ public function settingsSummary() {
   /**
    * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement().
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $element['value'] = $element + array(
       '#type' => 'email',
-      '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL,
+      '#default_value' => isset($items[$delta]->value) ? $items[$delta]->value : NULL,
       '#placeholder' => $this->getSetting('placeholder'),
     );
     return $element;
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceEntityFormatter.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceEntityFormatter.php
index 51d48b9..164583d 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceEntityFormatter.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceEntityFormatter.php
@@ -10,6 +10,7 @@
 use Drupal\field\Annotation\FieldFormatter;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\entity_reference\RecursiveRenderingException;
 use Drupal\entity_reference\Plugin\field\formatter\EntityReferenceFormatterBase;
 
@@ -76,7 +77,7 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     // Remove un-accessible items.
     parent::viewElements($entity, $langcode, $items);
 
@@ -92,17 +93,17 @@ public function viewElements(EntityInterface $entity, $langcode, array $items) {
       static $depth = 0;
       $depth++;
       if ($depth > 20) {
-        throw new RecursiveRenderingException(format_string('Recursive rendering detected when rendering entity @entity_type(@entity_id). Aborting rendering.', array('@entity_type' => $entity_type, '@entity_id' => $item['target_id'])));
+        throw new RecursiveRenderingException(format_string('Recursive rendering detected when rendering entity @entity_type(@entity_id). Aborting rendering.', array('@entity_type' => $entity_type, '@entity_id' => $item->target_id)));
       }
 
-      if (!empty($item['target_id'])) {
-        $entity = clone $item['entity'];
+      if (!empty($item->target_id)) {
+        $entity = clone $item->entity;
         unset($entity->content);
         $elements[$delta] = entity_view($entity, $view_mode, $langcode);
 
-        if (empty($links) && isset($result[$delta][$target_type][$item['target_id']]['links'])) {
+        if (empty($links) && isset($result[$delta][$target_type][$item->target_id]['links'])) {
           // Hide the element links.
-          $elements[$delta][$target_type][$item['target_id']]['links']['#access'] = FALSE;
+          $elements[$delta][$target_type][$item->target_id]['links']['#access'] = FALSE;
         }
       }
       else {
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceFormatterBase.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceFormatterBase.php
index af3774a..8232700 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceFormatterBase.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceFormatterBase.php
@@ -10,6 +10,7 @@
 use Drupal\field\Annotation\FieldFormatter;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 
 /**
@@ -24,18 +25,18 @@
    * values, as other may want to act on those values, even if they can
    * not be accessed.
    */
-  public function prepareView(array $entities, $langcode, array &$items) {
+  public function prepareView(array $entities, $langcode, array $items) {
     $target_ids = array();
     $revision_ids = array();
 
     // Collect every possible entity attached to any of the entities.
     foreach ($entities as $id => $entity) {
       foreach ($items[$id] as $delta => $item) {
-        if (!empty($item['revision_id'])) {
-          $revision_ids[] = $item['revision_id'];
+        if (!empty($item->revision_id)) {
+          $revision_ids[] = $item->revision_id;
         }
-        elseif (!empty($item['target_id'])) {
-          $target_ids[] = $item['target_id'];
+        elseif (!empty($item->target_id)) {
+          $target_ids[] = $item->target_id;
         }
       }
     }
@@ -63,8 +64,8 @@ public function prepareView(array $entities, $langcode, array &$items) {
       $rekey = FALSE;
       foreach ($items[$id] as $delta => $item) {
         // If we have a revision ID, the key uses it as well.
-        $identifier = !empty($item['revision_id']) ? $item['target_id'] . ':' . $item['revision_id'] : $item['target_id'];
-        if ($item['target_id'] !== 0) {
+        $identifier = !empty($item->revision_id) ? $item->target_id . ':' . $item->revision_id : $item->target_id;
+        if ($item->target_id !== 0) {
           if (!isset($target_entities[$identifier])) {
             // The entity no longer exists, so remove the key.
             $rekey = TRUE;
@@ -73,7 +74,7 @@ public function prepareView(array $entities, $langcode, array &$items) {
           }
 
           $entity = $target_entities[$identifier];
-          $items[$id][$delta]['entity'] = $entity;
+          $item->entity = $entity;
 
           if (!$entity->access('view')) {
             continue;
@@ -84,7 +85,7 @@ public function prepareView(array $entities, $langcode, array &$items) {
         }
 
         // Mark item as accessible.
-        $items[$id][$delta]['access'] = TRUE;
+        $item->access = TRUE;
       }
 
       if ($rekey) {
@@ -99,10 +100,10 @@ public function prepareView(array $entities, $langcode, array &$items) {
    *
    * @see \Drupal\entity_reference\Plugin\field\formatter\EntityReferenceFormatterBase::viewElements().
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     // Remove un-accessible items.
     foreach ($items as $delta => $item) {
-      if (empty($item['access'])) {
+      if (empty($item->access)) {
         unset($items[$delta]);
       }
     }
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceIdFormatter.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceIdFormatter.php
index 3de34ee..e3e86ff 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceIdFormatter.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceIdFormatter.php
@@ -10,6 +10,7 @@
 use Drupal\field\Annotation\FieldFormatter;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\entity_reference\Plugin\field\formatter\EntityReferenceFormatterBase;
 
 /**
@@ -30,12 +31,12 @@ class EntityReferenceIdFormatter extends EntityReferenceFormatterBase {
   /**
    * Overrides \Drupal\entity_reference\Plugin\field\formatter\EntityReferenceFormatterBase::viewElements().
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
 
     foreach ($items as $delta => $item) {
-      if (!empty($item['entity']) && !empty($item['target_id'])) {
-        $elements[$delta] = array('#markup' => check_plain($item['target_id']));
+      if (!empty($item->entity) && !empty($item->target_id)) {
+        $elements[$delta] = array('#markup' => check_plain($item->target_id));
       }
     }
 
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceLabelFormatter.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceLabelFormatter.php
index 568d3d8..56332ab 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceLabelFormatter.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceLabelFormatter.php
@@ -10,6 +10,7 @@
 use Drupal\field\Annotation\FieldFormatter;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\entity_reference\Plugin\field\formatter\EntityReferenceFormatterBase;
 
 /**
@@ -55,14 +56,14 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     // Remove un-accessible items.
     parent::viewElements($entity, $langcode, $items);
 
     $elements = array();
 
     foreach ($items as $delta => $item) {
-      if ($entity = $item['entity']) {
+      if ($entity = $item->entity) {
         $label = $entity->label();
         // If the link is to be displayed and the entity has a uri,
         // display a link.
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidget.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidget.php
index ee98bfe..a7003b0 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidget.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidget.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\entity_reference\Plugin\field\widget\AutocompleteWidgetBase;
 
 /**
@@ -40,14 +41,14 @@ class AutocompleteWidget extends AutocompleteWidgetBase {
   /**
    * {@inheritdoc}
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     // We let the Field API handles multiple values for us, only take care of
     // the one matching our delta.
     if (isset($items[$delta])) {
-      $items = array($items[$delta]);
+      $items->setValue(array($items[$delta]->getValue()));
     }
     else {
-      $items = array();
+      $items->setValue(array());
     }
 
     return parent::formElement($items, $delta, $element, $langcode, $form, $form_state);
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php
index 909b780..cbadac4 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\Type\Widget\WidgetBase;
 use Symfony\Component\Validator\ConstraintViolationInterface;
 
@@ -69,7 +70,7 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     global $user;
     $entity = $element['#entity'];
 
@@ -115,13 +116,17 @@ public function elementValidate($element, &$form_state, $form) { }
   /**
    * Gets the entity labels.
    */
-  protected function getLabels(array $items) {
+  protected function getLabels(FieldInterface $items) {
+    if ($items->isEmpty()) {
+      return array();
+    }
+
     $entity_ids = array();
     $entity_labels = array();
 
     // Build an array of entity IDs.
     foreach ($items as $item) {
-      $entity_ids[] = $item['target_id'];
+      $entity_ids[] = $item->target_id;
     }
 
     // Load those entities and loop through them to extract their labels.
diff --git a/core/modules/field/field.attach.inc b/core/modules/field/field.attach.inc
index 5ed17ff..e18fcff 100644
--- a/core/modules/field/field.attach.inc
+++ b/core/modules/field/field.attach.inc
@@ -177,7 +177,8 @@ function field_invoke_method($method, $target_function, EntityInterface $entity,
       $langcodes = _field_language_suggestion($available_langcodes, $options['langcode'], $field_name);
 
       foreach ($langcodes as $langcode) {
-        $items = isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : array();
+        $items = $entity->getTranslation($langcode)->get($field_name);
+        $items->filterEmptyValues();
 
         $result = $target->$method($entity, $langcode, $items, $a, $b);
 
@@ -191,12 +192,6 @@ function field_invoke_method($method, $target_function, EntityInterface $entity,
             $return[] = $result;
           }
         }
-
-        // Populate $items back in the field values, but avoid replacing missing
-        // fields with an empty array (those are not equivalent on update).
-        if ($items !== array() || isset($entity->{$field_name}[$langcode])) {
-          $entity->{$field_name}[$langcode] = $items;
-        }
       }
     }
   }
@@ -288,7 +283,9 @@ function field_invoke_method_multiple($method, $target_function, array $entities
         foreach ($langcodes as $langcode) {
           // Group the entities and items corresponding to the current field.
           $grouped_entities[$instance_id][$langcode][$id] = $entities[$id];
-          $grouped_items[$instance_id][$langcode][$id] = isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : array();
+          $items = $entity->getTranslation($langcode)->get($field_name);
+          $items->filterEmptyValues();
+          $grouped_items[$instance_id][$langcode][$id] = $items;
         }
       }
     }
@@ -301,7 +298,7 @@ function field_invoke_method_multiple($method, $target_function, array $entities
     $field_name = $instance['field_name'];
 
     // Iterate over all the field translations.
-    foreach ($grouped_items[$instance_id] as $langcode => &$items) {
+    foreach ($grouped_items[$instance_id] as $langcode => $items) {
       $entities = $grouped_entities[$instance_id][$langcode];
       $results = $grouped_targets[$instance_id]->$method($entities, $langcode, $items, $a, $b);
 
@@ -319,16 +316,6 @@ function field_invoke_method_multiple($method, $target_function, array $entities
         }
       }
     }
-
-    // Populate field values back in the entities, but avoid replacing missing
-    // fields with an empty array (those are not equivalent on update).
-    foreach ($grouped_entities[$instance_id] as $langcode => $entities) {
-      foreach ($entities as $id => $entity) {
-        if ($grouped_items[$instance_id][$langcode][$id] !== array() || isset($entity->{$field_name}[$langcode])) {
-          $entity->{$field_name}[$langcode] = $grouped_items[$instance_id][$langcode][$id];
-        }
-      }
-    }
   }
 
   return $return;
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 88f1574..e6ce267 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -799,24 +799,11 @@ function field_view_field(EntityInterface $entity, $field_name, $display_options
   if ($formatter) {
     $display_langcode = field_language($entity, $field_name, $langcode);
 
-    // Get the items.
-    if ($entity->getNGEntity() instanceof EntityNG) {
-      $items = $entity->getTranslation($display_langcode)->get($field_name);
-      $definition = $entity->getPropertyDefinition($field_name);
-    }
-    else {
-      $definitions = \Drupal::entityManager()->getFieldDefinitions($entity_type, $bundle);
-      $definition = $definitions[$field_name];
-      $itemsBC = isset($entity->{$field_name}[$display_langcode]) ? $entity->{$field_name}[$display_langcode] : array();
-      $items = \Drupal::typedData()->create($definitions[$field_name], $itemsBC, $field_name, $entity);
-    }
-
     // Invoke the formatter's prepareView() and view() methods.
+    $items = $entity->getNGEntity()->getTranslation($display_langcode)->get($field_name);
     $id = $entity->id();
-    $itemsBC_multi = array($id => $items->getValue());
-    $formatter->prepareView(array($id => $entity), $display_langcode, $itemsBC_multi);
-    $itemsBC = $itemsBC_multi[$id];
-    $result = $formatter->view($entity, $display_langcode, $itemsBC);
+    $formatter->prepareView(array($id => $entity), $display_langcode, array($id => $items));
+    $result = $formatter->view($entity, $display_langcode, $items);
 
     // Invoke hook_field_attach_view_alter() to let other modules alter the
     // renderable array, as in a full field_attach_view() execution.
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterBase.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterBase.php
index fa780a5..8091aa8 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterBase.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterBase.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\Field\FieldDefinitionInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\FieldInstanceInterface;
 use Drupal\field\Plugin\PluginSettingsBase;
 
@@ -73,7 +74,7 @@ public function __construct($plugin_id, array $plugin_definition, FieldDefinitio
   /**
    * {@inheritdoc}
    */
-  public function view(EntityInterface $entity, $langcode, array $items) {
+  public function view(EntityInterface $entity, $langcode, FieldInterface $items) {
     $addition = array();
 
     $elements = $this->viewElements($entity, $langcode, $items);
@@ -93,7 +94,8 @@ public function view(EntityInterface $entity, $langcode, array $items) {
         '#entity_type' => $entity_type,
         '#bundle' => $entity->bundle(),
         '#object' => $entity,
-        '#items' => $items,
+        // @todo Anything that uses #items should be converted as well...
+        '#items' => $items->getValue(TRUE),
         '#formatter' => $this->getPluginId(),
       );
 
@@ -120,7 +122,7 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  public function prepareView(array $entities, $langcode, array &$items) { }
+  public function prepareView(array $entities, $langcode, array $items) { }
 
   /**
    * Returns whether the currently logged in user has access to the field.
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterInterface.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterInterface.php
index dda43b0..70bc59a 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterInterface.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterInterface.php
@@ -8,7 +8,7 @@
 namespace Drupal\field\Plugin\Type\Formatter;
 
 use Drupal\Core\Entity\EntityInterface;
-use Drupal\field\Plugin\Core\Entity\FieldInstance;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\PluginSettingsInterface;
 
 /**
@@ -69,7 +69,7 @@ public function settingsSummary();
    * @param array $items
    *   Array of field values for the entities, keyed by entity ID.
    */
-  public function prepareView(array $entities, $langcode, array &$items);
+  public function prepareView(array $entities, $langcode, array $items);
 
   /**
    * Builds a renderable array for one field on one entity instance.
@@ -78,13 +78,13 @@ public function prepareView(array $entities, $langcode, array &$items);
    *   The entity being displayed.
    * @param string $langcode
    *   The language associated with $items.
-   * @param array $items
-   *   Array of field values already loaded for the entities, keyed by entity id.
+   * @param Drupal\Core\Entity\Field\FieldInterface $items
+   *   The field value for the entity for the language.
    *
    * @return array
    *   A renderable array for a themed field with its label and all its values.
    */
-  public function view(EntityInterface $entity, $langcode, array $items);
+  public function view(EntityInterface $entity, $langcode, FieldInterface $items);
 
   /**
    * Builds a renderable array for a field value.
@@ -100,6 +100,6 @@ public function view(EntityInterface $entity, $langcode, array $items);
    *   A renderable array for $items, as an array of child elements keyed by
    *   numeric indexes starting from 0.
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items);
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items);
 
 }
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php
index 654cbbe..7c7a343 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php
@@ -10,6 +10,7 @@
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\Field\FieldDefinitionInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\FieldInstanceInterface;
 use Drupal\field\Plugin\PluginSettingsBase;
 use Symfony\Component\Validator\ConstraintViolationInterface;
@@ -55,7 +56,7 @@ public function __construct($plugin_id, array $plugin_definition, FieldDefinitio
   /**
    * {@inheritdoc}
    */
-  public function form(EntityInterface $entity, $langcode, array $items, array &$form, array &$form_state, $get_delta = NULL) {
+  public function form(EntityInterface $entity, $langcode, FieldInterface $items, array &$form, array &$form_state, $get_delta = NULL) {
     $field_name = $this->fieldDefinition->getFieldName();
 
     $parents = $form['#parents'];
@@ -150,7 +151,7 @@ public function form(EntityInterface $entity, $langcode, array $items, array &$f
    * - AHAH-'add more' button
    * - table display and drag-n-drop value reordering
    */
-  protected function formMultipleElements(EntityInterface $entity, array $items, $langcode, array &$form, array &$form_state) {
+  protected function formMultipleElements(EntityInterface $entity, FieldInterface $items, $langcode, array &$form, array &$form_state) {
     $field_name = $this->fieldDefinition->getFieldName();
     $cardinality = $this->fieldDefinition->getFieldCardinality();
     $parents = $form['#parents'];
@@ -197,7 +198,7 @@ protected function formMultipleElements(EntityInterface $entity, array $items, $
             '#title_display' => 'invisible',
             // Note: this 'delta' is the FAPI #type 'weight' element's property.
             '#delta' => $max,
-            '#default_value' => isset($items[$delta]['_weight']) ? $items[$delta]['_weight'] : $delta,
+            '#default_value' => $items[$delta]->_weight ?: $delta,
             '#weight' => 100,
           );
         }
@@ -243,7 +244,7 @@ protected function formMultipleElements(EntityInterface $entity, array $items, $
   /**
    * Generates the form element for a single copy of the widget.
    */
-  protected function formSingleElement(EntityInterface $entity, array $items, $delta, $langcode, array $element, array &$form, array &$form_state) {
+  protected function formSingleElement(EntityInterface $entity, FieldInterface $items, $delta, $langcode, array $element, array &$form, array &$form_state) {
     $element += array(
       '#entity_type' => $entity->entityType(),
       '#bundle' => $entity->bundle(),
@@ -280,7 +281,7 @@ protected function formSingleElement(EntityInterface $entity, array $items, $del
   /**
    * {@inheritdoc}
    */
-  public function extractFormValues(EntityInterface $entity, $langcode, array &$items, array $form, array &$form_state) {
+  public function extractFormValues(EntityInterface $entity, $langcode, FieldInterface $items, array $form, array &$form_state) {
     $field_name = $this->fieldDefinition->getFieldName();
 
     // Extract the values from $form_state['values'].
@@ -295,42 +296,36 @@ public function extractFormValues(EntityInterface $entity, $langcode, array &$it
       // Let the widget turn the submitted values into actual field values.
       // Make sure the '_weight' entries are persisted in the process.
       $weights = array();
-      if (isset($values[0]['_weight'])) {
+      // Check that $values[0] is an array, because if it's a string, then in
+      // PHP 5.3, ['_weight'] returns the first character.
+      if (isset($values[0]) && is_array($values[0]) && isset($values[0]['_weight'])) {
         foreach ($values as $delta => $value) {
           $weights[$delta] = $value['_weight'];
         }
       }
-      $items = $this->massageFormValues($values, $form, $form_state);
+      $items->setValue($this->massageFormValues($values, $form, $form_state));
 
-      foreach ($items as $delta => &$item) {
+      foreach ($items as $delta => $item) {
         // Put back the weight.
         if (isset($weights[$delta])) {
-          $item['_weight'] = $weights[$delta];
+          $item->_weight = $weights[$delta];
         }
         // The tasks below are going to reshuffle deltas. Keep track of the
         // original deltas for correct reporting of errors in flagErrors().
-        $item['_original_delta'] = $delta;
+        $item->_original_delta = $delta;
       }
 
       // Account for drag-n-drop reordering.
       $this->sortItems($items);
 
       // Remove empty values.
-      if ($entity instanceof \Drupal\Core\Entity\EntityNG) {
-        $itemsNG = \Drupal::typedData()->getPropertyInstance($entity, $field_name, $items);
-      }
-      else {
-        $definitions = \Drupal::entityManager()->getFieldDefinitions($entity->entityType(), $entity->bundle());
-        $itemsNG = \Drupal::typedData()->create($definitions[$field_name], $items, $field_name, $entity);
-      }
-      $itemsNG->filterEmptyValues();
-      $items = $itemsNG->getValue(TRUE);
+      $items->filterEmptyValues();
 
       // Put delta mapping in $form_state, so that flagErrors() can use it.
       $field_state = field_form_get_state($form['#parents'], $field_name, $langcode, $form_state);
-      foreach ($items as $delta => &$item) {
-        $field_state['original_deltas'][$delta] = $item['_original_delta'];
-        unset($item['_original_delta']);
+      foreach ($items as $delta => $item) {
+        $field_state['original_deltas'][$delta] = $item->_original_delta;
+        unset($item->_original_delta);
       }
       field_form_set_state($form['#parents'], $field_name, $langcode, $form_state, $field_state);
     }
@@ -339,7 +334,7 @@ public function extractFormValues(EntityInterface $entity, $langcode, array &$it
   /**
    * {@inheritdoc}
    */
-  public function flagErrors(EntityInterface $entity, $langcode, array $items, array $form, array &$form_state) {
+  public function flagErrors(EntityInterface $entity, $langcode, FieldInterface $items, array $form, array &$form_state) {
     $field_name = $this->fieldDefinition->getFieldName();
 
     $field_state = field_form_get_state($form['#parents'], $field_name, $langcode, $form_state);
@@ -416,23 +411,23 @@ public function massageFormValues(array $values, array $form, array &$form_state
   /**
    * Sorts submitted field values according to drag-n-drop reordering.
    *
-   * @param array $items
+   * @param FieldInterface $items
    *   The field values.
    */
-  protected function sortItems(array &$items) {
+  protected function sortItems(FieldInterface $items) {
     $cardinality = $this->fieldDefinition->getFieldCardinality();
     $is_multiple = ($cardinality == FIELD_CARDINALITY_UNLIMITED) || ($cardinality > 1);
-    if ($is_multiple && isset($items[0]['_weight'])) {
-      usort($items, function ($a, $b) {
+    if ($is_multiple && isset($items[0]->_weight)) {
+      $itemValues = $items->getValue(TRUE);
+      usort($itemValues, function ($a, $b) {
         $a_weight = (is_array($a) ? $a['_weight'] : 0);
         $b_weight = (is_array($b) ? $b['_weight'] : 0);
         return $a_weight - $b_weight;
       });
+      $items->setValue($itemValues);
       // Remove the '_weight' entries.
-      foreach ($items as $delta => &$item) {
-        if (is_array($item)) {
-          unset($item['_weight']);
-        }
+      foreach ($items as $delta => $item) {
+        unset($item->_weight);
       }
     }
   }
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBaseInterface.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBaseInterface.php
index ae107c9..ac8c60b 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBaseInterface.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBaseInterface.php
@@ -8,6 +8,7 @@
 namespace Drupal\field\Plugin\Type\Widget;
 
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\PluginSettingsInterface;
 
 /**
@@ -31,7 +32,7 @@
    *   The entity for which the widget is being built.
    * @param string $langcode
    *   The language associated with the field.
-   * @param array $items
+   * @param FieldInterface $items
    *   An array of the field values. When creating a new entity this may be NULL
    *   or an empty array to use default values.
    * @param array $form
@@ -45,7 +46,7 @@
    * @return array
    *   The form element array created for this field.
    */
-  public function form(EntityInterface $entity, $langcode, array $items, array &$form, array &$form_state, $get_delta = NULL);
+  public function form(EntityInterface $entity, $langcode, FieldInterface $items, array &$form, array &$form_state, $get_delta = NULL);
 
   /**
    * Extracts field values from submitted form values.
@@ -54,7 +55,7 @@ public function form(EntityInterface $entity, $langcode, array $items, array &$f
    *   The entity for which the widget is being submitted.
    * @param string $langcode
    *   The language associated to $items.
-   * @param array $items
+   * @param FieldInterface $items
    *   The field values. This parameter is altered by reference to receive the
    *   incoming form values.
    * @param array $form
@@ -63,7 +64,7 @@ public function form(EntityInterface $entity, $langcode, array $items, array &$f
    * @param array $form_state
    *   The form state.
    */
-  public function extractFormValues(EntityInterface $entity, $langcode, array &$items, array $form, array &$form_state);
+  public function extractFormValues(EntityInterface $entity, $langcode, FieldInterface $items, array $form, array &$form_state);
 
   /**
    * Reports field-level validation errors against actual form elements.
@@ -72,7 +73,7 @@ public function extractFormValues(EntityInterface $entity, $langcode, array &$it
    *   The entity for which the widget is being submitted.
    * @param string $langcode
    *   The language associated to $items.
-   * @param array $items
+   * @param FieldInterface $items
    *   The field values.
    * @param array $form
    *   The form structure where field elements are attached to. This might be a
@@ -80,6 +81,6 @@ public function extractFormValues(EntityInterface $entity, $langcode, array &$it
    * @param array $form_state
    *   The form state.
    */
-  public function flagErrors(EntityInterface $entity, $langcode, array $items, array $form, array &$form_state);
+  public function flagErrors(EntityInterface $entity, $langcode, FieldInterface $items, array $form, array &$form_state);
 
 }
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetInterface.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetInterface.php
index fbc939c..6c9e88d 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetInterface.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetInterface.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\field\Plugin\Core\Entity\FieldInstance;
 use Symfony\Component\Validator\ConstraintViolationInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Interface definition for field widget plugins.
@@ -74,7 +75,7 @@ public function settingsSummary();
    * definition and set them as ad-hoc $element['#custom'] properties, for later
    * use by its element callbacks.
    *
-   * @param array $items
+   * @param FieldInterface $items
    *   Array of default values for this field.
    * @param int $delta
    *   The order of this item in the array of subelements (0, 1, 2, etc).
@@ -114,7 +115,7 @@ public function settingsSummary();
    * @see hook_field_widget_form_alter()
    * @see hook_field_widget_WIDGET_TYPE_form_alter()
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state);
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state);
 
   /**
    * Assigns a field-level validation error to the right widget sub-element.
diff --git a/core/modules/field/lib/Drupal/field/Plugin/field/widget/HiddenWidget.php b/core/modules/field/lib/Drupal/field/Plugin/field/widget/HiddenWidget.php
index d2ff3cb..43cc435 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/field/widget/HiddenWidget.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/field/widget/HiddenWidget.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\Type\Widget\WidgetBase;
 
 /**
@@ -27,7 +28,7 @@ class HiddenWidget extends WidgetBase {
   /**
    * {@inheritdoc}
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     // The purpose of this widget is to be hidden, so nothing to do here.
     return array();
   }
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/formatter/TestFieldDefaultFormatter.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/formatter/TestFieldDefaultFormatter.php
index 4e1f59a..5a719b9 100644
--- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/formatter/TestFieldDefaultFormatter.php
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/formatter/TestFieldDefaultFormatter.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Annotation\Translation;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'field_test_default' formatter.
@@ -56,11 +57,11 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
 
     foreach ($items as $delta => $item) {
-      $elements[$delta] = array('#markup' => $this->getSetting('test_formatter_setting') . '|' . $item['value']);
+      $elements[$delta] = array('#markup' => $this->getSetting('test_formatter_setting') . '|' . $item->value);
     }
 
     return $elements;
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/formatter/TestFieldEmptyFormatter.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/formatter/TestFieldEmptyFormatter.php
index df71b16..7addc4b 100644
--- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/formatter/TestFieldEmptyFormatter.php
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/formatter/TestFieldEmptyFormatter.php
@@ -10,6 +10,7 @@
 use Drupal\field\Annotation\FieldFormatter;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 
 /**
@@ -32,11 +33,11 @@ class TestFieldEmptyFormatter extends FormatterBase {
   /**
    * {@inheritdoc}
    */
-  public function prepareView(array $entities, $langcode, array &$items) {
-    foreach ($items as $id => $entity_items) {
-      if (empty($entity_items)) {
+  public function prepareView(array $entities, $langcode, array $items) {
+    foreach ($entities as $id => $entity) {
+      if ($items[$id]->isEmpty()) {
         // For fields with no value, just add the configured "empty" value.
-        $items[$id][0]['value'] = $this->getSetting('test_empty_string');
+        $items[$id][0]->value = $this->getSetting('test_empty_string');
       }
     }
   }
@@ -44,13 +45,13 @@ public function prepareView(array $entities, $langcode, array &$items) {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
 
     if (!empty($items)) {
       foreach ($items as $delta => $item) {
         // This formatter only needs to output raw for testing.
-        $elements[$delta] = array('#markup' => $item['value']);
+        $elements[$delta] = array('#markup' => $item->value);
       }
     }
 
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/formatter/TestFieldMultipleFormatter.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/formatter/TestFieldMultipleFormatter.php
index 2810e09..1894ba3 100644
--- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/formatter/TestFieldMultipleFormatter.php
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/formatter/TestFieldMultipleFormatter.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Annotation\Translation;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'field_test_multiple' formatter.
@@ -56,13 +57,13 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
 
     if (!empty($items)) {
       $array = array();
       foreach ($items as $delta => $item) {
-        $array[] = $delta . ':' . $item['value'];
+        $array[] = $delta . ':' . $item->value;
       }
       $elements[0] = array('#markup' => $this->getSetting('test_formatter_setting_multiple') . '|' . implode('|', $array));
     }
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/formatter/TestFieldPrepareViewFormatter.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/formatter/TestFieldPrepareViewFormatter.php
index ad0ea47..5c46e3b 100644
--- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/formatter/TestFieldPrepareViewFormatter.php
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/formatter/TestFieldPrepareViewFormatter.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Annotation\Translation;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'field_test_with_prepare_view' formatter.
@@ -56,12 +57,12 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  public function prepareView(array $entities, $langcode, array &$items) {
-    foreach ($items as $id => $item) {
-      foreach ($item as $delta => $value) {
+  public function prepareView(array $entities, $langcode, array $items) {
+    foreach ($entities as $id => $entity) {
+      foreach ($items[$id] as $delta => $item) {
         // Don't add anything on empty values.
-        if ($value) {
-          $items[$id][$delta]['additional_formatter_value'] = $value['value'] + 1;
+        if (!$item->isEmpty()) {
+          $item->additional_formatter_value = $item->value + 1;
         }
       }
     }
@@ -70,11 +71,11 @@ public function prepareView(array $entities, $langcode, array &$items) {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
 
     foreach ($items as $delta => $item) {
-      $elements[$delta] = array('#markup' => $this->getSetting('test_formatter_setting_additional') . '|' . $item['value'] . '|' . $item['additional_formatter_value']);
+      $elements[$delta] = array('#markup' => $this->getSetting('test_formatter_setting_additional') . '|' . $item->value . '|' . $item->additional_formatter_value);
     }
 
     return $elements;
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidget.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidget.php
index c6e850c..f6b1c7c 100644
--- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidget.php
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidget.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\Type\Widget\WidgetBase;
 use Symfony\Component\Validator\ConstraintViolationInterface;
 
@@ -56,10 +57,10 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $element += array(
       '#type' => 'textfield',
-      '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : '',
+      '#default_value' => isset($items[$delta]->value) ? $items[$delta]->value : '',
     );
     return array('value' => $element);
   }
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidgetMultiple.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidgetMultiple.php
index 1fb1f38..f5b3a98 100644
--- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidgetMultiple.php
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidgetMultiple.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\Type\Widget\WidgetBase;
 use Symfony\Component\Validator\ConstraintViolationInterface;
 
@@ -57,10 +58,10 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $values = array();
-    foreach ($items as $delta => $value) {
-      $values[] = $value['value'];
+    foreach ($items as $delta => $item) {
+      $values[] = $item->value;
     }
     $element += array(
       '#type' => 'textfield',
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php
index 26264ac..6239e42 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php
@@ -135,22 +135,9 @@ public function validateForm(array &$form, array &$form_state) {
       $element = $form['instance']['default_value_widget'];
 
       // Extract the 'default value'.
-      $items = array();
+      $items = $entity->getNGEntity()->{$field_name};
       $entity_form_display->getRenderer($this->instance->getField()->id)->extractFormValues($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state);
-
-      // @todo Simplify when all entity types are converted to EntityNG.
-      if ($entity instanceof EntityNG) {
-        $entity->{$field_name}->setValue($items);
-        $itemsNG = $entity->{$field_name};
-      }
-      else {
-        // For BC entities, instantiate NG items objects manually.
-        $definitions = \Drupal::entityManager()->getFieldDefinitions($entity->entityType(), $entity->bundle());
-        $itemsNG = \Drupal::typedData()->create($definitions[$field_name], $items, $field_name, $entity);
-      }
-      $violations = $itemsNG->validate();
-
-      // Grab the field definition from $form_state.
+      $violations = $items->validate();
 
       // Report errors.
       if (count($violations)) {
@@ -169,6 +156,7 @@ public function validateForm(array &$form, array &$form_state) {
    * {@inheritdoc}
    */
   public function submitForm(array &$form, array &$form_state) {
+    $field_name = $this->instance['field_name'];
     $entity = $form['#entity'];
     $entity_form_display = $form['#entity_form_display'];
 
@@ -177,10 +165,10 @@ public function submitForm(array &$form, array &$form_state) {
       $element = $form['instance']['default_value_widget'];
 
       // Extract field values.
-      $items = array();
+      $items = $entity->getNGEntity()->{$field_name};
       $entity_form_display->getRenderer($this->instance->getField()->id)->extractFormValues($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state);
 
-      $this->instance['default_value'] = $items ? $items : NULL;
+      $this->instance['default_value'] = $items->getValue() ?: NULL;
     }
 
     // Merge incoming values into the instance.
@@ -246,9 +234,9 @@ protected function getDefaultValueWidget($field, array &$form, &$form_state) {
 
     // Insert the widget. Since we do not use the "official" instance definition,
     // the whole flow cannot use field_invoke_method().
-    $items = array();
+    $items = $entity->getNGEntity()->{$this->instance->getField()->id};
     if (!empty($this->instance['default_value'])) {
-      $items = (array) $this->instance['default_value'];
+      $items->setValue((array) $this->instance['default_value']);
     }
     $element += $entity_form_display->getRenderer($this->instance->getField()->id)->form($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state);
 
diff --git a/core/modules/file/lib/Drupal/file/Plugin/field/formatter/FileFormatterBase.php b/core/modules/file/lib/Drupal/file/Plugin/field/formatter/FileFormatterBase.php
index ccf28d3..2ef9df2 100644
--- a/core/modules/file/lib/Drupal/file/Plugin/field/formatter/FileFormatterBase.php
+++ b/core/modules/file/lib/Drupal/file/Plugin/field/formatter/FileFormatterBase.php
@@ -17,14 +17,14 @@
   /**
    * {@inheritdoc}
    */
-  public function prepareView(array $entities, $langcode, array &$items) {
+  public function prepareView(array $entities, $langcode, array $items) {
     // Remove files specified to not be displayed.
     $fids = array();
     foreach ($entities as $id => $entity) {
       foreach ($items[$id] as $delta => $item) {
-        if ($this->isDisplayed($item) && !empty($item['target_id'])) {
+        if ($this->isDisplayed($item) && !empty($item->target_id)) {
           // Load the files from the files table.
-          $fids[] = $item['target_id'];
+          $fids[] = $item->target_id;
         }
       }
     }
@@ -35,8 +35,8 @@ public function prepareView(array $entities, $langcode, array &$items) {
       foreach ($entities as $id => $entity) {
         foreach ($items[$id] as $delta => $item) {
           // If the file does not exist, mark the entire item as empty.
-          if (!empty($item['target_id'])) {
-            $items[$id][$delta]['entity'] = isset($files[$item['target_id']]) ? $files[$item['target_id']] : NULL;
+          if (!empty($item->target_id)) {
+            $item->entity = isset($files[$item->target_id]) ? $files[$item->target_id] : NULL;
           }
         }
       }
@@ -57,7 +57,7 @@ public function prepareView(array $entities, $langcode, array &$items) {
   protected function isDisplayed($item) {
     $settings = $this->getFieldSettings();
     if (!empty($settings['display_field'])) {
-      return (bool) $item['display'];
+      return (bool) $item->display;
     }
     return TRUE;
   }
diff --git a/core/modules/file/lib/Drupal/file/Plugin/field/formatter/GenericFileFormatter.php b/core/modules/file/lib/Drupal/file/Plugin/field/formatter/GenericFileFormatter.php
index 6eae26a..91a5383 100644
--- a/core/modules/file/lib/Drupal/file/Plugin/field/formatter/GenericFileFormatter.php
+++ b/core/modules/file/lib/Drupal/file/Plugin/field/formatter/GenericFileFormatter.php
@@ -10,6 +10,7 @@
 use Drupal\field\Annotation\FieldFormatter;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'file_default' formatter.
@@ -28,15 +29,15 @@ class GenericFileFormatter extends FileFormatterBase {
   /**
    * Implements \Drupal\field\Plugin\Type\Formatter\FormatterInterface::viewElements().
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
 
     foreach ($items as $delta => $item) {
-      if ($item['display'] && $item['entity']) {
+      if ($item->display && $item->entity) {
         $elements[$delta] = array(
           '#theme' => 'file_link',
-          '#file' => $item['entity'],
-          '#description' => $item['description'],
+          '#file' => $item->entity,
+          '#description' => $item->description,
         );
       }
     }
diff --git a/core/modules/file/lib/Drupal/file/Plugin/field/formatter/RSSEnclosureFormatter.php b/core/modules/file/lib/Drupal/file/Plugin/field/formatter/RSSEnclosureFormatter.php
index af57980..2880e70 100644
--- a/core/modules/file/lib/Drupal/file/Plugin/field/formatter/RSSEnclosureFormatter.php
+++ b/core/modules/file/lib/Drupal/file/Plugin/field/formatter/RSSEnclosureFormatter.php
@@ -10,6 +10,7 @@
 use Drupal\field\Annotation\FieldFormatter;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'file_rss_enclosure' formatter.
@@ -28,13 +29,13 @@ class RSSEnclosureFormatter extends FileFormatterBase {
   /**
    * Implements \Drupal\field\Plugin\Type\Formatter\FormatterInterface::viewElements().
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
 
     // Add the first file as an enclosure to the RSS item. RSS allows only one
     // enclosure per item. See: http://en.wikipedia.org/wiki/RSS_enclosure
     foreach ($items as $item) {
-      if ($item['display'] && $item['entity']) {
-        $file = $item['entity'];
+      if ($item->display && $item->entity) {
+        $file = $item->entity;
         $entity->rss_elements[] = array(
           'key' => 'enclosure',
           'attributes' => array(
diff --git a/core/modules/file/lib/Drupal/file/Plugin/field/formatter/TableFormatter.php b/core/modules/file/lib/Drupal/file/Plugin/field/formatter/TableFormatter.php
index 95920f3..c97c092 100644
--- a/core/modules/file/lib/Drupal/file/Plugin/field/formatter/TableFormatter.php
+++ b/core/modules/file/lib/Drupal/file/Plugin/field/formatter/TableFormatter.php
@@ -10,6 +10,7 @@
 use Drupal\field\Annotation\FieldFormatter;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'file_table' formatter.
@@ -28,14 +29,14 @@ class TableFormatter extends FileFormatterBase {
   /**
    * Implements \Drupal\field\Plugin\Type\Formatter\FormatterInterface::viewElements().
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
 
-    if (!empty($items)) {
+    if (!$items->isEmpty()) {
       // Display all values in a single element.
       $elements[0] = array(
         '#theme' => 'file_formatter_table',
-        '#items' => $items,
+        '#items' => $items->getValue(TRUE),
       );
     }
 
diff --git a/core/modules/file/lib/Drupal/file/Plugin/field/formatter/UrlPlainFormatter.php b/core/modules/file/lib/Drupal/file/Plugin/field/formatter/UrlPlainFormatter.php
index 090bd37..7edcb06 100644
--- a/core/modules/file/lib/Drupal/file/Plugin/field/formatter/UrlPlainFormatter.php
+++ b/core/modules/file/lib/Drupal/file/Plugin/field/formatter/UrlPlainFormatter.php
@@ -10,6 +10,7 @@
 use Drupal\field\Annotation\FieldFormatter;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'file_url_plain' formatter.
@@ -28,12 +29,12 @@ class UrlPlainFormatter extends FileFormatterBase {
   /**
    * Implements \Drupal\field\Plugin\Type\Formatter\FormatterInterface::viewElements().
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
 
     foreach ($items as $delta => $item) {
-      if ($item['display'] && $item['entity']) {
-        $elements[$delta] = array('#markup' => empty($item['entity']) ? '' : file_create_url($item['entity']->getFileUri()));
+      if ($item->display && $item->entity) {
+        $elements[$delta] = array('#markup' => empty($item->entity) ? '' : file_create_url($item->entity->getFileUri()));
       }
     }
 
diff --git a/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php b/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php
index 63564fa..4a62229 100644
--- a/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php
+++ b/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Annotation\Translation;
 use Drupal\field\Plugin\Type\Widget\WidgetBase;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'file_generic' widget.
@@ -63,7 +64,7 @@ public function settingsSummary() {
    *
    * Special handling for draggable multiple widgets and 'add more' button.
    */
-  protected function formMultipleElements(EntityInterface $entity, array $items, $langcode, array &$form, array &$form_state) {
+  protected function formMultipleElements(EntityInterface $entity, FieldInterface $items, $langcode, array &$form, array &$form_state) {
     $field_name = $this->fieldDefinition->getFieldName();
 
     $parents = $form['#parents'];
@@ -73,7 +74,7 @@ protected function formMultipleElements(EntityInterface $entity, array $items, $
     // only passed in as $items when editing existing entities.
     $field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
     if (isset($field_state['items'])) {
-      $items = $field_state['items'];
+      $items->setValue($field_state['items']);
     }
 
     // Determine the number of widgets to display.
@@ -118,7 +119,7 @@ protected function formMultipleElements(EntityInterface $entity, array $items, $
             '#title_display' => 'invisible',
             // Note: this 'delta' is the FAPI #type 'weight' element's property.
             '#delta' => $max,
-            '#default_value' => isset($item['_weight']) ? $item['_weight'] : $delta,
+            '#default_value' => $item->_weight ?: $delta,
             '#weight' => 100,
           );
         }
@@ -173,7 +174,7 @@ protected function formMultipleElements(EntityInterface $entity, array $items, $
   /**
    * {@inheritdoc}
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $field_settings = $this->getFieldSettings();
 
     // The field settings include defaults for the field type. However, this
@@ -218,10 +219,10 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
 
     // Field stores FID value in a single mode, so we need to transform it for
     // form element to recognize it correctly.
-    if (!isset($items[$delta]['fids']) && isset($items[$delta]['target_id'])) {
-      $items[$delta]['fids'][0] = $items[$delta]['target_id'];
+    if (!isset($items[$delta]->fids) && isset($items[$delta]->target_id)) {
+      $items[$delta]->fids = array($items[$delta]->target_id);
     }
-    $element['#default_value'] = !empty($items[$delta]) ? $items[$delta] : $defaults;
+    $element['#default_value'] = $items[$delta]->getValue() + $defaults;
 
     $default_fids = $element['#extended'] ? $element['#default_value']['fids'] : $element['#default_value'];
     if (empty($default_fids)) {
diff --git a/core/modules/image/lib/Drupal/image/Plugin/field/formatter/ImageFormatter.php b/core/modules/image/lib/Drupal/image/Plugin/field/formatter/ImageFormatter.php
index 84b73ba..1148b3e 100644
--- a/core/modules/image/lib/Drupal/image/Plugin/field/formatter/ImageFormatter.php
+++ b/core/modules/image/lib/Drupal/image/Plugin/field/formatter/ImageFormatter.php
@@ -10,6 +10,7 @@
 use Drupal\field\Annotation\FieldFormatter;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'image' formatter.
@@ -92,7 +93,7 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
 
     $image_link_setting = $this->getSetting('image_link');
@@ -106,9 +107,9 @@ public function viewElements(EntityInterface $entity, $langcode, array $items) {
 
     $image_style_setting = $this->getSetting('image_style');
     foreach ($items as $delta => $item) {
-      if ($item['entity']) {
+      if ($item->entity) {
         if (isset($link_file)) {
-          $image_uri = $item['entity']->getFileUri();
+          $image_uri = $item->entity->getFileUri();
           $uri = array(
             'path' => file_create_url($image_uri),
             'options' => array(),
@@ -116,7 +117,7 @@ public function viewElements(EntityInterface $entity, $langcode, array $items) {
         }
         $elements[$delta] = array(
           '#theme' => 'image_formatter',
-          '#item' => $item,
+          '#item' => $item->getValue(TRUE),
           '#image_style' => $image_style_setting,
           '#path' => isset($uri) ? $uri : '',
         );
diff --git a/core/modules/image/lib/Drupal/image/Plugin/field/formatter/ImageFormatterBase.php b/core/modules/image/lib/Drupal/image/Plugin/field/formatter/ImageFormatterBase.php
index 06374b6..0ed0be4 100644
--- a/core/modules/image/lib/Drupal/image/Plugin/field/formatter/ImageFormatterBase.php
+++ b/core/modules/image/lib/Drupal/image/Plugin/field/formatter/ImageFormatterBase.php
@@ -17,12 +17,12 @@
   /**
    * {@inheritdoc}
    */
-  public function prepareView(array $entities, $langcode, array &$items) {
+  public function prepareView(array $entities, $langcode, array $items) {
     parent::prepareView($entities, $langcode, $items);
 
     // If there are no files specified at all, use the default.
     foreach ($entities as $id => $entity) {
-      if (empty($items[$id])) {
+      if ($items[$id]->isEmpty()) {
         $fid = array();
         $instance = field_info_instance($entity->entityType(), $this->fieldDefinition->getFieldName(), $entity->bundle());
         // Use the default for the instance if one is available.
@@ -38,13 +38,13 @@ public function prepareView(array $entities, $langcode, array &$items) {
 
         // Add the default image if one is found.
         if ($fid && ($file = file_load($fid[0]))) {
-          $items[$id][0] = array(
+          $items[$id]->setValue(array(array(
             'is_default' => TRUE,
             'alt' => '',
             'title' => '',
             'entity' => $file,
-            'fid' => $file->id(),
-          );
+            'target_id' => $file->id(),
+          )));
         }
       }
     }
diff --git a/core/modules/image/lib/Drupal/image/Plugin/field/widget/ImageWidget.php b/core/modules/image/lib/Drupal/image/Plugin/field/widget/ImageWidget.php
index d0ae8fa..d7b3d53 100644
--- a/core/modules/image/lib/Drupal/image/Plugin/field/widget/ImageWidget.php
+++ b/core/modules/image/lib/Drupal/image/Plugin/field/widget/ImageWidget.php
@@ -12,6 +12,7 @@
 use Drupal\field\Plugin\Type\Widget\WidgetBase;
 use Drupal\file\Plugin\field\widget\FileWidget;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'image_image' widget.
@@ -80,7 +81,7 @@ public function settingsSummary() {
    *
    * Special handling for draggable multiple widgets and 'add more' button.
    */
-  protected function formMultipleElements(EntityInterface $entity, array $items, $langcode, array &$form, array &$form_state) {
+  protected function formMultipleElements(EntityInterface $entity, FieldInterface $items, $langcode, array &$form, array &$form_state) {
     $elements = parent::formMultipleElements($entity, $items, $langcode, $form, $form_state);
 
     $cardinality = $this->fieldDefinition->getFieldCardinality();
@@ -100,7 +101,7 @@ protected function formMultipleElements(EntityInterface $entity, array $items, $
   /**
    * {@inheritdoc}
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $element = parent::formElement($items, $delta, $element, $langcode, $form, $form_state);
 
     $field_settings = $this->getFieldSettings();
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php
index 164cbad..6f311a0 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php
@@ -121,7 +121,7 @@ function testDefaultImages() {
     $article = $this->drupalCreateNode(array('type' => 'article'));
     $article_built = node_view($article);
     $this->assertEqual(
-      $article_built[$field_name]['#items'][0]['fid'],
+      $article_built[$field_name]['#items'][0]['target_id'],
       $default_images['instance']->id(),
       format_string(
         'A new article node without an image has the expected default image file ID of @fid.',
@@ -133,7 +133,7 @@ function testDefaultImages() {
     $page = $this->drupalCreateNode(array('type' => 'page'));
     $page_built = node_view($page);
     $this->assertEqual(
-      $page_built[$field_name]['#items'][0]['fid'],
+      $page_built[$field_name]['#items'][0]['target_id'],
       $default_images['instance2']->id(),
       format_string(
         'A new page node without an image has the expected default image file ID of @fid.',
@@ -160,7 +160,7 @@ function testDefaultImages() {
     $article_built = node_view($article = node_load($article->nid, TRUE));
     $page_built = node_view($page = node_load($page->nid, TRUE));
     $this->assertEqual(
-      $article_built[$field_name]['#items'][0]['fid'],
+      $article_built[$field_name]['#items'][0]['target_id'],
       $default_images['instance']->id(),
       format_string(
         'An existing article node without an image has the expected default image file ID of @fid.',
@@ -168,7 +168,7 @@ function testDefaultImages() {
       )
     );
     $this->assertEqual(
-      $page_built[$field_name]['#items'][0]['fid'],
+      $page_built[$field_name]['#items'][0]['target_id'],
       $default_images['instance2']->id(),
       format_string(
         'An existing page node without an image has the expected default image file ID of @fid.',
@@ -198,7 +198,7 @@ function testDefaultImages() {
 
     // Confirm the article uses the new default.
     $this->assertEqual(
-      $article_built[$field_name]['#items'][0]['fid'],
+      $article_built[$field_name]['#items'][0]['target_id'],
       $default_images['instance_new']->id(),
       format_string(
         'An existing article node without an image has the expected default image file ID of @fid.',
@@ -207,7 +207,7 @@ function testDefaultImages() {
     );
     // Confirm the page remains unchanged.
     $this->assertEqual(
-      $page_built[$field_name]['#items'][0]['fid'],
+      $page_built[$field_name]['#items'][0]['target_id'],
       $default_images['instance2']->id(),
       format_string(
         'An existing page node without an image has the expected default image file ID of @fid.',
@@ -232,7 +232,7 @@ function testDefaultImages() {
     $page_built = node_view($page = node_load($page->nid, TRUE));
     // Confirm the article uses the new field (not instance) default.
     $this->assertEqual(
-      $article_built[$field_name]['#items'][0]['fid'],
+      $article_built[$field_name]['#items'][0]['target_id'],
       $default_images['field_new']->id(),
       format_string(
         'An existing article node without an image has the expected default image file ID of @fid.',
@@ -241,7 +241,7 @@ function testDefaultImages() {
     );
     // Confirm the page remains unchanged.
     $this->assertEqual(
-      $page_built[$field_name]['#items'][0]['fid'],
+      $page_built[$field_name]['#items'][0]['target_id'],
       $default_images['instance2']->id(),
       format_string(
         'An existing page node without an image has the expected default image file ID of @fid.',
diff --git a/core/modules/link/lib/Drupal/link/Plugin/field/formatter/LinkFormatter.php b/core/modules/link/lib/Drupal/link/Plugin/field/formatter/LinkFormatter.php
index 27daeef..acafdfd 100644
--- a/core/modules/link/lib/Drupal/link/Plugin/field/formatter/LinkFormatter.php
+++ b/core/modules/link/lib/Drupal/link/Plugin/field/formatter/LinkFormatter.php
@@ -10,6 +10,7 @@
 use Drupal\field\Annotation\FieldFormatter;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 
 /**
@@ -115,28 +116,32 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  public function prepareView(array $entities, $langcode, array &$items) {
+  public function prepareView(array $entities, $langcode, array $items) {
     $settings = $this->getSettings();
 
     foreach ($entities as $id => $entity) {
-      foreach ($items[$id] as $delta => &$item) {
+      foreach ($items[$id] as $delta => $item) {
 
         // Split out the link into the parts required for url(): path and options.
-        $parsed = drupal_parse_url($item['url']);
-        $item['path'] = $parsed['path'];
-        $item['options'] = array(
+        $parsed = drupal_parse_url($item->url);
+        $item->path = $parsed['path'];
+        $item->options = array(
           'query' => $parsed['query'],
           'fragment' => $parsed['fragment'],
-          'attributes' => &$item['attributes'],
+          'attributes' => $item->attributes,
         );
 
         // Add optional 'rel' attribute to link options.
         if (!empty($settings['rel'])) {
-          $item['options']['attributes']['rel'] = $settings['rel'];
+          $options = $item->options;
+          $options['attributes']['rel'] = $settings['rel'];
+          $item->options = $options;
         }
         // Add optional 'target' attribute to link options.
         if (!empty($settings['target'])) {
-          $item['options']['attributes']['target'] = $settings['target'];
+          $options = $item->options;
+          $options['attributes']['target'] = $settings['target'];
+          $item->options = $options;
         }
       }
     }
@@ -145,19 +150,19 @@ public function prepareView(array $entities, $langcode, array &$items) {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $element = array();
     $settings = $this->getSettings();
 
     foreach ($items as $delta => $item) {
       // By default use the full URL as the link text.
-      $link_title = $item['url'];
+      $link_title = $item->url;
 
       // If the title field value is available, use it for the link text.
-      if (empty($settings['url_only']) && !empty($item['title'])) {
+      if (empty($settings['url_only']) && !empty($item->title)) {
         // Unsanitizied token replacement here because $options['html'] is FALSE
         // by default in l().
-        $link_title = \Drupal::token()->replace($item['title'], array($entity->entityType() => $entity), array('sanitize' => FALSE, 'clear' => TRUE));
+        $link_title = \Drupal::token()->replace($item->title, array($entity->entityType() => $entity), array('sanitize' => FALSE, 'clear' => TRUE));
       }
 
       // Trim the link text to the desired length.
@@ -174,8 +179,8 @@ public function viewElements(EntityInterface $entity, $langcode, array $items) {
         $element[$delta] = array(
           '#type' => 'link',
           '#title' => $link_title,
-          '#href' => $item['path'],
-          '#options' => $item['options'],
+          '#href' => $item->path,
+          '#options' => $item->options,
         );
       }
     }
diff --git a/core/modules/link/lib/Drupal/link/Plugin/field/formatter/LinkSeparateFormatter.php b/core/modules/link/lib/Drupal/link/Plugin/field/formatter/LinkSeparateFormatter.php
index d39d420..7ad4f43 100644
--- a/core/modules/link/lib/Drupal/link/Plugin/field/formatter/LinkSeparateFormatter.php
+++ b/core/modules/link/lib/Drupal/link/Plugin/field/formatter/LinkSeparateFormatter.php
@@ -15,6 +15,7 @@
 use Drupal\field\Annotation\FieldFormatter;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 
 /**
@@ -39,39 +40,39 @@ class LinkSeparateFormatter extends LinkFormatter {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $element = array();
     $settings = $this->getSettings();
 
     foreach ($items as $delta => $item) {
       // By default use the full URL as the link text.
-      $link_title = $item['url'];
+      $link_title = $item->url;
 
       // If the link text field value is available, use it for the text.
-      if (empty($settings['url_only']) && !empty($item['title'])) {
+      if (empty($settings['url_only']) && !empty($item->title)) {
         // Unsanitized token replacement here because $options['html'] is FALSE
         // by default in l().
-        $link_title = \Drupal::token()->replace($item['title'], array($entity->entityType() => $entity), array('sanitize' => FALSE, 'clear' => TRUE));
+        $link_title = \Drupal::token()->replace($item->title, array($entity->entityType() => $entity), array('sanitize' => FALSE, 'clear' => TRUE));
       }
 
       // The link_separate formatter has two titles; the link text (as in the
       // field values) and the URL itself. If there is no link text value,
       // $link_title defaults to the URL, so it needs to be unset.
       // The URL version may need to be trimmed as well.
-      if (empty($item['title'])) {
+      if (empty($item->title)) {
         $link_title = NULL;
       }
-      $url_title = $item['url'];
+      $url_title = $item->url;
       if (!empty($settings['trim_length'])) {
         $link_title = truncate_utf8($link_title, $settings['trim_length'], FALSE, TRUE);
-        $url_title = truncate_utf8($item['url'], $settings['trim_length'], FALSE, TRUE);
+        $url_title = truncate_utf8($item->url, $settings['trim_length'], FALSE, TRUE);
       }
       $element[$delta] = array(
         '#theme' => 'link_formatter_link_separate',
         '#title' => $link_title,
         '#url_title' => $url_title,
-        '#href' => $item['path'],
-        '#options' => $item['options'],
+        '#href' => $item->path,
+        '#options' => $item->options,
       );
     }
     return $element;
diff --git a/core/modules/link/lib/Drupal/link/Plugin/field/widget/LinkWidget.php b/core/modules/link/lib/Drupal/link/Plugin/field/widget/LinkWidget.php
index d5bc6fd..12d6fee 100644
--- a/core/modules/link/lib/Drupal/link/Plugin/field/widget/LinkWidget.php
+++ b/core/modules/link/lib/Drupal/link/Plugin/field/widget/LinkWidget.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\Type\Widget\WidgetBase;
 
 /**
@@ -32,12 +33,12 @@ class LinkWidget extends WidgetBase {
   /**
    * {@inheritdoc}
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $element['url'] = array(
       '#type' => 'url',
       '#title' => t('URL'),
       '#placeholder' => $this->getSetting('placeholder_url'),
-      '#default_value' => isset($items[$delta]['url']) ? $items[$delta]['url'] : NULL,
+      '#default_value' => isset($items[$delta]->url) ? $items[$delta]->url : NULL,
       '#maxlength' => 2048,
       '#required' => $element['#required'],
     );
@@ -45,7 +46,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
       '#type' => 'textfield',
       '#title' => t('Link text'),
       '#placeholder' => $this->getSetting('placeholder_title'),
-      '#default_value' => isset($items[$delta]['title']) ? $items[$delta]['title'] : NULL,
+      '#default_value' => isset($items[$delta]->title) ? $items[$delta]->title : NULL,
       '#maxlength' => 255,
       '#access' => $this->getFieldSetting('title') != DRUPAL_DISABLED,
     );
@@ -62,7 +63,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
     $element['attributes'] = array(
       '#type' => 'value',
       '#tree' => TRUE,
-      '#value' => !empty($items[$delta]['attributes']) ? $items[$delta]['attributes'] : array(),
+      '#value' => !empty($items[$delta]->attributes) ? $items[$delta]->attributes : array(),
       '#attributes' => array('class' => array('link-field-widget-attributes')),
     );
 
diff --git a/core/modules/number/lib/Drupal/number/Plugin/field/formatter/DefaultNumberFormatter.php b/core/modules/number/lib/Drupal/number/Plugin/field/formatter/DefaultNumberFormatter.php
index 8188dc1..c82c2af 100644
--- a/core/modules/number/lib/Drupal/number/Plugin/field/formatter/DefaultNumberFormatter.php
+++ b/core/modules/number/lib/Drupal/number/Plugin/field/formatter/DefaultNumberFormatter.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Annotation\Translation;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Parent plugin for decimal and integer formatters
@@ -64,18 +65,18 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
 
     foreach ($items as $delta => $item) {
-      $output = $this->numberFormat($item['value']);
+      $output = $this->numberFormat($item->value);
 
       // Account for prefix and suffix.
       if ($this->getSetting('prefix_suffix')) {
         $prefixes = isset($instance['settings']['prefix']) ? array_map('field_filter_xss', explode('|', $instance['settings']['prefix'])) : array('');
         $suffixes = isset($instance['settings']['suffix']) ? array_map('field_filter_xss', explode('|', $instance['settings']['suffix'])) : array('');
-        $prefix = (count($prefixes) > 1) ? format_plural($item['value'], $prefixes[0], $prefixes[1]) : $prefixes[0];
-        $suffix = (count($suffixes) > 1) ? format_plural($item['value'], $suffixes[0], $suffixes[1]) : $suffixes[0];
+        $prefix = (count($prefixes) > 1) ? format_plural($item->value, $prefixes[0], $prefixes[1]) : $prefixes[0];
+        $suffix = (count($suffixes) > 1) ? format_plural($item->value, $suffixes[0], $suffixes[1]) : $suffixes[0];
         $output = $prefix . $output . $suffix;
       }
 
diff --git a/core/modules/number/lib/Drupal/number/Plugin/field/formatter/NumberDecimalFormatter.php b/core/modules/number/lib/Drupal/number/Plugin/field/formatter/NumberDecimalFormatter.php
index 41f075d..21fe5c0 100644
--- a/core/modules/number/lib/Drupal/number/Plugin/field/formatter/NumberDecimalFormatter.php
+++ b/core/modules/number/lib/Drupal/number/Plugin/field/formatter/NumberDecimalFormatter.php
@@ -12,6 +12,7 @@
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 use Drupal\number\Plugin\field\formatter\DefaultNumberFormatter;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'number_decimal' formatter.
diff --git a/core/modules/number/lib/Drupal/number/Plugin/field/formatter/NumberIntegerFormatter.php b/core/modules/number/lib/Drupal/number/Plugin/field/formatter/NumberIntegerFormatter.php
index 16f36ad..446f226 100644
--- a/core/modules/number/lib/Drupal/number/Plugin/field/formatter/NumberIntegerFormatter.php
+++ b/core/modules/number/lib/Drupal/number/Plugin/field/formatter/NumberIntegerFormatter.php
@@ -12,6 +12,7 @@
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 use Drupal\number\Plugin\field\formatter\DefaultNumberFormatter;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'number_integer' formatter.
diff --git a/core/modules/number/lib/Drupal/number/Plugin/field/formatter/NumberUnformattedFormatter.php b/core/modules/number/lib/Drupal/number/Plugin/field/formatter/NumberUnformattedFormatter.php
index b8a3653..a7c0fee 100644
--- a/core/modules/number/lib/Drupal/number/Plugin/field/formatter/NumberUnformattedFormatter.php
+++ b/core/modules/number/lib/Drupal/number/Plugin/field/formatter/NumberUnformattedFormatter.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Annotation\Translation;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'number_unformatted' formatter.
@@ -31,11 +32,11 @@ class NumberUnformattedFormatter extends FormatterBase {
   /**
    * Implements Drupal\field\Plugin\Type\Formatter\FormatterInterface::viewElements().
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
 
     foreach ($items as $delta => $item) {
-      $elements[$delta] = array('#markup' => $item['value']);
+      $elements[$delta] = array('#markup' => $item->value);
     }
 
     return $elements;
diff --git a/core/modules/number/lib/Drupal/number/Plugin/field/widget/NumberWidget.php b/core/modules/number/lib/Drupal/number/Plugin/field/widget/NumberWidget.php
index 1d628ba..eeae935 100644
--- a/core/modules/number/lib/Drupal/number/Plugin/field/widget/NumberWidget.php
+++ b/core/modules/number/lib/Drupal/number/Plugin/field/widget/NumberWidget.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\Type\Widget\WidgetBase;
 use Symfony\Component\Validator\ConstraintViolationInterface;
 
@@ -64,8 +65,8 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
-    $value = isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL;
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+    $value = isset($items[$delta]->value) ? $items[$delta]->value : NULL;
     $field_settings = $this->getFieldSettings();
 
     $element += array(
diff --git a/core/modules/options/lib/Drupal/options/Plugin/field/formatter/OptionsDefaultFormatter.php b/core/modules/options/lib/Drupal/options/Plugin/field/formatter/OptionsDefaultFormatter.php
index 3da3b64..6f3bfcb 100644
--- a/core/modules/options/lib/Drupal/options/Plugin/field/formatter/OptionsDefaultFormatter.php
+++ b/core/modules/options/lib/Drupal/options/Plugin/field/formatter/OptionsDefaultFormatter.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Annotation\Translation;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'list_default' formatter.
@@ -32,18 +33,18 @@ class OptionsDefaultFormatter extends FormatterBase {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
 
     $allowed_values = options_allowed_values($this->fieldDefinition, $entity);
 
     foreach ($items as $delta => $item) {
-      if (isset($allowed_values[$item['value']])) {
-        $output = field_filter_xss($allowed_values[$item['value']]);
+      if (isset($allowed_values[$item->value])) {
+        $output = field_filter_xss($allowed_values[$item->value]);
       }
       else {
         // If no match was found in allowed values, fall back to the key.
-        $output = field_filter_xss($item['value']);
+        $output = field_filter_xss($item->value);
       }
       $elements[$delta] = array('#markup' => $output);
     }
diff --git a/core/modules/options/lib/Drupal/options/Plugin/field/formatter/OptionsKeyFormatter.php b/core/modules/options/lib/Drupal/options/Plugin/field/formatter/OptionsKeyFormatter.php
index de62b57..2e06b48 100644
--- a/core/modules/options/lib/Drupal/options/Plugin/field/formatter/OptionsKeyFormatter.php
+++ b/core/modules/options/lib/Drupal/options/Plugin/field/formatter/OptionsKeyFormatter.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Annotation\Translation;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'list_key' formatter.
@@ -32,11 +33,11 @@ class OptionsKeyFormatter extends FormatterBase {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
 
     foreach ($items as $delta => $item) {
-      $elements[$delta] = array('#markup' => field_filter_xss($item['value']));
+      $elements[$delta] = array('#markup' => field_filter_xss($item->value));
     }
 
     return $elements;
diff --git a/core/modules/options/lib/Drupal/options/Plugin/field/widget/ButtonsWidget.php b/core/modules/options/lib/Drupal/options/Plugin/field/widget/ButtonsWidget.php
index 163f46c..02f719b 100644
--- a/core/modules/options/lib/Drupal/options/Plugin/field/widget/ButtonsWidget.php
+++ b/core/modules/options/lib/Drupal/options/Plugin/field/widget/ButtonsWidget.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'options_buttons' widget.
@@ -31,7 +32,7 @@ class ButtonsWidget extends OptionsWidgetBase {
   /**
    * {@inheritdoc}
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $element = parent::formElement($items, $delta, $element, $langcode, $form, $form_state);
 
     $options = $this->getOptions();
diff --git a/core/modules/options/lib/Drupal/options/Plugin/field/widget/OnOffWidget.php b/core/modules/options/lib/Drupal/options/Plugin/field/widget/OnOffWidget.php
index 25f9865..3948a22 100644
--- a/core/modules/options/lib/Drupal/options/Plugin/field/widget/OnOffWidget.php
+++ b/core/modules/options/lib/Drupal/options/Plugin/field/widget/OnOffWidget.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'options_onoff' widget.
@@ -56,7 +57,7 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $element = parent::formElement($items, $delta, $element, $langcode, $form, $form_state);
 
     $options = $this->getOptions();
diff --git a/core/modules/options/lib/Drupal/options/Plugin/field/widget/OptionsWidgetBase.php b/core/modules/options/lib/Drupal/options/Plugin/field/widget/OptionsWidgetBase.php
index f6801c0..6dc91e9 100644
--- a/core/modules/options/lib/Drupal/options/Plugin/field/widget/OptionsWidgetBase.php
+++ b/core/modules/options/lib/Drupal/options/Plugin/field/widget/OptionsWidgetBase.php
@@ -8,6 +8,7 @@
 namespace Drupal\options\Plugin\field\widget;
 
 use Drupal\Core\Entity\Field\FieldDefinitionInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\Type\Widget\WidgetBase;
 
 /**
@@ -45,14 +46,14 @@ public function __construct($plugin_id, array $plugin_definition, FieldDefinitio
   /**
    * {@inheritdoc}
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     // Prepare some properties for the child methods to build the actual form
     // element.
     $this->entity = $element['#entity'];
     $this->required = $element['#required'];
     $cardinality = $this->fieldDefinition->getFieldCardinality();
     $this->multiple = ($cardinality == FIELD_CARDINALITY_UNLIMITED) || ($cardinality > 1);
-    $this->has_value = isset($items[0][$this->column]);
+    $this->has_value = isset($items[0]->{$this->column});
 
     // Add our custom validator.
     $element['#element_validate'][] = array(get_class($this), 'validateElement');
@@ -155,19 +156,19 @@ protected function getOptions() {
   /**
    * Determines selected options from the incoming field values.
    *
-   * @param array $items
+   * @param FieldInterface $items
    *   The field values.
    *
    * @return array
    *   The array of corresponding selected options.
    */
-  protected function getSelectedOptions(array $items) {
+  protected function getSelectedOptions(FieldInterface $items) {
     // We need to check against a flat list of options.
     $flat_options = $this->flattenOptions($this->getOptions());
 
     $selected_options = array();
     foreach ($items as $item) {
-      $value = $item[$this->column];
+      $value = $item->{$this->column};
       // Keep the value if it actually is in the list of options (needs to be
       // checked against the flat list).
       if (isset($flat_options[$value])) {
diff --git a/core/modules/options/lib/Drupal/options/Plugin/field/widget/SelectWidget.php b/core/modules/options/lib/Drupal/options/Plugin/field/widget/SelectWidget.php
index b17a448..6b2eeac 100644
--- a/core/modules/options/lib/Drupal/options/Plugin/field/widget/SelectWidget.php
+++ b/core/modules/options/lib/Drupal/options/Plugin/field/widget/SelectWidget.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'options_select' widget.
@@ -30,7 +31,7 @@ class SelectWidget extends OptionsWidgetBase {
   /**
    * {@inheritdoc}
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $element = parent::formElement($items, $delta, $element, $langcode, $form, $form_state);
 
     $element += array(
diff --git a/core/modules/picture/lib/Drupal/picture/Plugin/field/formatter/PictureFormatter.php b/core/modules/picture/lib/Drupal/picture/Plugin/field/formatter/PictureFormatter.php
index 0bf24cf..be7484b 100644
--- a/core/modules/picture/lib/Drupal/picture/Plugin/field/formatter/PictureFormatter.php
+++ b/core/modules/picture/lib/Drupal/picture/Plugin/field/formatter/PictureFormatter.php
@@ -10,6 +10,7 @@
 use Drupal\field\Annotation\FieldFormatter;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\image\Plugin\field\formatter\ImageFormatterBase;
 
 /**
@@ -115,7 +116,7 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
     // Check if the formatter involves a link.
     if ($this->getSetting('image_link') == 'content') {
@@ -167,7 +168,7 @@ public function viewElements(EntityInterface $entity, $langcode, array $items) {
     foreach ($items as $delta => $item) {
       if (isset($link_file)) {
         $uri = array(
-          'path' => file_create_url($item['entity']->getFileUri()),
+          'path' => file_create_url($item->entity->getFileUri()),
           'options' => array(),
         );
       }
@@ -176,7 +177,7 @@ public function viewElements(EntityInterface $entity, $langcode, array $items) {
         '#attached' => array('library' => array(
           array('picture', 'picturefill'),
         )),
-        '#item' => $item,
+        '#item' => $item->getValue(TRUE),
         '#image_style' => $fallback_image_style,
         '#breakpoints' => $breakpoint_styles,
         '#path' => isset($uri) ? $uri : '',
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/formatter/EntityReferenceTaxonomyTermRssFormatter.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/formatter/EntityReferenceTaxonomyTermRssFormatter.php
index eeb7437..a7f6530 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/formatter/EntityReferenceTaxonomyTermRssFormatter.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/formatter/EntityReferenceTaxonomyTermRssFormatter.php
@@ -10,6 +10,7 @@
 use Drupal\field\Annotation\FieldFormatter;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\entity_reference\Plugin\field\formatter\EntityReferenceFormatterBase;
 
 /**
@@ -32,15 +33,15 @@ class EntityReferenceTaxonomyTermRssFormatter extends EntityReferenceFormatterBa
   /**
    * Overrides Drupal\entity_reference\Plugin\field\formatter\EntityReferenceFormatterBase::viewElements().
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
 
     foreach ($items as $delta => $item) {
       $entity->rss_elements[] = array(
         'key' => 'category',
-        'value' => $item['entity']->label(),
+        'value' => $item->entity->label(),
         'attributes' => array(
-          'domain' => $item['target_id'] ? url('taxonomy/term/' . $item['target_id'], array('absolute' => TRUE)) : '',
+          'domain' => $item->target_id ? url('taxonomy/term/' . $item->target_id, array('absolute' => TRUE)) : '',
         ),
       );
     }
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/formatter/LinkFormatter.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/formatter/LinkFormatter.php
index b44002e..85ee340 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/formatter/LinkFormatter.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/formatter/LinkFormatter.php
@@ -10,6 +10,7 @@
 use Drupal\field\Annotation\FieldFormatter;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 use Drupal\taxonomy\Plugin\field\formatter\TaxonomyFormatterBase;
 
@@ -30,19 +31,19 @@ class LinkFormatter extends TaxonomyFormatterBase {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
 
     // Terms without target_id do not exist yet, theme such terms as just their
     // name.
     foreach ($items as $delta => $item) {
-      if (!$item['target_id']) {
+      if (!$item->target_id) {
         $elements[$delta] = array(
-          '#markup' => check_plain($item['entity']->label()),
+          '#markup' => check_plain($item->entity->label()),
         );
       }
       else {
-        $term = $item['entity'];
+        $term = $item->entity;
         $uri = $term->uri();
         $elements[$delta] = array(
           '#type' => 'link',
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/formatter/PlainFormatter.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/formatter/PlainFormatter.php
index 0294cb4..61cfb5b 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/formatter/PlainFormatter.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/formatter/PlainFormatter.php
@@ -10,6 +10,7 @@
 use Drupal\field\Annotation\FieldFormatter;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 use Drupal\taxonomy\Plugin\field\formatter\TaxonomyFormatterBase;
 
@@ -30,12 +31,12 @@ class PlainFormatter extends TaxonomyFormatterBase {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
 
     foreach ($items as $delta => $item) {
       $elements[$delta] = array(
-        '#markup' => check_plain($item['entity']->label()),
+        '#markup' => check_plain($item->entity->label()),
       );
     }
 
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/formatter/RSSCategoryFormatter.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/formatter/RSSCategoryFormatter.php
index 2a2af05..0a2ff80 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/formatter/RSSCategoryFormatter.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/formatter/RSSCategoryFormatter.php
@@ -10,6 +10,7 @@
 use Drupal\field\Annotation\FieldFormatter;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 use Drupal\taxonomy\Plugin\field\formatter\TaxonomyFormatterBase;
 
@@ -30,19 +31,19 @@ class RSSCategoryFormatter extends TaxonomyFormatterBase {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     // Terms whose target_id is 'autocreate' do not exist yet and
-    // $item['entity'] is not set. Theme such terms as just their name.
+    // $item->entity is not set. Theme such terms as just their name.
     foreach ($items as $item) {
-      if ($item['target_id']) {
-        $value = $item['entity']->label();
+      if ($item->target_id) {
+        $value = $item->entity->label();
 
-        $uri = $item['entity']->uri();
+        $uri = $item->entity->uri();
         $uri['options']['absolute'] = TRUE;
         $domain = url($uri['path'], $uri['options']);
       }
       else {
-        $value = $item['entity']->label();
+        $value = $item->entity->label();
         $domain = '';
       }
       $entity->rss_elements[] = array(
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/formatter/TaxonomyFormatterBase.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/formatter/TaxonomyFormatterBase.php
index 90f76ad..7403440 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/formatter/TaxonomyFormatterBase.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/formatter/TaxonomyFormatterBase.php
@@ -10,6 +10,7 @@
 use Drupal\field\Annotation\FieldFormatter;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 
 /**
@@ -23,15 +24,15 @@
    * This preloads all taxonomy terms for multiple loaded objects at once and
    * unsets values for invalid terms that do not exist.
    */
-  public function prepareView(array $entities, $langcode, array &$items) {
+  public function prepareView(array $entities, $langcode, array $items) {
     $tids = array();
 
     // Collect every possible term attached to any of the fieldable entities.
     foreach ($entities as $id => $entity) {
       foreach ($items[$id] as $delta => $item) {
         // Force the array key to prevent duplicates.
-        if ($item['target_id'] !== 0) {
-          $tids[$item['target_id']] = $item['target_id'];
+        if ($item->target_id !== 0) {
+          $tids[$item->target_id] = $item->target_id;
         }
       }
     }
@@ -46,12 +47,12 @@ public function prepareView(array $entities, $langcode, array &$items) {
         foreach ($items[$id] as $delta => $item) {
           // Check whether the taxonomy term field instance value could be
           // loaded.
-          if (isset($terms[$item['target_id']])) {
+          if (isset($terms[$item->target_id])) {
             // Replace the instance value with the term data.
-            $items[$id][$delta]['entity'] = $terms[$item['target_id']];
+            $items[$id][$delta]->entity = $terms[$item->target_id];
           }
           // Terms to be created are not in $terms, but are still legitimate.
-          elseif ($item['target_id'] === 0 && isset($item['entity'])) {
+          elseif ($item->target_id === 0 && isset($item->entity)) {
             // Leave the item in place.
           }
           // Otherwise, unset the instance value, since the term does not exist.
@@ -63,7 +64,7 @@ public function prepareView(array $entities, $langcode, array &$items) {
 
         if ($rekey) {
           // Rekey the items array.
-          $items[$id] = array_values($items[$id]);
+          $items[$id]->setValue(array_values($items[$id]->getValue()));
         }
       }
     }
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php
index 10c9aef..bf47233 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\Type\Widget\WidgetBase;
 
 /**
@@ -65,10 +66,10 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $tags = array();
     foreach ($items as $item) {
-      $tags[$item['target_id']] = isset($item['taxonomy_term']) ? $item['taxonomy_term'] : taxonomy_term_load($item['target_id']);
+      $tags[$item->target_id] = isset($item->taxonomy_term) ? $item->taxonomy_term : taxonomy_term_load($item->target_id);
     }
     $element += array(
       '#type' => 'textfield',
diff --git a/core/modules/telephone/lib/Drupal/telephone/Plugin/field/formatter/TelephoneLinkFormatter.php b/core/modules/telephone/lib/Drupal/telephone/Plugin/field/formatter/TelephoneLinkFormatter.php
index 208d6bd..a33409e 100644
--- a/core/modules/telephone/lib/Drupal/telephone/Plugin/field/formatter/TelephoneLinkFormatter.php
+++ b/core/modules/telephone/lib/Drupal/telephone/Plugin/field/formatter/TelephoneLinkFormatter.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Annotation\Translation;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'telephone_link' formatter.
@@ -62,18 +63,18 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  public function prepareView(array $entities, $langcode, array &$items) {
+  public function prepareView(array $entities, $langcode, array $items) {
     $settings = $this->getSettings();
 
     foreach ($entities as $id => $entity) {
-      foreach ($items[$id] as &$item) {
+      foreach ($items[$id] as $item) {
         // If available, set custom link text.
         if (!empty($settings['title'])) {
-          $item['title'] = $settings['title'];
+          $item->title = $settings['title'];
         }
         // Otherwise, use telephone number itself as title.
         else {
-          $item['title'] = $item['value'];
+          $item->title = $item->value;
         }
       }
     }
@@ -82,17 +83,17 @@ public function prepareView(array $entities, $langcode, array &$items) {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $element = array();
 
     foreach ($items as $delta => $item) {
       // Prepend 'tel:' to the telephone number.
-      $href = 'tel:' . rawurlencode(preg_replace('/\s+/', '', $item['value']));
+      $href = 'tel:' . rawurlencode(preg_replace('/\s+/', '', $item->value));
 
       // Render each element as link.
       $element[$delta] = array(
         '#type' => 'link',
-        '#title' => $item['title'],
+        '#title' => $item->title,
         '#href' => $href,
         '#options' => array('external' => TRUE),
       );
diff --git a/core/modules/telephone/lib/Drupal/telephone/Plugin/field/widget/TelephoneDefaultWidget.php b/core/modules/telephone/lib/Drupal/telephone/Plugin/field/widget/TelephoneDefaultWidget.php
index 444dc3a..ba81339 100644
--- a/core/modules/telephone/lib/Drupal/telephone/Plugin/field/widget/TelephoneDefaultWidget.php
+++ b/core/modules/telephone/lib/Drupal/telephone/Plugin/field/widget/TelephoneDefaultWidget.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\Type\Widget\WidgetBase;
 
 /**
@@ -62,10 +63,10 @@ public function settingsSummary() {
   /**
    * Implements \Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement().
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $element['value'] = $element + array(
       '#type' => 'tel',
-      '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL,
+      '#default_value' => isset($items[$delta]->value) ? $items[$delta]->value : NULL,
       '#placeholder' => $this->getSetting('placeholder'),
     );
     return $element;
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/formatter/TextDefaultFormatter.php b/core/modules/text/lib/Drupal/text/Plugin/field/formatter/TextDefaultFormatter.php
index 52b2388..429b468 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/formatter/TextDefaultFormatter.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/formatter/TextDefaultFormatter.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Annotation\Translation;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'text_default' formatter.
@@ -32,13 +33,16 @@
 class TextDefaultFormatter extends FormatterBase {
 
   /**
-   * Implements Drupal\field\Plugin\Type\Formatter\FormatterInterface::viewElements().
+   * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
 
     foreach ($items as $delta => $item) {
-      $output = text_sanitize($this->getFieldSetting('text_processing'), $langcode, $item, 'value');
+      // @todo Convert text_sanitize() to work on an NG $item (this requires
+      //   http://drupal.org/node/1969728.)
+      $itemBC = $item->getValue(TRUE);
+      $output = text_sanitize($this->getFieldSetting('text_processing'), $langcode, $itemBC, 'value');
       $elements[$delta] = array('#markup' => $output);
     }
 
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/formatter/TextPlainFormatter.php b/core/modules/text/lib/Drupal/text/Plugin/field/formatter/TextPlainFormatter.php
index 813bb92..d6c947d 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/formatter/TextPlainFormatter.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/formatter/TextPlainFormatter.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Annotation\Translation;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'text_plain' formatter.
@@ -34,13 +35,13 @@ class TextPlainFormatter extends FormatterBase {
   /**
    * Implements Drupal\field\Plugin\Type\Formatter\FormatterInterface::viewElements().
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
 
     foreach ($items as $delta => $item) {
       // The text value has no text format assigned to it, so the user input
       // should equal the output, including newlines.
-      $elements[$delta] = array('#markup' => nl2br(check_plain($item['value'])));
+      $elements[$delta] = array('#markup' => nl2br(check_plain($item->value)));
     }
 
     return $elements;
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/formatter/TextTrimmedFormatter.php b/core/modules/text/lib/Drupal/text/Plugin/field/formatter/TextTrimmedFormatter.php
index 88ef0c5..8cd7045 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/formatter/TextTrimmedFormatter.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/formatter/TextTrimmedFormatter.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Annotation\Translation;
 use Drupal\field\Plugin\Type\Formatter\FormatterBase;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'text_trimmed'' formatter.
@@ -65,17 +66,17 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(EntityInterface $entity, $langcode, array $items) {
+  public function viewElements(EntityInterface $entity, $langcode, FieldInterface $items) {
     $elements = array();
 
     $text_processing = $this->getFieldSetting('text_processing');
     foreach ($items as $delta => $item) {
-      if ($this->getPluginId() == 'text_summary_or_trimmed' && !empty($item['summary'])) {
-        $output = text_sanitize($text_processing, $langcode, $item, 'summary');
+      if ($this->getPluginId() == 'text_summary_or_trimmed' && !empty($item->summary)) {
+        $output = text_sanitize($text_processing, $langcode, $item->getValue(TRUE), 'summary');
       }
       else {
-        $output = text_sanitize($text_processing, $langcode, $item, 'value');
-        $output = text_summary($output, $text_processing ? $item['format'] : NULL, $this->getSetting('trim_length'));
+        $output = text_sanitize($text_processing, $langcode, $item->getValue(TRUE), 'value');
+        $output = text_summary($output, $text_processing ? $item->format : NULL, $this->getSetting('trim_length'));
       }
       $elements[$delta] = array('#markup' => $output);
     }
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php
index 72eff19..602e5f6 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\Type\Widget\WidgetBase;
 
 /**
@@ -67,10 +68,10 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $main_widget = $element + array(
       '#type' => 'textarea',
-      '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL,
+      '#default_value' => $items[$delta]->value,
       '#rows' => $this->getSetting('rows'),
       '#placeholder' => $this->getSetting('placeholder'),
       '#attributes' => array('class' => array('text-full')),
@@ -79,7 +80,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
     if ($this->getFieldSetting('text_processing')) {
       $element = $main_widget;
       $element['#type'] = 'text_format';
-      $element['#format'] = isset($items[$delta]['format']) ? $items[$delta]['format'] : NULL;
+      $element['#format'] = $items[$delta]->format;
       $element['#base_type'] = $main_widget['#type'];
     }
     else {
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWithSummaryWidget.php b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWithSummaryWidget.php
index 300af18..d815d78 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWithSummaryWidget.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWithSummaryWidget.php
@@ -10,6 +10,7 @@
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
 use Symfony\Component\Validator\ConstraintViolationInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
 
 /**
  * Plugin implementation of the 'text_textarea_with_summary' widget.
@@ -59,13 +60,13 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+  function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $element = parent::formElement($items, $delta, $element, $langcode, $form, $form_state);
 
-    $display_summary = !empty($items[$delta]['summary']) || $this->getFieldSetting('display_summary');
+    $display_summary = $items[$delta]->summary || $this->getFieldSetting('display_summary');
     $element['summary'] = array(
       '#type' => $display_summary ? 'textarea' : 'value',
-      '#default_value' => isset($items[$delta]['summary']) ? $items[$delta]['summary'] : NULL,
+      '#default_value' => $items[$delta]->summary,
       '#title' => t('Summary'),
       '#rows' => $this->getSetting('summary_rows'),
       '#description' => t('Leave blank to use trimmed value of full text as the summary.'),
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextfieldWidget.php b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextfieldWidget.php
index 5319aab..66e84fe 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextfieldWidget.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextfieldWidget.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\field\Plugin\Type\Widget\WidgetBase;
 
 /**
@@ -67,10 +68,10 @@ public function settingsSummary() {
   /**
    * {@inheritdoc}
    */
-  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+  public function formElement(FieldInterface $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $main_widget = $element + array(
       '#type' => 'textfield',
-      '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL,
+      '#default_value' => isset($items[$delta]->value) ? $items[$delta]->value : NULL,
       '#size' => $this->getSetting('size'),
       '#placeholder' => $this->getSetting('placeholder'),
       '#maxlength' => $this->getFieldSetting('max_length'),
@@ -80,7 +81,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
     if ($this->getFieldSetting('text_processing')) {
       $element = $main_widget;
       $element['#type'] = 'text_format';
-      $element['#format'] = isset($items[$delta]['format']) ? $items[$delta]['format'] : NULL;
+      $element['#format'] = isset($items[$delta]->format) ? $items[$delta]->format : NULL;
       $element['#base_type'] = $main_widget['#type'];
     }
     else {
