diff --git a/core/core.services.yml b/core/core.services.yml
index ede41a1d091d165f4b0aedb3f0684c6b7f523308..f98c9f269ef638976c9e3db71fdb94fc946029f3 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -287,7 +287,7 @@ services:
     arguments: ['@stream_wrapper_manager', '@settings', '@logger.channel.file']
   form_builder:
     class: Drupal\Core\Form\FormBuilder
-    arguments: ['@form_validator', '@form_submitter', '@form_cache', '@module_handler', '@event_dispatcher', '@request_stack', '@class_resolver', '@theme.manager', '@?csrf_token']
+    arguments: ['@form_validator', '@form_submitter', '@form_cache', '@module_handler', '@event_dispatcher', '@request_stack', '@class_resolver', '@element_info', '@theme.manager', '@?csrf_token']
   form_validator:
     class: Drupal\Core\Form\FormValidator
     arguments: ['@request_stack', '@string_translation', '@csrf_token', '@logger.channel.form']
@@ -856,7 +856,7 @@ services:
       - { name: event_subscriber }
   main_content_renderer.html:
     class: Drupal\Core\Render\MainContent\HtmlRenderer
-    arguments: ['@title_resolver', '@plugin.manager.display_variant', '@event_dispatcher', '@module_handler', '@renderer', '@cache_contexts']
+    arguments: ['@title_resolver', '@plugin.manager.display_variant', '@event_dispatcher', '@element_info', '@module_handler', '@renderer', '@cache_contexts']
     tags:
       - { name: render.main_content_renderer, format: html }
   main_content_renderer.ajax:
