diff --git a/core/lib/Drupal/Core/Entity/Field/FieldDefinition.php b/core/lib/Drupal/Core/Entity/Field/FieldDefinition.php
new file mode 100644
index 0000000..5ff9247
--- /dev/null
+++ b/core/lib/Drupal/Core/Entity/Field/FieldDefinition.php
@@ -0,0 +1,107 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Entity\Field\FieldDefinition.
+ */
+
+namespace Drupal\Core\Entity\Field;
+
+/**
+ * @todo Document.
+ */
+class FieldDefinition implements FieldDefinitionInterface {
+
+  /**
+   * @todo Document.
+   *
+   * @var \Drupal\Core\Entity\Field\FieldInterface
+   */
+  protected $field;
+
+  /**
+   * @todo Document.
+   *
+   * @var array
+   */
+  protected $definition;
+
+  /**
+   * @todo Document.
+   */
+  public function __construct(FieldInterface $field) {
+    $this->field = $field;
+    $this->definition = $field->getDefinition() + \Drupal::typedData()->getDefinition($field->getType());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldName() {
+    return $this->field->getName();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldType() {
+     return $this->definition['field_type'];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldSettings() {
+    return $this->definition['settings'];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldSetting($setting_name) {
+    return $this->definition['settings'][$setting_name];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldPropertyNames() {
+    return array_keys($this->field->getPropertyDefinitions());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isFieldTranslatable() {
+    return !empty($this->definition['translatable']);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldLabel() {
+    return $this->definition['label'];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldDescription() {
+    return $this->definition['description'];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldCardinality() {
+    return isset($this->definition['cardinality']) ? $this->definition['cardinality'] : 1;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isFieldRequired() {
+    return !empty($this->definition['required']);
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Entity/Field/FieldInterface.php b/core/lib/Drupal/Core/Entity/Field/FieldInterface.php
index c2dfbdb..4db0c48 100644
--- a/core/lib/Drupal/Core/Entity/Field/FieldInterface.php
+++ b/core/lib/Drupal/Core/Entity/Field/FieldInterface.php
@@ -28,6 +28,13 @@
 interface FieldInterface extends ListInterface, AccessibleInterface {

   /**
+   * Gets the field definition.
+   *
+   * @return \Drupal\Core\Entity\Field\FieldDefinitionInterface
+   */
+  public function getFieldDefinition();
+
+  /**
    * Filters out empty field items and re-numbers the item deltas.
    */
   public function filterEmptyValues();
diff --git a/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php b/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php
index 46a66b9..20b25cc 100644
--- a/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php
+++ b/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php
@@ -37,6 +37,13 @@ public function __construct(array $definition, $name = NULL, TypedDataInterface
   }

   /**
+   * {@inheritdoc}
+   */
+  public function getFieldDefinition() {
+    return $this->getParent()->getFieldDefinition();
+  }
+
+  /**
    * Overrides \Drupal\Core\TypedData\TypedData::setValue().
    *
    * @param array|null $values
diff --git a/core/lib/Drupal/Core/Entity/Field/FieldItemInterface.php b/core/lib/Drupal/Core/Entity/Field/FieldItemInterface.php
index 059a477..5d380a2 100644
--- a/core/lib/Drupal/Core/Entity/Field/FieldItemInterface.php
+++ b/core/lib/Drupal/Core/Entity/Field/FieldItemInterface.php
@@ -24,6 +24,13 @@
 interface FieldItemInterface extends ComplexDataInterface {

   /**
+   * Gets the field definition.
+   *
+   * @return \Drupal\Core\Entity\Field\FieldDefinitionInterface
+   */
+  public function getFieldDefinition();
+
+  /**
    * Magic method: Gets a property value.
    *
    * @param $property_name
diff --git a/core/lib/Drupal/Core/Entity/Field/Type/Field.php b/core/lib/Drupal/Core/Entity/Field/Type/Field.php
index 4d53c18..4b8186d 100644
--- a/core/lib/Drupal/Core/Entity/Field/Type/Field.php
+++ b/core/lib/Drupal/Core/Entity/Field/Type/Field.php
@@ -7,6 +7,7 @@

 namespace Drupal\Core\Entity\Field\Type;

+use Drupal\Core\Entity\Field\FieldDefinition;
 use Drupal\Core\Entity\Field\FieldInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\TypedData\TypedDataInterface;
@@ -37,6 +38,13 @@ class Field extends ItemList implements FieldInterface {
   protected $list = array();

   /**
+   * The field definition.
+   *
+   * @var \Drupal\Core\Entity\Field\FieldDefinitionInterface
+   */
+  protected $fieldDefinition;
+
+  /**
    * Overrides TypedData::__construct().
    */
   public function __construct(array $definition, $name = NULL, TypedDataInterface $parent = NULL) {
@@ -51,6 +59,16 @@ public function __construct(array $definition, $name = NULL, TypedDataInterface
   /**
    * {@inheritdoc}
    */
+  public function getFieldDefinition() {
+    if (!isset($this->fieldDefinition)) {
+      $this->fieldDefinition = new FieldDefinition($this);
+    }
+    return $this->fieldDefinition;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function filterEmptyValues() {
     if (isset($this->list)) {
       $this->list = array_values(array_filter($this->list, function($item) {
diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/FieldDataTypeDerivative.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/FieldDataTypeDerivative.php
index 504e427..81fc77f 100644
--- a/core/lib/Drupal/Core/Entity/Plugin/DataType/FieldDataTypeDerivative.php
+++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/FieldDataTypeDerivative.php
@@ -43,6 +43,16 @@ public function getDerivativeDefinitions(array $base_plugin_definition) {
       $definition['list class'] = $definition['list_class'];
       unset($definition['list_class']);

+      // Provide easy access to the field type without requiring consuming code
+      // to parse it from the full data type.
+      $definition['field_type'] = $plugin_id;
+
+      // The distinction between 'settings' and 'instance_settings' is only
+      // meaningful at the field type plugin level. At the Typed data API level,
+      // merge them.
+      $definition['settings'] = $definition['instance_settings'] + $definition['settings'];
+      unset($definition['instance_settings']);
+
       $this->derivatives[$plugin_id] = $definition;
     }
     return $this->derivatives;
diff --git a/core/modules/edit/js/editors/directEditor.js b/core/modules/edit/js/editors/directEditor.js
index aafbca3..993f2e2 100644
--- a/core/modules/edit/js/editors/directEditor.js
+++ b/core/modules/edit/js/editors/directEditor.js
@@ -21,7 +21,13 @@ Drupal.edit.editors.direct = Drupal.edit.EditorView.extend({
     var fieldModel = this.fieldModel;

     // Store the original value of this field. Necessary for reverting changes.
-    var $textElement = this.$textElement = this.$el.find('.field-item:first');
+    var $textElement;
+    if (this.$el.is(':has(.field-item)')) {
+      $textElement = this.$textElement = this.$el.find('.field-item:first');
+    }
+    else {
+     $textElement = this.$textElement = this.$el;
+    }
     editorModel.set('originalValue', $.trim(this.$textElement.text()));

     // Sets the state to 'changed' whenever the value changes
diff --git a/core/modules/edit/lib/Drupal/edit/Access/EditEntityFieldAccessCheck.php b/core/modules/edit/lib/Drupal/edit/Access/EditEntityFieldAccessCheck.php
index e139d0e..b09da96 100644
--- a/core/modules/edit/lib/Drupal/edit/Access/EditEntityFieldAccessCheck.php
+++ b/core/modules/edit/lib/Drupal/edit/Access/EditEntityFieldAccessCheck.php
@@ -41,7 +41,7 @@ public function access(Route $route, Request $request) {
    * Implements EntityFieldAccessCheckInterface::accessEditEntityField().
    */
   public function accessEditEntityField(EntityInterface $entity, $field_name) {
-    return $entity->access('update') && ($field = field_info_field($field_name)) && field_access('edit', $field, $entity->entityType(), $entity);
+    return $entity->access('update'); // && ($field = field_info_field($field_name)) && field_access('edit', $field, $entity->entityType(), $entity);
   }

   /**
@@ -64,13 +64,16 @@ protected function validateAndUpcastRequestAttributes(Request $request) {

     // Validate the field name and language.
     $field_name = $request->attributes->get('field_name');
-    if (!$field_name || !field_info_instance($entity->entityType(), $field_name, $entity->bundle())) {
+    if (!$field_name) {
       throw new NotFoundHttpException();
     }
     $langcode = $request->attributes->get('langcode');
     if (!$langcode || (field_valid_language($langcode) !== $langcode)) {
       throw new NotFoundHttpException();
     }
+    if (!($field_definition = $entity->getTranslation($langcode)->get($field_name)->getFieldDefinition())) {
+      throw new NotFoundHttpException();
+    }
   }

 }
diff --git a/core/modules/edit/lib/Drupal/edit/EditController.php b/core/modules/edit/lib/Drupal/edit/EditController.php
index 9ac62b4..bfdd800 100644
--- a/core/modules/edit/lib/Drupal/edit/EditController.php
+++ b/core/modules/edit/lib/Drupal/edit/EditController.php
@@ -54,14 +54,17 @@ public function metadata(Request $request) {
       }

       // Validate the field name and language.
-      if (!$field_name || !($instance = field_info_instance($entity->entityType(), $field_name, $entity->bundle()))) {
+      if (!$field_name) {
         throw new NotFoundHttpException();
       }
       if (!$langcode || (field_valid_language($langcode) !== $langcode)) {
         throw new NotFoundHttpException();
       }
+      if (!($field_definition = $entity->getTranslation($langcode)->get($field_name)->getFieldDefinition())) {
+        throw new NotFoundHttpException();
+      }

-      $metadata[$field] = $metadataGenerator->generate($entity, $instance, $langcode, $view_mode);
+      $metadata[$field] = $metadataGenerator->generate($entity, $field_definition, $langcode, $view_mode);
     }

     return new JsonResponse($metadata);
diff --git a/core/modules/edit/lib/Drupal/edit/EditPluginInterface.php b/core/modules/edit/lib/Drupal/edit/EditPluginInterface.php
index a568278..1dcc642 100644
--- a/core/modules/edit/lib/Drupal/edit/EditPluginInterface.php
+++ b/core/modules/edit/lib/Drupal/edit/EditPluginInterface.php
@@ -8,7 +8,7 @@
 namespace Drupal\edit;

 use Drupal\Component\Plugin\PluginInspectionInterface;
-use Drupal\field\Plugin\Core\Entity\FieldInstance;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;

 /**
  * Defines an interface for in-place editors (Create.js PropertyEditor widgets).
@@ -21,15 +21,15 @@
   /**
    * Checks whether this editor is compatible with a given field instance.
    *
-   * @param \Drupal\field\Plugin\Core\Entity\FieldInstance $instance
-   *   The field instance of the field being edited.
+   * @param \Drupal\Core\Entity\Field\FieldDefinitionInterface $field_definition
+   *   The field definition of the field being edited.
    * @param array $items
    *   The field's item values.
    *
    * @return bool
    *   TRUE if it is compatible, FALSE otherwise.
    */
-  public function isCompatible(FieldInstance $instance, array $items);
+  public function isCompatible(FieldDefinitionInterface $field_definition, array $items);

   /**
    * Generates metadata that is needed specifically for this editor.
@@ -37,8 +37,8 @@ public function isCompatible(FieldInstance $instance, array $items);
    * Will only be called by \Drupal\edit\MetadataGeneratorInterface::generate()
    * when the passed in field instance & item values will use this editor.
    *
-   * @param \Drupal\field\Plugin\Core\Entity\FieldInstance $instance
-   *   The field instance of the field being edited.
+   * @param \Drupal\Core\Entity\Field\FieldDefinitionInterface $field_definition
+   *   The field definition of the field being edited.
    * @param array $items
    *   The field's item values.
    *
@@ -46,7 +46,7 @@ public function isCompatible(FieldInstance $instance, array $items);
    *   A keyed array with metadata. Each key should be prefixed with the plugin
    *   ID of the editor.
    */
-  public function getMetadata(FieldInstance $instance, array $items);
+  public function getMetadata(FieldDefinitionInterface $field_definition, array $items);

   /**
    * Returns the attachments for this editor.
diff --git a/core/modules/edit/lib/Drupal/edit/EditorBase.php b/core/modules/edit/lib/Drupal/edit/EditorBase.php
index 39abaee..10b2f02 100644
--- a/core/modules/edit/lib/Drupal/edit/EditorBase.php
+++ b/core/modules/edit/lib/Drupal/edit/EditorBase.php
@@ -9,7 +9,7 @@

 use Drupal\Component\Plugin\PluginBase;
 use Drupal\edit\EditPluginInterface;
-use Drupal\field\Plugin\Core\Entity\FieldInstance;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;

 /**
  * Defines a base editor implementation.
@@ -17,9 +17,9 @@
 abstract class EditorBase extends PluginBase implements EditPluginInterface {

   /**
-   * Implements \Drupal\edit\EditPluginInterface::getMetadata().
+   * {@inheritdoc}
    */
-  function getMetadata(FieldInstance $instance, array $items) {
+  function getMetadata(FieldDefinitionInterface $field_definition, array $items) {
     return array();
   }

diff --git a/core/modules/edit/lib/Drupal/edit/EditorSelector.php b/core/modules/edit/lib/Drupal/edit/EditorSelector.php
index 232a52f..2636f38 100644
--- a/core/modules/edit/lib/Drupal/edit/EditorSelector.php
+++ b/core/modules/edit/lib/Drupal/edit/EditorSelector.php
@@ -9,7 +9,7 @@

 use Drupal\Component\Plugin\PluginManagerInterface;
 use Drupal\Component\Utility\NestedArray;
-use Drupal\field\Plugin\Core\Entity\FieldInstance;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;

 /**
  * Selects an in-place editor (an Editor plugin) for a field.
@@ -43,7 +43,7 @@ public function __construct(PluginManagerInterface $editor_manager) {
   /**
    * {@inheritdoc}
    */
-  public function getEditor($formatter_type, FieldInstance $instance, array $items) {
+  public function getEditor($formatter_type, FieldDefinitionInterface $field_definition, array $items) {
     // Build a static cache of the editors that have registered themselves as
     // alternatives to a certain editor.
     if (!isset($this->alternatives)) {
@@ -80,7 +80,7 @@ public function getEditor($formatter_type, FieldInstance $instance, array $items
     // Make a choice.
     foreach ($editor_choices as $editor_id) {
       $editor = $this->editorManager->createInstance($editor_id);
-      if ($editor->isCompatible($instance, $items)) {
+      if ($editor->isCompatible($field_definition, $items)) {
         return $editor_id;
       }
     }
diff --git a/core/modules/edit/lib/Drupal/edit/EditorSelectorInterface.php b/core/modules/edit/lib/Drupal/edit/EditorSelectorInterface.php
index 990c207..d36083a 100644
--- a/core/modules/edit/lib/Drupal/edit/EditorSelectorInterface.php
+++ b/core/modules/edit/lib/Drupal/edit/EditorSelectorInterface.php
@@ -7,7 +7,7 @@

 namespace Drupal\edit;

-use Drupal\field\Plugin\Core\Entity\FieldInstance;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;

 /**
  * Interface for selecting an in-place editor (an Editor plugin) for a field.
@@ -19,15 +19,15 @@
    *
    * @param string $formatter_type
    *   The field's formatter type name.
-   * @param \Drupal\field\Plugin\Core\Entity\FieldInstance $instance
-   *   The field's instance info.
+   * @param \Drupal\Core\Entity\Field\FieldDefinitionInterface $field_definition
+   *   The field definition.
    * @param array $items
    *   The field's item values.
    *
    * @return string|NULL
    *   The editor to use, or NULL to not enable in-place editing.
    */
-  public function getEditor($formatter_type, FieldInstance $instance, array $items);
+  public function getEditor($formatter_type, FieldDefinitionInterface $instance, array $items);

   /**
    * Returns the attachments for all editors.
diff --git a/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php b/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php
index 8930ace..f1fa703 100644
--- a/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php
+++ b/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php
@@ -9,9 +9,9 @@

 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Component\Plugin\PluginManagerInterface;
-use Drupal\field\Plugin\Core\Entity\FieldInstance;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;
 use Drupal\edit\Access\EditEntityFieldAccessCheckInterface;
-
+use Drupal\field\FieldInstanceInterface;

 /**
  * Generates in-place editing metadata for an entity field.
@@ -56,10 +56,10 @@ public function __construct(EditEntityFieldAccessCheckInterface $access_checker,
   }

   /**
-   * Implements \Drupal\edit\MetadataGeneratorInterface::generate().
+   * {@inheritdoc}
    */
-  public function generate(EntityInterface $entity, FieldInstance $instance, $langcode, $view_mode) {
-    $field_name = $instance['field_name'];
+  public function generate(EntityInterface $entity, FieldDefinitionInterface $field_definition, $langcode, $view_mode) {
+    $field_name = $field_definition->getFieldName();

     // Early-return if user does not have access.
     $access = $this->accessChecker->accessEditEntityField($entity, $field_name);
@@ -68,15 +68,21 @@ public function generate(EntityInterface $entity, FieldInstance $instance, $lang
     }

     // Early-return if no editor is available.
-    $formatter_id = entity_get_render_display($entity, $view_mode)->getRenderer($instance['field_name'])->getPluginId();
+    if ($field_definition instanceof FieldInstanceInterface) {
+      $formatter_id = entity_get_render_display($entity, $view_mode)->getRenderer($field_name)->getPluginId();
+    }
+    else {
+      $field_type_info = field_info_field_types($field_definition->getFieldType());
+      $formatter_id = $field_type_info['default_formatter'];
+    }
     $items = $entity->getTranslation($langcode, FALSE)->get($field_name)->getValue();
-    $editor_id = $this->editorSelector->getEditor($formatter_id, $instance, $items);
+    $editor_id = $this->editorSelector->getEditor($formatter_id, $field_definition, $items);
     if (!isset($editor_id)) {
       return array('access' => FALSE);
     }

     // Gather metadata, allow the editor to add additional metadata of its own.
-    $label = $instance['label'];
+    $label = $field_definition->getFieldLabel();
     $editor = $this->editorManager->createInstance($editor_id);
     $metadata = array(
       'label' => check_plain($label),
@@ -84,7 +90,7 @@ public function generate(EntityInterface $entity, FieldInstance $instance, $lang
       'editor' => $editor_id,
       'aria' => t('Entity @type @id, field @field', array('@type' => $entity->entityType(), '@id' => $entity->id(), '@field' => $label)),
     );
-    $custom_metadata = $editor->getMetadata($instance, $items);
+    $custom_metadata = $editor->getMetadata($field_definition, $items);
     if (count($custom_metadata)) {
       $metadata['custom'] = $custom_metadata;
     }
diff --git a/core/modules/edit/lib/Drupal/edit/MetadataGeneratorInterface.php b/core/modules/edit/lib/Drupal/edit/MetadataGeneratorInterface.php
index 16db770..89f1feb 100644
--- a/core/modules/edit/lib/Drupal/edit/MetadataGeneratorInterface.php
+++ b/core/modules/edit/lib/Drupal/edit/MetadataGeneratorInterface.php
@@ -8,7 +8,7 @@
 namespace Drupal\edit;

 use Drupal\Core\Entity\EntityInterface;
-use Drupal\field\Plugin\Core\Entity\FieldInstance;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;

 /**
  * Interface for generating in-place editing metadata for an entity field.
@@ -20,8 +20,8 @@
    *
    * @param \Drupal\Core\Entity\EntityInterface $entity
    *   The entity being edited.
-   * @param \Drupal\field\Plugin\Core\Entity\FieldInstance $instance
-   *   The field instance of the field being edited.
+   * @param \Drupal\Core\Entity\Field\FieldDefinitionInterface $field_definition
+   *   The field definition of the field being edited.
    * @param string $langcode
    *   The name of the language for which the field is being edited.
    * @param string $view_mode
@@ -34,6 +34,6 @@
    *   - aria: the ARIA label.
    *   - custom: (optional) any additional metadata that the editor provides.
    */
-  public function generate(EntityInterface $entity, FieldInstance $instance, $langcode, $view_mode);
+  public function generate(EntityInterface $entity, FieldDefinitionInterface $field_definition, $langcode, $view_mode);

 }
diff --git a/core/modules/edit/lib/Drupal/edit/Plugin/InPlaceEditor/DirectEditor.php b/core/modules/edit/lib/Drupal/edit/Plugin/InPlaceEditor/DirectEditor.php
index 39176d1..6a8f16b 100644
--- a/core/modules/edit/lib/Drupal/edit/Plugin/InPlaceEditor/DirectEditor.php
+++ b/core/modules/edit/lib/Drupal/edit/Plugin/InPlaceEditor/DirectEditor.php
@@ -9,7 +9,7 @@

 use Drupal\edit\EditorBase;
 use Drupal\edit\Annotation\InPlaceEditor;
-use Drupal\field\Plugin\Core\Entity\FieldInstance;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;

 /**
  * Defines the direct editor.
@@ -21,20 +21,18 @@
 class DirectEditor extends EditorBase {

   /**
-   * Implements \Drupal\edit\EditPluginInterface::isCompatible().
+   * {@inheritdoc}
    *
    * @todo The processed text logic is too coupled to text fields. Figure out
    *   how to generalize to other textual field types.
    */
-  function isCompatible(FieldInstance $instance, array $items) {
-    $field = field_info_field($instance['field_name']);
-
+  function isCompatible(FieldDefinitionInterface $field_definition, array $items) {
     // This editor is incompatible with multivalued fields.
-    if ($field['cardinality'] != 1) {
+    if ($field_definition->getFieldCardinality() != 1) {
       return FALSE;
     }
     // This editor is incompatible with processed ("rich") text fields.
-    elseif (!empty($instance['settings']['text_processing'])) {
+    elseif ($field_definition->getFieldSetting('text_processing')) {
       return FALSE;
     }
     else {
diff --git a/core/modules/edit/lib/Drupal/edit/Plugin/InPlaceEditor/FormEditor.php b/core/modules/edit/lib/Drupal/edit/Plugin/InPlaceEditor/FormEditor.php
index ec8d406..4c71db2 100644
--- a/core/modules/edit/lib/Drupal/edit/Plugin/InPlaceEditor/FormEditor.php
+++ b/core/modules/edit/lib/Drupal/edit/Plugin/InPlaceEditor/FormEditor.php
@@ -9,7 +9,7 @@

 use Drupal\edit\EditorBase;
 use Drupal\edit\Annotation\InPlaceEditor;
-use Drupal\field\Plugin\Core\Entity\FieldInstance;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;

 /**
  * Defines the form editor.
@@ -21,9 +21,9 @@
 class FormEditor extends EditorBase {

   /**
-   * Implements \Drupal\edit\EditPluginInterface::isCompatible().
+   * {@inheritdoc}
    */
-  function isCompatible(FieldInstance $instance, array $items) {
+  function isCompatible(FieldDefinitionInterface $field_definition, array $items) {
     return TRUE;
   }

diff --git a/core/modules/edit/tests/modules/lib/Drupal/edit_test/Plugin/InPlaceEditor/WysiwygEditor.php b/core/modules/edit/tests/modules/lib/Drupal/edit_test/Plugin/InPlaceEditor/WysiwygEditor.php
index 59fe895..61be894 100644
--- a/core/modules/edit/tests/modules/lib/Drupal/edit_test/Plugin/InPlaceEditor/WysiwygEditor.php
+++ b/core/modules/edit/tests/modules/lib/Drupal/edit_test/Plugin/InPlaceEditor/WysiwygEditor.php
@@ -9,7 +9,7 @@

 use Drupal\edit\EditorBase;
 use Drupal\edit\Annotation\InPlaceEditor;
-use Drupal\field\Plugin\Core\Entity\FieldInstance;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;

 /**
  * Defines the wysiwyg editor.
@@ -22,19 +22,17 @@
 class WysiwygEditor extends EditorBase {

   /**
-   * Implements \Drupal\edit\EditPluginInterface::isCompatible().
+   * {@inheritdoc}
    */
-  function isCompatible(FieldInstance $instance, array $items) {
-    $field = field_info_field($instance['field_name']);
-
+  function isCompatible(FieldDefinitionInterface $field_definition, array $items) {
     // This editor is incompatible with multivalued fields.
-    if ($field['cardinality'] != 1) {
+    if ($field_definition->getFieldCardinality() != 1) {
       return FALSE;
     }
     // This editor is compatible with processed ("rich") text fields; but only
     // if there is a currently active text format and that text format is the
     // 'full_html' text format.
-    elseif (!empty($instance['settings']['text_processing'])) {
+    elseif ($field_definition->getFieldSetting('text_processing')) {
       $format_id = $items[0]['format'];
       if (isset($format_id) && $format_id === 'full_html') {
         return TRUE;
@@ -44,9 +42,9 @@ function isCompatible(FieldInstance $instance, array $items) {
   }

   /**
-   * Implements \Drupal\edit\EditPluginInterface::getMetadata().
+   * {@inheritdoc}
    */
-  function getMetadata(FieldInstance $instance, array $items) {
+  function getMetadata(FieldDefinitionInterface $field_definition, array $items) {
     $format_id = $items[0]['format'];
     $metadata['format'] = $format_id;
     return $metadata;
diff --git a/core/modules/editor/lib/Drupal/editor/Plugin/InPlaceEditor/Editor.php b/core/modules/editor/lib/Drupal/editor/Plugin/InPlaceEditor/Editor.php
index 7c281c0..1a4981a 100644
--- a/core/modules/editor/lib/Drupal/editor/Plugin/InPlaceEditor/Editor.php
+++ b/core/modules/editor/lib/Drupal/editor/Plugin/InPlaceEditor/Editor.php
@@ -11,7 +11,7 @@
 use Drupal\edit\Annotation\InPlaceEditor;
 use Drupal\Core\Annotation\Translation;
 use Drupal\edit\EditPluginInterface;
-use Drupal\field\Plugin\Core\Entity\FieldInstance;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;

 /**
  * Defines the formatted text editor.
@@ -24,19 +24,17 @@
 class Editor extends PluginBase implements EditPluginInterface {

   /**
-   * Implements \Drupal\edit\Plugin\EditPluginInterface::isCompatible().
+   * {@inheritdoc}
    */
-  function isCompatible(FieldInstance $instance, array $items) {
-    $field = field_info_field($instance['field_name']);
-
+  function isCompatible(FieldDefinitionInterface $field_definition, array $items) {
     // This editor is incompatible with multivalued fields.
-    if ($field['cardinality'] != 1) {
+    if ($field_definition->getFieldCardinality() != 1) {
       return FALSE;
     }
     // This editor is compatible with processed ("rich") text fields; but only
     // if there is a currently active text format, that text format has an
     // associated editor and that editor supports inline editing.
-    elseif (!empty($instance['settings']['text_processing'])) {
+    elseif ($field_definition->getFieldSetting('text_processing')) {
       $format_id = $items[0]['format'];
       if (isset($format_id) && $editor = editor_load($format_id)) {
         $definition = \Drupal::service('plugin.manager.editor')->getDefinition($editor->editor);
@@ -50,9 +48,9 @@ function isCompatible(FieldInstance $instance, array $items) {
   }

   /**
-   * Implements \Drupal\edit\Plugin\EditPluginInterface::getMetadata().
+   * {@inheritdoc}
    */
-  function getMetadata(FieldInstance $instance, array $items) {
+  function getMetadata(FieldDefinitionInterface $field_definition, array $items) {
     $format_id = $items[0]['format'];
     $metadata['format'] = $format_id;
     $metadata['formatHasTransformations'] = $this->textFormatHasTransformationFilters($format_id);
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 19bf6ed..0fa26dc 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -173,6 +173,9 @@ function field_theme() {
     'field' => array(
       'render element' => 'element',
     ),
+    'field__title' => array(
+      'base hook' => 'field',
+    ),
     'field_multiple_value_form' => array(
       'render element' => 'element',
     ),
@@ -1099,6 +1102,13 @@ function theme_field($variables) {
 }

 /**
+ * @todo Document.
+ */
+function theme_field__title($variables) {
+  return '<span' . $variables['attributes'] . '>' . drupal_render($variables['items']) . '</span>';
+}
+
+/**
  * Assembles a partial entity structure with initial IDs.
  *
  * @param stdClass $ids
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigField.php b/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigField.php
index 3134160..1e356b3 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigField.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigField.php
@@ -24,6 +24,13 @@ class ConfigField extends Field implements ConfigFieldInterface {
   protected $instance;

   /**
+   * @todo Document.
+   *
+   * @var array
+   */
+  protected $instances;
+
+  /**
    * {@inheritdoc}
    */
   public function __construct(array $definition, $name = NULL, TypedDataInterface $parent = NULL) {
@@ -37,9 +44,14 @@ public function __construct(array $definition, $name = NULL, TypedDataInterface
    * {@inheritdoc}
    */
   public function getInstance() {
-    if (!isset($this->instance) && $parent = $this->getParent()) {
-      $instances = FieldAPI::fieldInfo()->getBundleInstances($parent->entityType(), $parent->bundle());
-      $this->instance = $instances[$this->getName()];
+    if (!isset($this->instance)) {
+      if (!isset($this->instances) && $parent = $this->getParent()) {
+        $this->instances = FieldAPI::fieldInfo()->getBundleInstances($parent->entityType(), $parent->bundle());
+      }
+      $field_name = $this->getName();
+      if (isset($this->instances[$field_name])) {
+        $this->instance = $this->instances[$field_name];
+      }
     }
     return $this->instance;
   }
@@ -47,18 +59,25 @@ public function getInstance() {
   /**
    * {@inheritdoc}
    */
+  public function getFieldDefinition() {
+    return $this->getInstance() ?: parent::getFieldDefinition();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function getConstraints() {
     $constraints = array();
     // Check that the number of values doesn't exceed the field cardinality. For
     // form submitted values, this can only happen with 'multiple value'
     // widgets.
-    $cardinality = $this->getInstance()->getField()->cardinality;
+    $cardinality = $this->getFieldDefinition()->getFieldCardinality();
     if ($cardinality != FIELD_CARDINALITY_UNLIMITED) {
       $constraints[] = \Drupal::typedData()
         ->getValidationConstraintManager()
         ->create('Count', array(
           'max' => $cardinality,
-          'maxMessage' => t('%name: this field cannot hold more than @count values.', array('%name' => $this->getInstance()->label, '@count' => $cardinality)),
+          'maxMessage' => t('%name: this field cannot hold more than @count values.', array('%name' => $this->getFieldDefinition()->getFieldLabel(), '@count' => $cardinality)),
         ));
     }

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..b6e70f7 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
@@ -134,7 +134,7 @@ protected function checkFieldAccess($op, $entity) {
       return field_access($op, $field, $entity->entityType(), $entity);
     }
     else {
-      return FALSE;
+      return TRUE;
     }
   }

diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php
index 39deee9..3235a6d 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php
@@ -12,7 +12,7 @@
 use Drupal\Core\Plugin\Discovery\CacheDecorator;
 use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
 use Drupal\Core\Plugin\Discovery\AlterDecorator;
-use Drupal\field\Plugin\Core\Entity\FieldInstance;
+use Drupal\Core\Entity\Field\FieldInterface;

 /**
  * Plugin type manager for field formatters.
@@ -175,4 +175,31 @@ public function getDefaultSettings($type) {
     return isset($info['settings']) ? $info['settings'] : array();
   }

+  /**
+   * @todo Document.
+   */
+  public function viewBaseField(FieldInterface $field) {
+    $options = array(
+      'field_definition' => $field->getFieldDefinition(),
+      'view_mode' => 'default',
+      'configuration' => array(
+        'label' => 'hidden',
+      ),
+    );
+    $formatter = $this->getInstance($options);
+
+    $entity = $field->getParent()->getBCEntity();
+    $entity_id = $entity->id();
+    $langcode = $entity->language()->langcode;
+    $items = $field->getValue();
+
+    $items_multi = array($entity_id => $items);
+    $formatter->prepareView(array($entity_id => $entity), $langcode, $items_multi);
+    $items = $items_multi[$entity_id];
+
+    $result = $formatter->view($entity, $langcode, $items);
+    $field_name = $field->getName();
+    return isset($result[$field_name]) ? $result[$field_name] : array();
+  }
+
 }
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..e0c2432 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
@@ -449,7 +449,7 @@ protected function checkFieldAccess($op, $entity) {
       return field_access($op, $field, $entity->entityType(), $entity);
     }
     else {
-      return FALSE;
+      return TRUE;
     }
   }

diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php
index b8213ca..dfca5eb 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Plugin\Discovery\CacheDecorator;
 use Drupal\Core\Plugin\Discovery\AlterDecorator;
 use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
+use Drupal\Core\Entity\Field\FieldInterface;

 /**
  * Plugin type manager for field widgets.
@@ -176,4 +177,48 @@ public function getDefaultSettings($type) {
     return isset($info['settings']) ? $info['settings'] : array();
   }

+  /**
+   * @todo Document.
+   */
+  public function baseFieldForm(FieldInterface $field, array &$form, array &$form_state, $langcode) {
+    $options = array(
+      'field_definition' => $field->getFieldDefinition(),
+      'form_mode' => 'default',
+      'configuration' => array(),
+    );
+    if (($field_data_definition = $field->getDefinition()) && isset($field_data_definition['default_widget'])) {
+      $options['configuration']['type'] = $field_data_definition['default_widget'];
+    }
+    $widget = $this->getInstance($options);
+
+    $entity = $field->getParent()->getBCEntity();
+    $items = $field->getValue();
+
+    $form += array('#parents' => array());
+    $result = $widget->form($entity, $langcode, $items, $form, $form_state);
+    $field_name = $field->getName();
+    return isset($result[$field_name]) ? $result[$field_name] : array();
+  }
+
+  /**
+   * @todo Document.
+   */
+  public function baseFieldExtractFormValues(FieldInterface $field, array &$form, array &$form_state, $langcode) {
+    $options = array(
+      'field_definition' => $field->getFieldDefinition(),
+      'form_mode' => 'default',
+      'configuration' => array(),
+    );
+    if (($field_data_definition = $field->getDefinition()) && isset($field_data_definition['default_widget'])) {
+      $options['configuration']['type'] = $field_data_definition['default_widget'];
+    }
+    $widget = $this->getInstance($options);
+
+    $entity = $field->getParent()->getBCEntity();
+    $items = $field->getValue();
+
+    $widget->extractFormValues($entity, $langcode, $items, $form, $form_state);
+    $field->setValue($items);
+  }
+
 }
diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php
index e55e056..3b8be33 100644
--- a/core/modules/node/lib/Drupal/node/NodeFormController.php
+++ b/core/modules/node/lib/Drupal/node/NodeFormController.php
@@ -101,14 +101,8 @@ public function form(array $form, array &$form_state) {

     $node_type = node_type_load($node->type);
     if ($node_type->has_title) {
-      $form['title'] = array(
-        '#type' => 'textfield',
-        '#title' => check_plain($node_type->title_label),
-        '#required' => TRUE,
-        '#default_value' => $node->title,
-        '#maxlength' => 255,
-        '#weight' => -5,
-      );
+      $form['title'] = \Drupal::service('plugin.manager.field.widget')->baseFieldForm($node->getNGEntity()->title, $form, $form_state, $this->getFormLangcode($form_state));
+      $form['title']['#weight'] = -5;
     }

     $language_configuration = module_invoke('language', 'get_default_configuration', 'node', $node->type);
@@ -322,6 +316,15 @@ protected function actions(array $form, array &$form_state) {
   }

   /**
+   * {@inheritdoc}
+   */
+  public function buildEntity(array $form, array &$form_state) {
+    $node = parent::buildEntity($form, $form_state);
+    \Drupal::service('plugin.manager.field.widget')->baseFieldExtractFormValues($node->getNGEntity()->title, $form, $form_state, $this->getFormLangcode($form_state));
+    return $node;
+  }
+
+  /**
    * Overrides Drupal\Core\Entity\EntityFormController::validate().
    */
   public function validate(array $form, array &$form_state) {
diff --git a/core/modules/node/lib/Drupal/node/NodeStorageController.php b/core/modules/node/lib/Drupal/node/NodeStorageController.php
index 524036b..91b4e35 100644
--- a/core/modules/node/lib/Drupal/node/NodeStorageController.php
+++ b/core/modules/node/lib/Drupal/node/NodeStorageController.php
@@ -154,7 +154,9 @@ public function baseFieldDefinitions() {
     $properties['title'] = array(
       'label' => t('Title'),
       'description' => t('The title of this node, always treated as non-markup plain text.'),
-      'type' => 'string_field',
+      'type' => 'field_item:text',
+      'required' => TRUE,
+      'default_widget' => 'node_title',
     );
     $properties['uid'] = array(
       'label' => t('User ID'),
diff --git a/core/modules/node/lib/Drupal/node/Plugin/field/widget/TitleWidget.php b/core/modules/node/lib/Drupal/node/Plugin/field/widget/TitleWidget.php
new file mode 100644
index 0000000..b5710f2
--- /dev/null
+++ b/core/modules/node/lib/Drupal/node/Plugin/field/widget/TitleWidget.php
@@ -0,0 +1,79 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\node\Plugin\field\widget\TitleWidget.
+ */
+
+namespace Drupal\node\Plugin\field\widget;
+
+use Drupal\Component\Annotation\Plugin;
+use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\field\Plugin\Type\Widget\WidgetBase;
+
+/**
+ * Plugin implementation of the 'node_title' widget.
+ *
+ * @Plugin(
+ *   id = "node_title",
+ *   module = "node",
+ *   label = @Translation("Node title field"),
+ *   field_types = {
+ *     "text"
+ *   }
+ * )
+ */
+class TitleWidget extends WidgetBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function form(EntityInterface $entity, $langcode, array $items, array &$form, array &$form_state, $get_delta = NULL) {
+    $field_name = $this->fieldDefinition->getFieldName();
+
+    // @todo Make EntityManager::getFieldDefinitions() allow for per-bundle
+    //   definitions of base fields, so that here, we could just call
+    //   $this->fieldDefinition->getFieldLabel() instead.
+    if ($entity->entityType() == 'node' && $field_name == 'title') {
+      $node_type = node_type_load($entity->bundle());
+      $label = $node_type->title_label;
+    }
+    else {
+      $label = $this->fieldDefinition->getFieldLabel();
+    }
+
+    $addition[$field_name] = array(
+      '#type' => 'textfield',
+      '#title' => check_plain($label),
+      '#required' => $this->fieldDefinition->isFieldRequired(),
+      '#default_value' => isset($items[0]['value']) ? $items[0]['value'] : '',
+      '#maxlength' => $this->fieldDefinition->getFieldSetting('max_length'),
+    );
+    return $addition;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function extractFormValues(EntityInterface $entity, $langcode, array &$items, array $form, array &$form_state) {
+    $field_name = $this->fieldDefinition->getFieldName();
+
+    // Extract the values from $form_state['values'].
+    $path = array_merge($form['#parents'], array($field_name));
+    $key_exists = NULL;
+    $value = NestedArray::getValue($form_state['values'], $path, $key_exists);
+
+    if ($key_exists) {
+      $items = array(array('value' => $value));
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+    return array();
+  }
+}
diff --git a/core/modules/node/lib/Drupal/node/Tests/Condition/NodeConditionTest.php b/core/modules/node/lib/Drupal/node/Tests/Condition/NodeConditionTest.php
index 31d515f..6ee7d48 100644
--- a/core/modules/node/lib/Drupal/node/Tests/Condition/NodeConditionTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/Condition/NodeConditionTest.php
@@ -14,7 +14,7 @@
  */
 class NodeConditionTest extends DrupalUnitTestBase {

-  public static $modules = array('system', 'node', 'field');
+  public static $modules = array('system', 'node', 'field', 'text');

   public static function getInfo() {
     return array(
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTitleTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTitleTest.php
index e03e4b0..0deff22 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeTitleTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeTitleTest.php
@@ -59,7 +59,7 @@ function testNodeTitle() {
     $this->assertEqual(current($this->xpath($xpath)), $node->label(), 'Node breadcrumb is equal to node title.', 'Node');

     // Test node title in comment preview.
-    $this->assertEqual(current($this->xpath('//article[@id=:id]/h2/a', array(':id' => 'node-' . $node->nid))), $node->label(), 'Node preview title is equal to node title.', 'Node');
+    $this->assertEqual(current($this->xpath('//article[@id=:id]/h2/a/span', array(':id' => 'node-' . $node->nid))), $node->label(), 'Node preview title is equal to node title.', 'Node');

     // Test node title is clickable on teaser list (/node).
     $this->drupalGet('node');
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 7057db2..9f3227f 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -747,7 +747,7 @@ function template_preprocess_node(&$variables) {

   $uri = $node->uri();
   $variables['node_url']  = url($uri['path'], $uri['options']);
-  $variables['label'] = check_plain($node->label());
+  $variables['label'] = Drupal::service('plugin.manager.field.formatter')->viewBaseField($node->getNGEntity()->title);
   $variables['page'] = $variables['view_mode'] == 'full' && node_is_page($node);

   // Helpful $content variable for templates.
diff --git a/core/modules/rdf/rdf.module b/core/modules/rdf/rdf.module
index 526ef66..bb29703 100644
--- a/core/modules/rdf/rdf.module
+++ b/core/modules/rdf/rdf.module
@@ -315,7 +315,7 @@ function rdf_preprocess_node(&$variables) {
     $element = array(
       '#tag' => 'meta',
       '#attributes' => array(
-        'content' => $variables['label'],
+        'content' => $variables['node']->label(),
         'about' => $variables['node_url'],
       ),
     );
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index 8e295b3..1ca7dbe 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -2048,7 +2048,7 @@ protected function assertNoLinkByHref($href, $message = '', $group = 'Other') {
    */
   protected function clickLink($label, $index = 0) {
     $url_before = $this->getUrl();
-    $urls = $this->xpath('//a[normalize-space(text())=:label]', array(':label' => $label));
+    $urls = $this->xpath('//a[normalize-space()=:label]', array(':label' => $label));

     if (isset($urls[$index])) {
       $url_target = $this->getAbsoluteUrl($urls[$index]['href']);
diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/ContextPluginTest.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/ContextPluginTest.php
index b04e2d8..cb8ec55 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Plugin/ContextPluginTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/ContextPluginTest.php
@@ -17,7 +17,7 @@
  */
 class ContextPluginTest extends DrupalUnitTestBase {

-  public static $modules = array('system', 'user', 'node');
+  public static $modules = array('system', 'user', 'node', 'text');

   public static function getInfo() {
     return array(
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItem.php b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItem.php
index 26326fc..1c79cf7 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItem.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItem.php
@@ -63,6 +63,27 @@ public static function schema(Field $field) {
   /**
    * {@inheritdoc}
    */
+  public function getConstraints() {
+    $constraint_manager = \Drupal::typedData()->getValidationConstraintManager();
+    $constraints = parent::getConstraints();
+
+    if ($max_length = $this->getFieldDefinition()->getFieldSetting('max_length')) {
+      $constraints[] = $constraint_manager->create('ComplexData', array(
+        'value' => array(
+          'Length' => array(
+            'max' => $max_length,
+            'maxMessage' => t('%name: the text may not be longer than @max characters.', array('%name' => $this->getFieldDefinition()->getFieldLabel(), '@max' => $max_length)),
+          )
+        ),
+      ));
+    }
+
+    return $constraints;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function settingsForm(array $form, array &$form_state) {
     $element = array();
     $field = $this->getInstance()->getField();
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItemBase.php b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItemBase.php
index 17f2ba3..e16f961 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItemBase.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItemBase.php
@@ -70,38 +70,17 @@ public function isEmpty() {
   /**
    * {@inheritdoc}
    */
-  public function getConstraints() {
-    $constraint_manager = \Drupal::typedData()->getValidationConstraintManager();
-    $constraints = parent::getConstraints();
-
-    if (!empty($this->getInstance()->getField()->settings['max_length'])) {
-      $max_length = $this->getInstance()->getField()->settings['max_length'];
-      $constraints[] = $constraint_manager->create('ComplexData', array(
-        'value' => array(
-          'Length' => array(
-            'max' => $max_length,
-            'maxMessage' => t('%name: the text may not be longer than @max characters.', array('%name' => $this->getInstance()->label, '@max' => $max_length)),
-          )
-        ),
-      ));
-    }
-
-    return $constraints;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function prepareCache() {
     // Where possible, generate the sanitized version of each field early so
     // that it is cached in the field cache. This avoids the need to look up the
     // field in the filter cache separately.
-    if (!$this->getInstance()->settings['text_processing'] || filter_format_allowcache($this->get('format')->getValue())) {
+    $text_processing = $this->getFieldDefinition()->getFieldSetting('text_processing');
+    if (!$text_processing || filter_format_allowcache($this->get('format')->getValue())) {
       $itemBC = $this->getValue();
       $langcode = $this->getParent()->getParent()->language()->langcode;
-      $this->set('safe_value', text_sanitize($this->getInstance()->settings['text_processing'], $langcode, $itemBC, 'value'));
+      $this->set('safe_value', text_sanitize($text_processing, $langcode, $itemBC, 'value'));
       if ($this->getType() == 'field_item:text_with_summary') {
-        $this->set('safe_summary', text_sanitize($this->getInstance()->settings['text_processing'], $langcode, $itemBC, 'summary'));
+        $this->set('safe_summary', text_sanitize($text_processing, $langcode, $itemBC, 'summary'));
       }
     }
   }
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextWithSummaryItem.php b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextWithSummaryItem.php
index 4d9030d..7aecf67 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextWithSummaryItem.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextWithSummaryItem.php
@@ -106,28 +106,6 @@ public function isEmpty() {
   /**
    * {@inheritdoc}
    */
-  public function getConstraints() {
-    $constraint_manager = \Drupal::typedData()->getValidationConstraintManager();
-    $constraints = parent::getConstraints();
-
-    if (!empty($this->getInstance()->getField()->settings['max_length'])) {
-      $max_length = $this->getInstance()->getField()->settings['max_length'];
-      $constraints[] = $constraint_manager->create('ComplexData', array(
-        'summary' => array(
-          'Length' => array(
-            'max' => $max_length,
-            'maxMessage' => t('%name: the summary may not be longer than @max characters.', array('%name' => $this->getInstance()->label, '@max' => $max_length)),
-          )
-        ),
-      ));
-    }
-
-    return $constraints;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function instanceSettingsForm(array $form, array &$form_state) {
     $element = array();

