From 9d3a2280208ee3078adb931d80cbd08b06c7f495 Mon Sep 17 00:00:00 2001
From: webchick <webchick@24967.no-reply.drupal.org>
Date: Wed, 12 Mar 2014 08:46:33 -0700
Subject: [PATCH] =?UTF-8?q?Issue=20#2171071=20by=20jessebeach,=20dawehner,?=
 =?UTF-8?q?=20chakrapani,=20longwave,=20G=C3=A1bor=20Hojtsy,=20xjm,=20Wim?=
 =?UTF-8?q?=20Leers:=20Rename=20drupal=5Fadd=5Flibrary()=20to=20=5Fdrupal?=
 =?UTF-8?q?=5Fadd=5Flibrary()=20and=20remove=20its=20uses.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 core/core.libraries.yml                       |   2 +-
 core/includes/common.inc                      |  20 +-
 core/includes/form.inc                        |   2 +-
 core/includes/tablesort.inc                   |  10 +-
 core/includes/theme.inc                       |  71 +++--
 .../Drupal/Core/Ajax/OpenDialogCommand.php    |  17 +-
 .../Core/Entity/EntityListController.php      |   2 +-
 .../Core/Page/DefaultHtmlPageRenderer.php     |   2 +-
 .../Controller/AggregatorController.php       |   2 +-
 .../ban/lib/Drupal/ban/Form/BanAdmin.php      |   2 +-
 .../Drupal/book/Controller/BookController.php |   2 +-
 .../comment/Controller/AdminController.php    |   2 +-
 .../config/Controller/ConfigController.php    |   2 +-
 .../lib/Drupal/config/Form/ConfigSync.php     |   4 +-
 .../ConfigTranslationMapperList.php           |   2 +-
 .../content_translation.pages.inc             |   2 +-
 .../dblog/Controller/DbLogController.php      |   6 +-
 core/modules/field_ui/field_ui.module         |   2 +-
 core/modules/file/file.field.inc              |   2 +-
 .../filter/Plugin/Filter/FilterHtml.php       |   4 +-
 core/modules/image/image.admin.inc            |   2 +-
 core/modules/language/language.admin.inc      |   4 +-
 .../Drupal/locale/Tests/LocaleExportTest.php  |   6 +-
 .../Tests/LocaleLibraryInfoAlterTest.php      |   3 +-
 core/modules/locale/locale.pages.inc          |   2 +-
 core/modules/node/node.module                 |   2 +-
 core/modules/node/node.pages.inc              |   2 +-
 core/modules/path/path.admin.inc              |   2 +-
 .../simpletest/Form/SimpletestResultsForm.php |   2 +-
 .../system/Tests/Common/JavaScriptTest.php    | 291 +++++++++++++-----
 core/modules/system/system.admin.inc          |   4 +-
 core/modules/system/system.api.php            |   2 +-
 core/modules/system/system.module             |  12 +-
 core/modules/tracker/tracker.pages.inc        |   2 +-
 core/modules/update/update.manager.inc        |   2 +-
 core/modules/update/update.report.inc         |   2 +-
 .../views/Controller/ViewAjaxController.php   |  18 +-
 .../Controller/ViewAjaxControllerTest.php     |  21 +-
 core/modules/views/views.api.php              |   4 +-
 core/modules/views/views.module               |  35 ++-
 core/modules/views/views.theme.inc            |  24 --
 .../views_ui/Controller/ViewsUIController.php |   4 +-
 .../Drupal/views_ui/ViewListController.php    |   2 +-
 .../views_ui/lib/Drupal/views_ui/ViewUI.php   |   2 +-
 core/modules/views_ui/views_ui.theme.inc      |   6 +-
 .../Tests/Core/Ajax/AjaxCommandsTest.php      |  30 +-
 46 files changed, 427 insertions(+), 217 deletions(-)

diff --git a/core/core.libraries.yml b/core/core.libraries.yml
index e405d95d6373..d2c35b99e8f1 100644
--- a/core/core.libraries.yml
+++ b/core/core.libraries.yml
@@ -280,7 +280,7 @@ html5shiv:
   remote: https://github.com/aFarkas/html5shiv
   version: 3.6.2
   js:
-    assets/vendor/html5shiv/html5.js: { weight: -22, browsers: { IE: 'lte IE 8', '!IE': false } }
+    assets/vendor/html5shiv/html5.js: { every_page: true, weight: -22, browsers: { IE: 'lte IE 8', '!IE': false } }
 
 jquery:
   remote: https://github.com/jquery/jquery