diff --git a/core/includes/common.inc b/core/includes/common.inc
index 54714db2b43dfebc1288461fbce2bee9dec2f1e3..654a0f35dd3f36469c7adb690375f4f69475c1fa 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -1306,8 +1306,8 @@ function drupal_render_cache_generate_placeholder($callback, array &$context) {
  * @param $type
  *   An element type as defined by hook_element_info().
  *
- * @deprecated As of Drupal 8.0, use \Drupal::service('element_info')->getInfo()
- *   instead.
+ * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0.
+ *   Use \Drupal::service('element_info')->getInfo() instead.
  */
 function element_info($type) {
   return \Drupal::service('element_info')->getInfo($type);
@@ -1323,9 +1323,12 @@ function element_info($type) {
  * @param $default
  *   (Optional) The value to return if the element type does not specify a
  *   value for the property. Defaults to NULL.
+ *
+ * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0.
+ *   Use \Drupal::service('element_info')->getInfoProperty() instead.
  */
 function element_info_property($type, $property_name, $default = NULL) {
-  return (($info = element_info($type)) && array_key_exists($property_name, $info)) ? $info[$property_name] : $default;
+  return \Drupal::service('element_info')->getInfoProperty($type, $property_name, $default);
 }
 
 /**
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index a061ebc2ac1b83771b12161fb30ce50d9f9ad69a..dfee854c8a96cb8586b3737dadc7720ec7ee1ce5 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1556,7 +1556,7 @@ function template_preprocess_field(&$variables, $hook) {
   // We want other preprocess functions and the theme implementation to have
   // fast access to the field item render arrays. The item render array keys
   // (deltas) should always be numerically indexed starting from 0, and looping
-  // on those keys is faster than calling element_children() or looping on all
+  // on those keys is faster than calling Element::children() or looping on all
   // keys within $element, since that requires traversal of all element
   // properties.
   $variables['items'] = array();
diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php
index 8d532ed8dda23e6f6ef03d3d3f922f95c4dec12e..4bc6272420d265cc0fbaf4fd57f848c21aef93a6 100644
--- a/core/lib/Drupal/Core/Form/FormBuilder.php
+++ b/core/lib/Drupal/Core/Form/FormBuilder.php
@@ -16,6 +16,7 @@
 use Drupal\Core\DependencyInjection\ClassResolverInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Render\Element;
+use Drupal\Core\Render\ElementInfoManagerInterface;
 use Drupal\Core\Theme\ThemeManagerInterface;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 use Symfony\Component\HttpFoundation\RequestStack;
@@ -49,6 +50,13 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormS
    */
   protected $requestStack;
 
+  /**
+   * The element info manager.
+   *
+   * @var \Drupal\Core\Render\ElementInfoManagerInterface
+   */
+  protected $elementInfo;
+
   /**
    * The CSRF token generator to validate the form token.
    *
@@ -111,12 +119,14 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormS
    *   The request stack.
    * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver
    *   The class resolver.
+   * @param \Drupal\Core\Render\ElementInfoManagerInterface $element_info
+   *   The element info manager.
    * @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager
    *   The theme manager.
    * @param \Drupal\Core\Access\CsrfTokenGenerator $csrf_token
    *   The CSRF token generator.
    */
-  public function __construct(FormValidatorInterface $form_validator, FormSubmitterInterface $form_submitter, FormCacheInterface $form_cache, ModuleHandlerInterface $module_handler, EventDispatcherInterface $event_dispatcher, RequestStack $request_stack, ClassResolverInterface $class_resolver, ThemeManagerInterface $theme_manager, CsrfTokenGenerator $csrf_token = NULL) {
+  public function __construct(FormValidatorInterface $form_validator, FormSubmitterInterface $form_submitter, FormCacheInterface $form_cache, ModuleHandlerInterface $module_handler, EventDispatcherInterface $event_dispatcher, RequestStack $request_stack, ClassResolverInterface $class_resolver, ElementInfoManagerInterface $element_info, ThemeManagerInterface $theme_manager, CsrfTokenGenerator $csrf_token = NULL) {
     $this->formValidator = $form_validator;
     $this->formSubmitter = $form_submitter;
     $this->formCache = $form_cache;
@@ -124,6 +134,7 @@ public function __construct(FormValidatorInterface $form_validator, FormSubmitte
     $this->eventDispatcher = $event_dispatcher;
     $this->requestStack = $request_stack;
     $this->classResolver = $class_resolver;
+    $this->elementInfo = $element_info;
     $this->csrfToken = $csrf_token;
     $this->themeManager = $theme_manager;
   }
@@ -606,7 +617,7 @@ public function prepareForm($form_id, &$form, FormStateInterface &$form_state) {
       $form['#id'] = Html::getUniqueId($form_id);
     }
 
-    $form += $this->getElementInfo('form');
+    $form += $this->elementInfo->getInfo('form');
     $form += array('#tree' => FALSE, '#parents' => array());
     $form['#validate'][] = '::validateForm';
     $form['#submit'][] = '::submitForm';
@@ -677,7 +688,7 @@ public function doBuildForm($form_id, &$element, FormStateInterface &$form_state
     $element['#processed'] = FALSE;
 
     // Use element defaults.
-    if (isset($element['#type']) && empty($element['#defaults_loaded']) && ($info = $this->getElementInfo($element['#type']))) {
+    if (isset($element['#type']) && empty($element['#defaults_loaded']) && ($info = $this->elementInfo->getInfo($element['#type']))) {
       // Overlay $info onto $element, retaining preexisting keys in $element.
       $element += $info;
       $element['#defaults_loaded'] = TRUE;
@@ -751,7 +762,7 @@ public function doBuildForm($form_id, &$element, FormStateInterface &$form_state
     foreach (Element::children($element) as $key) {
       // Prior to checking properties of child elements, their default
       // properties need to be loaded.
-      if (isset($element[$key]['#type']) && empty($element[$key]['#defaults_loaded']) && ($info = $this->getElementInfo($element[$key]['#type']))) {
+      if (isset($element[$key]['#type']) && empty($element[$key]['#defaults_loaded']) && ($info = $this->elementInfo->getInfo($element[$key]['#type']))) {
         $element[$key] += $info;
         $element[$key]['#defaults_loaded'] = TRUE;
       }
@@ -1078,15 +1089,6 @@ protected function buttonWasClicked($element, FormStateInterface &$form_state) {
     return FALSE;
   }
 
-  /**
-   * Wraps element_info().
-   *
-   * @return array
-   */
-  protected function getElementInfo($type) {
-    return element_info($type);
-  }
-
   /**
    * Gets the current active user.
    *
diff --git a/core/lib/Drupal/Core/Render/ElementInfoManager.php b/core/lib/Drupal/Core/Render/ElementInfoManager.php
index 0c593da06c8f477b339b60b890673ec2b1fb725b..1bc1600d71fafdcf1a3b526ca4e0e77a30f98b50 100644
--- a/core/lib/Drupal/Core/Render/ElementInfoManager.php
+++ b/core/lib/Drupal/Core/Render/ElementInfoManager.php
@@ -85,6 +85,15 @@ public function getInfo($type) {
     return $info;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getInfoProperty($type, $property_name, $default = NULL) {
+    $info = $this->getInfo($type);
+
+    return isset($info[$property_name]) ? $info[$property_name] : $default;
+  }
+
   /**
    * Builds up all element information.
    *
diff --git a/core/lib/Drupal/Core/Render/ElementInfoManagerInterface.php b/core/lib/Drupal/Core/Render/ElementInfoManagerInterface.php
index d32acd690f93598349647c6905e55c0d5cec9d2f..7a460c1419dacb82a96dce31cb27496fe0fb8590 100644
--- a/core/lib/Drupal/Core/Render/ElementInfoManagerInterface.php
+++ b/core/lib/Drupal/Core/Render/ElementInfoManagerInterface.php
@@ -23,8 +23,7 @@ interface ElementInfoManagerInterface {
    * http://drupal.org/node/169815.
    *
    * @param string $type
-   *   An element type as defined by hook_element_info() or the machine name
-   *   of an element type plugin.
+   *   The machine name of an element type plugin.
    *
    * @return array
    *   An associative array describing the element types being defined. The
@@ -52,4 +51,21 @@ interface ElementInfoManagerInterface {
    */
   public function getInfo($type);
 
+  /**
+   * Retrieves a single property for the defined element type.
+   *
+   * @param string $type
+   *   An element type as defined by hook_element_info().
+   * @param string $property_name
+   *   The property within the element type that should be returned.
+   * @param $default
+   *   (Optional) The value to return if the element type does not specify a
+   *   value for the property. Defaults to NULL.
+   *
+   * @return string
+   *   The property value of the defined element type. Or the provided
+   *   default value, which can be NULL.
+   */
+  public function getInfoProperty($type, $property_name, $default = NULL);
+
 }
diff --git a/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php b/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php
index d12b18b750fea7fb99bf6e7f71d4a78e84147f13..882193000e60463591c93da0f2a3f2f44a9300e0 100644
--- a/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php
+++ b/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php
@@ -14,6 +14,7 @@
 use Drupal\Core\Controller\TitleResolverInterface;
 use Drupal\Core\Display\PageVariantInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Render\ElementInfoManagerInterface;
 use Drupal\Core\Render\PageDisplayVariantSelectionEvent;
 use Drupal\Core\Render\Renderer;
 use Drupal\Core\Render\RendererInterface;
@@ -50,6 +51,13 @@ class HtmlRenderer implements MainContentRendererInterface {
    */
   protected $eventDispatcher;
 
+  /**
+  * The element info manager.
+  *
+  * @var \Drupal\Core\Render\ElementInfoManagerInterface
+  */
+  protected $elementInfoManager;
+
   /**
    * The module handler.
    *
@@ -80,6 +88,8 @@ class HtmlRenderer implements MainContentRendererInterface {
    *   The display variant manager.
    * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
    *   The event dispatcher.
+   * @param \Drupal\Core\Render\ElementInfoManagerInterface
+   *   The element info manager.
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
    *   The module handler.
    * @param \Drupal\Core\Render\RendererInterface $renderer
@@ -87,10 +97,11 @@ class HtmlRenderer implements MainContentRendererInterface {
    * @param \Drupal\Core\Cache\CacheContexts $cache_contexts
    *   The cache contexts service.
    */
-  public function __construct(TitleResolverInterface $title_resolver, PluginManagerInterface $display_variant_manager, EventDispatcherInterface $event_dispatcher, ModuleHandlerInterface $module_handler, RendererInterface $renderer, CacheContexts $cache_contexts) {
+  public function __construct(TitleResolverInterface $title_resolver, PluginManagerInterface $display_variant_manager, EventDispatcherInterface $event_dispatcher, ElementInfoManagerInterface $element_info_manager, ModuleHandlerInterface $module_handler, RendererInterface $renderer, CacheContexts $cache_contexts) {
     $this->titleResolver = $title_resolver;
     $this->displayVariantManager = $display_variant_manager;
     $this->eventDispatcher = $event_dispatcher;
+    $this->elementInfoManager = $element_info_manager;
     $this->moduleHandler = $module_handler;
     $this->renderer = $renderer;
     $this->cacheContexts = $cache_contexts;
@@ -117,7 +128,7 @@ public function renderResponse(array $main_content, Request $request, RouteMatch
       '#type' => 'html',
       'page' => $page,
     ];
-    $html += element_info('html');
+    $html += $this->elementInfoManager->getInfo('html');
 
     // The special page regions will appear directly in html.html.twig, not in
     // page.html.twig, hence add them here, just before rendering html.html.twig.
diff --git a/core/lib/Drupal/Core/Render/RendererInterface.php b/core/lib/Drupal/Core/Render/RendererInterface.php
index fe133b64348db0ee47101b5375ea8efa4f77fb0f..d2b799008f915d2194313044b07a31d7c623323c 100644
--- a/core/lib/Drupal/Core/Render/RendererInterface.php
+++ b/core/lib/Drupal/Core/Render/RendererInterface.php
@@ -147,8 +147,9 @@ public function renderPlain(&$elements);
    *     element have not already been merged in (#defaults_loaded = TRUE) then
    *     the defaults for this type of element, defined in hook_element_info(),
    *     are merged into the array. #defaults_loaded is set by functions that
-   *     process render arrays and call element_info() before passing the array
-   *     to Renderer::render(), such as form_builder() in the Form API.
+   *     process render arrays and call the element info service before passing
+   *     the array to Renderer::render(), such as form_builder() in the Form
+   *     API.
    *   - If this element has an array of #pre_render functions defined, they are
    *     called sequentially to modify the element before rendering. After all
    *     the #pre_render functions have been called, #printed is checked a
diff --git a/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php b/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php
index 6fe9d753cc88266c6a7c6685524d6ffa1b839e9a..da48f74122dc3b232871226bd765cf2ba7786111 100644
--- a/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php
+++ b/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php
@@ -9,13 +9,17 @@
 
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Field\WidgetBase;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Drupal\Core\Render\Element;
-use Drupal\file\Element\ManagedFile;
+use Drupal\Core\Render\ElementInfoManagerInterface;
 use Drupal\Core\Url;
+use Drupal\file\Element\ManagedFile;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Plugin implementation of the 'file_generic' widget.
@@ -28,7 +32,22 @@
  *   }
  * )
  */
-class FileWidget extends WidgetBase {
+class FileWidget extends WidgetBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, ElementInfoManagerInterface $element_info) {
+    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
+    $this->elementInfo = $element_info;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static($plugin_id, $plugin_definition,$configuration['field_definition'], $configuration['settings'], $configuration['third_party_settings'], $container->get('element_info'));
+  }
 
   /**
    * {@inheritdoc}
@@ -212,7 +231,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
 
     // Essentially we use the managed_file type, extended with some
     // enhancements.
-    $element_info = element_info('managed_file');
+    $element_info = $this->elementInfo->getInfo('managed_file');
     $element += array(
       '#type' => 'managed_file',
       '#upload_location' => $items[$delta]->getUploadLocation(),
diff --git a/core/modules/language/language.admin.inc b/core/modules/language/language.admin.inc
index 19e9f4fab8c48a44f1fa336e16c1a7b661c872aa..8c35c6bf848ba766642b9cbbf57accea50b83083 100644
--- a/core/modules/language/language.admin.inc
+++ b/core/modules/language/language.admin.inc
@@ -51,7 +51,7 @@ function template_preprocess_language_negotiation_configure_form(&$variables) {
 
     foreach ($form[$type]['title'] as $id => $element) {
       // Do not take form control structures.
-      if (is_array($element) && element_child($id)) {
+      if (is_array($element) && Element::child($id)) {
         $table[$id]['#attributes']['class'][] = 'draggable';
         $table[$id]['#weight'] = $element['#weight'];
 
diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php
index c4f5cee951df72aa4c646fd459bd4387c0db1137..1ae8e58e76d58f819688e20ced1d527eeb840e68 100644
--- a/core/modules/simpletest/src/WebTestBase.php
+++ b/core/modules/simpletest/src/WebTestBase.php
@@ -327,7 +327,7 @@ protected function drupalBuildEntityView(EntityInterface $entity, $view_mode = '
       // If the default values for this element have not been loaded yet, populate
       // them.
       if (isset($elements['#type']) && empty($elements['#defaults_loaded'])) {
-        $elements += element_info($elements['#type']);
+        $elements += \Drupal::service('element_info')->getInfo($elements['#type']);
       }
 
       // Make any final changes to the element before it is rendered. This means
diff --git a/core/modules/views_ui/admin.inc b/core/modules/views_ui/admin.inc
index 97af75e8ced4ffffa764f3b56c6bd7bc15a96d98..64b90779478e4af6179f32ecba555c69734f7fd4 100644
--- a/core/modules/views_ui/admin.inc
+++ b/core/modules/views_ui/admin.inc
@@ -62,6 +62,7 @@ function views_ui_add_ajax_trigger(&$wrapping_element, $trigger_key, $refresh_pa
   // Add a submit button for users who do not have JavaScript enabled. It
   // should be displayed next to the triggering element on the form.
   $button_key = $trigger_key . '_trigger_update';
+  $element_info = \Drupal::service('element_info');
   $wrapping_element[$button_key] = array(
     '#type' => 'submit',
     // Hide this button when JavaScript is enabled.
@@ -72,14 +73,14 @@ function views_ui_add_ajax_trigger(&$wrapping_element, $trigger_key, $refresh_pa
     // form API has added the #parents property to the triggering element for
     // us, we don't have any (easy) way to find out where its submitted values
     // will eventually appear in $form_state->getValues().
-    '#process' => array_merge(array('views_ui_add_limited_validation'), element_info_property('submit', '#process', array())),
+    '#process' => array_merge(array('views_ui_add_limited_validation'), $element_info->getInfoProperty('submit', '#process', array())),
     // Add an after-build function that inserts a wrapper around the region of
     // the form that needs to be refreshed by AJAX (so that the AJAX system can
     // detect and dynamically update it). This is done in #after_build because
     // it's a convenient place where we have automatic access to the complete
     // form array, but also to minimize the chance that the HTML we add will
     // get clobbered by code that runs after we have added it.
-    '#after_build' => array_merge(element_info_property('submit', '#after_build', array()), array('views_ui_add_ajax_wrapper')),
+    '#after_build' => array_merge($element_info->getInfoProperty('submit', '#after_build', array()), array('views_ui_add_ajax_wrapper')),
   );
   // Copy #weight and #access from the triggering element to the button, so
   // that the two elements will be displayed together.
diff --git a/core/modules/views_ui/src/ViewEditForm.php b/core/modules/views_ui/src/ViewEditForm.php
index d47c2b0c10331126b1fbaa50733c7b9dc2314e74..2fc7fc4f821251eb551d47ec2361092076ab9926 100644
--- a/core/modules/views_ui/src/ViewEditForm.php
+++ b/core/modules/views_ui/src/ViewEditForm.php
@@ -18,6 +18,7 @@
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Render\Element;
+use Drupal\Core\Render\ElementInfoManagerInterface;
 use Drupal\Core\Url;
 use Drupal\user\SharedTempStoreFactory;
 use Drupal\views\Views;
@@ -51,6 +52,13 @@ class ViewEditForm extends ViewFormBase {
    */
   protected $dateFormatter;
 
+  /**
+   * The element info manager.
+   *
+   * @var \Drupal\Core\Render\ElementInfoManagerInterface
+   */
+  protected $elementInfo;
+
   /**
    * Constructs a new ViewEditForm object.
    *
@@ -60,11 +68,14 @@ class ViewEditForm extends ViewFormBase {
    *   The request stack object.
    * @param \Drupal\Core\Datetime\DateFormatter $date_formatter
    *   The date Formatter service.
+   * @param \Drupal\Core\Render\ElementInfoManagerInterface $element_info
+   *   The element info manager.
    */
-  public function __construct(SharedTempStoreFactory $temp_store_factory, RequestStack $requestStack, DateFormatter $date_formatter) {
+  public function __construct(SharedTempStoreFactory $temp_store_factory, RequestStack $requestStack, DateFormatter $date_formatter, ElementInfoManagerInterface $element_info) {
     $this->tempStore = $temp_store_factory->get('views');
     $this->requestStack = $requestStack;
     $this->dateFormatter = $date_formatter;
+    $this->elementInfo = $element_info;
   }
 
   /**
@@ -74,7 +85,8 @@ public static function create(ContainerInterface $container) {
     return new static(
       $container->get('user.shared_tempstore'),
       $container->get('request_stack'),
-      $container->get('date.formatter')
+      $container->get('date.formatter'),
+      $container->get('element_info')
     );
   }
 
@@ -759,7 +771,7 @@ public function renderDisplayTop(ViewUI $view) {
         '#attributes' => array('class' => array('add-display')),
         // Allow JavaScript to remove the 'Add ' prefix from the button label when
         // placing the button in a "Add" dropdown menu.
-        '#process' => array_merge(array('views_ui_form_button_was_clicked'), element_info_property('submit', '#process', array())),
+        '#process' => array_merge(array('views_ui_form_button_was_clicked'), $this->elementInfo->getInfoProperty('submit', '#process', array())),
         '#values' => array($this->t('Add !display', array('!display' => $label)), $label),
       );
     }
diff --git a/core/modules/views_ui/src/ViewUI.php b/core/modules/views_ui/src/ViewUI.php
index 028281b870810e2b776198742c5a0d89ccd00f22..4c82de70844a32e48c0f23afeb5ae05fa5aec16d 100644
--- a/core/modules/views_ui/src/ViewUI.php
+++ b/core/modules/views_ui/src/ViewUI.php
@@ -349,7 +349,7 @@ public function getStandardButtons(&$form, FormStateInterface $form_state, $form
       // button labels.
       if (isset($names)) {
         $form['actions']['submit']['#values'] = $names;
-        $form['actions']['submit']['#process'] = array_merge(array('views_ui_form_button_was_clicked'), element_info_property($form['actions']['submit']['#type'], '#process', array()));
+        $form['actions']['submit']['#process'] = array_merge(array('views_ui_form_button_was_clicked'), \Drupal::service('element_info')->getInfoProperty($form['actions']['submit']['#type'], '#process', array()));
       }
       // If a validation handler exists for the form, assign it to this button.
       $form['actions']['submit']['#validate'][] = [$form_state->getFormObject(), 'validateForm'];
diff --git a/core/tests/Drupal/Tests/Core/Form/FormTestBase.php b/core/tests/Drupal/Tests/Core/Form/FormTestBase.php
index 3ad3d09cdd5d16e6a56bced6fb9e5c8002d07642..e11f60fe8e0e657d78b1c11a218f6bc0ccc8a466 100644
--- a/core/tests/Drupal/Tests/Core/Form/FormTestBase.php
+++ b/core/tests/Drupal/Tests/Core/Form/FormTestBase.php
@@ -62,6 +62,13 @@ abstract class FormTestBase extends UnitTestCase {
    */
   protected $formCache;
 
+  /**
+   * The cache backend to use.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $cache;
+
   /**
    * The current user.
    *
@@ -105,6 +112,14 @@ abstract class FormTestBase extends UnitTestCase {
   protected $classResolver;
 
   /**
+   * The element info manager.
+   *
+   * @var \Drupal\Core\Render\ElementInfoManagerInterface
+   */
+  protected $elementInfo;
+
+  /**
+   *
    * The event dispatcher.
    *
    * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject
@@ -137,8 +152,18 @@ protected function setUp() {
     $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
 
     $this->formCache = $this->getMock('Drupal\Core\Form\FormCacheInterface');
+    $this->cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
     $this->urlGenerator = $this->getMock('Drupal\Core\Routing\UrlGeneratorInterface');
+
     $this->classResolver = $this->getClassResolverStub();
+
+    $this->elementInfo = $this->getMockBuilder('\Drupal\Core\Render\ElementInfoManagerInterface')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $this->elementInfo->expects($this->any())
+      ->method('getInfo')
+      ->will($this->returnCallback(array($this, 'getInfo')));
+
     $this->csrfToken = $this->getMockBuilder('Drupal\Core\Access\CsrfTokenGenerator')
       ->disableOriginalConstructor()
       ->getMock();
@@ -162,7 +187,7 @@ protected function setUp() {
       ->getMock();
     $this->root = dirname(dirname(substr(__DIR__, 0, -strlen(__NAMESPACE__))));
 
-    $this->formBuilder = new TestFormBuilder($this->formValidator, $this->formSubmitter, $this->formCache, $this->moduleHandler, $this->eventDispatcher, $this->requestStack, $this->classResolver, $this->themeManager, $this->csrfToken, $this->kernel);
+    $this->formBuilder = new TestFormBuilder($this->formValidator, $this->formSubmitter, $this->formCache, $this->moduleHandler, $this->eventDispatcher, $this->requestStack, $this->classResolver, $this->elementInfo, $this->themeManager, $this->csrfToken, $this->kernel);
     $this->formBuilder->setCurrentUser($this->account);
   }
 
@@ -250,24 +275,17 @@ protected function assertFormElement(array $expected_form, array $actual_form, $
     $this->assertSame(array_intersect_key($expected_element, $actual_element), $expected_element);
   }
 
-}
-
-/**
- * Provides a test form builder class.
- */
-class TestFormBuilder extends FormBuilder {
-
-  /**
-   * @param \Drupal\Core\Session\AccountInterface $account
-   */
-  public function setCurrentUser(AccountInterface $account) {
-    $this->currentUser = $account;
-  }
-
   /**
-   * {@inheritdoc}
+   * A stub method returning properties for the defined element type.
+   *
+   * @param string $type
+   *   The machine name of an element type plugin.
+   *
+   * @return array
+   *   An array with dummy values to be used in tests. Defaults to an empty
+   *   array.
    */
-  protected function getElementInfo($type) {
+  public function getInfo($type) {
     $types['token'] = array(
       '#input' => TRUE,
     );
@@ -290,8 +308,66 @@ protected function getElementInfo($type) {
     }
     return $types[$type];
   }
+
 }
 
+/**
+ * Provides a test form builder class.
+ */
+class TestFormBuilder extends FormBuilder {
+  protected static $seenIds = array();
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function sendResponse(Response $response) {
+    parent::sendResponse($response);
+    // Throw an exception instead of exiting.
+    throw new \Exception('exit');
+  }
+
+  /**
+   * @param \Drupal\Core\Session\AccountInterface $account
+   */
+  public function setCurrentUser(AccountInterface $account) {
+    $this->currentUser = $account;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function drupalHtmlClass($class) {
+    return $class;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function drupalHtmlId($id) {
+    if (isset(static::$seenIds[$id])) {
+      $id = $id . '--' . ++static::$seenIds[$id];
+    }
+    else {
+      static::$seenIds[$id] = 1;
+    }
+    return $id;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function drupalStaticReset($name = NULL) {
+    static::$seenIds = array();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function requestUri() {
+    return '';
+  }
+
+}
 }
 
 namespace {
diff --git a/core/tests/Drupal/Tests/Core/Render/ElementInfoManagerTest.php b/core/tests/Drupal/Tests/Core/Render/ElementInfoManagerTest.php
index 75b59ca7b8c538573c21341a95a10c48736127df..b0ca1f7ae7e7a7e30d0171a76da6aefc146ac0a7 100644
--- a/core/tests/Drupal/Tests/Core/Render/ElementInfoManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Render/ElementInfoManagerTest.php
@@ -18,7 +18,7 @@
 class ElementInfoManagerTest extends UnitTestCase {
 
   /**
-   * The class under test.
+   * The mocked element_info.
    *
    * @var \Drupal\Core\Render\ElementInfoManagerInterface
    */
@@ -237,4 +237,35 @@ public function providerTestGetInfoElementPlugin() {
     return $data;
   }
 
+  /**
+   * @covers ::getInfoProperty
+   */
+  public function testGetInfoProperty() {
+    $this->themeManager
+      ->method('getActiveTheme')
+      ->willReturn(new ActiveTheme(['name' => 'test']));
+
+    $element_info = new TestElementInfoManager(new \ArrayObject(), $this->cache, $this->cacheTagsInvalidator, $this->moduleHandler, $this->themeManager);
+    $this->assertSame('baz', $element_info->getInfoProperty('foo', '#bar'));
+    $this->assertNull($element_info->getInfoProperty('foo', '#non_existing_property'));
+    $this->assertSame('qux', $element_info->getInfoProperty('foo', '#non_existing_property', 'qux'));
+  }
+}
+
+/**
+ * Provides a test custom element plugin.
+ */
+class TestElementInfoManager extends ElementInfoManager {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $elementInfo = array(
+    'test' => array(
+      'foo' => array(
+        '#bar' => 'baz',
+      ),
+    ),
+  );
+
 }