diff --git a/core/includes/common.inc b/core/includes/common.inc
index ecdce536929d..d18c0c107369 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -2457,7 +2457,7 @@ function drupal_pre_render_scripts($elements) {
  *   FALSE if there were any missing library dependencies; TRUE if all library
  *   dependencies were met.
  *
- * @see drupal_add_library()
+ * @see _drupal_add_library()
  * @see _drupal_add_js()
  * @see _drupal_add_css()
  * @see drupal_render()
@@ -2473,7 +2473,7 @@ function drupal_process_attached($elements, $dependency_check = FALSE) {
   // Add the libraries first.
   $success = TRUE;
   foreach ($elements['#attached']['library'] as $library) {
-    if (drupal_add_library($library) === FALSE) {
+    if (_drupal_add_library($library) === FALSE) {
       $success = FALSE;
       // Exit if the dependency is missing.
       if ($dependency_check) {
@@ -2672,7 +2672,7 @@ function drupal_process_states(&$elements) {
  * @see drupal_get_library()
  * @see hook_library_info_alter()
  */
-function drupal_add_library($library_name, $every_page = NULL) {
+function _drupal_add_library($library_name, $every_page = NULL) {
   $added = &drupal_static(__FUNCTION__, array());
 
   list($extension, $name) = explode('/', $library_name, 2);
@@ -2731,7 +2731,7 @@ function drupal_add_library($library_name, $every_page = NULL) {
  *   or FALSE if it does not exist. If no $name was passed, an associative array
  *   of libraries registered by the module is returned (which may be empty).
  *
- * @see drupal_add_library()
+ * @see _drupal_add_library()
  * @see hook_library_info_alter()
  *
  * @todo The purpose of drupal_get_*() is completely different to other page
@@ -3894,6 +3894,12 @@ function drupal_render(&$elements, $is_recursive_call = FALSE) {
     drupal_process_states($elements);
   }
 
+  // Add additional libraries, CSS, JavaScript and other custom
+  // attached data associated with this element.
+  if (!empty($elements['#attached'])) {
+    drupal_process_attached($elements);
+  }
+
   // Get the children of the element, sorted by weight.
   $children = Element::children($elements, TRUE);
 
@@ -3939,12 +3945,6 @@ function drupal_render(&$elements, $is_recursive_call = FALSE) {
     $elements['#children'] = $elements['#markup'] . $elements['#children'];
   }
 
-  // Add additional libraries, CSS, JavaScript an other custom
-  // attached data associated with this element.
-  if (!empty($elements['#attached'])) {
-    drupal_process_attached($elements);
-  }
-
   // Let the theme functions in #theme_wrappers add markup around the rendered
   // children.
   // #states and #attached have to be processed before #theme_wrappers, because
diff --git a/core/includes/form.inc b/core/includes/form.inc
index f56a36461831..f4a77183eb6c 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -1600,7 +1600,7 @@ function form_process_container($element, &$form_state) {
 function theme_tableselect($variables) {
   $element = $variables['element'];
   $table = array(
-    '#theme' => 'table',
+    '#type' => 'table',
   );
   $rows = array();
   $header = $element['#header'];
diff --git a/core/includes/tablesort.inc b/core/includes/tablesort.inc
index 5b1440cfc6d3..cd5c0c1f9ef3 100644
--- a/core/includes/tablesort.inc
+++ b/core/includes/tablesort.inc
@@ -9,7 +9,7 @@
  * @file
  * Functions to aid in the creation of sortable tables.
  *
- * All tables created when rendering a '#theme' => 'table' have the option of
+ * All tables created when rendering a '#type' => 'table' have the option of
  * having column headers that the user can click on to sort the table by that
  * column.
  */
@@ -33,7 +33,7 @@ function tablesort_init($header) {
  * @param $cell
  *   The cell to format.
  * @param $header
- *   An array of column headers in the format described in '#theme' => 'table'.
+ *   An array of column headers in the format described in '#type' => 'table'.
  * @param $ts
  *   The current table sort context as returned from tablesort_init().
  *
@@ -77,7 +77,7 @@ function tablesort_header($cell, $header, $ts) {
  * @param $cell
  *   The cell to format.
  * @param $header
- *   An array of column headers in the format described in '#theme' => 'table'.
+ *   An array of column headers in the format described in '#type' => 'table'.
  * @param $ts
  *   The current table sort context as returned from tablesort_init().
  * @param $i
@@ -113,7 +113,7 @@ function tablesort_get_query_parameters() {
  * Determines the current sort criterion.
  *
  * @param $headers
- *   An array of column headers in the format described in '#theme' => 'table'.
+ *   An array of column headers in the format described in '#type' => 'table'.
  *
  * @return
  *   An associative array describing the criterion, containing the keys:
@@ -150,7 +150,7 @@ function tablesort_get_order($headers) {
  * Determines the current sort direction.
  *
  * @param $headers
- *   An array of column headers in the format described in '#theme' => 'table'.
+ *   An array of column headers in the format described in '#type' => 'table'.
  *
  * @return
  *   The current sort direction ("asc" or "desc").
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index a58b59a2e586..49a8bd1367e3 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1416,6 +1416,24 @@ function drupal_pre_render_table(array $element) {
   // Take over $element['#id'] as HTML ID attribute, if not already set.
   element_set_attributes($element, array('id'));
 
+
+  // Add sticky headers, if applicable.
+  if (count($element['#header']) && $element['#sticky']) {
+    $element['#attached']['library'][] = 'core/drupal.tableheader';
+    // Add 'sticky-enabled' class to the table to identify it for JS.
+    // This is needed to target tables constructed by this function.
+    $element['#attributes']['class'][] = 'sticky-enabled';
+  }
+  // If the table has headers and it should react responsively to columns hidden
+  // with the classes represented by the constants RESPONSIVE_PRIORITY_MEDIUM
+  // and RESPONSIVE_PRIORITY_LOW, add the tableresponsive behaviors.
+  if (count($element['#header']) && $element['#responsive']) {
+    $element['#attached']['library'][] = 'core/drupal.tableresponsive';
+    // Add 'responsive-enabled' class to the table to identify it for JS.
+    // This is needed to target tables constructed by this function.
+    $element['#attributes']['class'][] = 'responsive-enabled';
+  }
+
   // If the custom #tabledrag is set and there is a HTML ID, add the table's
   // HTML ID to the options and attach the behavior.
   if (!empty($element['#tabledrag']) && isset($element['#attributes']['id'])) {
@@ -1523,23 +1541,6 @@ function theme_table($variables) {
   $responsive = $variables['responsive'];
   $empty = $variables['empty'];
 
-  // Add sticky headers, if applicable.
-  if (count($header) && $sticky) {
-    drupal_add_library('core/drupal.tableheader');
-    // Add 'sticky-enabled' class to the table to identify it for JS.
-    // This is needed to target tables constructed by this function.
-    $attributes['class'][] = 'sticky-enabled';
-  }
-  // If the table has headers and it should react responsively to columns hidden
-  // with the classes represented by the constants RESPONSIVE_PRIORITY_MEDIUM
-  // and RESPONSIVE_PRIORITY_LOW, add the tableresponsive behaviors.
-  if (count($header) && $responsive) {
-    drupal_add_library('core/drupal.tableresponsive');
-    // Add 'responsive-enabled' class to the table to identify it for JS.
-    // This is needed to target tables constructed by this function.
-    $attributes['class'][] = 'responsive-enabled';
-  }
-
   $output = '<table' . new Attribute($attributes) . ">\n";
 
   if (isset($caption)) {
@@ -1967,6 +1968,28 @@ function _template_preprocess_default_variables() {
   return $variables;
 }
 
+/**
+ * #pre_render callback for the html element type.
+ *
+ * @param array $element
+ *   A structured array containing the html element type build properties.
+ *
+ * @see system_element_info()
+ */
+function drupal_pre_render_html(array $element) {
+  // Add favicon.
+  if (theme_get_setting('features.favicon')) {
+    $favicon = theme_get_setting('favicon.url');
+    $type = theme_get_setting('favicon.mimetype');
+    $element['#attached']['drupal_add_html_head_link'][][] = array(
+      'rel' => 'shortcut icon',
+      'href' => UrlHelper::stripDangerousProtocols($favicon),
+      'type' => $type,
+    );
+  }
+
+  return $element;
+}
 /**
  * Prepares variables for HTML document templates.
  *
@@ -2016,18 +2039,6 @@ function template_preprocess_html(&$variables) {
   $variables['html_attributes']['lang'] = $language_interface->id;
   $variables['html_attributes']['dir'] = $language_interface->direction ? 'rtl' : 'ltr';
 
-  // Add favicon.
-  if (theme_get_setting('features.favicon')) {
-    $favicon = theme_get_setting('favicon.url');
-    $type = theme_get_setting('favicon.mimetype');
-    $build['#attached']['drupal_add_html_head_link'][][] = array(
-      'rel' => 'shortcut icon',
-      'href' => UrlHelper::stripDangerousProtocols($favicon),
-      'type' => $type,
-    );
-    drupal_render($build);
-  }
-
   $site_config = \Drupal::config('system.site');
   // Construct page title.
   if ($page->hasTitle()) {
@@ -2088,8 +2099,6 @@ function template_preprocess_html(&$variables) {
     drupal_add_html_head($element, $name);
   }
 
-  drupal_add_library('core/html5shiv', TRUE);
-
   $variables['page_top'][] = array('#markup' => $page->getBodyTop());
   $variables['page_bottom'][] = array('#markup' => $page->getBodyBottom());
 
diff --git a/core/lib/Drupal/Core/Ajax/OpenDialogCommand.php b/core/lib/Drupal/Core/Ajax/OpenDialogCommand.php
index 07d823b52c35..4b42bf701005 100644
--- a/core/lib/Drupal/Core/Ajax/OpenDialogCommand.php
+++ b/core/lib/Drupal/Core/Ajax/OpenDialogCommand.php
@@ -124,7 +124,7 @@ public function setDialogTitle($title) {
    */
   public function render() {
     // Add the library for handling the dialog in the response.
-    drupal_add_library('core/drupal.dialog.ajax');
+    $this->drupalAttachLibrary('core/drupal.dialog.ajax');
 
     // For consistency ensure the modal option is set to TRUE or FALSE.
     $this->dialogOptions['modal'] = isset($this->dialogOptions['modal']) && $this->dialogOptions['modal'];
@@ -136,4 +136,19 @@ public function render() {
       'dialogOptions' => $this->dialogOptions,
     );
   }
+
+  /**
+   * Wraps drupal_render.
+   *
+   * @param string $name
+   *   The name of the library.
+   *
+   * @todo Remove once drupal_render is converted to autoloadable code.
+   * @see https://drupal.org/node/2171071
+   */
+  protected function drupalAttachLibrary($name) {
+    $attached['#attached']['library'][] = $name;
+    drupal_render($attached);
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Entity/EntityListController.php b/core/lib/Drupal/Core/Entity/EntityListController.php
index 0703f5026ef8..c6585bee7522 100644
--- a/core/lib/Drupal/Core/Entity/EntityListController.php
+++ b/core/lib/Drupal/Core/Entity/EntityListController.php
@@ -171,7 +171,7 @@ public function buildOperations(EntityInterface $entity) {
    */
   public function render() {
     $build = array(
-      '#theme' => 'table',
+      '#type' => 'table',
       '#header' => $this->buildHeader(),
       '#title' => $this->getTitle(),
       '#rows' => array(),
diff --git a/core/lib/Drupal/Core/Page/DefaultHtmlPageRenderer.php b/core/lib/Drupal/Core/Page/DefaultHtmlPageRenderer.php
index 63e0d9c600dd..821d42d9e145 100644
--- a/core/lib/Drupal/Core/Page/DefaultHtmlPageRenderer.php
+++ b/core/lib/Drupal/Core/Page/DefaultHtmlPageRenderer.php
@@ -17,7 +17,7 @@ class DefaultHtmlPageRenderer implements HtmlPageRendererInterface {
    */
   public function render(HtmlPage $page) {
     $render = array(
-      '#theme' => 'html',
+      '#type' => 'html',
       '#page_object' => $page,
     );
     return drupal_render($render);
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Controller/AggregatorController.php b/core/modules/aggregator/lib/Drupal/aggregator/Controller/AggregatorController.php
index f7313cc0364d..5e89acf245d5 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Controller/AggregatorController.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Controller/AggregatorController.php
@@ -174,7 +174,7 @@ public function adminOverview() {
     }
     $build['feeds'] = array(
       '#prefix' => '<h3>' . $this->t('Feed overview') . '</h3>',
-      '#theme' => 'table',
+      '#type' => 'table',
       '#header' => $header,
       '#rows' => $rows,
       '#empty' => $this->t('No feeds available. <a href="@link">Add feed</a>.', array('@link' => $this->urlGenerator()->generateFromPath('admin/config/services/aggregator/add/feed'))),
diff --git a/core/modules/ban/lib/Drupal/ban/Form/BanAdmin.php b/core/modules/ban/lib/Drupal/ban/Form/BanAdmin.php
index 29ca186ffeb3..bfaeb7ac2586 100644
--- a/core/modules/ban/lib/Drupal/ban/Form/BanAdmin.php
+++ b/core/modules/ban/lib/Drupal/ban/Form/BanAdmin.php
@@ -90,7 +90,7 @@ public function buildForm(array $form, array &$form_state, $default_ip = '') {
     );
 
     $form['ban_ip_banning_table'] = array(
-      '#theme' => 'table',
+      '#type' => 'table',
       '#header' => $header,
       '#rows' => $rows,
       '#empty' => $this->t('No blocked IP addresses available.'),
diff --git a/core/modules/book/lib/Drupal/book/Controller/BookController.php b/core/modules/book/lib/Drupal/book/Controller/BookController.php
index 49a49476b535..dec592c5ff0b 100644
--- a/core/modules/book/lib/Drupal/book/Controller/BookController.php
+++ b/core/modules/book/lib/Drupal/book/Controller/BookController.php
@@ -89,7 +89,7 @@ public function adminOverview() {
       $rows[] = $row;
     }
     return array(
-      '#theme' => 'table',
+      '#type' => 'table',
       '#header' => $headers,
       '#rows' => $rows,
       '#empty' => t('No books available.'),
diff --git a/core/modules/comment/lib/Drupal/comment/Controller/AdminController.php b/core/modules/comment/lib/Drupal/comment/Controller/AdminController.php
index f46a606632cd..b0c7cbec0655 100644
--- a/core/modules/comment/lib/Drupal/comment/Controller/AdminController.php
+++ b/core/modules/comment/lib/Drupal/comment/Controller/AdminController.php
@@ -174,7 +174,7 @@ public function overviewBundles() {
     }
 
     $build['overview'] = array(
-      '#theme' => 'table',
+      '#type' => 'table',
       '#header' => $header,
       '#rows' => $rows,
       '#empty' => $this->t('No comment forms available.'),
diff --git a/core/modules/config/lib/Drupal/config/Controller/ConfigController.php b/core/modules/config/lib/Drupal/config/Controller/ConfigController.php
index ee5cd4aad696..18f628704014 100644
--- a/core/modules/config/lib/Drupal/config/Controller/ConfigController.php
+++ b/core/modules/config/lib/Drupal/config/Controller/ConfigController.php
@@ -115,7 +115,7 @@ public function diff($config_file) {
     $build['#attached']['css'][] = drupal_get_path('module', 'system') . '/css/system.diff.css';
 
     $build['diff'] = array(
-      '#theme' => 'table',
+      '#type' => 'table',
       '#header' => array(
         array('data' => t('Old'), 'colspan' => '2'),
         array('data' => t('New'), 'colspan' => '2'),
diff --git a/core/modules/config/lib/Drupal/config/Form/ConfigSync.php b/core/modules/config/lib/Drupal/config/Form/ConfigSync.php
index 22ac55fa6977..c6000016c1e7 100644
--- a/core/modules/config/lib/Drupal/config/Form/ConfigSync.php
+++ b/core/modules/config/lib/Drupal/config/Form/ConfigSync.php
@@ -136,7 +136,7 @@ public function buildForm(array $form, array &$form_state) {
     $storage_comparer = new StorageComparer($this->sourceStorage, $this->targetStorage);
     if (empty($source_list) || !$storage_comparer->createChangelist()->hasChanges()) {
       $form['no_changes'] = array(
-        '#theme' => 'table',
+        '#type' => 'table',
         '#header' => array('Name', 'Operations'),
         '#rows' => array(),
         '#empty' => $this->t('There are no configuration changes.'),
@@ -182,7 +182,7 @@ public function buildForm(array $form, array &$form_state) {
           break;
       }
       $form[$config_change_type]['list'] = array(
-        '#theme' => 'table',
+        '#type' => 'table',
         '#header' => array('Name', 'Operations'),
       );
 
diff --git a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationMapperList.php b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationMapperList.php
index 8b7f63f2ddd5..14f972457e3e 100644
--- a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationMapperList.php
+++ b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationMapperList.php
@@ -53,7 +53,7 @@ public static function create(ContainerInterface $container) {
    */
   public function render() {
     $build = array(
-      '#theme' => 'table',
+      '#type' => 'table',
       '#header' => $this->buildHeader(),
       '#rows' => array(),
     );
diff --git a/core/modules/content_translation/content_translation.pages.inc b/core/modules/content_translation/content_translation.pages.inc
index bed50a047202..ac36ff7de792 100644
--- a/core/modules/content_translation/content_translation.pages.inc
+++ b/core/modules/content_translation/content_translation.pages.inc
@@ -136,7 +136,7 @@ function content_translation_overview(EntityInterface $entity) {
   $build['#entity'] = $entity;
 
   $build['content_translation_overview'] = array(
-    '#theme' => 'table',
+    '#type' => 'table',
     '#header' => $header,
     '#rows' => $rows,
   );
diff --git a/core/modules/dblog/lib/Drupal/dblog/Controller/DbLogController.php b/core/modules/dblog/lib/Drupal/dblog/Controller/DbLogController.php
index 9728f350157d..d891bfe406ef 100644
--- a/core/modules/dblog/lib/Drupal/dblog/Controller/DbLogController.php
+++ b/core/modules/dblog/lib/Drupal/dblog/Controller/DbLogController.php
@@ -205,7 +205,7 @@ public function overview() {
     }
 
     $build['dblog_table'] = array(
-      '#theme' => 'table',
+      '#type' => 'table',
       '#header' => $header,
       '#rows' => $rows,
       '#attributes' => array('id' => 'admin-dblog', 'class' => array('admin-dblog')),
@@ -280,7 +280,7 @@ public function eventDetails($event_id) {
         ),
       );
       $build['dblog_table'] = array(
-        '#theme' => 'table',
+        '#type' => 'table',
         '#rows' => $rows,
         '#attributes' => array('class' => array('dblog-event')),
       );
@@ -379,7 +379,7 @@ public function topLogMessages($type) {
     }
 
     $build['dblog_top_table']  = array(
-      '#theme' => 'table',
+      '#type' => 'table',
       '#header' => $header,
       '#rows' => $rows,
       '#empty' => $this->t('No log messages available.'),
diff --git a/core/modules/field_ui/field_ui.module b/core/modules/field_ui/field_ui.module
index 4279bb3dbfae..a08593aba5f6 100644
--- a/core/modules/field_ui/field_ui.module
+++ b/core/modules/field_ui/field_ui.module
@@ -237,7 +237,7 @@ function field_ui_view_mode_delete(EntityViewModeInterface $view_mode) {
  */
 function theme_field_ui_table($variables) {
   $elements = $variables['elements'];
-  $table = array('#theme' => 'table');
+  $table = array('#type' => 'table');
 
   // Add table headers and attributes.
   foreach (array('#header', '#attributes') as $key) {
diff --git a/core/modules/file/file.field.inc b/core/modules/file/file.field.inc
index ee805603c9f0..a3c7140fdbb2 100644
--- a/core/modules/file/file.field.inc
+++ b/core/modules/file/file.field.inc
@@ -271,7 +271,7 @@ function theme_file_formatter_table($variables) {
   }
 
   $build = array(
-    '#theme' => 'table',
+    '#type' => 'table',
     '#header' => $header,
     '#rows' => $rows,
   );
diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterHtml.php b/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterHtml.php
index dcb931c93591..f94037a510fd 100644
--- a/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterHtml.php
+++ b/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterHtml.php
@@ -152,7 +152,7 @@ public function tips($long = FALSE) {
       }
     }
     $table = array(
-      '#theme' => 'table',
+      '#type' => 'table',
       '#header' => $header,
       '#rows' => $rows,
     );
@@ -177,7 +177,7 @@ public function tips($long = FALSE) {
       );
     }
     $table = array(
-      '#theme' => 'table',
+      '#type' => 'table',
       '#header' => $header,
       '#rows' => $rows,
     );
diff --git a/core/modules/image/image.admin.inc b/core/modules/image/image.admin.inc
index a883bc26d133..1f43cf882be7 100644
--- a/core/modules/image/image.admin.inc
+++ b/core/modules/image/image.admin.inc
@@ -192,7 +192,7 @@ function theme_image_anchor($variables) {
   }
 
   $table = array(
-    '#theme' => 'table',
+    '#type' => 'table',
     '#header' => array(),
     '#rows' => $rows,
     '#attributes' => array('class' => array('image-anchor')),
diff --git a/core/modules/language/language.admin.inc b/core/modules/language/language.admin.inc
index 8fefe3d3b0b5..b506136ac891 100644
--- a/core/modules/language/language.admin.inc
+++ b/core/modules/language/language.admin.inc
@@ -140,7 +140,7 @@ function theme_language_negotiation_configure_browser_form_table($variables) {
   );
 
   $table = array(
-    '#theme' => 'table',
+    '#type' => 'table',
     '#header' => $header,
     '#rows' => $rows,
     '#attributes' => array('id' => 'lang-neg-browser'),
@@ -292,7 +292,7 @@ function template_preprocess_language_content_settings_table(&$variables) {
     '#title' => $element['#title'],
     '#header' => $header,
     '#rows' => $rows,
-    '#theme' => 'table',
+    '#type' => 'table',
   );
 }
 
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleExportTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleExportTest.php
index d77fdc2bff51..c0ceb052fd66 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleExportTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleExportTest.php
@@ -121,9 +121,9 @@ function testExportTranslation() {
    * Test exportation of translation template file.
    */
   function testExportTranslationTemplateFile() {
-    // Load an admin page with JavaScript so drupal_add_library() fires at least
-    // once and _locale_parse_js_file() gets to run at least once so that the
-    // locales_source table gets populated with something.
+    // Load an admin page with JavaScript so _drupal_add_library() fires at
+    // least once and _locale_parse_js_file() gets to run at least once so that
+    // the locales_source table gets populated with something.
     $this->drupalGet('admin/config/regional/language');
     // Get the translation template file.
     $this->drupalPostForm('admin/config/regional/translate/export', array(), t('Export'));
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleLibraryInfoAlterTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleLibraryInfoAlterTest.php
index 30e0c8d266ff..1bf13735f2e4 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleLibraryInfoAlterTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleLibraryInfoAlterTest.php
@@ -36,7 +36,8 @@ public static function getInfo() {
      * @see locale_library_info_alter()
      */
   public function testLibraryInfoAlter() {
-    drupal_add_library('core/jquery.ui.datepicker');
+    $attached['#attached']['library'][] = 'core/jquery.ui.datepicker';
+    drupal_render($attached);
     $scripts = drupal_get_js();
     $this->assertTrue(strpos($scripts, 'locale.datepicker.js'), 'locale.datepicker.js added to scripts.');
   }
diff --git a/core/modules/locale/locale.pages.inc b/core/modules/locale/locale.pages.inc
index 73125fd951a4..00a27f91eea9 100644
--- a/core/modules/locale/locale.pages.inc
+++ b/core/modules/locale/locale.pages.inc
@@ -298,7 +298,7 @@ function theme_locale_translate_edit_form_strings($variables) {
     );
   }
   $table = array(
-    '#theme' => 'table',
+    '#type' => 'table',
     '#header' => $header,
     '#rows' => $rows,
     '#empty' => t('No strings available.'),
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 74dc5486c785..c97851ed9a34 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -898,7 +898,7 @@ function theme_node_search_admin($variables) {
     $rows[] = $row;
   }
   $table = array(
-    '#theme' => 'table',
+    '#type' => 'table',
     '#header' => $header,
     '#rows' => $rows,
   );
diff --git a/core/modules/node/node.pages.inc b/core/modules/node/node.pages.inc
index 99f402470209..fe5b0c15bdf6 100644
--- a/core/modules/node/node.pages.inc
+++ b/core/modules/node/node.pages.inc
@@ -175,7 +175,7 @@ function node_revision_overview($node) {
   }
 
   $build['node_revisions_table'] = array(
-    '#theme' => 'table',
+    '#type' => 'table',
     '#rows' => $rows,
     '#header' => $header,
     '#attached' => array (
diff --git a/core/modules/path/path.admin.inc b/core/modules/path/path.admin.inc
index a2b20722fd06..d22fe66d49c6 100644
--- a/core/modules/path/path.admin.inc
+++ b/core/modules/path/path.admin.inc
@@ -89,7 +89,7 @@ function path_admin_overview($keys = NULL) {
   }
 
   $build['path_table'] = array(
-    '#theme' => 'table',
+    '#type' => 'table',
     '#header' => $header,
     '#rows' => $rows,
     '#empty' => t('No URL aliases available. <a href="@link">Add URL alias</a>.', array('@link' => url('admin/config/search/path/add'))),
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Form/SimpletestResultsForm.php b/core/modules/simpletest/lib/Drupal/simpletest/Form/SimpletestResultsForm.php
index bfc9b8cddfee..d3f6a4cb1699 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/Form/SimpletestResultsForm.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/Form/SimpletestResultsForm.php
@@ -172,7 +172,7 @@ public function buildForm(array $form, array &$form_state, $test_id = NULL) {
         $form['result']['summary']['#' . $assertion->status]++;
       }
       $form['result']['results'][$group]['table'] = array(
-        '#theme' => 'table',
+        '#type' => 'table',
         '#header' => $header,
         '#rows' => $rows,
       );
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/JavaScriptTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/JavaScriptTest.php
index bdb091073364..4c282d82edb5 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/JavaScriptTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/JavaScriptTest.php
@@ -47,9 +47,8 @@ function setUp() {
     $config->set('js.preprocess', 0);
     $config->save();
 
-    // Reset _drupal_add_js() and drupal_add_library() statics before each test.
+    // Reset _drupal_add_js() statics before each test.
     drupal_static_reset('_drupal_add_js');
-    drupal_static_reset('drupal_add_library');
   }
 
   function tearDown() {
@@ -71,7 +70,9 @@ function testDefault() {
    * Tests adding a JavaScript file.
    */
   function testAddFile() {
-    $javascript = _drupal_add_js('core/misc/collapse.js');
+    $attached['#attached']['js']['core/misc/collapse.js'] = array();
+    drupal_render($attached);
+    $javascript = _drupal_add_js();
     $this->assertTrue(array_key_exists('core/misc/collapse.js', $javascript), 'JavaScript files are correctly added.');
   }
 
@@ -80,7 +81,8 @@ function testAddFile() {
    */
   function testAddSetting() {
     // Add a file in order to test default settings.
-    drupal_add_library('core/drupalSettings');
+    $attached['#attached']['library'][] = 'core/drupalSettings';
+    drupal_render($attached);
     $javascript = _drupal_add_js();
     $last_settings = reset($javascript['settings']['data']);
     $this->assertTrue(array_key_exists('currentPath', $last_settings['path']), 'The current path JavaScript setting is set correctly.');
@@ -95,8 +97,9 @@ function testAddSetting() {
    * Tests adding an external JavaScript File.
    */
   function testAddExternal() {
-    $path = 'http://example.com/script.js';
-    $javascript = _drupal_add_js($path, 'external');
+    $attached['#attached']['js']['http://example.com/script.js'] = array('type' => 'external');
+    drupal_render($attached);
+    $javascript = _drupal_add_js();
     $this->assertTrue(array_key_exists('http://example.com/script.js', $javascript), 'Added an external JavaScript file.');
   }
 
@@ -106,12 +109,18 @@ function testAddExternal() {
   function testAttributes() {
     $default_query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0';
 
-    drupal_add_library('core/drupal');
-    _drupal_add_js('http://example.com/script.js', array('attributes' => array('defer' => 'defer')));
-    _drupal_add_js('core/misc/collapse.js', array('attributes' => array('defer' => 'defer')));
+    $attached['#attached']['library'][] = 'core/drupal';
+    $attached['#attached']['js']['http://example.com/script.js'] = array(
+      'type' => 'external',
+      'attributes' => array('defer' => 'defer'),
+    );
+    $attached['#attached']['js']['core/misc/collapse.js'] = array(
+      'attributes' => array('defer' => 'defer'),
+    );
+    drupal_render($attached);
     $javascript = drupal_get_js();
 
-    $expected_1 = '<script src="http://example.com/script.js?' . $default_query_string . '" defer="defer"></script>';
+    $expected_1 = '<script src="http://example.com/script.js" defer="defer"></script>';
     $expected_2 = '<script src="' . file_create_url('core/misc/collapse.js') . '?' . $default_query_string . '" defer="defer"></script>';
 
     $this->assertTrue(strpos($javascript, $expected_1) > 0, 'Rendered external JavaScript with correct defer attribute.');
@@ -127,12 +136,18 @@ function testAggregatedAttributes() {
 
     $default_query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0';
 
-    drupal_add_library('core/drupal');
-    _drupal_add_js('http://example.com/script.js', array('attributes' => array('defer' => 'defer')));
-    _drupal_add_js('core/misc/collapse.js', array('attributes' => array('defer' => 'defer')));
+    $attached['#attached']['library'][] = 'core/drupal';
+    $attached['#attached']['js']['http://example.com/script.js'] = array(
+      'type' => 'external',
+      'attributes' => array('defer' => 'defer'),
+    );
+    $attached['#attached']['js']['core/misc/collapse.js'] = array(
+      'attributes' => array('defer' => 'defer'),
+    );
+    drupal_render($attached);
     $javascript = drupal_get_js();
 
-    $expected_1 = '<script src="http://example.com/script.js?' . $default_query_string . '" defer="defer"></script>';
+    $expected_1 = '<script src="http://example.com/script.js" defer="defer"></script>';
     $expected_2 = '<script src="' . file_create_url('core/misc/collapse.js') . '?' . $default_query_string . '" defer="defer"></script>';
 
     $this->assertTrue(strpos($javascript, $expected_1) > 0, 'Rendered external JavaScript with correct defer attribute with aggregation enabled.');
@@ -143,7 +158,9 @@ function testAggregatedAttributes() {
    * Tests drupal_get_js() for JavaScript settings.
    */
   function testHeaderSetting() {
-    drupal_add_library('core/drupalSettings');
+    $attached = array();
+    $attached['#attached']['library'][] = 'core/drupalSettings';
+    drupal_render($attached);
 
     $javascript = drupal_get_js('header');
     $this->assertTrue(strpos($javascript, 'basePath') > 0, 'Rendered JavaScript header returns basePath setting.');
@@ -152,25 +169,57 @@ function testHeaderSetting() {
     $this->assertTrue(strpos($javascript, 'currentPath') > 0, 'Rendered JavaScript header returns currentPath setting.');
 
     // Only the second of these two entries should appear in drupalSettings.
-    _drupal_add_js(array('commonTest' => 'commonTestShouldNotAppear'), 'setting');
-    _drupal_add_js(array('commonTest' => 'commonTestShouldAppear'), 'setting');
+    $attached = array();
+    $attached['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('commonTest' => 'commonTestShouldNotAppear'),
+    );
+    $attached['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('commonTest' => 'commonTestShouldAppear'),
+    );
     // Only the second of these entries should appear in drupalSettings.
-    _drupal_add_js(array('commonTestJsArrayLiteral' => array('commonTestJsArrayLiteralOldValue')), 'setting');
-    _drupal_add_js(array('commonTestJsArrayLiteral' => array('commonTestJsArrayLiteralNewValue')), 'setting');
+    $attached['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('commonTestJsArrayLiteral' => array('commonTestJsArrayLiteralOldValue')),
+    );
+    $attached['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('commonTestJsArrayLiteral' => array('commonTestJsArrayLiteralNewValue')),
+    );
     // Only the second of these two entries should appear in drupalSettings.
-    _drupal_add_js(array('commonTestJsObjectLiteral' => array('key' => 'commonTestJsObjectLiteralOldValue')), 'setting');
-    _drupal_add_js(array('commonTestJsObjectLiteral' => array('key' => 'commonTestJsObjectLiteralNewValue')), 'setting');
+    $attached['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('commonTestJsObjectLiteral' => array('key' => 'commonTestJsObjectLiteralOldValue')),
+    );
+    $attached['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('commonTestJsObjectLiteral' => array('key' => 'commonTestJsObjectLiteralNewValue')),
+    );
     // Real world test case: multiple elements in a render array are adding the
     // same (or nearly the same) JavaScript settings. When merged, they should
     // contain all settings and not duplicate some settings.
     $settings_one = array('moduleName' => array('ui' => array('button A', 'button B'), 'magical flag' => 3.14159265359));
-    _drupal_add_js(array('commonTestRealWorldIdentical' => $settings_one), 'setting');
-    _drupal_add_js(array('commonTestRealWorldIdentical' => $settings_one), 'setting');
+    $attached['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('commonTestRealWorldIdentical' => $settings_one),
+    );
+    $attached['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('commonTestRealWorldIdentical' => $settings_one),
+    );
     $settings_two = array('moduleName' => array('ui' => array('button A', 'button B'), 'magical flag' => 3.14159265359, 'thingiesOnPage' => array('id1' => array())));
-    _drupal_add_js(array('commonTestRealWorldAlmostIdentical' => $settings_two), 'setting');
+    $attached['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('commonTestRealWorldAlmostIdentical' => $settings_two),
+    );
     $settings_two = array('moduleName' => array('ui' => array('button C', 'button D'), 'magical flag' => 3.14, 'thingiesOnPage' => array('id2' => array())));
-    _drupal_add_js(array('commonTestRealWorldAlmostIdentical' => $settings_two), 'setting');
+    $attached['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('commonTestRealWorldAlmostIdentical' => $settings_two),
+    );
 
+    drupal_render($attached);
     $javascript = drupal_get_js('header');
 
     // Test whether _drupal_add_js can be used to override a previous setting.
@@ -205,8 +254,9 @@ function testHeaderSetting() {
    * Tests to see if resetting the JavaScript empties the cache.
    */
   function testReset() {
-    drupal_add_library('core/drupal');
-    _drupal_add_js('core/misc/collapse.js');
+    $attached['#attached']['library'][] = 'core/drupal';
+    $attached['#attached']['js']['core/misc/collapse.js'] = array();
+    drupal_render($attached);
     drupal_static_reset('_drupal_add_js');
     $this->assertEqual(array(), _drupal_add_js(), 'Resetting the JavaScript correctly empties the cache.');
   }
@@ -215,9 +265,15 @@ function testReset() {
    * Tests adding inline scripts.
    */
   function testAddInline() {
-    drupal_add_library('core/jquery');
     $inline = 'jQuery(function () { });';
-    $javascript = _drupal_add_js($inline, array('type' => 'inline', 'scope' => 'footer'));
+    $attached['#attached']['library'][] = 'core/jquery';
+    $attached['#attached']['js'][] = array(
+      'type' => 'inline',
+      'data' => $inline,
+      'attributes' => array('defer' => 'defer'),
+    );
+    drupal_render($attached);
+    $javascript = _drupal_add_js();
     $this->assertTrue(array_key_exists('core/assets/vendor/jquery/jquery.js', $javascript), 'jQuery is added when inline scripts are added.');
     $data = end($javascript);
     $this->assertEqual($inline, $data['data'], 'Inline JavaScript is correctly added to the footer.');
@@ -227,9 +283,14 @@ function testAddInline() {
    * Tests rendering an external JavaScript file.
    */
   function testRenderExternal() {
-    drupal_add_library('core/drupal');
     $external = 'http://example.com/example.js';
-    _drupal_add_js($external, 'external');
+    $attached['#attached']['library'][] = 'core/drupal';
+    $attached['#attached']['js'][] = array(
+      'type' => 'external',
+      'data' => $external,
+    );
+    drupal_render($attached);
+
     $javascript = drupal_get_js();
     // Local files have a base_path() prefix, external files should not.
     $this->assertTrue(strpos($javascript, 'src="' . $external) > 0, 'Rendering an external JavaScript file.');
@@ -239,9 +300,16 @@ function testRenderExternal() {
    * Tests drupal_get_js() with a footer scope.
    */
   function testFooterHTML() {
-    drupal_add_library('core/drupal');
     $inline = 'jQuery(function () { });';
-    _drupal_add_js($inline, array('type' => 'inline', 'scope' => 'footer'));
+    $attached['#attached']['library'][] = 'core/drupal';
+    $attached['#attached']['js'][] = array(
+      'type' => 'inline',
+      'data' => $inline,
+      'scope' => 'footer',
+      'attributes' => array('defer' => 'defer'),
+    );
+    drupal_render($attached);
+
     $javascript = drupal_get_js('footer');
     $this->assertTrue(strpos($javascript, $inline) > 0, 'Rendered JavaScript footer returns the inline code.');
   }
@@ -250,8 +318,10 @@ function testFooterHTML() {
    * Tests _drupal_add_js() sets preproccess to FALSE when cache is also FALSE.
    */
   function testNoCache() {
-    drupal_add_library('core/drupal');
-    $javascript = _drupal_add_js('core/misc/collapse.js', array('cache' => FALSE));
+    $attached['#attached']['library'][] = 'core/drupal';
+    $attached['#attached']['js']['core/misc/collapse.js'] = array('cache' => FALSE);
+    drupal_render($attached);
+    $javascript = _drupal_add_js();
     $this->assertFalse($javascript['core/misc/collapse.js']['preprocess'], 'Setting cache to FALSE sets proprocess to FALSE when adding JavaScript.');
   }
 
@@ -259,8 +329,10 @@ function testNoCache() {
    * Tests adding a JavaScript file with a different group.
    */
   function testDifferentGroup() {
-    drupal_add_library('core/drupal');
-    $javascript = _drupal_add_js('core/misc/collapse.js', array('group' => JS_THEME));
+    $attached['#attached']['library'][] = 'core/drupal';
+    $attached['#attached']['js']['core/misc/collapse.js'] = array('group' => JS_THEME);
+    drupal_render($attached);
+    $javascript = _drupal_add_js();
     $this->assertEqual($javascript['core/misc/collapse.js']['group'], JS_THEME, 'Adding a JavaScript file with a different group caches the given group.');
   }
 
@@ -268,7 +340,9 @@ function testDifferentGroup() {
    * Tests adding a JavaScript file with a different weight.
    */
   function testDifferentWeight() {
-    $javascript = _drupal_add_js('core/misc/collapse.js', array('weight' => 2));
+    $attached['#attached']['js']['core/misc/collapse.js'] = array('weight' => 2);
+    drupal_render($attached);
+    $javascript = _drupal_add_js();
     $this->assertEqual($javascript['core/misc/collapse.js']['weight'], 2, 'Adding a JavaScript file with a different weight caches the given weight.');
   }
 
@@ -280,9 +354,16 @@ function testDifferentWeight() {
   function testBrowserConditionalComments() {
     $default_query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0';
 
-    drupal_add_library('core/drupal');
-    _drupal_add_js('core/misc/collapse.js', array('browsers' => array('IE' => 'lte IE 8', '!IE' => FALSE)));
-    _drupal_add_js('jQuery(function () { });', array('type' => 'inline', 'browsers' => array('IE' => FALSE)));
+    $attached['#attached']['library'][] = 'core/drupal';
+    $attached['#attached']['js']['core/misc/collapse.js'] = array(
+      'browsers' => array('IE' => 'lte IE 8', '!IE' => FALSE),
+    );
+    $attached['#attached']['js'][] = array(
+      'type' => 'inline',
+      'data' => 'jQuery(function () { });',
+      'browsers' => array('IE' => FALSE),
+    );
+    drupal_render($attached);
     $javascript = drupal_get_js();
 
     $expected_1 = "<!--[if lte IE 8]>\n" . '<script src="' . file_create_url('core/misc/collapse.js') . '?' . $default_query_string . '"></script>' . "\n<![endif]-->";
@@ -296,9 +377,10 @@ function testBrowserConditionalComments() {
    * Tests JavaScript versioning.
    */
   function testVersionQueryString() {
-    drupal_add_library('core/drupal');
-    _drupal_add_js('core/misc/collapse.js', array('version' => 'foo'));
-    _drupal_add_js('core/misc/ajax.js', array('version' => 'bar'));
+    $attached['#attached']['library'][] = 'core/drupal';
+    $attached['#attached']['js']['core/misc/collapse.js'] = array('version' => 'foo');
+    $attached['#attached']['js']['core/misc/ajax.js'] = array('version' => 'bar');
+    drupal_render($attached);
     $javascript = drupal_get_js();
     $this->assertTrue(strpos($javascript, 'core/misc/collapse.js?v=foo') > 0 && strpos($javascript, 'core/misc/ajax.js?v=bar') > 0 , 'JavaScript version identifiers correctly appended to URLs');
   }
@@ -313,11 +395,13 @@ function testAggregation() {
     // ahead of ones without. The order of JavaScript execution must be the
     // same regardless of whether aggregation is enabled, so ensure this
     // expected order, first with aggregation off.
-    drupal_add_library('core/drupal');
-    _drupal_add_js('core/misc/ajax.js');
-    _drupal_add_js('core/misc/collapse.js', array('every_page' => TRUE));
-    _drupal_add_js('core/misc/autocomplete.js');
-    _drupal_add_js('core/misc/batch.js', array('every_page' => TRUE));
+    $attached = array();
+    $attached['#attached']['library'][] = 'core/drupal';
+    $attached['#attached']['js']['core/misc/ajax.js'] = array();
+    $attached['#attached']['js']['core/misc/collapse.js'] = array('every_page' => TRUE);
+    $attached['#attached']['js']['core/misc/autocomplete.js'] = array();
+    $attached['#attached']['js']['core/misc/batch.js'] = array('every_page' => TRUE);
+    drupal_render($attached);
     $javascript = drupal_get_js();
     $expected = implode("\n", array(
       '<script src="' . file_create_url('core/misc/collapse.js') . '?' . $default_query_string . '"></script>',
@@ -333,11 +417,13 @@ function testAggregation() {
     $config = \Drupal::config('system.performance');
     $config->set('js.preprocess', 1);
     $config->save();
-    drupal_add_library('core/drupal');
-    _drupal_add_js('core/misc/ajax.js');
-    _drupal_add_js('core/misc/collapse.js', array('every_page' => TRUE));
-    _drupal_add_js('core/misc/autocomplete.js');
-    _drupal_add_js('core/misc/batch.js', array('every_page' => TRUE));
+    $attached = array();
+    $attached['#attached']['library'][] = 'core/drupal';
+    $attached['#attached']['js']['core/misc/ajax.js'] = array();
+    $attached['#attached']['js']['core/misc/collapse.js'] = array('every_page' => TRUE);
+    $attached['#attached']['js']['core/misc/autocomplete.js'] = array();
+    $attached['#attached']['js']['core/misc/batch.js'] = array('every_page' => TRUE);
+    drupal_render($attached);
     $js_items = _drupal_add_js();
     $javascript = drupal_get_js();
     $expected = implode("\n", array(
@@ -356,9 +442,11 @@ function testAggregationOrder() {
     drupal_static_reset('_drupal_add_js');
 
     // Add two JavaScript files to the current request and build the cache.
-    drupal_add_library('core/drupal');
-    _drupal_add_js('core/misc/ajax.js');
-    _drupal_add_js('core/misc/autocomplete.js');
+    $attached = array();
+    $attached['#attached']['library'][] = 'core/drupal';
+    $attached['#attached']['js']['core/misc/ajax.js'] = array();
+    $attached['#attached']['js']['core/misc/autocomplete.js'] = array();
+    drupal_render($attached);
 
     $js_items = _drupal_add_js();
     $scripts_html = array(
@@ -377,10 +465,12 @@ function testAggregationOrder() {
     // Reset variables and add a file in a different scope first.
     \Drupal::state()->delete('system.js_cache_files');
     drupal_static_reset('_drupal_add_js');
-    drupal_add_library('core/drupal');
-    _drupal_add_js('some/custom/javascript_file.js', array('scope' => 'footer'));
-    _drupal_add_js('core/misc/ajax.js');
-    _drupal_add_js('core/misc/autocomplete.js');
+    $attached = array();
+    $attached['#attached']['library'][] = 'core/drupal';
+    $attached['#attached']['js']['some/custom/javascript_file.js'] = array('scope' => 'footer');
+    $attached['#attached']['js']['core/misc/ajax.js'] = array();
+    $attached['#attached']['js']['core/misc/autocomplete.js'] = array();
+    drupal_render($attached);
 
     // Rebuild the cache.
     $js_items = _drupal_add_js();
@@ -403,17 +493,50 @@ function testAggregationOrder() {
    * Tests JavaScript ordering.
    */
   function testRenderOrder() {
+    $shared_options = array(
+      'type' => 'inline',
+      'scope' => 'footer',
+    );
     // Add a bunch of JavaScript in strange ordering.
-    _drupal_add_js('(function($){alert("Weight 5 #1");})(jQuery);', array('type' => 'inline', 'scope' => 'footer', 'weight' => 5));
-    _drupal_add_js('(function($){alert("Weight 0 #1");})(jQuery);', array('type' => 'inline', 'scope' => 'footer'));
-    _drupal_add_js('(function($){alert("Weight 0 #2");})(jQuery);', array('type' => 'inline', 'scope' => 'footer'));
-    _drupal_add_js('(function($){alert("Weight -8 #1");})(jQuery);', array('type' => 'inline', 'scope' => 'footer', 'weight' => -8));
-    _drupal_add_js('(function($){alert("Weight -8 #2");})(jQuery);', array('type' => 'inline', 'scope' => 'footer', 'weight' => -8));
-    _drupal_add_js('(function($){alert("Weight -8 #3");})(jQuery);', array('type' => 'inline', 'scope' => 'footer', 'weight' => -8));
-    _drupal_add_js('http://example.com/example.js?Weight -5 #1', array('type' => 'external', 'scope' => 'footer', 'weight' => -5));
-    _drupal_add_js('(function($){alert("Weight -8 #4");})(jQuery);', array('type' => 'inline', 'scope' => 'footer', 'weight' => -8));
-    _drupal_add_js('(function($){alert("Weight 5 #2");})(jQuery);', array('type' => 'inline', 'scope' => 'footer', 'weight' => 5));
-    _drupal_add_js('(function($){alert("Weight 0 #3");})(jQuery);', array('type' => 'inline', 'scope' => 'footer'));
+    $attached['#attached']['js'][] = $shared_options + array(
+      'data' => '(function($){alert("Weight 5 #1");})(jQuery);',
+      'weight' => 5,
+    );
+    $attached['#attached']['js'][] = $shared_options + array(
+      'data' => '(function($){alert("Weight 0 #1");})(jQuery);',
+    );
+    $attached['#attached']['js'][] = $shared_options + array(
+      'data' => '(function($){alert("Weight 0 #2");})(jQuery);',
+    );
+    $attached['#attached']['js'][] = $shared_options + array(
+      'data' => '(function($){alert("Weight -8 #1");})(jQuery);',
+      'weight' => -8,
+    );
+    $attached['#attached']['js'][] = $shared_options + array(
+      'data' => '(function($){alert("Weight -8 #2");})(jQuery);',
+      'weight' => -8,
+    );
+    $attached['#attached']['js'][] = $shared_options + array(
+      'data' => '(function($){alert("Weight -8 #3");})(jQuery);',
+      'weight' => -8,
+    );
+    $attached['#attached']['js']['http://example.com/example.js?Weight -5 #1'] = array(
+      'type' => 'external',
+      'scope' => 'footer',
+      'weight' => -5,
+    );
+    $attached['#attached']['js'][] = $shared_options + array(
+      'data' => '(function($){alert("Weight -8 #4");})(jQuery);',
+      'weight' => -8,
+    );
+    $attached['#attached']['js'][] = $shared_options + array(
+      'data' => '(function($){alert("Weight 5 #2");})(jQuery);',
+      'weight' => 5,
+    );
+    $attached['#attached']['js'][] = $shared_options + array(
+      'data' => '(function($){alert("Weight 0 #3");})(jQuery);',
+    );
+    drupal_render($attached);
 
     // Construct the expected result from the regex.
     $expected = array(
@@ -448,8 +571,13 @@ function testRenderDifferentWeight() {
     // JavaScript files are sorted first by group, then by the 'every_page'
     // flag, then by weight (see drupal_sort_css_js()), so to test the effect of
     // weight, we need the other two options to be the same.
-    drupal_add_library('core/jquery');
-    _drupal_add_js('core/misc/collapse.js', array('group' => JS_LIBRARY, 'every_page' => TRUE, 'weight' => -21));
+    $attached['#attached']['library'][] = 'core/jquery';
+    $attached['#attached']['js']['core/misc/collapse.js'] = array(
+      'group' => JS_LIBRARY,
+      'every_page' => TRUE,
+      'weight' => -21,
+    );
+    drupal_render($attached);
     $javascript = drupal_get_js();
     $this->assertTrue(strpos($javascript, 'core/misc/collapse.js') < strpos($javascript, 'core/assets/vendor/jquery/jquery.js'), 'Rendering a JavaScript file above jQuery.');
   }
@@ -461,8 +589,9 @@ function testRenderDifferentWeight() {
    */
   function testAlter() {
     // Add both tableselect.js and simpletest.js, with a larger weight on SimpleTest.
-    _drupal_add_js('core/misc/tableselect.js');
-    _drupal_add_js(drupal_get_path('module', 'simpletest') . '/simpletest.js', array('weight' => 9999));
+    $attached['#attached']['js']['core/misc/tableselect.js'] = array();
+    $attached['#attached']['js'][drupal_get_path('module', 'simpletest') . '/simpletest.js'] = array('weight' => 9999);
+    drupal_render($attached);
 
     // Render the JavaScript, testing if simpletest.js was altered to be before
     // tableselect.js. See simpletest_js_alter() to see where this alteration
@@ -475,8 +604,9 @@ function testAlter() {
    * Adds a library to the page and tests for both its JavaScript and its CSS.
    */
   function testLibraryRender() {
-    $result = drupal_add_library('core/jquery.farbtastic');
-    $this->assertTrue($result !== FALSE, 'Library was added without errors.');
+    $attached = array();
+    $attached['#attached']['library'][] = 'core/jquery.farbtastic';
+    drupal_render($attached);
     $scripts = drupal_get_js();
     $styles = drupal_get_css();
     $this->assertTrue(strpos($scripts, 'core/assets/vendor/farbtastic/farbtastic.js'), 'JavaScript of library was added to the page.');
@@ -494,7 +624,8 @@ function testLibraryAlter() {
     $this->assertEqual($library['version'], '0.0', 'Registered libraries were altered.');
 
     // common_test_library_info_alter() also added a dependency on jQuery Form.
-    drupal_add_library('core/jquery.farbtastic');
+    $attached['#attached']['library'][] = 'core/jquery.farbtastic';
+    drupal_render($attached);
     $scripts = drupal_get_js();
     $this->assertTrue(strpos($scripts, 'core/assets/vendor/jquery-form/jquery.form.js'), 'Altered library dependencies are added to the page.');
   }
@@ -517,8 +648,8 @@ function testLibraryUnknown() {
     $this->assertFalse($result, 'Unknown library returned FALSE.');
     drupal_static_reset('drupal_get_library');
 
-    $result = drupal_add_library('unknown/unknown');
-    $this->assertFalse($result, 'Unknown library returned FALSE.');
+    $attached['#attached']['library'][] = 'unknown/unknown';
+    drupal_render($attached);
     $scripts = drupal_get_js();
     $this->assertTrue(strpos($scripts, 'unknown') === FALSE, 'Unknown library was not added to the page.');
   }
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index 5064e61e5455..57898529dd2a 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -395,7 +395,7 @@ function theme_system_modules_details($variables) {
   }
 
   $table = array(
-    '#theme' => 'table',
+    '#type' => 'table',
     '#header' => $form['#header'],
     '#rows' => $rows,
   );
@@ -459,7 +459,7 @@ function theme_system_modules_uninstall($variables) {
   }
 
   $table = array(
-    '#theme' => 'table',
+    '#type' => 'table',
     '#header' => $header,
     '#rows' => $rows,
     '#empty' => t('No modules are available to uninstall.'),
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index 2df7c2eb967e..8ae6c7c86cf2 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -360,7 +360,7 @@ function hook_library_info_alter(&$libraries, $module) {
  * @param string $name
  *   The name of the library.
  *
- * @see drupal_add_library()
+ * @see _drupal_add_library()
  */
 function hook_library_alter(array &$library, $name) {
   if ($name == 'core/jquery.ui.datepicker') {
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 721bcf8fd98e..eef5bce800bc 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -276,6 +276,14 @@ function system_hook_info() {
  */
 function system_element_info() {
   // Top level elements.
+  $types['html'] = array(
+    '#theme' => 'html',
+    '#pre_render' => array('drupal_pre_render_html'),
+    // HTML5 Shiv
+    '#attached' => array(
+      'library' => array('core/html5shiv'),
+    ),
+  );
   $types['form'] = array(
     '#method' => 'post',
     '#action' => request_uri(),
@@ -611,6 +619,8 @@ function system_element_info() {
     '#input' => TRUE,
     '#tree' => TRUE,
     '#tableselect' => FALSE,
+    '#sticky' => FALSE,
+    '#responsive' => TRUE,
     '#multiple' => TRUE,
     '#js_select' => TRUE,
     '#value_callback' => 'form_type_table_value',
@@ -1218,8 +1228,8 @@ function system_user_timezone(&$form, &$form_state) {
   );
   if (!$account->getTimezone() && $account->id() == $user->id() && empty($form_state['input']['timezone'])) {
     $form['timezone']['#description'] = t('Your time zone setting will be automatically detected if possible. Confirm the selection and click save.');
+    $form['timezone']['#attached']['library'][] = 'core/drupal.timezone';
     $form['timezone']['timezone']['#attributes'] = array('class' => array('timezone-detect'));
-    drupal_add_library('core/drupal.timezone');
   }
 }
 
diff --git a/core/modules/tracker/tracker.pages.inc b/core/modules/tracker/tracker.pages.inc
index e94c163ba3e6..89226725b9af 100644
--- a/core/modules/tracker/tracker.pages.inc
+++ b/core/modules/tracker/tracker.pages.inc
@@ -139,7 +139,7 @@ function tracker_page($account = NULL) {
   $page['tracker'] = array(
     '#rows' => $rows,
     '#header' => array(t('Type'), t('Title'), t('Author'), t('Replies'), t('Last updated')),
-    '#theme' => 'table',
+    '#type' => 'table',
     '#empty' => t('No content available.'),
   );
   $page['pager'] = array(
diff --git a/core/modules/update/update.manager.inc b/core/modules/update/update.manager.inc
index c93b63b13b9f..f5c1d8a5a0d5 100644
--- a/core/modules/update/update.manager.inc
+++ b/core/modules/update/update.manager.inc
@@ -267,7 +267,7 @@ function update_manager_update_form($form, $form_state = array(), $context) {
     $prefix = '<h2>' . t('Manual updates required') . '</h2>';
     $prefix .= '<p>' . t('Updates of Drupal core are not supported at this time.') . '</p>';
     $form['manual_updates'] = array(
-      '#theme' => 'table',
+      '#type' => 'table',
       '#header' => $headers,
       '#rows' => $projects['manual'],
       '#prefix' => $prefix,
diff --git a/core/modules/update/update.report.inc b/core/modules/update/update.report.inc
index bb87e61bec68..bf3a6d22f5ad 100644
--- a/core/modules/update/update.report.inc
+++ b/core/modules/update/update.report.inc
@@ -283,7 +283,7 @@ function theme_update_report($variables) {
       ksort($rows[$type_name]);
       $output .= "\n<h3>" . $type_label . "</h3>\n";
       $table = array(
-        '#theme' => 'table',
+        '#type' => 'table',
         '#header' => $header,
         '#rows' => $rows[$type_name],
         '#attributes' => array(
diff --git a/core/modules/views/lib/Drupal/views/Controller/ViewAjaxController.php b/core/modules/views/lib/Drupal/views/Controller/ViewAjaxController.php
index 8df3017b6d9e..cd38199711c8 100644
--- a/core/modules/views/lib/Drupal/views/Controller/ViewAjaxController.php
+++ b/core/modules/views/lib/Drupal/views/Controller/ViewAjaxController.php
@@ -131,7 +131,7 @@ public function ajaxView(Request $request) {
         $view->dom_id = $dom_id;
 
         $preview = $view->preview($display_id, $args);
-        $response->addCommand(new ReplaceCommand(".view-dom-id-$dom_id", drupal_render($preview)));
+        $response->addCommand(new ReplaceCommand(".view-dom-id-$dom_id", $this->drupalRender($preview)));
         return $response;
       }
       else {
@@ -143,4 +143,20 @@ public function ajaxView(Request $request) {
     }
   }
 
+  /**
+   * Wraps drupal_render.
+   *
+   * @param array $elements
+   *   The structured array describing the data to be rendered.
+   *
+   * @return string
+   *   The rendered HTML.
+   *
+   * @todo Remove once drupal_render is converted to autoloadable code.
+   * @see https://drupal.org/node/2171071
+   */
+  protected function drupalRender(array $elements) {
+    return drupal_render($elements);
+  }
+
 }
diff --git a/core/modules/views/tests/Drupal/views/Tests/Controller/ViewAjaxControllerTest.php b/core/modules/views/tests/Drupal/views/Tests/Controller/ViewAjaxControllerTest.php
index 8cc5d104e596..da1245b699ee 100644
--- a/core/modules/views/tests/Drupal/views/Tests/Controller/ViewAjaxControllerTest.php
+++ b/core/modules/views/tests/Drupal/views/Tests/Controller/ViewAjaxControllerTest.php
@@ -58,7 +58,7 @@ protected function setUp() {
       ->disableOriginalConstructor()
       ->getMock();
 
-    $this->viewAjaxController = new ViewAjaxController($this->viewStorage, $this->executableFactory);
+    $this->viewAjaxController = new TestViewAjaxController($this->viewStorage, $this->executableFactory);
   }
 
   /**
@@ -280,6 +280,18 @@ protected function assertViewResultCommand(ViewAjaxResponse $response, $position
 
 }
 
+/**
+ * Overrides ViewAjaxController::drupalRender to protect the parent method.
+ */
+class TestViewAjaxController extends ViewAjaxController {
+
+  // @todo Remove once drupal_render is converted to autoloadable code.
+  protected function drupalRender(array $elements) {
+    return isset($elements['#markup']) ? $elements['#markup'] : '';
+  }
+
+}
+
 }
 
 namespace {
@@ -290,11 +302,4 @@ function &drupal_static($key) {
     }
   }
 
-  // @todo Remove once drupal_render is converted to autoloadable code.
-  if (!function_exists('drupal_render')) {
-    function drupal_render($array) {
-      return isset($array['#markup']) ? $array['#markup'] : '';
-    }
-  }
-
 }
diff --git a/core/modules/views/views.api.php b/core/modules/views/views.api.php
index faacf8a69b8d..f2d2a1e31ac5 100644
--- a/core/modules/views/views.api.php
+++ b/core/modules/views/views.api.php
@@ -576,9 +576,9 @@ function hook_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
  *
  * @param array $rows
  *   An associative array with two keys:
- *   - query: An array of rows suitable for '#theme' => 'table', containing
+ *   - query: An array of rows suitable for '#type' => 'table', containing
  *     information about the query and the display title and path.
- *   - statistics: An array of rows suitable for '#theme' => 'table',
+ *   - statistics: An array of rows suitable for '#type' => 'table',
  *     containing performance statistics.
  * @param \Drupal\views\ViewExecutable $view
  *   The view object.
diff --git a/core/modules/views/views.module b/core/modules/views/views.module
index a4311e8b1b1d..922a8d959b8e 100644
--- a/core/modules/views/views.module
+++ b/core/modules/views/views.module
@@ -9,6 +9,7 @@
  * incoming page and block requests.
  */
 
+use Drupal\Component\Utility\String;
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Database\Query\AlterableInterface;
 use Drupal\Core\Language\Language;
@@ -56,6 +57,37 @@ function views_element_info() {
   return $types;
 }
 
+/**
+ * Implements hook_views_pre_render().
+ */
+function views_views_pre_render($view) {
+  // If using AJAX, send identifying data about this view.
+  if ($view->ajaxEnabled() && empty($view->is_attachment) && empty($view->live_preview)) {
+    $settings = array(
+      'views' => array(
+        'ajax_path' => url('views/ajax'),
+        'ajaxViews' => array(
+          'views_dom_id:' . $view->dom_id => array(
+            'view_name' => $view->storage->id(),
+            'view_display_id' => $view->current_display,
+            'view_args' => String::checkPlain(implode('/', $view->args)),
+            'view_path' => String::checkPlain(current_path()),
+            'view_base_path' => $view->getPath(),
+            'view_dom_id' => $view->dom_id,
+            // To fit multiple views on a page, the programmer may have
+            // overridden the display's pager_element.
+            'pager_element' => isset($view->pager) ? $view->pager->getPagerId() : 0,
+          ),
+        ),
+      ),
+    );
+    $view->element['#attached']['js'][] = array('type' => 'setting', 'data' => $settings);
+    $view->element['#attached']['library'][] = 'views/views.ajax';
+  }
+
+  return $view;
+}
+
 /**
  * View element pre render callback.
  */
@@ -332,7 +364,8 @@ function views_preprocess_page(&$variables) {
       unset($class[$key]);
       $attributes['class'] = $class;
       $attributes['data-views-page-contextual-id'] = $variables['title_suffix']['contextual_links']['#id'];
-      drupal_add_library('views/views.contextual-links');
+      $attached['#attached']['library'][] = 'views/views.contextual-links';
+      drupal_render($attached);
     }
   }
 }
diff --git a/core/modules/views/views.theme.inc b/core/modules/views/views.theme.inc
index 1acadb72772d..eaf3d8607887 100644
--- a/core/modules/views/views.theme.inc
+++ b/core/modules/views/views.theme.inc
@@ -106,30 +106,6 @@ function template_preprocess_views_view(&$variables) {
     $variables['attributes']['class'][] = 'view-dom-id-' . $variables['dom_id'];
   }
 
-  // If using AJAX, send identifying data about this view.
-  if ($view->ajaxEnabled() && empty($view->is_attachment) && empty($view->live_preview)) {
-    $settings = array(
-      'views' => array(
-        'ajax_path' => url('views/ajax'),
-        'ajaxViews' => array(
-          'views_dom_id:' . $variables['dom_id'] => array(
-            'view_name' => $view->storage->id(),
-            'view_display_id' => $view->current_display,
-            'view_args' => String::checkPlain(implode('/', $view->args)),
-            'view_path' => String::checkPlain(current_path()),
-            'view_base_path' => $view->getPath(),
-            'view_dom_id' => $variables['dom_id'],
-            // To fit multiple views on a page, the programmer may have
-            // overridden the display's pager_element.
-            'pager_element' => isset($view->pager) ? $view->pager->getPagerId() : 0,
-          ),
-        ),
-      ),
-    );
-    $view->element['#attached']['js'][] = array('type' => 'setting', 'data' => $settings);
-    $view->element['#attached']['library'][] = 'views/views.ajax';
-  }
-
   // If form fields were found in the view, reformat the view output as a form.
   if ($view->hasFormElements()) {
     // Copy the rows so as not to modify them by reference when rendering.
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Controller/ViewsUIController.php b/core/modules/views_ui/lib/Drupal/views_ui/Controller/ViewsUIController.php
index df9aff3fb235..018d4d9e01a8 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/Controller/ViewsUIController.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/Controller/ViewsUIController.php
@@ -98,7 +98,7 @@ public function reportFields() {
     // Sort rows by field name.
     ksort($rows);
     $output = array(
-      '#theme' => 'table',
+      '#type' => 'table',
       '#header' => $header,
       '#rows' => $rows,
       '#empty' => t('No fields have been used in views yet.'),
@@ -126,7 +126,7 @@ public function reportPlugins() {
     // Sort rows by field name.
     ksort($rows);
     return array(
-      '#theme' => 'table',
+      '#type' => 'table',
       '#header' => array(t('Type'), t('Name'), t('Provided by'), t('Used in')),
       '#rows' => $rows,
       '#empty' => t('There are no enabled views.'),
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewListController.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewListController.php
index ec643203c816..1facb3c4017c 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/ViewListController.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewListController.php
@@ -196,7 +196,7 @@ public function render() {
       $list[$status]['#type'] = 'container';
       $list[$status]['#attributes'] = array('class' => array('views-list-section', $status));
       $list[$status]['table'] = array(
-        '#theme' => 'table',
+        '#type' => 'table',
         '#attributes' => array(
           'class' => array('views-listing-table'),
         ),
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
index 1ea7ee217a8e..f959d0de7897 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
@@ -712,7 +712,7 @@ public function renderPreview($display_id, $args = array()) {
     // Assemble the preview, the query info, and the query statistics in the
     // requested order.
     $table = array(
-      '#theme' => 'table',
+      '#type' => 'table',
       '#prefix' => '<div class="views-query-info">',
       '#suffix' => '</div>',
     );
diff --git a/core/modules/views_ui/views_ui.theme.inc b/core/modules/views_ui/views_ui.theme.inc
index 87ca306bdee6..b224dca383a2 100644
--- a/core/modules/views_ui/views_ui.theme.inc
+++ b/core/modules/views_ui/views_ui.theme.inc
@@ -195,7 +195,7 @@ function theme_views_ui_build_group_filter_form($variables) {
     $rows[] = array('data' => $data, 'id' => 'views-row-' . $group_id, 'class' => array('draggable'));
   }
   $table = array(
-    '#theme' => 'table',
+    '#type' => 'table',
     '#header' => $header,
     '#rows' => $rows,
     '#attributes' => array(
@@ -297,7 +297,7 @@ function theme_views_ui_rearrange_filter_form(&$variables) {
   if (!empty($ungroupable_rows)) {
     $header = array(t('Ungroupable filters'), t('Weight'), array('class' => array('views-hide-label'), 'data' => t('Group')), array('class' => array('views-hide-label'), 'data' => t('Remove')));
     $table = array(
-      '#theme' => 'table',
+      '#type' => 'table',
       '#header' => $header,
       '#rows' => $ungroupable_rows,
       '#attributes' => array(
@@ -317,7 +317,7 @@ function theme_views_ui_rearrange_filter_form(&$variables) {
 
   // Set up tabledrag so that the weights are changed when rows are dragged.
   $table = array(
-    '#theme' => 'table',
+    '#type' => 'table',
     '#rows' => $rows,
     '#attributes' => array(
       'id' => 'views-rearrange-filters',
diff --git a/core/tests/Drupal/Tests/Core/Ajax/AjaxCommandsTest.php b/core/tests/Drupal/Tests/Core/Ajax/AjaxCommandsTest.php
index 188c042073c1..038414826974 100644
--- a/core/tests/Drupal/Tests/Core/Ajax/AjaxCommandsTest.php
+++ b/core/tests/Drupal/Tests/Core/Ajax/AjaxCommandsTest.php
@@ -5,7 +5,7 @@
  * Contains \Drupal\Tests\Core\Ajax\AjaxCommandsTest.
  */
 
-namespace Drupal\Tests\Core\Ajax {
+namespace Drupal\Tests\Core\Ajax;
 
 use Drupal\Tests\UnitTestCase;
 use Drupal\Core\Ajax\AddCssCommand;
@@ -308,7 +308,7 @@ public function testSettingsCommand() {
    * Tests that OpenDialogCommand objects can be constructed and rendered.
    */
   public function testOpenDialogCommand() {
-    $command = new OpenDialogCommand('#some-dialog', 'Title', '<p>Text!</p>', array(
+    $command = new TestOpenDialogCommand('#some-dialog', 'Title', '<p>Text!</p>', array(
       'url' => FALSE,
       'width' => 500,
     ));
@@ -332,7 +332,7 @@ public function testOpenDialogCommand() {
    * Tests that OpenModalDialogCommand objects can be constructed and rendered.
    */
   public function testOpenModalDialogCommand() {
-    $command = new OpenModalDialogCommand('Title', '<p>Text!</p>', array(
+    $command = new TestOpenModalDialogCommand('Title', '<p>Text!</p>', array(
       'url' => 'example',
       'width' => 500,
     ));
@@ -425,12 +425,26 @@ public function testRedirectCommand() {
 
 }
 
+/**
+ * Wraps OpenModalDialogCommand::drupalAttachLibrary().
+ *
+ * {@inheritdoc}
+ */
+class TestOpenModalDialogCommand extends OpenModalDialogCommand {
+
+  protected function drupalAttachLibrary($name) {
+  }
+
 }
 
-namespace {
-  if (!function_exists('drupal_add_library')) {
-    function drupal_add_library() {
-      return TRUE;
-    }
+/**
+ * Wraps OpenDialogCommand::drupalAttachLibrary().
+ *
+ * {@inheritdoc}
+ */
+class TestOpenDialogCommand extends OpenDialogCommand {
+
+  protected function drupalAttachLibrary($name) {
   }
+
 }
-- 
GitLab